Sentenças aninhadas

alexgarzao

Alex Sandro Garzão

Posted on July 31, 2024

Sentenças aninhadas

Para quem não está acompanhando o POJ (Pascal on the JVM) é um compilador que transforma um subset de Pascal para JASM (Java Assembly) de forma que possamos usar a JVM como ambiente de execução.

Na última postagem resolvemos alguns bugs importantes, em especial na geração do assembly. Nesta publicação vamos falar sobre como gerar corretamente o assembly para sentenças aninhadas.

Como estamos compilando para a JVM faz-se necessário detalhar o funcionamento de vários pontos desta incrível máquina virtual. Com isso, em vários momentos eu detalho o funcionamento interno da JVM bem como algumas das suas instruções (opcodes).

Contextos

Uma das funcionalidades necessárias para lidarmos corretamente com sentenças aninhadas é a possibilidade de termos vários contextos no parser. Isso ocorre porque se o parser assume um contexto apenas, sentenças de controle aninhadas que geram labels e saltos (como if, for, while e repeat) gerariam o endereçamento de saltos incorretamente.

Existem duas formas de lidar com contextos, que são:

  • Parser recursivo
  • Empilhar contextos

Usualmente eu utilizaria a abordagem de parser recursivo. Porém, para podermos implementar um parser recursivo com o ANTLR, pela forma como a gramática foi estruturada no POJ, seria necessário injetar código diretamente na gramática, uma abordagem pouco recomendada. Em função disso optou-se pela abordagem de empilhar contextos.

Como já existia uma implementação de pilha que monitorava os tipos que o parser empilhou/desempilhou na JVM, para não ter que criar mais uma pilha para um tipo específico, optou-se por criar uma stack genérica neste PR. Além de poder aproveitar esta implementação posteriormente, ainda posso refatorar o código antigo e remover a stack específica existente.

Neste commit o parser foi alterado para empilhar/desempilhar corretamente os contextos das funções. Basicamente no início do parser de uma função o contexto é empilhado, e no seu final o contexto é desempilhado.

Sentenças aninhadas

Sentenças de controle como if, for, while e repeat funcionavam corretamente. Porém, caso houvesse sentenças aninhadas, o POJ não guardava contexto e acaba por gerar erroneamente os labels e saltos. Aqui e aqui foi abordado como funciona a geração do assembly para estas sentenças de controle.

Para o exemplo abaixo, que contém um if aninhado dentro de outro, o POJ gerava erroneamente os labels e saltos necessários:

program NestedIfs;
begin
  if (1 > 2) then
    if (2 > 3 ) then
      writeln('1 > 2 and 2 > 3')
    else
      writeln('1 > 2 and 2 <= 3')
  else
    writeln('1 <= 2');
end.
Enter fullscreen mode Exit fullscreen mode

Este bug era conhecido e eu optei por resolvê-lo no momento em que o parser tivesse suporte a contextos.

Neste commit foi criado a estrutura LabelsContext contendo os seguintes labels:

  • Else: necessário para o caso do if com else;
  • NextStatement: contém o label da próxima instrução;
  • IterationStart: indica o teste da estrutura de repetição no caso de while, repeat e for.

Para validar a correta geração do assembly foram criados testes para validar if's aninhados, repeat's aninhados, while's aninhados bem como for's aninhados. Aqui foi criado os testes para validar a geração do assembly no caso de funções recursivas. Além disso foi necessário atualizar o assembly esperado de todos os testes existentes. Por fim, neste PR foi atualizado o parser para utilizar a nova estrutura de contextos.

Aqui está o PR completo destas modificações. Aqui temos o commit contendo as mudanças para o correto funcionamento da sentença if, aqui o commit referente ao repeat, aqui o commit referente ao while e aqui o commit referente ao for.

Próximos passos

Na próxima publicação vamos falar sobre entrada de dados. Agora falta pouco para concluirmos um dos objetivos deste projeto: ler um número da entrada padrão e calcular o seu fatorial.

Código completo do projeto

O repositório com o código completo do projeto e a sua documentação está aqui.

💖 💪 🙅 🚩
alexgarzao
Alex Sandro Garzão

Posted on July 31, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Sentenças aninhadas
compiling Sentenças aninhadas

July 31, 2024