Etapa 7: Geração de Código para JVM

Published

25/03/2026

Modified

17/03/2026

Objetivos

  • Aprender sobre a máquina de pilha da JVM (Java Virtual Machine).
  • Utilizar a biblioteca ASM para gerar bytecode.
  • Finalizar o compilador gerando um artefato executável (.class).

Fundamentação Teórica

A JVM não possui registradores de uso geral (como EAX, EBX). Ela opera sobre uma Pilha de Operandos. Exemplo para a = b + c: 1. iload_1 (Carrega b na pilha) 2. iload_2 (Carrega c na pilha) 3. iadd (Desempilha dois, soma, empilha o resultado) 4. istore_0 (Desempilha o resultado e salva em a)

Atividades Práticas

1. Configurando a Biblioteca ASM

Adicione ao pom.xml:

<dependency>
    <groupId>org.ow2.asm</groupId>
    <artifactId>asm</artifactId>
    <version>9.6</version>
</dependency>

2. O CodeGen Visitor

Crie um pacote br.com.comcet.tp7. Crie nele um Visitor que percorre a AST e emite instruções ASM. Ele precisará de: - ClassWriter: Para criar a estrutura da classe. - MethodVisitor: Para escrever instruções dentro do método main.

Mapeamento de Variáveis: Diferente da Tabela de Símbolos (que usa nomes), a JVM usa índices numéricos (0, 1, 2…). Você precisará de um mapa String -> Integer para saber qual índice representa a variável x.

3. Implementando Instruções

  • Programa: Cria a classe Program, cria o método public static void main(String[] args).
  • Atribuição (x := expr):
    • Visita expr (gera código que deixa o resultado na pilha).
    • Emite istore varIndex (salva da pilha na variável).
  • Soma (a + b):
    • Visita a (pilha: a).
    • Visita b (pilha: a, b).
    • Emite iadd (pilha: a+b).
  • Print (writeln(x)):
    • getstatic System.out
    • Visita x (carrega valor)
    • invokevirtual println

4. Compilador Final

O seu programa deve: 1. Ler arquivo .pas. 2. Analisar Lexico/Sintatico. 3. Analisar Semântico. 4. Gerar arquivo .class.

5. Testes Automatizados (JUnit) — públicos

Crie ao menos um teste JUnit público que valide o resultado final de ponta a ponta: compilar um programinha, gerar .class e executar.

Uma forma simples é: - gerar o .class em um diretório temporário; - executar com ProcessBuilder e comparar a saída.

Crie, por exemplo, src/test/java/br/com/comcet/tp7/CodeGenSmokeTest.java:

package br.com.comcet.tp7;

import org.junit.jupiter.api.Test;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;

import static org.junit.jupiter.api.Assertions.*;

public class CodeGenSmokeTest {

    @Test
    void geraEClassExecuta() throws Exception {
        // Exemplo mínimo: gerar uma classe que imprime 120.
        // Adapte o código para o seu Mini-Pascal (pode ser writeln(120) ou equivalente).
        String codigo = "program p; begin writeln(120); end.";

        Path outDir = Files.createTempDirectory("codegen-test");

        Compiler compiler = new Compiler(); // adapte para o nome do seu compilador/driver
        String className = "P";            // adapte para sua estratégia de nome
        compiler.compileToClass(codigo, outDir, className); // adapte assinatura

        Process p = new ProcessBuilder(
                "java",
                "-cp",
                outDir.toAbsolutePath().toString(),
                className
        ).redirectErrorStream(true).start();

        String output;
        try (InputStream is = p.getInputStream()) {
            output = new String(is.readAllBytes(), StandardCharsets.UTF_8).trim();
        }
        int exit = p.waitFor();

        assertEquals(0, exit);
        assertEquals("120", output);
    }
}

Observação: este teste é um “smoke test”. Ele não verifica todas as instruções, mas garante que o pipeline completo gera um .class executável e com saída esperada.

O que entregar

  • O compilador completo funcionando.
  • Exemplo fatorial.pas compilado e executado.
  • Pelo menos um teste JUnit público (smoke test) para a geração e execução do .class.

Exemplo de execução:

java -jar target/comcet-1.0-SNAPSHOT.jar fatorial.pas
# Gera fatorial.class
java fatorial
# Saída: 120
Back to top