<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Alex Sandro Garzão</title>
    <description>The latest articles on Forem by Alex Sandro Garzão (@alexgarzao).</description>
    <link>https://forem.com/alexgarzao</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F480814%2Fc6f9cacd-e3d1-420a-89d2-7bfb4fc0953e.jpeg</url>
      <title>Forem: Alex Sandro Garzão</title>
      <link>https://forem.com/alexgarzao</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/alexgarzao"/>
    <language>en</language>
    <item>
      <title>Teste de fogo: fatorial recursivo</title>
      <dc:creator>Alex Sandro Garzão</dc:creator>
      <pubDate>Tue, 13 Aug 2024 21:58:59 +0000</pubDate>
      <link>https://forem.com/alexgarzao/teste-de-fogo-fatorial-recursivo-1hin</link>
      <guid>https://forem.com/alexgarzao/teste-de-fogo-fatorial-recursivo-1hin</guid>
      <description>&lt;p&gt;Para quem não está acompanhando o POJ (&lt;em&gt;Pascal on the JVM&lt;/em&gt;) é um compilador que transforma um &lt;em&gt;subset&lt;/em&gt; de Pascal para JASM (&lt;em&gt;Java Assembly&lt;/em&gt;) de forma que possamos usar a JVM como ambiente de execução.&lt;/p&gt;

&lt;p&gt;Na última &lt;a href="https://dev.to/alexgarzao/lendo-dados-da-entrada-padrao-stdin-a47"&gt;postagem&lt;/a&gt; foi implementado o suporte ao &lt;em&gt;read/readln&lt;/em&gt; de &lt;em&gt;Pascal&lt;/em&gt;, funções que possibilitam a leitura de dados da entrada padrão (&lt;em&gt;stdin&lt;/em&gt;). Nesta publicação vamos concluir um dos objetivos do POJ: ler um número da entrada padrão e calcular o fatorial de forma recursiva.&lt;/p&gt;

&lt;p&gt;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 (&lt;em&gt;opcodes&lt;/em&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Fatorial recursivo, a cereja do bolo :-)
&lt;/h2&gt;

&lt;p&gt;Como &lt;a href="https://dev.to/alexgarzao/pascal-rodando-na-jvm-1m3b"&gt;citado no início do projeto&lt;/a&gt; um dos objetivos era podermos calcular o fatorial de forma recursiva, lendo o número a ser calculado da entrada padrão. As implementações no POJ até o momento possibilitaram este objetivo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/alexgarzao/compilando-o-hello-world-em-pascal-jan"&gt;Hello world&lt;/a&gt;: criou a base de código do projeto com ANTLR, parser e geração de código &lt;em&gt;Java Assembly&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;Operadores de &lt;a href="https://dev.to/alexgarzao/operadores-de-adicao-e-subtracao-3ikm"&gt;adição, subtração&lt;/a&gt;, &lt;a href="https://dev.to/alexgarzao/novos-operadores-e-a-sentenca-if-b5f"&gt;multiplicação, divisão e o início das sentenças condicionais - if&lt;/a&gt;: iniciou o suporte aos operadores bem como o suporte inicial às senteças condicionais;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/alexgarzao/estruturas-de-repeticao-repeat-while-e-for-4ph6"&gt;Repeat, while e for&lt;/a&gt;: suporte às estruturas de repetição;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/alexgarzao/suporte-as-funcoes-do-pascal-2fl9"&gt;Funções em Pascal&lt;/a&gt;: implementação de funções recursivas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agora chegou o momento de validar o que foi desenvolvido até o momento. Dito isso, a partir do programa Pascal abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program fatorial;

var numero : integer;

function fatorial(n : integer) : integer;
begin
    if n&amp;lt;0 then fatorial := 0
    else begin
        if n&amp;lt;=1 then fatorial := 1
        else fatorial := n * fatorial(n-1);
    end;
end;

begin
    write('Introduza numero inteiro: ');
    readln(numero);
    writeln;
    writeln('O fatorial de ', numero, ' e: ', fatorial(numero));
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ gera corretamente o seguinte &lt;em&gt;assembly&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Code generated by POJ 0.1
public class fatorial {
    public static numero I

    static fatorial(I)I {
        iload 0
        sipush 0
        if_icmpge L4
        iconst 1 
        goto L5
    L4: iconst 0 
    L5: ifeq L1
        sipush 0
        istore 100
        goto L2
    L1: iload 0
        sipush 1
        if_icmpgt L9
        iconst 1 
        goto L10
    L9: iconst 0 
    L10:ifeq L6
        sipush 1
        istore 100
        goto L7
    L6: iload 0
        iload 0
        sipush 1
        isub 
        invokestatic fatorial.fatorial(I)I 
        imul 
        istore 100
L7: L2: iload 100
        ireturn 
    }

    public static main([java/lang/String)V {
        getstatic java/lang/System.out java/io/PrintStream
        ldc "Introduza numero inteiro: "
        invokevirtual java/io/PrintStream.print(java/lang/String)V

        invokestatic java/lang/System.console()java/io/Console
        invokevirtual java/io/Console.readLine()java/lang/String
        invokestatic java/lang/Integer.parseInt(java/lang/String)I
        putstatic fatorial.numero I

        getstatic java/lang/System.out java/io/PrintStream
        invokevirtual java/io/PrintStream.println()V

        getstatic java/lang/System.out java/io/PrintStream
        ldc "O fatorial de "
        invokevirtual java/io/PrintStream.print(java/lang/String)V

        getstatic java/lang/System.out java/io/PrintStream
        getstatic fatorial.numero I
        invokevirtual java/io/PrintStream.print(I)V

        getstatic java/lang/System.out java/io/PrintStream
        ldc " e: "
        invokevirtual java/io/PrintStream.print(java/lang/String)V

        getstatic java/lang/System.out java/io/PrintStream
        getstatic fatorial.numero I
        invokestatic fatorial.fatorial(I)I 
        invokevirtual java/io/PrintStream.print(I)V

        getstatic java/lang/System.out java/io/PrintStream
        invokevirtual java/io/PrintStream.println()V

        return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Enfim, o fim
&lt;/h2&gt;

&lt;p&gt;Aqui chegamos ao final desta jornada de aprendizado com este projeto.&lt;/p&gt;

&lt;p&gt;Algumas coisas interessantes da área de compiladores podem ser exploradas com este projeto (como otimização de código gerado). Quem sabe em futuro breve iniciamos uma nova série com otimizações :-)&lt;/p&gt;

&lt;h2&gt;
  
  
  Código completo do projeto
&lt;/h2&gt;

&lt;p&gt;O repositório com o código completo do projeto e a sua documentação está &lt;a href="https://github.com/alexgarzao/poj" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>compiling</category>
      <category>go</category>
      <category>antlr</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Lendo dados da entrada padrão (stdin)</title>
      <dc:creator>Alex Sandro Garzão</dc:creator>
      <pubDate>Wed, 07 Aug 2024 00:01:05 +0000</pubDate>
      <link>https://forem.com/alexgarzao/lendo-dados-da-entrada-padrao-stdin-a47</link>
      <guid>https://forem.com/alexgarzao/lendo-dados-da-entrada-padrao-stdin-a47</guid>
      <description>&lt;p&gt;Para quem não está acompanhando o POJ (&lt;em&gt;Pascal on the JVM&lt;/em&gt;) é um compilador que transforma um &lt;em&gt;subset&lt;/em&gt; de Pascal para JASM (&lt;em&gt;Java Assembly&lt;/em&gt;) de forma que possamos usar a JVM como ambiente de execução.&lt;/p&gt;

&lt;p&gt;Na última &lt;a href="https://dev.to/alexgarzao/sentencas-aninhadas-334a"&gt;postagem&lt;/a&gt; foi abordado contextos (do &lt;em&gt;parser&lt;/em&gt;) e sentenças aninhadas. Nesta publicação vamos falar sobre as alterações necessárias para possibilitar a leitura de dados da entrada padrão (&lt;em&gt;stdin&lt;/em&gt;), isso utilizando a função &lt;em&gt;read/readln&lt;/em&gt; do &lt;em&gt;Pascal&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;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 (&lt;em&gt;opcodes&lt;/em&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Lendo dados de &lt;em&gt;stdin&lt;/em&gt; (entrada padrão)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Standard_streams" rel="noopener noreferrer"&gt;&lt;em&gt;Standard input&lt;/em&gt;&lt;/a&gt; (stdin) é o stream do qual um programa lê seus dados de entrada. Até o momento tínhamos suporte ao &lt;em&gt;stdout&lt;/em&gt; (saída padrão) apenas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/alexgarzao/poj/pull/34/commits/a967b7c0592367eb27ffcc21e3879cec2bf9eeb0" rel="noopener noreferrer"&gt;Neste &lt;em&gt;commit&lt;/em&gt;&lt;/a&gt; foi implementado um programa em Java para entendermos como a JVM lida com &lt;em&gt;stdin&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class InputData {
    public static String name;
    public static int age;

    public static void main(String[] args) {
        name = System.console().readLine();
        age = Integer.parseInt(System.console().readLine());
        System.out.println("You entered string " + name);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando desassemblamos o arquivo &lt;em&gt;class&lt;/em&gt; obtemos o &lt;em&gt;assembly&lt;/em&gt; abaixo. Trechos irrelevantes foram omitidos, bem como o trecho original (em Java) que deu origem ao &lt;em&gt;assembly&lt;/em&gt; foi inserido com ";;":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; 1: public class InputData {
 2:     ;; public static String name;
 3:     public static name java/lang/String
 4: 
 5:     ;; public static int age;
 6:     public static age I
 7:
 8:     public static main([java/lang/String)V {
 9:         ;; name = System.console().readLine();
10:         invokestatic java/lang/System.console()java/io/Console
11:         invokevirtual java/io/Console.readLine()java/lang/String
12:         putstatic InputData.name java/lang/String
13:
14:         ;; age = Integer.parseInt(System.console().readLine());
15:         invokestatic java/lang/System.console()java/io/Console
16:         invokevirtual java/io/Console.readLine()java/lang/String
17:         invokestatic java/lang/Integer.parseInt(java/lang/String)I
18:         putstatic InputData.age I
19:
20:         ;; System.out.println("You entered string " + name);
21:         getstatic java/lang/System.out java/io/PrintStream
22:         getstatic InputData.name java/lang/String
23:         invokedynamic makeConcatWithConstants(java/lang/String)java/lang/String {
                invokestatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants(java/lang/invoke/MethodHandles$Lookup, java/lang/String, java/lang/invoke/MethodType, java/lang/String, [java/lang/Object)java/lang/invoke/CallSite
                ["You entered string "]
            }
24:
25:         invokevirtual java/io/PrintStream.println(java/lang/String)V
26:
27:         return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com este exemplo foi possível identificar que para ler dados da &lt;em&gt;stdin&lt;/em&gt; era necessário utilizar a instrução &lt;em&gt;System.console().readLine()&lt;/em&gt; (linhas 11 e 16). E como &lt;em&gt;readLine()&lt;/em&gt; retorna uma string, para lermos números era necessário converter com o uso da função &lt;em&gt;Integer.parseInt&lt;/em&gt; (linha 17).&lt;/p&gt;

&lt;p&gt;Dito isso, a partir do programa Pascal abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program NameAndAge;
var
    myname: string;
    myage: integer;
begin
    write('What is your name? '); readln(myname);
    write('How old are you? '); readln(myage);
    writeln;
    writeln('Hello ', myname);
    writeln('You are ', myage, ' years old');
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ foi ajustado para gerar o seguinte JASM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Code generated by POJ 0.1
public class name_and_age {
    ;; var myname: string;
    public static myname java/lang/String

    ;; var myage: integer;
    public static myage I

    ;; procedure main
    public static main([java/lang/String)V {
        ;; write('What is your name? ');
        getstatic java/lang/System.out java/io/PrintStream
        ldc "What is your name? "
        invokevirtual java/io/PrintStream.print(java/lang/String)V

        ;; readln(myname);
        invokestatic java/lang/System.console()java/io/Console
        invokevirtual java/io/Console.readLine()java/lang/String
        putstatic name_and_age.myname java/lang/String

        ;; write('How old are you? ');
        getstatic java/lang/System.out java/io/PrintStream
        ldc "How old are you? "
        invokevirtual java/io/PrintStream.print(java/lang/String)V

        ;; readln(myage);
        invokestatic java/lang/System.console()java/io/Console
        invokevirtual java/io/Console.readLine()java/lang/String
        invokestatic java/lang/Integer.parseInt(java/lang/String)I
        putstatic name_and_age.myage I

        ;; writeln;
        getstatic java/lang/System.out java/io/PrintStream
        invokevirtual java/io/PrintStream.println()V

        ;; writeln('Hello ', myname);
        getstatic java/lang/System.out java/io/PrintStream
        ldc "Hello "
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        getstatic java/lang/System.out java/io/PrintStream
        getstatic name_and_age.myname java/lang/String
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        getstatic java/lang/System.out java/io/PrintStream
        invokevirtual java/io/PrintStream.println()V

        ;; writeln('You are ', myage, ' years old');
        getstatic java/lang/System.out java/io/PrintStream
        ldc "You are "
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        getstatic java/lang/System.out java/io/PrintStream
        getstatic name_and_age.myage I
        invokevirtual java/io/PrintStream.print(I)V
        getstatic java/lang/System.out java/io/PrintStream
        ldc " years old"
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        getstatic java/lang/System.out java/io/PrintStream
        invokevirtual java/io/PrintStream.println()V

        return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este &lt;a href="https://github.com/alexgarzao/poj/pull/34/commits/7b4d0a97d5266cbe06e29dc02d581f6fc105b9a8" rel="noopener noreferrer"&gt;commit&lt;/a&gt; implementa as alterações necessárias no parser do POJ.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/alexgarzao/poj/pull/34/" rel="noopener noreferrer"&gt;Aqui&lt;/a&gt; está o PR completo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Próximos passos
&lt;/h2&gt;

&lt;p&gt;Na próxima publicação vamos concluir um dos objetivos deste projeto: cálculo do fatorial de forma recursiva.&lt;/p&gt;

&lt;h2&gt;
  
  
  Código completo do projeto
&lt;/h2&gt;

&lt;p&gt;O repositório com o código completo do projeto e a sua documentação está &lt;a href="https://github.com/alexgarzao/poj" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>compiling</category>
      <category>go</category>
      <category>antlr</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Sentenças aninhadas</title>
      <dc:creator>Alex Sandro Garzão</dc:creator>
      <pubDate>Wed, 31 Jul 2024 00:00:19 +0000</pubDate>
      <link>https://forem.com/alexgarzao/sentencas-aninhadas-334a</link>
      <guid>https://forem.com/alexgarzao/sentencas-aninhadas-334a</guid>
      <description>&lt;p&gt;Para quem não está acompanhando o POJ (&lt;em&gt;Pascal on the JVM&lt;/em&gt;) é um compilador que transforma um &lt;em&gt;subset&lt;/em&gt; de Pascal para JASM (&lt;em&gt;Java Assembly&lt;/em&gt;) de forma que possamos usar a JVM como ambiente de execução.&lt;/p&gt;

&lt;p&gt;Na última &lt;a href="https://dev.to/alexgarzao/resolucao-de-alguns-bugs-3a1i"&gt;postagem&lt;/a&gt; resolvemos alguns bugs importantes, em especial na geração do &lt;em&gt;assembly&lt;/em&gt;. Nesta publicação vamos falar sobre como gerar corretamente o &lt;em&gt;assembly&lt;/em&gt; para &lt;a href="https://www.bbc.co.uk/bitesize/guides/znh6pbk/revision/8" rel="noopener noreferrer"&gt;sentenças aninhadas&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;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 (&lt;em&gt;opcodes&lt;/em&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Contextos
&lt;/h2&gt;

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

&lt;p&gt;Existem duas formas de lidar com contextos, que são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Parser&lt;/em&gt; recursivo&lt;/li&gt;
&lt;li&gt;Empilhar contextos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Usualmente eu utilizaria a abordagem de &lt;em&gt;parser&lt;/em&gt; recursivo. Porém, para podermos implementar um &lt;em&gt;parser&lt;/em&gt; 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.&lt;/p&gt;

&lt;p&gt;Como já existia uma implementação de pilha que monitorava os tipos que o &lt;em&gt;parser&lt;/em&gt; empilhou/desempilhou na JVM, para não ter que criar mais uma pilha para um tipo específico, optou-se por criar uma &lt;em&gt;stack&lt;/em&gt; genérica &lt;a href="https://github.com/alexgarzao/poj/pull/31/commits/7f1799c9d086c54f50152a2fd6280a33cbf530ff" rel="noopener noreferrer"&gt;neste PR&lt;/a&gt;. Além de poder aproveitar esta implementação posteriormente, ainda posso refatorar o código antigo e remover a &lt;em&gt;stack&lt;/em&gt; específica existente.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/alexgarzao/poj/pull/31/commits/44b6736869a1bc5bdf09a9b2901b358ee155ae95" rel="noopener noreferrer"&gt;Neste &lt;em&gt;commit&lt;/em&gt;&lt;/a&gt; o &lt;em&gt;parser&lt;/em&gt; foi alterado para empilhar/desempilhar corretamente os contextos das funções. Basicamente no início do &lt;em&gt;parser&lt;/em&gt; de uma função o contexto é empilhado, e no seu final o contexto é desempilhado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sentenças aninhadas
&lt;/h2&gt;

&lt;p&gt;Sentenças de controle como &lt;em&gt;if&lt;/em&gt;, &lt;em&gt;for&lt;/em&gt;, &lt;em&gt;while&lt;/em&gt; e &lt;em&gt;repeat&lt;/em&gt; funcionavam corretamente. Porém, caso houvesse sentenças aninhadas, o POJ não guardava contexto e acaba por gerar erroneamente os &lt;em&gt;labels&lt;/em&gt; e saltos. &lt;a href="https://dev.to/alexgarzao/novos-operadores-e-a-sentenca-if-b5f"&gt;Aqui&lt;/a&gt; e &lt;a href="https://dev.to/alexgarzao/estruturas-de-repeticao-repeat-while-e-for-4ph6"&gt;aqui&lt;/a&gt; foi abordado como funciona a geração do &lt;em&gt;assembly&lt;/em&gt; para estas sentenças de controle.&lt;/p&gt;

&lt;p&gt;Para o exemplo abaixo, que contém um &lt;em&gt;if&lt;/em&gt; aninhado dentro de outro, o POJ gerava erroneamente os &lt;em&gt;labels&lt;/em&gt; e saltos necessários:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program NestedIfs;
begin
  if (1 &amp;gt; 2) then
    if (2 &amp;gt; 3 ) then
      writeln('1 &amp;gt; 2 and 2 &amp;gt; 3')
    else
      writeln('1 &amp;gt; 2 and 2 &amp;lt;= 3')
  else
    writeln('1 &amp;lt;= 2');
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este bug era conhecido e eu optei por resolvê-lo no momento em que o parser tivesse suporte a contextos.&lt;/p&gt;

&lt;p&gt;Neste &lt;a href="https://github.com/alexgarzao/poj/pull/32/commits/0fe3742848928d53f8c9c5eb1d080a056a9ce90e" rel="noopener noreferrer"&gt;commit&lt;/a&gt; foi criado a estrutura LabelsContext contendo os seguintes &lt;em&gt;labels&lt;/em&gt;:&lt;/p&gt;

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

&lt;p&gt;Para validar a correta geração do &lt;em&gt;assembly&lt;/em&gt; foram criados testes para validar &lt;a href="https://github.com/alexgarzao/poj/pull/32/commits/7b25e5be645fded331ce7dc38679f03be649e7a7" rel="noopener noreferrer"&gt;&lt;em&gt;if's&lt;/em&gt; aninhados&lt;/a&gt;, &lt;a href="https://github.com/alexgarzao/poj/pull/32/commits/fbc261d3978ca61fc85eaa726dc4ced3b81b12af" rel="noopener noreferrer"&gt;&lt;em&gt;repeat's&lt;/em&gt; aninhados&lt;/a&gt;, &lt;a href="https://github.com/alexgarzao/poj/pull/32/commits/e46e2a87ea86fb8c7a6f67c6b75cb0b04daa9151" rel="noopener noreferrer"&gt;while's aninhados&lt;/a&gt; bem como &lt;a href="https://github.com/alexgarzao/poj/pull/32/commits/402dae1aed3559f937b71fb7d5d3a8b0ebe1a836" rel="noopener noreferrer"&gt;&lt;em&gt;for's&lt;/em&gt; aninhados&lt;/a&gt;. &lt;a href="https://github.com/alexgarzao/poj/pull/32/commits/2fc773b205f9a5b89d3b8486e40bd4ec95b4e1af" rel="noopener noreferrer"&gt;Aqui&lt;/a&gt; foi criado os testes para validar a geração do &lt;em&gt;assembly&lt;/em&gt; no caso de funções recursivas. Além disso foi necessário &lt;a href="https://github.com/alexgarzao/poj/pull/32/commits/844fe8bde605858c7d329e13e9778cafbee38073" rel="noopener noreferrer"&gt;atualizar o &lt;em&gt;assembly&lt;/em&gt; esperado de todos os testes existentes&lt;/a&gt;. Por fim, &lt;a href="https://github.com/alexgarzao/poj/pull/32/commits/68916ce054065bb4678e6d342329c8b899836b83" rel="noopener noreferrer"&gt;neste PR&lt;/a&gt; foi atualizado o &lt;em&gt;parser&lt;/em&gt; para utilizar a nova estrutura de contextos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/alexgarzao/poj/pull/32" rel="noopener noreferrer"&gt;Aqui&lt;/a&gt; está o PR completo destas modificações. &lt;a href="https://github.com/alexgarzao/poj/pull/32/commits/7b25e5be645fded331ce7dc38679f03be649e7a7" rel="noopener noreferrer"&gt;Aqui&lt;/a&gt; temos o &lt;em&gt;commit&lt;/em&gt; contendo as mudanças para o correto funcionamento da sentença &lt;em&gt;if&lt;/em&gt;, &lt;a href="https://github.com/alexgarzao/poj/pull/32/commits/fbc261d3978ca61fc85eaa726dc4ced3b81b12af" rel="noopener noreferrer"&gt;aqui&lt;/a&gt; o &lt;em&gt;commit&lt;/em&gt; referente ao &lt;em&gt;repeat&lt;/em&gt;, &lt;a href="https://github.com/alexgarzao/poj/pull/32/commits/e46e2a87ea86fb8c7a6f67c6b75cb0b04daa9151" rel="noopener noreferrer"&gt;aqui&lt;/a&gt; o &lt;em&gt;commit&lt;/em&gt; referente ao &lt;em&gt;while&lt;/em&gt; e &lt;a href="https://github.com/alexgarzao/poj/pull/32/commits/402dae1aed3559f937b71fb7d5d3a8b0ebe1a836" rel="noopener noreferrer"&gt;aqui&lt;/a&gt; o &lt;em&gt;commit&lt;/em&gt; referente ao &lt;em&gt;for&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Próximos passos
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Código completo do projeto
&lt;/h2&gt;

&lt;p&gt;O repositório com o código completo do projeto e a sua documentação está &lt;a href="https://github.com/alexgarzao/poj" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>compiling</category>
      <category>go</category>
      <category>antlr</category>
      <category>pascal</category>
    </item>
    <item>
      <title>Resolução de alguns bugs</title>
      <dc:creator>Alex Sandro Garzão</dc:creator>
      <pubDate>Tue, 23 Jul 2024 19:12:12 +0000</pubDate>
      <link>https://forem.com/alexgarzao/resolucao-de-alguns-bugs-3a1i</link>
      <guid>https://forem.com/alexgarzao/resolucao-de-alguns-bugs-3a1i</guid>
      <description>&lt;p&gt;Para quem não está acompanhando o POJ (&lt;em&gt;Pascal on the JVM&lt;/em&gt;) é um compilador que transforma um &lt;em&gt;subset&lt;/em&gt; de Pascal para JASM (&lt;em&gt;Java Assembly&lt;/em&gt;) de forma que possamos usar a JVM como ambiente de execução.&lt;/p&gt;

&lt;p&gt;Na última &lt;a href="https://dev.to/alexgarzao/suporte-as-funcoes-do-pascal-2fl9"&gt;postagem&lt;/a&gt; implementamos o suporte às &lt;em&gt;functions&lt;/em&gt; do Pascal.&lt;/p&gt;

&lt;p&gt;Nesta publicação vamos falar sobre coisas bacanas? Nem tanto rsrsrs. Desta vez só vamos falar de bugs mesmo :-)&lt;/p&gt;

&lt;p&gt;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 (&lt;em&gt;opcodes&lt;/em&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Bug referente aos parâmetros passados ao programa pela linha de comando
&lt;/h2&gt;

&lt;p&gt;Quando implementei a declaração de variáveis eu não atentei para o fato de que, na JVM, a primeira variável na função principal é o args, um array que contém os argumentos passados para o programa. Com isso &lt;a href="https://github.com/alexgarzao/poj/pull/31/commits/535e903072e6dcc4ad654c9425e4f589abfb2d11" rel="noopener noreferrer"&gt;neste PR&lt;/a&gt; eu reservo a primeira posição implicitamente para args.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bug ao lidar com variáveis locais e globais
&lt;/h2&gt;

&lt;p&gt;Como os programas em Pascal de teste continham apenas variáveis globais eu não havia notado um erro grave na geração do JASM. No momento em que criei programas que continham variáveis globais e locais percebi que algo de errado não estava certo rsrsrs.&lt;/p&gt;

&lt;p&gt;A partir do programa Pascal abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program global_var_declaration;
var
    globalvar : integer;
begin
    globalvar := 123;
    write (globalvar);
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ gerava o seguinte JASM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Code generated by POJ 0.1
public class global_var_declaration {
    public static main([java/lang/String)V {
        ;; globalvar := 123;
        bipush 123
        istore 1

        ;; write (globalvar);
        getstatic java/lang/System.out java/io/PrintStream
        iload 1
        invokevirtual java/io/PrintStream.print(I)V

        return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para tentar identificar o problema criei um programa em Java equivalente ao programa em Pascal acima:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class GlobalVarDeclaration {
    public static int globalVar;

    public static void main(String[] args) {
        globalVar = 123;
        System.out.println(globalVar);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando desassemblei o &lt;em&gt;class&lt;/em&gt; eu obtive o seguinte &lt;em&gt;assembly&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; 1: public class GlobalVarDeclaration {
 2:     public static globalVar I
 3:
 4:     public static main([java/lang/String)V {
 5:         bipush 123
 6:         putstatic GlobalVarDeclaration.globalVar I
 7:
 8:         getstatic java/lang/System.out java/io/PrintStream
 9:         getstatic GlobalVarDeclaration.globalVar I
10:         invokevirtual java/io/PrintStream.println(I)V
11:
12:         return
13:     }
14: }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste momento percebi a declaração "&lt;em&gt;public static globalVar I&lt;/em&gt;" (linha 2) e as instruções &lt;em&gt;putstatic&lt;/em&gt; (linha 6) e &lt;em&gt;getstatic&lt;/em&gt; (linha 9). O esperado eram as instruções &lt;em&gt;astore&lt;/em&gt; e &lt;em&gt;istore&lt;/em&gt; utilizadas pelo POJ até o momento. Lendo a &lt;a href="https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.putstatic" rel="noopener noreferrer"&gt;documentação da JVM&lt;/a&gt; percebi que o POJ estava declarando as variáveis globais como se fossem variáveis locais de uma função para a JVM :-D&lt;/p&gt;

&lt;p&gt;Enfim, até o momento o POJ estava usando (erroneamente) os &lt;em&gt;opcodes&lt;/em&gt; &lt;em&gt;aload&lt;/em&gt;/&lt;em&gt;iload&lt;/em&gt;/&lt;em&gt;astore&lt;/em&gt;/&lt;em&gt;istore&lt;/em&gt; para variáveis globais, mas o correto seria declarar as variáveis como públicas (como na linha 2) e utilizar o &lt;em&gt;getstatic&lt;/em&gt;/&lt;em&gt;putstatic&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Com isso o código foi refatorado &lt;a href="https://github.com/alexgarzao/poj/pull/31/commits/1272ef628b9d5741877294495582754630e6e4fd" rel="noopener noreferrer"&gt;aqui&lt;/a&gt; para que a tabela de símbolos consiga lidar com declarações locais e globais. E &lt;a href="https://github.com/alexgarzao/poj/pull/31/commits/d94ce556bbec3c3b0a3c2cec4a33b4b2882b64f2" rel="noopener noreferrer"&gt;aqui&lt;/a&gt; o código foi refatorado para que a tabela de símbolos consiga gerar as instruções corretas para as variáveis locais e globais.&lt;/p&gt;

&lt;p&gt;A geração de código JASM foi alterada &lt;a href="https://github.com/alexgarzao/poj/pull/31/commits/44d03128a71a17647b1a8ba11521d9f11e3fa451" rel="noopener noreferrer"&gt;aqui&lt;/a&gt; para lidar com a nova tabela de símbolos bem como limpar as declarações locais após o término de uma função ou procedimento.&lt;/p&gt;

&lt;p&gt;Com isso, a partir do programa Pascal abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program GlobalVarDeclaration;
var
    globalvar : integer;
begin
    globalvar := 123;
    write (globalvar);
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ passou a gerar corretamente o seguinte JASM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Code generated by POJ 0.1
public class global_var_declaration {
    public static globalvar I

    public static main([java/lang/String)V {
        ;; globalvar := 123;
        bipush 123
        putstatic global_var_declaration.globalvar I

        ;; write (globalvar);
        getstatic java/lang/System.out java/io/PrintStream
        getstatic global_var_declaration.globalvar I
        invokevirtual java/io/PrintStream.print(I)V

        return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Próximos passos
&lt;/h2&gt;

&lt;p&gt;Na próxima publicação vamos falar sobre contextos e sentenças aninhadas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Código completo do projeto
&lt;/h2&gt;

&lt;p&gt;O repositório com o código completo do projeto e a sua documentação está &lt;a href="https://github.com/alexgarzao/poj" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>go</category>
      <category>antlr</category>
      <category>compiling</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Suporte às funções do Pascal</title>
      <dc:creator>Alex Sandro Garzão</dc:creator>
      <pubDate>Sun, 07 Jul 2024 17:20:08 +0000</pubDate>
      <link>https://forem.com/alexgarzao/suporte-as-funcoes-do-pascal-2fl9</link>
      <guid>https://forem.com/alexgarzao/suporte-as-funcoes-do-pascal-2fl9</guid>
      <description>&lt;p&gt;Para quem não está acompanhando o POJ (&lt;em&gt;Pascal on the JVM&lt;/em&gt;) é um compilador que transforma um &lt;em&gt;subset&lt;/em&gt; de Pascal para JASM (&lt;em&gt;Java Assembly&lt;/em&gt;) de forma que possamos usar a JVM como ambiente de execução.&lt;/p&gt;

&lt;p&gt;Na última &lt;a href="https://dev.to/alexgarzao/captura-de-erros-operadores-relacionais-para-string-e-procedures-3e46"&gt;postagem&lt;/a&gt; tivemos algumas melhorias na captura de erros, suporte a operadores relacionais para o tipo &lt;em&gt;string&lt;/em&gt; e a possibilidade de definir (e utilizar) as &lt;em&gt;procedures&lt;/em&gt; do Pascal.&lt;/p&gt;

&lt;p&gt;Nesta publicação vamos abordar o suporte às funções (&lt;em&gt;functions&lt;/em&gt;) do Pascal. Falta pouco para podemos concluir o último objetivo do projeto: ler um número da entrada padrão e calcular o seu fatorial.&lt;/p&gt;

&lt;p&gt;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 (&lt;em&gt;opcodes&lt;/em&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Suporte às funções (&lt;em&gt;functions&lt;/em&gt;) do Pascal
&lt;/h2&gt;

&lt;p&gt;Até o momento tínhamos como definir e invocar às &lt;em&gt;procedures&lt;/em&gt; do Pascal. A partir &lt;a href="https://github.com/alexgarzao/poj/pull/31" rel="noopener noreferrer"&gt;deste PR&lt;/a&gt; é possível também definir bem como invocar as &lt;em&gt;functions&lt;/em&gt; do Pascal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/alexgarzao/poj/pull/31/commits/d89e401c7ed70da6b79ed9921f526d64de545395" rel="noopener noreferrer"&gt;Neste commit&lt;/a&gt; foi implementado um programa em Java para entender como a JVM lida com a definição e a chamada de funções. A partir do programa Java abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class FunctionCall {
    public static void main(String[] args) {
        System.out.println("Hello from main!");
        System.out.println(myMethod());
    }

    static String myMethod() {
        return "Hello from myMethod!";
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando desassemblamos o &lt;em&gt;class&lt;/em&gt; obtemos o seguinte &lt;em&gt;assembly&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1:  public class FunctionCall {
2:      public static main([java/lang/String)V {
3:          getstatic java/lang/System.out java/io/PrintStream
4:          ldc "Hello from main!"
5:          invokevirtual java/io/PrintStream.println(java/lang/String)V
6:
7:          getstatic java/lang/System.out java/io/PrintStream
8:          invokestatic FunctionCall.myMethod()java/lang/String
9:          invokevirtual java/io/PrintStream.println(java/lang/String)V
10:
11:         return
12:     }
13:
14:     static myMethod()java/lang/String {
15:         ldc "Hello from myMethod!"
16:
17:         areturn
18:     }
19: }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com este exemplo foi possível identificar que:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Para invocar um método a JVM utilizou a instrução "&lt;em&gt;invokestatic FunctionCall.myMethod()java/lang/String&lt;/em&gt;" (linha 8) onde:

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;invokestatic&lt;/em&gt; é a instrução que recebe como argumento a assinatura completa do método a ser chamado;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;FunctionCall&lt;/em&gt; é o nome da classe;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;myMethod()java/lang/String&lt;/em&gt; é assinatura completa do método com seus parâmetros (neste exemplo nenhum) e o tipo de retorno (neste exemplo &lt;em&gt;java/lang/String&lt;/em&gt;);&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Instrução &lt;em&gt;areturn&lt;/em&gt; (linha 17) encerra a função e deixa na pilha a string de retorno.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Dito isso, a partir do programa Pascal abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program function_call_wo_params;

function myfunction : string;
begin
    myfunction := 'Hello from myfunction!';
end;

begin
    writeln('Hello from main!');
    writeln(myfunction());
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ foi ajustado para gerar o seguinte JASM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Code generated by POJ 0.1
public class function_call_wo_params {
    ;; function myfunction : string;
    static myfunction()java/lang/String {
        ldc "Hello from myfunction!"
        astore 100   ;; Posição 100 guarda o retorno da função
        aload 100    ;; Empilha o retorno da função
        areturn      ;; Deixa "Hello from myfunction!" na pilha
    }

    ;; procedure principal (main)
    public static main([java/lang/String)V {
        ;; writeln('Hello from main!');
        getstatic java/lang/System.out java/io/PrintStream
        ldc "Hello from main!"
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        getstatic java/lang/System.out java/io/PrintStream
        invokevirtual java/io/PrintStream.println()V

        ;; writeln(myfunction());
        getstatic java/lang/System.out java/io/PrintStream
        invokestatic function_call_wo_params.myfunction()java/lang/String 
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        getstatic java/lang/System.out java/io/PrintStream
        invokevirtual java/io/PrintStream.println()V

        return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Os mais atentos devem ter notado o "astore 100" acima e pensado:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Por que guardar o retorno da função em uma variável local? Isso se deve ao fato de que em Pascal o valor de retorno de uma função pode ser definido N vezes durante a função, mas só podemos empilhar um resultado na JVM;&lt;/li&gt;
&lt;li&gt;Por que na posição 100? As variáveis locais de uma função ou procedimento iniciam na posição 0 então arbitrariamente foi escolhido a posição 100 para guardar o retorno;&lt;/li&gt;
&lt;li&gt;Mas não seria possível otimizar para que neste exemplo somente fosse gerado a instrução &lt;em&gt;ldc "Hello from myfunction!"&lt;/em&gt; seguida da instrução &lt;em&gt;areturn&lt;/em&gt;? Sim, seria, mas o POJ não implementa a &lt;a href="https://www.geeksforgeeks.org/phases-of-a-compiler/?ref=lbp" rel="noopener noreferrer"&gt;fase de otimizações&lt;/a&gt; existente em compiladores de mercado, algo que pode ser implementado futuramente.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Este &lt;a href="https://github.com/alexgarzao/poj/pull/31/commits/4ab69de56d815424051466228ed9fc3ef7df6d2c" rel="noopener noreferrer"&gt;commit&lt;/a&gt; implementa o suporte ao tipo "&lt;em&gt;function&lt;/em&gt;" na tabela de símbolos e no &lt;em&gt;parser&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Nos exemplos acima as funções não tinham argumentos. Neste &lt;a href="https://github.com/alexgarzao/poj/pull/31/commits/8a65062ae36139886f1066847294007b6aeb2de1" rel="noopener noreferrer"&gt;commit&lt;/a&gt; foi implementado o resultado esperado para funções com argumentos. Com isso a partir do programa Pascal abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program function_call_with_two_params;

function addvalues(value1, value2: integer) : integer;
begin
    addvalues := value1 + value2;
end;

begin
    writeln('2+4=', addvalues(2, 4));
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ gerou corretamente o seguinte JASM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Code generated by POJ 0.1
public class function_call_with_two_params {
    ;; function addvalues(value1, value2: integer) : integer;
    static addvalues(I, I)I {
        ;; addvalues := value1 + value2;
        iload 0
        iload 1
        iadd 
        istore 100
        iload 100

        ireturn 
    }

    ;; procedure main
    public static main([java/lang/String)V {
        ;; writeln('2+4=', ...);
        getstatic java/lang/System.out java/io/PrintStream
        ldc "2+4="
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        getstatic java/lang/System.out java/io/PrintStream

        ;; aqui código para invocar addvalues(2, 4)
        sipush 2
        sipush 4
        invokestatic function_call_with_two_params.addvalues(I, I)I 

        ;; aqui código para invocar writeln com retorno addvalues
        invokevirtual java/io/PrintStream.print(I)V
        getstatic java/lang/System.out java/io/PrintStream
        invokevirtual java/io/PrintStream.println()V

        return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Próximos passos
&lt;/h2&gt;

&lt;p&gt;Nas próximas publicações vamos falar sobre contextos, bugs encontrados, sentenças aninhadas, entrada de dados e concluir o último dos objetivos deste projeto: cálculo do fatorial de forma recursiva.&lt;/p&gt;

&lt;h2&gt;
  
  
  Código completo do projeto
&lt;/h2&gt;

&lt;p&gt;O repositório com o código completo do projeto e a sua documentação está &lt;a href="https://github.com/alexgarzao/poj" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>go</category>
      <category>antlr</category>
      <category>learning</category>
      <category>compiling</category>
    </item>
    <item>
      <title>Captura de erros, operadores relacionais para string e procedures</title>
      <dc:creator>Alex Sandro Garzão</dc:creator>
      <pubDate>Sun, 26 May 2024 19:32:08 +0000</pubDate>
      <link>https://forem.com/alexgarzao/captura-de-erros-operadores-relacionais-para-string-e-procedures-3e46</link>
      <guid>https://forem.com/alexgarzao/captura-de-erros-operadores-relacionais-para-string-e-procedures-3e46</guid>
      <description>&lt;p&gt;Para quem não está acompanhando, o POJ (&lt;em&gt;Pascal on the JVM&lt;/em&gt;) é um compilador que transforma um &lt;em&gt;subset&lt;/em&gt; de Pascal para JASM (&lt;em&gt;Java Assembly&lt;/em&gt;) de forma que possamos usar a JVM como ambiente de execução.&lt;/p&gt;

&lt;p&gt;Na &lt;a href="https://dev.to/alexgarzao/estruturas-de-repeticao-repeat-while-e-for-4ph6"&gt;última postagem&lt;/a&gt; foi adicionado suporte às estruturas de repetição repeat, while e for.&lt;/p&gt;

&lt;p&gt;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 (&lt;em&gt;Java Assembly&lt;/em&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Melhorias na saída de erros
&lt;/h2&gt;

&lt;p&gt;Sempre que existia um erro léxico, sintático ou semântico no código Pascal, o POJ apenas listava os erros gerados sem nenhum tipo de abstração. Além disso, a compilação seguia normalmente.&lt;/p&gt;

&lt;p&gt;Para implementar melhorias, as seguintes modificações foram realizadas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/alexgarzao/poj/pull/26/commits/233c325e5ef09fa9eab6fbd47d8704ce263d0fbb" rel="noopener noreferrer"&gt;Neste &lt;em&gt;commit&lt;/em&gt;&lt;/a&gt; o código foi alterado para que a análise léxica, sintática e semântica retornem os erros encontrados;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/alexgarzao/poj/pull/26/commits/26816073da6fffead78b371911da0fb5bda173b6" rel="noopener noreferrer"&gt;Neste &lt;em&gt;commit&lt;/em&gt;&lt;/a&gt; foi criada uma classe customizada de erros para ser utilizada pelo &lt;em&gt;runtime&lt;/em&gt; do ANTLR. Com isso podemos obter os erros encontrados pelo &lt;em&gt;parser&lt;/em&gt; bem como realizar o tratamento adequado;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/alexgarzao/poj/pull/26/commits/0a7c9be57bbf4fc5cb9837591b5026b19a05171e" rel="noopener noreferrer"&gt;Neste &lt;em&gt;commit&lt;/em&gt;&lt;/a&gt; o código principal do POJ obtém os possíveis erros gerados, lista eles e aborta o processo de compilação quando necessário;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/alexgarzao/poj/pull/26/commits/c47aa50abcec1cb9ab2f0b5929e549321e6117fc" rel="noopener noreferrer"&gt;Neste &lt;em&gt;commit&lt;/em&gt;&lt;/a&gt; foram introduzidos programas em Pascal inválidos bem como a saída de erros esperada. Com isso os testes automatizados, além de validarem a saída esperada de programas válidos (&lt;em&gt;Java Assembly&lt;/em&gt;), também verificam a saída de erros esperada a partir de programas inválidos (lista de erros).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/alexgarzao/poj/pull/26/files" rel="noopener noreferrer"&gt;Aqui&lt;/a&gt; está o PR completo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Operadores relacionais para o tipo &lt;em&gt;String&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Até o momento tínhamos o suporte aos operadores relacionais apenas para o tipo inteiro (&lt;em&gt;integer&lt;/em&gt;). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/alexgarzao/poj/pull/28/commits/42c6b32be74368381b5e011b926fd7477732aba9" rel="noopener noreferrer"&gt;Neste &lt;em&gt;commit&lt;/em&gt;&lt;/a&gt; foi implementado um programa em Java para entendermos como a JVM lida com os operadores relacionais para o tipo &lt;em&gt;String&lt;/em&gt;. A partir do programa Java abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class IfWithStrings {
   public static void main(String[] args) {
      String v1 = "aaa";
      String v2 = "bbb";
      if (v1.compareTo(v2) &amp;gt; 0)
         System.out.println("v1&amp;gt;v2");
      else
         System.out.println("v1&amp;lt;=v2");
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando desassemblamos o arquivo &lt;em&gt;class&lt;/em&gt; obtemos o &lt;em&gt;assembly&lt;/em&gt; abaixo. Trechos irrelevantes foram omitidos, bem como o trecho original (em Java) que deu origem ao &lt;em&gt;assembly&lt;/em&gt; foi inserido com ";;":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class IfWithStrings {

    ;; public static void main(String[] args)
    public static main([java/lang/String)V {

        ;; String v1 = "aaa";
        ldc "aaa"
        astore 1

        ;; String v2 = "bbb";
        ldc "bbb"
        astore 2

        ;; v1.compareTo(v2)
        aload 1
        aload 2
        invokevirtual java/lang/String.compareTo(java/lang/String)I

        ;; if (v1.compareTo(v2) &amp;gt; 0)
        ifle label3

        ;; System.out.println("v1&amp;gt;v2");
        getstatic java/lang/System.out java/io/PrintStream
        ldc "v1&amp;gt;v2"
        invokevirtual java/io/PrintStream.println(java/lang/String)V
        goto label5

        ;; System.out.println("v1&amp;lt;=v2");
        label3:
        getstatic java/lang/System.out java/io/PrintStream
        ldc "v1&amp;lt;=v2"
        invokevirtual java/io/PrintStream.println(java/lang/String)V

        label5:
        return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com este exemplo foi possível identificar que para comparar duas &lt;em&gt;strings&lt;/em&gt; a JVM obtém da pilha as &lt;em&gt;strings&lt;/em&gt; e executa o método "compareTo" da classe &lt;em&gt;String&lt;/em&gt;. Este método compara as &lt;em&gt;strings&lt;/em&gt; e empilha o seguinte resultado:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;-1, caso o 1o valor seja menor que o segundo;&lt;/li&gt;
&lt;li&gt;0, caso os dois valores sejam iguais;&lt;/li&gt;
&lt;li&gt;+1, caso o 2o valor seja maior que o primeiro.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dito isso, a partir do programa Pascal abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program IfWithStrings;
begin
  if ( 'aaa' &amp;gt; 'bbb' ) then
    write('true')
  else
    write('false');
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ foi ajustado para gerar o seguinte JASM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Code generated by POJ 0.1
public class if_with_strings {
    public static main([java/lang/String)V {

        ;; if ( 'aaa' &amp;gt; 'bbb' ) then
        ldc "aaa"
        ldc "bbb"
        invokevirtual java/lang/String.compareTo(java/lang/String)I
        iflt L3
        iconst 1 
        goto L4

    L3: iconst 0 

    L4: ifeq L1

        ;; write('true')
        getstatic java/lang/System.out java/io/PrintStream
        ldc "true"
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        goto L2

    L1: ;; write('true')
        getstatic java/lang/System.out java/io/PrintStream
        ldc "false"
        invokevirtual java/io/PrintStream.print(java/lang/String)V

    L2: return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este &lt;a href="https://github.com/alexgarzao/poj/pull/28/commits/e689ba9f797847a68934dda216c8bbe220430148" rel="noopener noreferrer"&gt;commit&lt;/a&gt; implementa a chamada ao método &lt;em&gt;String.compareTo&lt;/em&gt; bem como a geração do teste (&lt;em&gt;iflt&lt;/em&gt;) citados acima.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/alexgarzao/poj/pull/28/files" rel="noopener noreferrer"&gt;Aqui&lt;/a&gt; está o PR completo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chamada de &lt;em&gt;procedures&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Até o momento tínhamos que implementar todo o código no bloco principal (&lt;em&gt;main&lt;/em&gt;) do programa em Pascal. &lt;a href="https://github.com/alexgarzao/poj/pull/30/files" rel="noopener noreferrer"&gt;Neste PR&lt;/a&gt; foi implementado o suporte à chamada de &lt;em&gt;procedures&lt;/em&gt;. Reforçando que, em Pascal, uma &lt;em&gt;procedure&lt;/em&gt; é o equivalente a uma &lt;em&gt;function&lt;/em&gt; que não retorna um resultado.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/alexgarzao/poj/pull/30/commits/58082456f186692389695ee7e52aef4e2d041ecb" rel="noopener noreferrer"&gt;Neste commit&lt;/a&gt; foi implementado um programa em Java para entender como a JVM lida com a chamada de procedures (funções sem retorno). A partir do programa Java abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ProcedureCall {
   public static void main(String[] args) {
      System.out.println("Hello from main!");
      myMethod();
   }

   static void myMethod() {
      System.out.println("Hello from myMethod!");
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando desassemblamos o &lt;em&gt;class&lt;/em&gt; obtemos o seguinte &lt;em&gt;assembly&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ProcedureCall {

    ;; public static void main(String[] args)
    public static main([java/lang/String)V {

        ;; System.out.println("Hello from main!");
        getstatic java/lang/System.out java/io/PrintStream
        ldc "Hello from main!"
        invokevirtual java/io/PrintStream.println(java/lang/String)V

        ;; myMethod();
        invokestatic ProcedureCall.myMethod()V

        return
    }

    ;; static void myMethod()
    static myMethod()V {

        ;; System.out.println("Hello from myMethod!");
        getstatic java/lang/System.out java/io/PrintStream
        ldc "Hello from myMethod!"
        invokevirtual java/io/PrintStream.println(java/lang/String)V

        return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com este exemplo foi possível identificar que para invocar uma &lt;em&gt;procedure&lt;/em&gt; a JVM utiliza a instrução "invokestatic ProcedureCall.myMethod()V" onde:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;invokestatic é a instrução que recebe como argumento a assinatura completa do método a ser chamado;&lt;/li&gt;
&lt;li&gt;ProcedureCall é o nome da classe;&lt;/li&gt;
&lt;li&gt;myMethod()V é assinatura completa do método com seus parâmetros (neste exemplo nenhum) e o tipo de retorno (neste exemplo V - &lt;em&gt;void&lt;/em&gt; - que indica nenhum).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dito isso, a partir do programa Pascal abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program procedure_call_wo_params;

procedure myprocedure;
begin
    write('Hello from myprocedure!');
end;

begin
    write('Hello from main!');
    myprocedure();
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ foi ajustado para gerar o seguinte JASM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Code generated by POJ 0.1
public class procedure_call_wo_params {

    ;; procedure myprocedure;
    static myprocedure()V {

        ;; write('Hello from myprocedure!');
        getstatic java/lang/System.out java/io/PrintStream
        ldc "Hello from myprocedure!"
        invokevirtual java/io/PrintStream.print(java/lang/String)V

        return
    }

    ;; bloco principal (main)
    public static main([java/lang/String)V {

        ;; write('Hello from main!');
        getstatic java/lang/System.out java/io/PrintStream
        ldc "Hello from main!"
        invokevirtual java/io/PrintStream.print(java/lang/String)V

        ;; myprocedure();
        invokestatic procedure_call_wo_params.myprocedure()V 

        return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este &lt;a href="https://github.com/alexgarzao/poj/pull/30/commits/09ecc90a3a56f40a3c4e7283fae87bca7efe7dbe" rel="noopener noreferrer"&gt;commit&lt;/a&gt; implementa o suporte ao tipo "&lt;em&gt;procedure&lt;/em&gt;" na tabela de símbolos.&lt;/p&gt;

&lt;p&gt;Este &lt;a href="https://github.com/alexgarzao/poj/pull/30/commits/708232d2a4561d1c50f941cb247bde39e10d4892" rel="noopener noreferrer"&gt;commit&lt;/a&gt; implementa o suporte a geração do &lt;em&gt;assembly&lt;/em&gt; correto. Para tal, o POJ precisa lidar com contextos (&lt;em&gt;procedure&lt;/em&gt; sendo interpretada) para saber quando está interpretando o código de um procedimento ou do bloco principal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Passagem de argumentos para o procedimento
&lt;/h2&gt;

&lt;p&gt;Até então tínhamos a chamada de procedimentos funcional, mas sem argumentos. Neste &lt;a href="https://github.com/alexgarzao/poj/pull/30/commits/b1e00fc706a196c0531720b28e710d3a6f3f8d53" rel="noopener noreferrer"&gt;commit&lt;/a&gt; foi implementado um programa em Java para identificar como a JVM lida com a passagem de argumentos. No exemplo é possível ver que, assim como com outros &lt;em&gt;opcodes&lt;/em&gt;, no início de sua execução o procedimento retira seus argumentos da pilha. Com isso basta empilhar os argumentos antes de invocar o procedimento.&lt;/p&gt;

&lt;p&gt;Dito isso, a partir do programa Pascal abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program procedure_call_add_numbers;

procedure add(value1, value2: integer);
begin
    write(value1 + value2);
end;

begin
    add(4, 6);
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ gera o seguinte JASM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Code generated by POJ 0.1
public class procedure_call_add_numbers {

    ;; procedure add(value1, value2: integer);
    static add(I, I)V {

        ;; write(value1 + value2);
        getstatic java/lang/System.out java/io/PrintStream
        iload 0 ;; carrega o parâmetro 0 (value1)
        iload 1 ;; carrega o parâmetro 1 (value2)
        iadd 
        invokevirtual java/io/PrintStream.print(I)V

        return
    }

    ;; Bloco principal (main)
    public static main([java/lang/String)V {
        ;; add(4, 6);
        sipush 4
        sipush 6
        invokestatic procedure_call_add_numbers.add(I, I)V 

        return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para o correto suporte à chamada com argumentos foi necessário &lt;a href="https://github.com/alexgarzao/poj/pull/30/commits/8b4ba9f4e69d08560486b96c7f3d902d7b607b39" rel="noopener noreferrer"&gt;acrescentar na tabela de símbolos&lt;/a&gt; os tipos dos argumentos dos procedimentos. Por sua vez, para a correta invocação dos procedimentos, o &lt;a href="https://github.com/alexgarzao/poj/pull/30/commits/a89bedf78dabfa7fbd1de513e35cad932dcfcf65" rel="noopener noreferrer"&gt;&lt;em&gt;parser&lt;/em&gt; teve que validar bem como gerar o &lt;em&gt;assembly&lt;/em&gt;&lt;/a&gt; corretamente conforme a assinatura do procedimento.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/alexgarzao/poj/pull/30/files" rel="noopener noreferrer"&gt;Aqui&lt;/a&gt; está o PR completo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Próximos passos
&lt;/h2&gt;

&lt;p&gt;Na próxima publicação vamos falar sobre funções, entrada de dados e, se possível, concluir um dos objetivos deste projeto: cálculo do fatorial de forma recursiva.&lt;/p&gt;

&lt;h2&gt;
  
  
  Código completo do projeto
&lt;/h2&gt;

&lt;p&gt;O repositório com o código completo do projeto e a sua documentação está &lt;a href="https://github.com/alexgarzao/poj" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>go</category>
      <category>compiling</category>
      <category>antlr</category>
      <category>jasm</category>
    </item>
    <item>
      <title>Estruturas de repetição: repeat, while e for</title>
      <dc:creator>Alex Sandro Garzão</dc:creator>
      <pubDate>Fri, 12 Apr 2024 02:40:48 +0000</pubDate>
      <link>https://forem.com/alexgarzao/estruturas-de-repeticao-repeat-while-e-for-4ph6</link>
      <guid>https://forem.com/alexgarzao/estruturas-de-repeticao-repeat-while-e-for-4ph6</guid>
      <description>&lt;p&gt;Para quem não está acompanhando, o POJ (&lt;em&gt;Pascal on the JVM&lt;/em&gt;) é um compilador que transforma um &lt;em&gt;subset&lt;/em&gt; de Pascal para JASM (&lt;em&gt;Java Assembly&lt;/em&gt;) de forma que possamos usar a JVM como ambiente de execução.&lt;/p&gt;

&lt;p&gt;Na &lt;a href="https://dev.to/alexgarzao/novos-operadores-e-a-sentenca-if-b5f"&gt;última postagem&lt;/a&gt; eu tinha mais algumas funcionalidades para comentar, mas para facilitar a compreensão achei mais prudente separar em mais de uma postagem.&lt;/p&gt;

&lt;p&gt;Como estamos compilando para a JVM faz-se necessário detalhar o funcionamento de várias 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Declaração de variáveis
&lt;/h2&gt;

&lt;p&gt;Apesar de importante, declaração de variáveis em Pascal não era a minha próxima meta, mas sim estruturas de controle como &lt;em&gt;for&lt;/em&gt;, &lt;em&gt;while&lt;/em&gt; e &lt;em&gt;repeat&lt;/em&gt;. Mas, para podermos exemplificar e corretamente implementar estas estruturas, a declaração de variáveis torna-se essencial.&lt;/p&gt;

&lt;p&gt;Após todo o aprendizado no desenvolvimento do POJ (todas as postagens estão &lt;a href="https://dev.to/alexgarzao/series/26440"&gt;aqui&lt;/a&gt;) foi relativamente fácil &lt;a href="https://github.com/alexgarzao/poj/pull/22/commits/23bc8a94b966d8112eee6d57d9a3fdb50bfef9b9" rel="noopener noreferrer"&gt;alterar o parser&lt;/a&gt; bem como gerar o &lt;em&gt;assembly&lt;/em&gt; para declarar as variáveis em Java Assembly.&lt;/p&gt;

&lt;p&gt;A partir do programa Pascal abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program VarDeclarations;
var
    msg1, msg2 : string;
begin
    msg1 := 'Message 1!';
    msg2 := 'Message 2!';
    writeln (msg1);
    writeln (msg2);
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ gera o seguinte JASM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Code generated by POJ 0.1
public class var_declarations {
    public static main([java/lang/String)V {

        ;; msg1 := 'Message 1!';
        ldc "Message 1!"
        astore 1

        ;; msg2 := 'Message 2!';
        ldc "Message 2!"
        astore 2

        ;; writeln (msg1);
        getstatic java/lang/System.out java/io/PrintStream
        aload 1
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        getstatic java/lang/System.out java/io/PrintStream
        invokevirtual java/io/PrintStream.println()V

        ;; writeln (msg2);
        getstatic java/lang/System.out java/io/PrintStream
        aload 2
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        getstatic java/lang/System.out java/io/PrintStream
        invokevirtual java/io/PrintStream.println()V

        return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cabe aqui salientar que, para facilitar a compreensão, no exemplo acima as linhas iniciando com ";;" contém o trecho em Pascal que originou o JASM.&lt;/p&gt;

&lt;p&gt;Em relação aos exemplos anteriores agora estamos utilizando duas novas instruções da JVM:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;astore &amp;lt;N&amp;gt;: retira da pilha uma string e armazena no slot de variáveis N&lt;/li&gt;
&lt;li&gt;aload &amp;lt;N&amp;gt;: carrega na pilha a string existente no slot de variáveis N&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A alteração mais significativa é que agora o POJ gera uma &lt;a href="https://github.com/alexgarzao/poj/blob/23bc8a94b966d8112eee6d57d9a3fdb50bfef9b9/codegen/symbol_table.go" rel="noopener noreferrer"&gt;tabela de símbolos&lt;/a&gt; compartilhada durante todo o processo de compilação.&lt;/p&gt;

&lt;p&gt;Para quem tiver interesse, o PR que implementa a declaração de variáveis está &lt;a href="https://github.com/alexgarzao/poj/pull/22" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Estrutura de controle &lt;em&gt;Repeat&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;De posse de todo o conhecimento obtido até aqui, e com os pré-requisitos para implementarmos as estruturas de repetição de Pascal (sentença &lt;em&gt;if&lt;/em&gt;, operadores relacionais e booleanos), optamos por iniciar com a estrutura "&lt;em&gt;Repeat Until&lt;/em&gt;" por ser a mais simples dentre as estruturas de repetição.&lt;/p&gt;

&lt;p&gt;Abaixo temos a sintaxe do &lt;em&gt;Repeat&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1:    repeat            
2:        &amp;lt;bloco código&amp;gt;
3:    until &amp;lt;condição&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ implementa o seguinte comportamento:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Na linha 1, ao reconhecer o &lt;em&gt;token&lt;/em&gt; &lt;em&gt;repeat&lt;/em&gt;, gera e emite um &lt;em&gt;label&lt;/em&gt; (L1) que indica onde inicia o laço de repetição&lt;/li&gt;
&lt;li&gt;Na linha 2 o bloco de código é traduzido para JASM&lt;/li&gt;
&lt;li&gt;Na linha 3 a condição é avaliada e, caso seja válida (&lt;em&gt;true&lt;/em&gt;) a execução salta para L1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vamos a um exemplo que imprime os números de 10 até 19. A partir do programa Pascal abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program RepeatExample;
var
    i: integer;
begin
    i := 10;
    repeat
        writeln ('i=', i);
        i := i + 1;
    until i = 20;
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ gera o seguinte JASM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Code generated by POJ 0.1
public class repeat_example {
    public static main([java/lang/String)V {

        ;; i := 10;
        sipush 10
        istore 1

    L1: ;; repeat
        ;; writeln ('i=', i);
        getstatic java/lang/System.out java/io/PrintStream
        ldc "i="
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        getstatic java/lang/System.out java/io/PrintStream
        iload 1
        invokevirtual java/io/PrintStream.print(I)V
        getstatic java/lang/System.out java/io/PrintStream
        invokevirtual java/io/PrintStream.println()V

        ;; i := i + 1;
        iload 1
        sipush 1
        iadd 
        istore 1

        ;; until i = 20;
        iload 1
        sipush 20
        if_icmpne L2
        iconst 1 
        goto L3

    L2: iconst 0 

    L3: ifeq L1
        return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste JASM não foram utilizadas novas instruções da JVM. Mais detalhes sobre estas instruções podem ser obtidas na &lt;a href="https://dev.to/alexgarzao/novos-operadores-e-a-sentenca-if-b5f"&gt;postagem anterior&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Para quem tiver interesse o PR que implementa a estrutura &lt;em&gt;Repeat&lt;/em&gt; está &lt;a href="https://github.com/alexgarzao/poj/pull/23" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Estrutura de controle &lt;em&gt;While&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Dando sequências às estruturas de controle, a próxima estrutura implementada foi a &lt;em&gt;While&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A estrutura &lt;em&gt;While&lt;/em&gt; pode ser vista como uma variação da &lt;em&gt;Repeat&lt;/em&gt;, onde no caso do &lt;em&gt;Repeat&lt;/em&gt; o teste é executado no final enquanto que no &lt;em&gt;While&lt;/em&gt; o teste é executado no início. &lt;em&gt;Repeat&lt;/em&gt; sempre executa o bloco de código pelo menos uma vez, enquanto que o &lt;em&gt;While&lt;/em&gt; executa 0 ou mais vezes.&lt;/p&gt;

&lt;p&gt;Abaixo temos a sintaxe do &lt;em&gt;While&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1:    while &amp;lt;condição&amp;gt; do
2:    begin
3:        &amp;lt;bloco código&amp;gt;
4:    end;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ implementa o seguinte comportamento:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Na linha 1, ao reconhecer o &lt;em&gt;token&lt;/em&gt; &lt;em&gt;while&lt;/em&gt;, executa os seguintes passos:

&lt;ul&gt;
&lt;li&gt;gera e emite um &lt;em&gt;label&lt;/em&gt; (L1) que indica onde está o condicional do &lt;em&gt;while&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;gera um &lt;em&gt;label&lt;/em&gt; (L2) que indica o término do &lt;em&gt;while&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;avalia a condição e, caso seja inválida (false) a execução salta para L2&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;A linha 2 apenas indica o início do bloco&lt;/li&gt;

&lt;li&gt;Na linha 3 o bloco de código é traduzido para JASM&lt;/li&gt;

&lt;li&gt;Na linha 4 são executados os seguintes passos:

&lt;ul&gt;
&lt;li&gt;a execução salta para L1&lt;/li&gt;
&lt;li&gt;emite o &lt;em&gt;label&lt;/em&gt; L2&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Vamos a um exemplo. A partir do programa Pascal abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program WhileExample;
var
    i: integer;
begin
    i := 10;
    while i &amp;lt; 20 do
    begin
        writeln ('i=', i);
        i := i + 1;
    end;
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ gera o seguinte JASM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Code generated by POJ 0.1
public class while_example {
    public static main([java/lang/String)V {

        ;; i := 10;
        sipush 10
        istore 1

    L1: ;; while i &amp;lt; 20 do
        iload 1
        sipush 20
        if_icmpge L3
        iconst 1 
        goto L4

    L3: iconst 0 

    L4: ifeq L2

        ;; writeln ('i=', i);
        getstatic java/lang/System.out java/io/PrintStream
        ldc "i="
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        getstatic java/lang/System.out java/io/PrintStream
        iload 1
        invokevirtual java/io/PrintStream.print(I)V
        getstatic java/lang/System.out java/io/PrintStream
        invokevirtual java/io/PrintStream.println()V

        ;; i := i + 1;
        iload 1
        sipush 1
        iadd 
        istore 1

        ;; end; (do while)
        goto L1

    L2: return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Em comparação com os exemplos anteriores, não foram utilizadas novas instruções da JVM.&lt;/p&gt;

&lt;p&gt;Para quem tiver interesse o PR que implementa a estrutura "While" está &lt;a href="https://github.com/alexgarzao/poj/pull/24" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Estrutura de controle &lt;em&gt;For&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Por ser considerada a mais complexa das estruturas de controle citadas nesta publicação (&lt;em&gt;repeat&lt;/em&gt;, &lt;em&gt;while&lt;/em&gt; e &lt;em&gt;for&lt;/em&gt;), propositadamente o &lt;em&gt;For&lt;/em&gt; foi deixado por último. &lt;/p&gt;

&lt;p&gt;Abaixo temos a sintaxe do &lt;em&gt;For&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1:  for &amp;lt;var&amp;gt; := &amp;lt;início&amp;gt; to &amp;lt;fim&amp;gt; do
2:  begin
3:      &amp;lt;bloco código&amp;gt;
4:  end;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ implementa o seguinte comportamento:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Na linha 1, ao reconhecer o &lt;em&gt;token&lt;/em&gt; &lt;em&gt;for&lt;/em&gt;, são executados os seguintes passos:

&lt;ul&gt;
&lt;li&gt;inicializa &amp;lt;var&amp;gt; com o valor &amp;lt;início&amp;gt;&lt;/li&gt;
&lt;li&gt;gera e emite um &lt;em&gt;label&lt;/em&gt; (L1) que indica onde está o condicional do &lt;em&gt;for&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;gera um &lt;em&gt;label&lt;/em&gt; (L2) que indica o término do &lt;em&gt;for&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;avalia se &amp;lt;var&amp;gt; é &amp;lt;= a &amp;lt;fim&amp;gt; e, caso seja inválida (false) a execução salta para o &lt;em&gt;label&lt;/em&gt; L2&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;A linha 2 apenas indica o início do bloco&lt;/li&gt;

&lt;li&gt;Na linha 3 o bloco de código é traduzido para JASM&lt;/li&gt;

&lt;li&gt;Na linha 4 são executados os seguintes passos:

&lt;ul&gt;
&lt;li&gt;incrementa &amp;lt;var&amp;gt; em 1 unidade&lt;/li&gt;
&lt;li&gt;a execução salta para o &lt;em&gt;label&lt;/em&gt; L1&lt;/li&gt;
&lt;li&gt;emite o &lt;em&gt;label&lt;/em&gt; L2&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Para a sua correta implementação o for engloba as seguintes tarefas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;inicializar a variável definida no &lt;em&gt;for&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;incrementar/decrementar esta variável automaticamente no final do laço&lt;/li&gt;
&lt;li&gt;validar no início da sentença se o bloco deve ser executado&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vamos ao exemplo. A partir do programa Pascal abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program ForExample;
var
    i: integer;
begin
    for i := 10 to 19 do
    begin
        writeln ('inc i=', i);
    end;
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ gera o seguinte JASM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Code generated by POJ 0.1
public class for_example {
    public static main([java/lang/String)V {

        ;; i := 10
        sipush 10
        istore 1

    L1: ;; i &amp;lt;= 19 ?
        iload 1
        sipush 19
        if_icmpgt L2

        ;; writeln ('inc i=', i);
        getstatic java/lang/System.out java/io/PrintStream
        ldc "inc i="
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        getstatic java/lang/System.out java/io/PrintStream
        iload 1
        invokevirtual java/io/PrintStream.print(I)V
        getstatic java/lang/System.out java/io/PrintStream
        invokevirtual java/io/PrintStream.println()V

        ;; i := i + 1
        iload 1
        sipush 1
        iadd 
        istore 1

        ;; end; (do for)
        goto L1

    L2: return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para quem tiver interesse o PR que implementa a estrutura &lt;em&gt;For&lt;/em&gt; está &lt;a href="https://github.com/alexgarzao/poj/pull/25" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maiores informações
&lt;/h2&gt;

&lt;p&gt;O repositório com o código completo do projeto e a sua documentação está &lt;a href="https://github.com/alexgarzao/poj" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>compiling</category>
      <category>go</category>
      <category>antlr</category>
      <category>ijvm</category>
    </item>
    <item>
      <title>Novos operadores e a sentença if</title>
      <dc:creator>Alex Sandro Garzão</dc:creator>
      <pubDate>Thu, 04 Apr 2024 23:48:53 +0000</pubDate>
      <link>https://forem.com/alexgarzao/novos-operadores-e-a-sentenca-if-b5f</link>
      <guid>https://forem.com/alexgarzao/novos-operadores-e-a-sentenca-if-b5f</guid>
      <description>&lt;p&gt;A sensação que tenho é que nestas últimas 2 semanas o projeto evoluiu muito. Espero que gostem :-)&lt;/p&gt;

&lt;p&gt;Tenho várias novidades, mas aqui vou comentar apenas sobre os novos operadores implementados (multiplicação, divisão, relacionais e booleanos) e a sentença if.&lt;/p&gt;

&lt;p&gt;Após resolver a pegadinha da precedência de operadores existente na gramática original (mais informações &lt;a href="https://dev.to/alexgarzao/operadores-de-adicao-e-subtracao-3ikm"&gt;aqui&lt;/a&gt;) foi relativamente fácil implementar os novos operadores. Além do que escrevi vários exemplos em Java para analisar os &lt;em&gt;opcodes&lt;/em&gt; gerados pelo JavaC.&lt;/p&gt;

&lt;p&gt;Abaixo detalharei mais sobre o JASM (&lt;em&gt;Java Assembly&lt;/em&gt;) gerado pelo POJ.&lt;/p&gt;

&lt;h2&gt;
  
  
  Operadores de multiplicação e divisão
&lt;/h2&gt;

&lt;p&gt;Após o aprendizado gerando o JASM para soma e subtração, foi relativamente fácil gerar o &lt;em&gt;assembly&lt;/em&gt; para multiplicação e divisão.&lt;/p&gt;

&lt;p&gt;A partir do programa Pascal abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program MulDivIntegers;
begin
  writeln (8*4/2);
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ gera o seguinte JASM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Code generated by POJ 0.1
public class mul_div_integers {
    public static main([java/lang/String)V {
        getstatic java/lang/System.out java/io/PrintStream
        ;; multiplica 8 * 4
        sipush 8
        sipush 4
        imul
        ;; divide o resultado por 2
        sipush 2
        idiv
        ;; desempilha e imprime um inteiro
        invokevirtual java/io/PrintStream.println(I)V
        return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vale aqui relembrar que a JVM é uma &lt;a href="https://en.wikipedia.org/wiki/Stack_machine" rel="noopener noreferrer"&gt;&lt;em&gt;stack based machine&lt;/em&gt;&lt;/a&gt;, ou seja, é uma máquina baseada em pilha. Isso quer dizer que suas instruções utilizam uma pilha para realizar as suas operações.&lt;/p&gt;

&lt;p&gt;No &lt;em&gt;assembly&lt;/em&gt; acima getstatic, sipush, imul, idiv, invokevirtual e return são mnemônicos do &lt;em&gt;Java Assembly&lt;/em&gt;. Possuem a seguinte finalidade:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;getstatic: obtém uma referência de um método estático de uma classe&lt;/li&gt;
&lt;li&gt;sipush &amp;lt;N&amp;gt;: empilha o inteiro N&lt;/li&gt;
&lt;li&gt;imul: desempilha dois inteiros e empilha a multiplicação destes valores&lt;/li&gt;
&lt;li&gt;idiv: desempilha dois inteiros e empilha a divisão destes valores&lt;/li&gt;
&lt;li&gt;invokevirtual: desempilha dois valores (método a ser invocado e parâmetro) e executa&lt;/li&gt;
&lt;li&gt;return: finaliza a execução do método&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Na prática o par getstatic/invokevirtual serve para invocar o println, responsável por enviar dados para a saída padrão. O "I" em println(I) indica que será exibido um inteiro. E para saber qual método println invocar, o POJ precisa fazer o &lt;em&gt;tracking&lt;/em&gt; dos tipos de dados que estão sendo empilhados/desempilhados na JVM.&lt;/p&gt;

&lt;p&gt;Na tabela abaixo é possível ver as instruções geradas a partir da expressão "8*4/2" bem como o estado da pilha da JVM após a execução de cada instrução:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Instrução&lt;/th&gt;
&lt;th&gt;Estado pilha após instrução&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;sipush 8&lt;/td&gt;
&lt;td&gt;[ 8 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sipush 4&lt;/td&gt;
&lt;td&gt;[ 8, 4 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;imul&lt;/td&gt;
&lt;td&gt;[ 32 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sipush 2&lt;/td&gt;
&lt;td&gt;[ 32, 2 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;idiv&lt;/td&gt;
&lt;td&gt;[ 16 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No final da execução a pilha contém o resultado esperado de 8*4/2: 16.&lt;/p&gt;

&lt;h2&gt;
  
  
  Operadores relacionais e a sentença if
&lt;/h2&gt;

&lt;p&gt;Para corretamente implementarmos os operadores relacionais (&amp;gt;, &amp;lt;, &amp;gt;=, &amp;lt;=, = e &amp;lt;&amp;gt;) foi necessário introduzir as instruções da JVM relacionadas à condicionais (ifs) e saltos (goto e labels). Sim, o famigerado goto existe na JVM, e faz todo sentido existir :-)&lt;/p&gt;

&lt;p&gt;Vamos a um exemplo com if/then/else. A partir do programa Pascal abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program IfWithIntegers;
begin
  if ( 111 &amp;lt; 222 ) then
    write('true')
  else
    write('false');
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ gera o seguinte JASM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Code generated by POJ 0.1
public class if_with_integers {
    public static main([java/lang/String)V {
        ;; se 111 &amp;gt;= 222 salta para L1
        sipush 111
        sipush 222
        if_icmpge L1
        ;; imprime true
        getstatic java/lang/System.out java/io/PrintStream
        ldc "true"
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        goto L2
    L1: ;; imprime false
        getstatic java/lang/System.out java/io/PrintStream        
        ldc "false"
        invokevirtual java/io/PrintStream.print(java/lang/String)V
    L2: return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Em relação ao exemplo anterior agora estamos utilizando novas instruções:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;if_icmpge &amp;lt;label&amp;gt;: desempilha dois inteiros e salta para o label indicado se o primeiro valor for maior ou igual ao segundo&lt;/li&gt;
&lt;li&gt;labels: no exemplo acima "L1:" e "L2:"&lt;/li&gt;
&lt;li&gt;goto &amp;lt;label&amp;gt;: salta para o label indicado&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A instrução if_icmpge faz parte de um &lt;a href="https://en.wikipedia.org/wiki/List_of_Java_bytecode_instructions" rel="noopener noreferrer"&gt;conjunto amplo de instruções&lt;/a&gt; de teste e salto. O "ge" (de if_icmpge) é a abreviatura de "&lt;em&gt;greater or equal&lt;/em&gt;". Outras variações são gt (&lt;em&gt;greater than&lt;/em&gt;), eq (&lt;em&gt;equal&lt;/em&gt;), ne (&lt;em&gt;not equal&lt;/em&gt;), lt (&lt;em&gt;less than&lt;/em&gt;) e le (&lt;em&gt;less or equal&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Na tabela abaixo é possível ver as instruções geradas a partir do &lt;em&gt;assembly&lt;/em&gt; acima bem como o estado da pilha da JVM após a execução de cada instrução:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Label&lt;/th&gt;
&lt;th&gt;Instrução&lt;/th&gt;
&lt;th&gt;Estado pilha após instrução&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;sipush 111&lt;/td&gt;
&lt;td&gt;[ 111 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;sipush 222&lt;/td&gt;
&lt;td&gt;[ 111, 222 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;if_icmpge L1&lt;/td&gt;
&lt;td&gt;[ ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;getstatic ...&lt;/td&gt;
&lt;td&gt;[ getstatic ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;ldc "true"&lt;/td&gt;
&lt;td&gt;[ getstatic, "true" ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;invokevirtual ...&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;goto L2&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;del&gt;L1&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;del&gt;getstatic ...&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;del&gt;ldc "false"&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;del&gt;invokevirtual ...&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L2&lt;/td&gt;
&lt;td&gt;return&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As instruções &lt;del&gt;marcadas desta forma&lt;/del&gt; não são executadas durante o fluxo de execução deste programa.&lt;/p&gt;

&lt;p&gt;No final da execução o programa exibe a saída esperada: "true".&lt;/p&gt;

&lt;p&gt;Vale ressaltar que a condição utilizada na geração do assembly (ge) é a inversa do programa em pascal (&amp;lt;). Esta técnica facilita a geração do &lt;em&gt;assembly&lt;/em&gt; para os casos onde a sentença if somente tem o então (&lt;em&gt;then&lt;/em&gt;), sem o senão (&lt;em&gt;else&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Vamos a um exemplo com if/then (sem o &lt;em&gt;else&lt;/em&gt;). A partir do programa Pascal abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program IfWithIntegers;
begin
  if ( 111 &amp;lt; 222 ) then
    write('true');
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ gera o seguinte JASM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Code generated by POJ 0.1
public class if_with_integers {
    public static main([java/lang/String)V {
        ;; se 111 &amp;gt;= 222 salta para L1
        sipush 111
        sipush 222
        if_icmpge L1
        ;; imprime true
        getstatic java/lang/System.out java/io/PrintStream
        ldc "true"
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        goto L2
  L1:L2:return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Os mais atentos podem ter notado que o último goto (goto L2) é desnecessário. O código gerado está funcionalmente correto, apesar de não otimizado. Não só esta otimização bem como &lt;a href="https://compileroptimizations.com/category/static.htm" rel="noopener noreferrer"&gt;várias outras&lt;/a&gt; podem ser implementadas futuramente no POJ.&lt;/p&gt;

&lt;h2&gt;
  
  
  Operadores booleanos and e or
&lt;/h2&gt;

&lt;p&gt;Para implementarmos os operadores booleanos (&lt;em&gt;and&lt;/em&gt; e &lt;em&gt;or&lt;/em&gt;) foi necessário introduzir as seguintes instruções:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;iand: desempilha dois inteiros, executa o &lt;em&gt;and&lt;/em&gt; e empilha o resultado&lt;/li&gt;
&lt;li&gt;ior: desempilha dois inteiros, executa o &lt;em&gt;or&lt;/em&gt; e empilha o resultado&lt;/li&gt;
&lt;li&gt;ifeq &amp;lt;label&amp;gt;: desempilha o último valor, e caso igual a 0 salta para o label indicado&lt;/li&gt;
&lt;li&gt;iconst &amp;lt;N&amp;gt;: empilha o inteiro N&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vamos a um exemplo. A partir do programa Pascal abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program IfWithAnd;
begin
  if ( 111 &amp;lt; 222) and ( 222 &amp;lt; 333 ) then
    write('true')
  else
    write('false');
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ gera o seguinte JASM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Code generated by POJ 0.1
public class if_with_and {
    public static main([java/lang/String)V {
        sipush 111    ;; se 111 &amp;gt;= 222 salta para L1
        sipush 222
        if_icmpge L1
        iconst 1      ;; carrega true (1) na pilha
        goto L2
    L1: iconst 0      ;; carrega false (0) na pilha
    L2: sipush 222    ;; se 222 &amp;gt;= 333 salta para L3
        sipush 333
        if_icmpge L3
        iconst 1      ;; carrega true (1) na pilha
        goto L4
    L3: iconst 0      ;; carrega false (0) na pilha
    L4: iand          ;; se algum teste falhou salta para L5
        ifeq L5
        ;; imprime true
        getstatic java/lang/System.out java/io/PrintStream
        ldc "true"
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        goto L6
    L5: ;; imprime false
        getstatic java/lang/System.out java/io/PrintStream
        ldc "false"
        invokevirtual java/io/PrintStream.print(java/lang/String)V
    L6: return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vale aqui ressaltar que a JVM não possui os tipos booleanos true e false. Estes tipos são emulados através dos inteiros 1 e 0, respectivamente. Para tal utilizamos as instruções "iconst 1" e "iconst 0".&lt;/p&gt;

&lt;p&gt;Na tabela abaixo é possível ver as instruções geradas a partir do assembly acima bem como o estado da pilha da JVM após a execução de cada instrução:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Label&lt;/th&gt;
&lt;th&gt;Instrução&lt;/th&gt;
&lt;th&gt;Estado pilha após instrução&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;sipush 111&lt;/td&gt;
&lt;td&gt;[ 111 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;sipush 222&lt;/td&gt;
&lt;td&gt;[ 111, 222 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;if_icmpge L1&lt;/td&gt;
&lt;td&gt;[ ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;iconst 1&lt;/td&gt;
&lt;td&gt;[ 1 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;goto L2&lt;/td&gt;
&lt;td&gt;[ 1 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;del&gt;L1&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;del&gt;iconst 0&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L2&lt;/td&gt;
&lt;td&gt;sipush 222&lt;/td&gt;
&lt;td&gt;[ 1, 222 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;sipush 333&lt;/td&gt;
&lt;td&gt;[ 1, 222, 333 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;if_icmpge L3&lt;/td&gt;
&lt;td&gt;[ 1 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;iconst 1&lt;/td&gt;
&lt;td&gt;[ 1, 1 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;goto L4&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;del&gt;L3&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;del&gt;iconst 0&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L4&lt;/td&gt;
&lt;td&gt;iand&lt;/td&gt;
&lt;td&gt;[ 1 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;ifeq L5&lt;/td&gt;
&lt;td&gt;[ ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;getstatic ...&lt;/td&gt;
&lt;td&gt;[ getstatic ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;ldc "true"&lt;/td&gt;
&lt;td&gt;[ getstatic, "true" ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;invokevirtual ...&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;goto L6&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;del&gt;L5&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;del&gt;getstatic ...&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;del&gt;ldc "false"&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;del&gt;invokevirtual ...&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L6&lt;/td&gt;
&lt;td&gt;return&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No final da execução o programa exibe a saída esperada: "true".&lt;/p&gt;

&lt;h2&gt;
  
  
  Operador booleano not
&lt;/h2&gt;

&lt;p&gt;Até aqui falamos sobre os operadores &lt;em&gt;and&lt;/em&gt; e &lt;em&gt;or&lt;/em&gt;. E o operador &lt;em&gt;not&lt;/em&gt;? Vamos a um exemplo.&lt;/p&gt;

&lt;p&gt;A partir do programa Pascal abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program IfWithAndNot;
begin
  if not(( 111 &amp;lt; 222) and ( 222 &amp;lt; 333 )) then
    write('true')
  else
    write('false');
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O POJ gera o seguinte JASM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Code generated by POJ 0.1
public class if_with_and_not {
    public static main([java/lang/String)V {
        sipush 111   ;; se 111 &amp;gt;= 222 salta para L1
        sipush 222
        if_icmpge L1
        iconst 1     ;; carrega true (1) na pilha
        goto L2
    L1: iconst 0     ;; carrega false (0) na pilha
    L2: sipush 222   ;; se 222 &amp;gt;= 333 salta para L3
        sipush 333
        if_icmpge L3
        iconst 1     ;; carrega true (1) na pilha
        goto L4
    L3: iconst 0     ;; carrega false (0) na pilha
    L4: iand         ;; se testes foram ok salta para L5
        ifne L5
        iconst 1     ;; carrega true (1) na pilha
        goto L6
    L5: iconst 0     ;; carrega false (0) na pilha
    L6: ifeq L7
        ;; imprime true
        getstatic java/lang/System.out java/io/PrintStream
        ldc "true"
        invokevirtual java/io/PrintStream.print(java/lang/String)V
        goto L8
    L7: ;; imprime false
        getstatic java/lang/System.out java/io/PrintStream
        ldc "false"
        invokevirtual java/io/PrintStream.print(java/lang/String)V
    L8: return
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vale aqui ressaltar que apesar da JVM ter as instruções &lt;em&gt;iand&lt;/em&gt; e &lt;em&gt;ior&lt;/em&gt;, ela não possui uma instrução como &lt;em&gt;inot&lt;/em&gt;. Esta "negação" da operação deve ser implementada com ifne e labels. O ifne (&lt;em&gt;if not equal&lt;/em&gt;) salta para o label indicado caso o último valor da pilha não seja zero.&lt;/p&gt;

&lt;p&gt;Na tabela abaixo é possível ver as instruções geradas a partir do assembly acima bem como o estado da pilha da JVM após a execução de cada instrução:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Label&lt;/th&gt;
&lt;th&gt;Instrução&lt;/th&gt;
&lt;th&gt;Estado pilha após instrução&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;sipush 111&lt;/td&gt;
&lt;td&gt;[ 111 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;sipush 222&lt;/td&gt;
&lt;td&gt;[ 111, 222 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;if_icmpge L1&lt;/td&gt;
&lt;td&gt;[ ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;iconst 1&lt;/td&gt;
&lt;td&gt;[ 1 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;goto L2&lt;/td&gt;
&lt;td&gt;[ 1 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;del&gt;L1&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;del&gt;iconst 0&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L2&lt;/td&gt;
&lt;td&gt;sipush 222&lt;/td&gt;
&lt;td&gt;[ 1, 222 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;sipush 333&lt;/td&gt;
&lt;td&gt;[ 1, 222, 333 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;if_icmpge L3&lt;/td&gt;
&lt;td&gt;[ 1 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;iconst 1&lt;/td&gt;
&lt;td&gt;[ 1, 1 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;goto L4&lt;/td&gt;
&lt;td&gt;[ 1, 1 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;del&gt;L3&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;del&gt;iconst 0&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L4&lt;/td&gt;
&lt;td&gt;iand&lt;/td&gt;
&lt;td&gt;[ 1 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;ifne L5&lt;/td&gt;
&lt;td&gt;[ ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;del&gt;iconst 1&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;del&gt;goto L6&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L5&lt;/td&gt;
&lt;td&gt;iconst 0&lt;/td&gt;
&lt;td&gt;[ 0 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L6&lt;/td&gt;
&lt;td&gt;ifeq L7&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;del&gt;getstatic ...&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;del&gt;ldc "true"&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;del&gt;invokevirtual ...&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;del&gt;goto L8&lt;/del&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L7&lt;/td&gt;
&lt;td&gt;getstatic ...&lt;/td&gt;
&lt;td&gt;[ getstatic ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;ldc "false"&lt;/td&gt;
&lt;td&gt;[ getstatic, "false" ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;invokevirtual ...&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L8&lt;/td&gt;
&lt;td&gt;return&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No final da execução o programa exibe a saída esperada: "false".&lt;/p&gt;

&lt;h2&gt;
  
  
  "Perrengue" com JASM e uma grata surpresa
&lt;/h2&gt;

&lt;p&gt;No início do projeto tive que decidir entre gerar o arquivo &lt;em&gt;class&lt;/em&gt; diretamente ou utilizar um assemblador de &lt;em&gt;Java Assembly&lt;/em&gt;. Optei por utilizar o &lt;a href="https://github.com/roscopeco/jasm" rel="noopener noreferrer"&gt;JASM&lt;/a&gt;, um assemblador Java em que rapidamente consegui rodar alguns exemplos.&lt;/p&gt;

&lt;p&gt;Eis que em pleno feriado (29/3, sexta-feira santa), após gerar o &lt;em&gt;assembly&lt;/em&gt; para o operador &lt;em&gt;not&lt;/em&gt;, ao executar o JASM ele simplesmente gerava um "NullPointerException". Fiz alguns testes mas não identifiquei nada estranho no &lt;em&gt;assembly&lt;/em&gt; gerado pelo POJ.&lt;/p&gt;

&lt;p&gt;Como é o usual entrei no github do JASM e tentei identificar algum bug relacionado, mas não havia nada.  Como o projeto é pouco movimentado eu já estava esperando por alguma mudança drástica no POJ: ter que escolher outro assemblador ou gerar o arquivo class diretamente.&lt;/p&gt;

&lt;p&gt;Antes que alguém diga "o JASM é open source, contribui lá". Até pensei nisso, mas eu não sei programar em Java, e sendo bem sincero, não é uma das linguagens que eu tenha interesse em aprender :-)&lt;/p&gt;

&lt;p&gt;Bom, abri uma &lt;a href="https://github.com/roscopeco/jasm/issues/56" rel="noopener noreferrer"&gt;issue&lt;/a&gt; no JASM, e para minha surpresa, em menos de 1 hora o mantenedor respondeu e identificou o problema. Inicialmente eu estava utilizando a instrução "iconst_1" (ao invés de "iconst 1"). A JVM tem a instrução "iconst_1", mas como é uma otimização da instrução "iconst 1", o JASM não a implementa. Enfim, ajustei para "iconst 1" e tudo funcionou.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maiores informações
&lt;/h2&gt;

&lt;p&gt;O repositório com o código completo do projeto e a sua documentação está &lt;a href="https://github.com/alexgarzao/poj" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>compiling</category>
      <category>go</category>
      <category>antlr</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Operadores de adição e subtração</title>
      <dc:creator>Alex Sandro Garzão</dc:creator>
      <pubDate>Sat, 23 Mar 2024 18:06:02 +0000</pubDate>
      <link>https://forem.com/alexgarzao/operadores-de-adicao-e-subtracao-3ikm</link>
      <guid>https://forem.com/alexgarzao/operadores-de-adicao-e-subtracao-3ikm</guid>
      <description>&lt;p&gt;Faz mais de um mês desde a última publicação sobre o projeto. Culpa da correria do dia-a-dia :-D&lt;/p&gt;

&lt;p&gt;Após a &lt;a href="https://dev.to/alexgarzao/compilando-o-hello-world-em-pascal-jan"&gt;primeira versão&lt;/a&gt;, que conseguia compilar e executar o "Hello world!" em &lt;a href="https://en.wikipedia.org/wiki/Pascal_(programming_language)" rel="noopener noreferrer"&gt;Pascal&lt;/a&gt; na JVM, fiz alguns avanços neste último mês. Os mais relevantes foram:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Concatenação de strings&lt;/li&gt;
&lt;li&gt;Soma e subtração de inteiros&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conforme citado em uma &lt;a href="https://dev.to/alexgarzao/compilando-o-hello-world-em-pascal-jan"&gt;publicação anterior&lt;/a&gt;, o POJ (Pascal on the JVM) lê um programa Pascal e gera o &lt;a href="https://www.eg.bucknell.edu/~cs360/java-assembler/examples.html" rel="noopener noreferrer"&gt;JASM (&lt;em&gt;Java Assembly&lt;/em&gt;)&lt;/a&gt; para posteriormente ser transformado em um arquivo &lt;a href="https://en.wikipedia.org/wiki/Java_class_file" rel="noopener noreferrer"&gt;class&lt;/a&gt; e executado na JVM.&lt;/p&gt;

&lt;p&gt;Para exemplificar o que o POJ faz, abaixo temos um exemplo em Pascal que concatena três strings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program ConcatStrings;
begin
  writeln ('Hello ' + 'world ' + 'again!');
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Abaixo temos o JASM gerado pelo POJ:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Code generated by POJ 0.1
public class concat_three_strings {
  public static main([java/lang/String)V {
    getstatic java/lang/System.out java/io/PrintStream
    ldc "Hello "
    ldc "world "
    invokedynamic makeConcatWithConstants(java/lang/String, java/lang/String)java/lang/String {
      invokestatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants(java/lang/invoke/MethodHandles$Lookup, java/lang/String, java/lang/invoke/MethodType, java/lang/String, [java/lang/Object)java/lang/invoke/CallSite 
      [""] 
    }
    ldc "again!"
    invokedynamic makeConcatWithConstants(java/lang/String, java/lang/String)java/lang/String {
      invokestatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants(java/lang/invoke/MethodHandles$Lookup, java/lang/String, java/lang/invoke/MethodType, java/lang/String, [java/lang/Object)java/lang/invoke/CallSite 
      [""] 
    }
    invokevirtual java/io/PrintStream.println(java/lang/String)V
    return
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A partir deste &lt;em&gt;assembly&lt;/em&gt; utilizamos o &lt;a href="https://github.com/roscopeco/jasm" rel="noopener noreferrer"&gt;JASM (assemblador de Java Assembly)&lt;/a&gt; para criar o arquivo class final.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testes End2End
&lt;/h2&gt;

&lt;p&gt;Para auxiliar no desenvolvimento, além dos testes unitários agora temos uma &lt;a href="https://github.com/alexgarzao/poj/tree/889bd91606ad8ef00faaccdeec5044e4297b886c/tests" rel="noopener noreferrer"&gt;pasta com exemplos em pascal e a saída esperada em JASM&lt;/a&gt;. Com isso temos &lt;a href="https://microsoft.github.io/code-with-engineering-playbook/automated-testing/e2e-testing/" rel="noopener noreferrer"&gt;testes End2End&lt;/a&gt; no POJ que validam a entrada (exemplos em Pascal) com a saída esperada (JASM).&lt;/p&gt;

&lt;h2&gt;
  
  
  Validação de tipos
&lt;/h2&gt;

&lt;p&gt;Outra funcionalidade implementada foi a validação de tipos. Apesar da JVM validar a tipagem dos dados, é extremamente recomendado que o POJ valide o código Pascal para não gerar um arquivo JASM inválido.&lt;/p&gt;

&lt;p&gt;Para exemplificar, o código abaixo está sintaticamente correto, mas semanticamente incorreto porque em Pascal não é possível somar strings com inteiros.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program Hello;
begin
  writeln ('Hello ' + 1);
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para realizar esta tipagem o &lt;em&gt;parser&lt;/em&gt; agora mantém uma pilha com os tipos de dados que estão sendo empilhados na JVM. Com isso, nas operações de soma e subtração o tipo dos dados são validados durante a &lt;a href="https://www.javatpoint.com/compiler-phases" rel="noopener noreferrer"&gt;análise semântica&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Concatenação de strings, soma e subtração de inteiros
&lt;/h2&gt;

&lt;p&gt;Algumas modificações foram realizadas no &lt;em&gt;parser&lt;/em&gt; para reconhecer a expressão "expression additiveoperator expression" (trecho da gramática abaixo).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;expression
  : expression op = relationaloperator expression # RelOp
  | expression op = ('*' | '/') expression        # MulDivOp
  | expression op = additiveoperator expression   # AddOp
  | signedFactor                                  # ExpSignedFactor
  ;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta expressão é responsável pela derivação tanto da soma bem como da subtração de strings e inteiros.&lt;/p&gt;

&lt;p&gt;O "# AddOp" na gramática acima é uma &lt;a href="https://github.com/antlr/antlr4/blob/master/doc/parser-rules.md#alternative-labels" rel="noopener noreferrer"&gt;anotação do ANTLR&lt;/a&gt; que permite que cada regra da gramática possa ser facilmente identificada durante o &lt;em&gt;parser&lt;/em&gt;. Com esta anotação o ANTLR gera um método (ExitAddOp abaixo) que será executado sempre que o &lt;em&gt;parser&lt;/em&gt; terminar o reconhecimento da expressão.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func (t *TreeShapeListener) ExitAddOp(ctx *parsing.AddOpContext) {
  // Check pascal types.
  pt1 := t.pst.Pop()
  pt2 := t.pst.Pop()
  if pt1 != pt2 {
    t.jasm.AddOpcode("invalid types")
    return
  }

  // Get operator.
  op := ctx.GetOp().GetText()
  switch {
  case op == "+":
    switch pt1 {
    case String:
      t.GenAddStrings()
    case Integer:
      t.GenAddIntegers()
    default:
      t.jasm.AddOpcode("invalid type in add")
    }
  case op == "-":
    switch pt1 {
    case Integer:
      t.GenSubIntegers()
    default:
      t.jasm.AddOpcode("invalid type in sub")
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este método inicia retirando os últimos 2 tipos da pilha e verificando se possuem o mesmo tipo. Após isso é verificado qual o operador (+ ou -) e, baseado no operador e no tipo do dado, executado o método que irá gerar o JASM. Neste ponto o código também indica uma operação inválida (como no caso da subtração de strings, que é uma operação inválida em Pascal).&lt;/p&gt;

&lt;p&gt;Como exemplo temos abaixo o método GenAddStrings, responsável por gerar o JASM para concatenar duas string, invocado no trecho acima:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func (t *TreeShapeListener) GenAddStrings() {
t.jasm.StartInvokeDynamic(`makeConcatWithConstants(java/lang/String, java/lang/String)java/lang/String`)
  t.jasm.AddOpcode(`invokestatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants(java/lang/invoke/MethodHandles$Lookup, java/lang/String, java/lang/invoke/MethodType, java/lang/String, [java/lang/Object)java/lang/invoke/CallSite`)
  t.jasm.AddOpcode(`[""]`)
  t.jasm.FinishInvokeDynamic()
  t.pst.Push(String)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O jasm (em t.jasm) é um objeto que auxilia na geração do JASM, podendo emitir assinaturas de métodos, classes (do Java Assembly) bem como os &lt;em&gt;opcodes&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Vale observar a última linha do trecho acima: &lt;code&gt;t.pst.Push(String)&lt;/code&gt;. "pst" (&lt;em&gt;pascal stack type&lt;/em&gt;) é a pilha que guarda os tipos dos dados. Neste caso, como foi reconhecida uma concatenação de strings, e foi emitido código para concatená-las, estamos também inserindo o tipo String na pst.&lt;/p&gt;

&lt;p&gt;Até este ponto reconhecemos o operador, o tipo do dado, realizamos uma validação de tipos e geramos código para executar a operação. Mas e as strings e os inteiros? Como eles são carregados para a pilha da JVM?&lt;/p&gt;

&lt;p&gt;Na &lt;a href="https://github.com/alexgarzao/poj/blob/889bd91606ad8ef00faaccdeec5044e4297b886c/parser/Pascal.g4" rel="noopener noreferrer"&gt;gramática&lt;/a&gt; os strings e os inteiros de um programa Pascal são considerados "símbolos terminais" e derivam a partir da regra &lt;em&gt;signedFactor&lt;/em&gt; existente na regra &lt;em&gt;expression&lt;/em&gt; (vide trecho da gramática acima). E o &lt;em&gt;parser&lt;/em&gt;, baseado nas regras instrumentadas em Go, sempre que reconhece estes símbolos terminais automaticamente gera o JASM para carregá-los na pilha da JVM.&lt;/p&gt;

&lt;p&gt;No trecho abaixo é possível ver que ao terminar o reconhecimento de uma string o método &lt;em&gt;ExitString&lt;/em&gt; gera o &lt;em&gt;opcode&lt;/em&gt; ldc (&lt;em&gt;load constant&lt;/em&gt;) seguido da string a ser carregada na pilha da JVM. O &lt;code&gt;ctx.GetText()&lt;/code&gt; é disponibilizado pelo &lt;em&gt;runtime&lt;/em&gt; Go do ANTLR e permite obter o valor do símbolo terminal, que no nosso caso é a string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func (t *TreeShapeListener) ExitString(ctx *parsing.StringContext) {
  str := ctx.GetText()
  t.jasm.AddOpcode("ldc", "\""+str+"\"")
  t.pst.Push(String)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A "pegadinha" da precedência de operadores
&lt;/h2&gt;

&lt;p&gt;No site do ANTLR tem a &lt;a href="https://github.com/antlr/grammars-v4/blob/master/pascal/pascal.g4" rel="noopener noreferrer"&gt;gramática pronta de Pascal&lt;/a&gt;. Porém, apesar de reconhecer corretamente os programas em Pascal, esta gramática não lida corretamente com a precedência de operadores. A forma recomendada no próprio site do &lt;a href="https://www.antlr.org/" rel="noopener noreferrer"&gt;ANTLR&lt;/a&gt; é similar ao exemplo abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grammar Expr;
prog:   (expr NEWLINE)* ;
expr:   expr ('*'|'/') expr
    |   expr ('+'|'-') expr
    |   INT
    |   '(' expr ')'
    ;
NEWLINE : [\r\n]+ ;
INT     : [0-9]+ ;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com isso a derivação do &lt;em&gt;parser&lt;/em&gt; não respeitava a precedência de operadores e o POJ gerava um JASM errado.&lt;/p&gt;

&lt;p&gt;Por exemplo, para o trecho em Pascal abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;writeln (8-4-2);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O correto seria o POJ gerar o seguinte &lt;em&gt;assembly&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;getstatic java/lang/System.out java/io/PrintStream
sipush 8
sipush 4
isub 
sipush 2
isub 
invokevirtual java/io/PrintStream.println(I)V
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No exemplo acima atentem para a localização dos &lt;em&gt;opcodes&lt;/em&gt; isub.&lt;/p&gt;

&lt;p&gt;Basicamente o &lt;em&gt;assembly&lt;/em&gt; acima é executado na JVM da seguinte forma:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Instrução&lt;/th&gt;
&lt;th&gt;Descrição instrução&lt;/th&gt;
&lt;th&gt;Estado pilha após instrução&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;sipush 8&lt;/td&gt;
&lt;td&gt;Empilha o inteiro 8&lt;/td&gt;
&lt;td&gt;[ 8 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sipush 4&lt;/td&gt;
&lt;td&gt;Empilha o inteiro 4&lt;/td&gt;
&lt;td&gt;[ 8, 4 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;isub&lt;/td&gt;
&lt;td&gt;Retira os 2 últimos elementos da pilha (8 e 4), subtrai e empilha o resultado (4)&lt;/td&gt;
&lt;td&gt;[ 4 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sipush 2&lt;/td&gt;
&lt;td&gt;Empilha o inteiro 2&lt;/td&gt;
&lt;td&gt;[ 4, 2 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;isub&lt;/td&gt;
&lt;td&gt;Retira os 2 últimos elementos da pilha (4 e 2), subtrai e empilha o resultado (2)&lt;/td&gt;
&lt;td&gt;[ 2 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No final da execução a pilha contém o resultado esperado de 8-4-2: 2.&lt;/p&gt;

&lt;p&gt;Porém por não lidar corretamente com a precedência de operadores, a partir da gramática original era gerado o &lt;em&gt;assembly&lt;/em&gt; abaixo. Reparem novamente na localização dos &lt;em&gt;opcodes&lt;/em&gt; isub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;getstatic java/lang/System.out java/io/PrintStream
sipush 8
sipush 4
sipush 2
isub 
isub 
invokevirtual java/io/PrintStream.println(I)V
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E o &lt;em&gt;assembly&lt;/em&gt; acima é executado na JVM da seguinte forma:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Instrução&lt;/th&gt;
&lt;th&gt;Descrição instrução&lt;/th&gt;
&lt;th&gt;Estado pilha após instrução&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;sipush 8&lt;/td&gt;
&lt;td&gt;Empilha o inteiro 8&lt;/td&gt;
&lt;td&gt;[ 8 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sipush 4&lt;/td&gt;
&lt;td&gt;Empilha o inteiro 4&lt;/td&gt;
&lt;td&gt;[ 8, 4 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sipush 2&lt;/td&gt;
&lt;td&gt;Empilha o inteiro 2&lt;/td&gt;
&lt;td&gt;[ 8, 4, 2 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;isub&lt;/td&gt;
&lt;td&gt;Retira os 2 últimos elementos da pilha (4 e 2), subtrai e empilha o resultado (2)&lt;/td&gt;
&lt;td&gt;[ 8, 2 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;isub&lt;/td&gt;
&lt;td&gt;Retira os 2 últimos elementos da pilha (8 e 2), subtrai e empilha o resultado (6)&lt;/td&gt;
&lt;td&gt;[ 6 ]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Com isso o resultado do &lt;em&gt;assembly&lt;/em&gt; acima era 6 :-)&lt;/p&gt;

&lt;p&gt;O repositório com o código completo do projeto e instruções sobre como criar o executável bem como executar os testes está &lt;a href="https://github.com/alexgarzao/poj" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>compiler</category>
      <category>antlr</category>
      <category>go</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Compilando o "Hello world" em Pascal</title>
      <dc:creator>Alex Sandro Garzão</dc:creator>
      <pubDate>Mon, 19 Feb 2024 21:55:43 +0000</pubDate>
      <link>https://forem.com/alexgarzao/compilando-o-hello-world-em-pascal-jan</link>
      <guid>https://forem.com/alexgarzao/compilando-o-hello-world-em-pascal-jan</guid>
      <description>&lt;p&gt;Como citei anteriormente, eu iria iniciar o projeto de um novo compilador, &lt;em&gt;open source&lt;/em&gt;, em Go. Basicamente, o POJ (&lt;em&gt;Pascal on the JVM&lt;/em&gt;) possibilita que seja executado um &lt;em&gt;subset&lt;/em&gt; de &lt;a href="https://en.wikipedia.org/wiki/Pascal_(programming_language)" rel="noopener noreferrer"&gt;Pascal&lt;/a&gt; na &lt;a href="https://en.wikipedia.org/wiki/Java_virtual_machine" rel="noopener noreferrer"&gt;JVM&lt;/a&gt;. Mais detalhes sobre o projeto nesta postagem &lt;a href="https://dev.to/alexgarzao/pascal-rodando-na-jvm-1m3b"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A primeira meta do projeto era conseguir compilar e executar o "Hello world" em Pascal na JVM. Apesar de parecer simples, envolvia uma série de tarefas como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Definir qual gerador de &lt;em&gt;parsers&lt;/em&gt; será utilizado: realizei alguns testes com o &lt;a href="https://www.antlr.org/" rel="noopener noreferrer"&gt;ANTLR&lt;/a&gt; e, apesar de alguns "perrengues" no início, optei por ele;&lt;/li&gt;
&lt;li&gt;Encontrar uma gramática de Pascal pronta no formato do ANTLR: isso foi bem tranquilo, já que no repositório do ANTLR existe a &lt;a href="https://github.com/antlr/grammars-v4/tree/master" rel="noopener noreferrer"&gt;gramática pronta para várias linguagens&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Ajustar a gramática para reconhecer o &lt;em&gt;subset&lt;/em&gt; de Pascal esperado: no momento, apenas removi algumas sintaxes que realmente não serão utilizadas;&lt;/li&gt;
&lt;li&gt;No &lt;em&gt;parser&lt;/em&gt; identificar a definição de procedimentos no Pascal para determinar o bloco principal: isso gerou um pouco de trabalho por falta de conhecimento minha sobre a V4 do ANTLR (usei muito a V2 e V3 anteriormente);&lt;/li&gt;
&lt;li&gt;Encontrar um montador Java &lt;em&gt;Assembly&lt;/em&gt;: o mais conhecido é o &lt;a href="https://github.com/davidar/jasmin" rel="noopener noreferrer"&gt;Jasmin&lt;/a&gt;, mas não consegui rodar os exemplos simples (talvez por imperícia minha, enfim), então acabei optando pelo &lt;a href="https://github.com/roscopeco/jasm" rel="noopener noreferrer"&gt;JASM&lt;/a&gt; porque rapidamente consegui executar os exemplos;&lt;/li&gt;
&lt;li&gt;POJ gerar um código &lt;em&gt;assembly&lt;/em&gt; Java válido para o JASM: aqui a dificuldade foi entender como a V4 do ANTLR funciona para obter os tokens no código em Go;&lt;/li&gt;
&lt;li&gt;Criar o README inicial: tentei criar o mínimo necessário, mas já tem as instruções sobre como criar o binário, executar o POJ, executar o "Hello world" na JVM, entre outros.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No momento, dos exemplos citados na &lt;a href="https://dev.to/alexgarzao/pascal-rodando-na-jvm-1m3b"&gt;postagem anterior&lt;/a&gt;, apenas o exemplo do "Hello world" funciona no POJ. Claro que variações deste exemplo, como várias chamadas a writeln funcionam também:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program Hello;
begin
  writeln ('Hello world1!');
  writeln ('Hello world2!');
  writeln ('Hello world3!');
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para possibilitar a execução de outros programas em Pascal, nas próximas semanas vou focar em recursos como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Declaração e uso de variáveis;&lt;/li&gt;
&lt;li&gt;Entrada e saída de dados (terminal);&lt;/li&gt;
&lt;li&gt;Instrução If/Else, For, Repeat e While;&lt;/li&gt;
&lt;li&gt;Operações aritméticas;&lt;/li&gt;
&lt;li&gt;Declaração e uso de procedures e funções;&lt;/li&gt;
&lt;li&gt;Uso de funções recursivas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para quem se interessou, o repositório do projeto é este &lt;a href="https://github.com/alexgarzao/poj" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>pascal</category>
      <category>compiler</category>
      <category>go</category>
      <category>antlr</category>
    </item>
    <item>
      <title>Pascal rodando na JVM</title>
      <dc:creator>Alex Sandro Garzão</dc:creator>
      <pubDate>Tue, 30 Jan 2024 22:20:48 +0000</pubDate>
      <link>https://forem.com/alexgarzao/pascal-rodando-na-jvm-1m3b</link>
      <guid>https://forem.com/alexgarzao/pascal-rodando-na-jvm-1m3b</guid>
      <description>&lt;p&gt;Compiladores é um dos temas do qual tenho muito interesse. Inclusive estou publicando alguns projetos antigos meus nesta série &lt;a href="https://dev.to/alexgarzao/series/25859"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Porém, como &lt;a href="https://dev.to/alexgarzao/ambiente-para-desenvolvimento-e-execucao-de-aplicacoes-escritas-em-hololinguagem-17nf#:~:text=Mas%2C%20para%20tentar%20compensar%20a%20falta%20de%20detalhes%20aqui%2C%20logo%20que%20poss%C3%ADvel%20vou%20iniciar%20um%20projeto%20open%20source%20de%20um%20compilador.%20J%C3%A1%20adianto%20que%20este%20novo%20projeto%20ser%C3%A1%20em%20Go%20e%20irei%20utilizar%20um%20gerador%20de%20parsers%20bem%20conhecido."&gt;comentei em uma publicação desta série&lt;/a&gt;, vou iniciar uma abordagem mais prática onde irei construir um compilador "&lt;em&gt;from scratch&lt;/em&gt;", passo-a-passo, de código aberto, tanto para consolidar alguns temas abordados bem como para termos algo concreto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sobre o desafio
&lt;/h2&gt;

&lt;p&gt;Compiladores são, por natureza, projetos que eu considero desafiadores e complexos. E para termos um objetivo claro e, dentro do possível, simples para este projeto, o que vamos fazer é implementar uma nova solução para o trabalho de faculdade que comentei &lt;a href="https://dev.to/alexgarzao/compilador-para-um-subset-de-pascal-27b1"&gt;nesta publicação&lt;/a&gt;: rodar um &lt;em&gt;subset&lt;/em&gt; de &lt;a href="https://en.wikipedia.org/wiki/Pascal_(programming_language)" rel="noopener noreferrer"&gt;Pascal&lt;/a&gt; na &lt;a href="https://en.wikipedia.org/wiki/Java_virtual_machine" rel="noopener noreferrer"&gt;JVM&lt;/a&gt;. Para tal, iremos criar um compilador que entende este &lt;em&gt;subset&lt;/em&gt; de Pascal e gera o arquivo &lt;a href="https://en.wikipedia.org/wiki/Java_class_file" rel="noopener noreferrer"&gt;class&lt;/a&gt; para ser executado na JVM.&lt;/p&gt;

&lt;p&gt;Como a minha criatividade para criar nomes de projetos é baixa, vou batizar o projeto de POJ (Pascal On the JVM). Se alguém tiver um nome bacana, eu aceito :-)&lt;/p&gt;

&lt;h2&gt;
  
  
  Visão macro do projeto
&lt;/h2&gt;

&lt;p&gt;Na solução anterior (mais detalhes &lt;a href="https://dev.to/alexgarzao/compilador-para-um-subset-de-pascal-27b1"&gt;aqui&lt;/a&gt;) o compilador gerava o arquivo class diretamente. Porém, para tentar simplificar a nossa solução, vou abstrair a geração do arquivo class utilizando um montador &lt;a href="https://www.eg.bucknell.edu/~cs360/java-assembler/examples.html" rel="noopener noreferrer"&gt;Java Assembly&lt;/a&gt; qualquer (Figura abaixo). Com isso o nosso compilador (POJ) será responsável por ler um programa contendo código Pascal e gerar o assembly Java equivalente enquanto o montador será responsável por ler este assembly e gerar o arquivo class para ser executado na JVM.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fimojbfhnmluzgu9nupny.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fimojbfhnmluzgu9nupny.png" alt="Image description" width="800" height="52"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Entendo que seja uma proposta válida no momento, mas só após alguns testes com montadores assembly Java será possível validar esta proposta. Caso não seja encontrado um montador que atenda as necessidades do projeto, teremos que partir para gerar o arquivo class diretamente. &lt;/p&gt;

&lt;p&gt;Assim como no projeto anterior, para facilitar o desenvolvimento do compilador eu optei por utilizar um &lt;a href="https://en.wikipedia.org/wiki/Compiler-compiler" rel="noopener noreferrer"&gt;gerador de &lt;em&gt;parsers&lt;/em&gt;&lt;/a&gt;. Desde 2003 sou fã do &lt;a href="https://www.antlr.org/" rel="noopener noreferrer"&gt;ANTLR&lt;/a&gt;, que além de fornecer uma integração interessante entre a &lt;a href="https://www.scaler.com/topics/phases-of-compiler/" rel="noopener noreferrer"&gt;análise léxica e sintática&lt;/a&gt;, também utiliza &lt;a href="https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form" rel="noopener noreferrer"&gt;EBNF&lt;/a&gt; para especificar a gramática da linguagem. Além disso, ANTLR gera código para diversas linguagens, entre elas Go :-)&lt;/p&gt;

&lt;p&gt;A Figura abaixo contém as etapas necessárias para criarmos o nosso compilador (POJ). A partir da gramática da linguagem Pascal, o ANTLR gera o parser em Golang. A partir deste código Go gerado iremos instrumentar as regras necessárias, tanto na análise léxica bem como na sintática. Após isso utilizaremos o compilador do Go para gerar o binário do POJ.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd3rje0qvzmv2a46z5nv7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd3rje0qvzmv2a46z5nv7.png" alt="Image description" width="800" height="67"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;em&gt;Subset&lt;/em&gt; aceito
&lt;/h2&gt;

&lt;p&gt;Quando falamos em &lt;em&gt;subset&lt;/em&gt; de Pascal entendam um programa Pascal válido, mas com um conjunto reduzido de instruções e operações:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Declaração de variáveis utilizando os tipos básicos: integer, real, boolean e string;&lt;/li&gt;
&lt;li&gt;Estruturas condicionais: If/Else;&lt;/li&gt;
&lt;li&gt;Estruturas de repetição: For, While, Repeat;&lt;/li&gt;
&lt;li&gt;Entrada e saída de dados via console: Write, WriteLn, Read, ReadLn;&lt;/li&gt;
&lt;li&gt;Operações matemáticas com precedência de operadores: soma, subtração, divisão, multiplicação e módulo;&lt;/li&gt;
&lt;li&gt;Declaração de blocos de código: procedures e funções.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Exemplos de programas aceitos
&lt;/h2&gt;

&lt;p&gt;Abaixo é possível ver o clássico “Hello world!” em Pascal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program Hello;
begin
  writeln ('Hello world!');
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Abaixo temos o cálculo do fatorial, de forma recursiva:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program fatorial;

var numero : integer;

function fatorial(n : integer) : integer;
begin
    if n&amp;lt;0 then fatorial := 0
    else begin
        if n&amp;lt;=1 then fatorial := 1
        else fatorial := n * fatorial(n-1);
    end;
end;

begin
    write('Introduza numero inteiro: ');
    readln(numero);
    writeln;
    writeln('O fatorial de ', numero, ' e: ', fatorial(numero));
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Abaixo temos um exemplo com entrada e saída de dados:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;program NameAndAge;
var
  MyName: String;
  MyAge : Byte;
begin
  Write('What is your name? '); Readln(MyName);
  Write('How old are you? '); Readln(MyAge);
  Writeln;
  Writeln('Hello ', MyName);
  Writeln('You are ', MyAge, ' years old');
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para quem tiver interesse de ver a execução destes programas, sugiro utilizar o &lt;a href="https://www.freepascal.org/" rel="noopener noreferrer"&gt;Free Pascal Compiler&lt;/a&gt; no momento. Nas próximas semanas poderemos utilizar o POJ para tal :-)&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que refazer?
&lt;/h2&gt;

&lt;p&gt;Uma dúvida comum talvez seja: por que refazer? Por que não melhorar o projeto anterior?&lt;/p&gt;

&lt;p&gt;Bom, eu até encontrei o código antigo, de 1999, do projeto de faculdade. Mas esta versão utiliza o JavaCC e Java, tecnologias que praticamente só utilizei naquele período. Aprender Java e ajustar um código Java de 1999 não está nos meus objetivos. E como pretendo manter e evoluir este projeto, optei por reescrevê-lo em tecnologias que tenho mais interesse como ANTLR e Go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que JVM?
&lt;/h2&gt;

&lt;p&gt;Outra dúvida comum talvez seja: porque foi escolhida a JVM? Em 1999 foi utilizada a especificação 1.1 da JVM, e garanto que havia pouca documentação na época. O motivo da escolha da JVM foi porque, dentre as VMs da época, a JVM era &lt;a href="https://en.wikipedia.org/wiki/Stack_machine" rel="noopener noreferrer"&gt;&lt;em&gt;stack based machine&lt;/em&gt;&lt;/a&gt;, o que simplifica (e muito) a geração do &lt;em&gt;bytecode&lt;/em&gt;. Isso porque, além de necessitar de poucas operações, todas as operações da máquina virtual operam sobre a pilha. Já VMs &lt;a href="https://en.wikipedia.org/wiki/Register_machine" rel="noopener noreferrer"&gt;&lt;em&gt;register based&lt;/em&gt;&lt;/a&gt; necessitam de um conjunto maior de operações e precisam lidar com a alocação de registradores (mesmo que estes sejam virtuais). Para quem tiver interesse de ler mais sobre, &lt;a href="https://www.codeproject.com/Articles/461052/Stack-Based-vs-Register-Based-Virtual-Machine-Arch" rel="noopener noreferrer"&gt;aqui&lt;/a&gt; tem uma publicação bem interessante sobre este tópico. Isso sem falar que a JVM já é utilizada por várias linguagens além do Java, como Clojure, Lisp, Scala e Kotlin, isso só citando algumas das mais conhecidas.&lt;/p&gt;

</description>
      <category>compiler</category>
      <category>go</category>
      <category>braziliandevs</category>
      <category>learning</category>
    </item>
    <item>
      <title>Ambiente para desenvolvimento e execução de aplicações escritas em HoloLinguagem</title>
      <dc:creator>Alex Sandro Garzão</dc:creator>
      <pubDate>Tue, 02 Jan 2024 18:15:54 +0000</pubDate>
      <link>https://forem.com/alexgarzao/ambiente-para-desenvolvimento-e-execucao-de-aplicacoes-escritas-em-hololinguagem-17nf</link>
      <guid>https://forem.com/alexgarzao/ambiente-para-desenvolvimento-e-execucao-de-aplicacoes-escritas-em-hololinguagem-17nf</guid>
      <description>&lt;p&gt;Durante o seu doutorado na &lt;a href="http://www.ufrgs.br/ufrgs/inicial" rel="noopener noreferrer"&gt;UFRGS&lt;/a&gt; o professor &lt;a href="https://www.linkedin.com/in/jorge-barbosa-a0688320b/" rel="noopener noreferrer"&gt;Jorge Barbosa&lt;/a&gt; criou o &lt;a href="https://lume.ufrgs.br/handle/10183/2255" rel="noopener noreferrer"&gt;Holoparadigma&lt;/a&gt;, um novo &lt;a href="https://en.wikipedia.org/wiki/Programming_paradigm" rel="noopener noreferrer"&gt;paradigma de programação&lt;/a&gt; que dava suporte ao desenvolvimento de &lt;a href="https://en.wikipedia.org/wiki/Distributed_computing" rel="noopener noreferrer"&gt;aplicações distribuídas&lt;/a&gt;. Algumas características deste paradigma (citados mais abaixo) facilitavam (e muito) o desenvolvimento de aplicações móveis, algo bem inovador para a época (ano de 2000, aproximadamente).&lt;/p&gt;

&lt;p&gt;Como prova de conceito deste novo paradigma foi criado um ambiente de desenvolvimento e execução de aplicações (figura abaixo).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F001sblnqd9ek8d5ozlzh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F001sblnqd9ek8d5ozlzh.png" alt="Image description" width="349" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nesta figura temos os seguintes componentes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Programa Holo: Programa escrito em HoloLinguagem, uma &lt;a href="https://en.wikipedia.org/wiki/Programming_language" rel="noopener noreferrer"&gt;linguagem de programação&lt;/a&gt; acadêmica que implementa o HoloParadigma&lt;/li&gt;
&lt;li&gt;HoloJava: &lt;a href="https://en.wikipedia.org/wiki/Compiler" rel="noopener noreferrer"&gt;Compilador&lt;/a&gt; que traduz um programa em HoloLinguagem para código &lt;a href="https://en.wikipedia.org/wiki/Java_(programming_language)" rel="noopener noreferrer"&gt;Java&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Javac" rel="noopener noreferrer"&gt;Compilador Java (JavaC)&lt;/a&gt;: Compilador que processa o código gerado pelo HoloJava e gera o &lt;a href="https://en.wikipedia.org/wiki/Bytecode" rel="noopener noreferrer"&gt;&lt;em&gt;bytecode&lt;/em&gt;&lt;/a&gt; para ser executado na JVM&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Java_virtual_machine" rel="noopener noreferrer"&gt;Máquina Virtual Java (JVM)&lt;/a&gt;: Máquina virtual que executa o &lt;em&gt;bytecode&lt;/em&gt; gerado pelo JavaC&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O principal objetivo desde ambiente era possibilitar a execução dos exemplos em HoloLinguagem.&lt;/p&gt;

&lt;p&gt;Abaixo temos um exemplo em HoloLinguagem que demonstra como o paralelismo e a sincronia são explorados. Entes são um conceito elementar do HoloParadigma, sendo similares às classes do paradigma OO. Neste exemplo o Holo, que é o ente principal de um programa, cria dois novos entes (a partir de ente_paralelo) e aguarda que terminem sua execução. Para sincronia é utilizado um &lt;em&gt;blackboard&lt;/em&gt; (o &lt;em&gt;history&lt;/em&gt;) onde cada ente insere a chave "terminei" em conjunto com o seu ID. Por sua vez, o ente Holo aguarda em &lt;em&gt;history&lt;/em&gt; o término dos entes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;holo() {
   holo() {
      writeln('Exemplo que demonstra paralelismo e sincronia'),
      clone(ente_paralelo(1), ente_paralelo1),
      clone(ente_paralelo(2), ente_paralelo2), 
      for X := 1 to 5 do {
         writeln('Ente holo esta na iteracao ', X)
      }
      // aguarda o término dos entes clonados
      history#terminei(#Id),
      // informa qual ente terminou
      writeln('Ente ', Id, ' terminou...'),
      // aguarda o término dos entes clonados
      history#terminei(#Id),
      // informa qual ente terminou
      writeln('Ente ', Id, ' terminou...')
   }
}

ente_paralelo() {
   ente_paralelo(Id) {
      for X := 1 to 20 do {
         writeln('Ente ', Id, ' esta na iteracao ', X)
      }
      // sinaliza na história externa que terminou
      out(history)!terminei(Id)
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Porém, durante o seu doutorado, não foi possível explorarem alguns recursos da HoloLinguagem, em especial alguns conceitos da computação móvel como mover aplicações em execução para outros dispositivos e o compartilhamento de dados entre aplicações distribuídas.&lt;/p&gt;

&lt;p&gt;É neste momento que eu entro no projeto. Em 2002 o tema do meu TCC na &lt;a href="https://www.unisinos.br/" rel="noopener noreferrer"&gt;UNISINOS&lt;/a&gt; foi sobre como criar um ambiente de desenvolvimento e execução para aplicações escritas em HoloLinguagem. Meu orientador foi o Barbosa, um professor fantástico 🙂&lt;/p&gt;

&lt;p&gt;Na época tínhamos 3 opções para implementar estes conceitos da computação móvel e explorar ainda mais as potencialidades da HoloLinguagem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implementar através de bibliotecas e usar a estrutura atual do projeto: neste caso teríamos que alterar o compilador (HoloJava) para que reconhecesse os novos comandos e criar as bibliotecas necessárias&lt;/li&gt;
&lt;li&gt;Implementar diretamente na JVM através de novos &lt;a href="https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html" rel="noopener noreferrer"&gt;&lt;em&gt;opcodes&lt;/em&gt;&lt;/a&gt;: neste caso, além de alterar a JVM, teríamos que alterar o JavaC ou então gerar diretamente &lt;em&gt;bytecode&lt;/em&gt; para a JVM&lt;/li&gt;
&lt;li&gt;Criar uma nova VM com suporte a estes novos conceitos: neste caso teríamos que criar um novo compilador e uma nova VM&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Entendi que seria mais interessante (e divertido) a última opção, o famoso “reinventar a roda”, e foi o que eu fiz 🙂&lt;/p&gt;

&lt;p&gt;A figura abaixo contém a proposta do meu TCC: implementar um novo ambiente para o desenvolvimento e execução de aplicações escritas em HoloLinguagem. Seguindo alguns aprendizados de um &lt;a href="https://dev.to/alexgarzao/compilador-para-um-subset-de-pascal-27b1"&gt;projeto anterior&lt;/a&gt;, optei por criar também o HoloAssembly, uma linguagem intermediária para facilitar os testes e a implementação do projeto.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqag12uixyi1o7sblrh29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqag12uixyi1o7sblrh29.png" alt="Image description" width="441" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nesta figura temos os seguintes componentes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Programa Holo: Programa escrito em HoloLinguagem que implementa o HoloParadigma&lt;/li&gt;
&lt;li&gt;HoloC: É o compilador que traduz aplicações escritas em HoloLinguagem para HoloAssembly, uma linguagem intermediária&lt;/li&gt;
&lt;li&gt;HoloASM: É o &lt;a href="https://en.wikipedia.org/wiki/Assembly_language#Assembler" rel="noopener noreferrer"&gt;montador &lt;em&gt;assembly&lt;/em&gt;&lt;/a&gt; responsável por traduzir HoloAssembly para o &lt;em&gt;bytecode&lt;/em&gt; que a HoloVM entende&lt;/li&gt;
&lt;li&gt;HoloVM: É a &lt;a href="https://en.wikipedia.org/wiki/Virtual_machine" rel="noopener noreferrer"&gt;máquina virtual (VM)&lt;/a&gt; capaz de dar suporte à execução das aplicações de forma distribuída&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://docplayer.com.br/89487224-Holovm-uma-maquina-virtual-com-suporte-a-concorrencia-mobilidade-e-blackboards.html" rel="noopener noreferrer"&gt;Aqui&lt;/a&gt; tem um artigo publicado no WSCAD de 2002 sobre o meu TCC.&lt;/p&gt;

&lt;p&gt;Como &lt;a href="https://en.wikipedia.org/wiki/Compiler-compiler" rel="noopener noreferrer"&gt;gerador de parsers&lt;/a&gt; utilizei o YAPG (&lt;em&gt;Yet Another Parser Generator&lt;/em&gt;), um projeto pessoal que irei abordar em outra publicação. Basicamente o YAPG tinha como entrada uma gramática &lt;a href="https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form" rel="noopener noreferrer"&gt;EBNF&lt;/a&gt; da HoloLinguagem contendo ações codificadas em &lt;a href="https://en.wikipedia.org/wiki/C%2B%2B" rel="noopener noreferrer"&gt;C++&lt;/a&gt;, o que resultava em um parser em C++ que entendia código escritos na HoloLinguagem e executava as ações determinadas. Este parser nada mais era que o HoloC. Da mesma forma, o HoloASM também era gerado através do YAPG.&lt;/p&gt;

&lt;p&gt;Para exemplificar o processo de compilação do HoloC vou usar o “Hello world” em HoloLinguagem abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;holo() {
   holo() {
      writeln('Hello world !!!')
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para o código acima o HoloC gerava o seguinte código em HoloAssembly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;holo
    holo( )
        ;; V1 := 'Hello world !!!',
        lsb     'Hello world !!!'
        sv      V1
        ;; writeln(V1)
        lv      V1
        wr   
        wrln 
    end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por sua vez, o HoloASM gerava o seguinte &lt;em&gt;bytecode&lt;/em&gt; para a HoloVM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Header
    Magic number : 0xB0 0xCA 0xBA 0xBE
    File type    : HoloVM Version 0.1
    Major version: 0
    Minor version: 1

Constant pool size: 4
    000:    Size:   4   Type: 1--&amp;gt;[symbol]    Info: [holo]
    001:    Size:   6   Type: 1--&amp;gt;[symbol]    Info: [holo/0]
    002:    Size:  15   Type: 3--&amp;gt;[string]    Info: [Hello world !!!]
    003:    Size:   2   Type: 3--&amp;gt;[string]    Info: [V1]

Static beings count: 1
    Being cpindex: [000]--&amp;gt;[holo]
    Action count : 1
    Action 0
        Action cpindex: [001]--&amp;gt;[holo/0]
        Bytecode size : 9
            000:    lsb    [002]--&amp;gt;[Hello world !!!]
            002:    sv     [003]--&amp;gt;[V1]
            004:    lv     [003]--&amp;gt;[V1]
            006:    wr
            007:    wrln
            008:    ret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quem conhece a estrutura da JVM vai perceber as semelhanças com o &lt;em&gt;assembly&lt;/em&gt; da HoloVM. E, assim como a JVM, a HoloVM é uma &lt;a href="https://en.wikipedia.org/wiki/Stack_machine" rel="noopener noreferrer"&gt;&lt;em&gt;stack based machine&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Posso dizer que foi um projeto muito divertido, mas que gerou muito trabalho, muito mesmo. Mas o resultado compensou o esforço :-)&lt;/p&gt;

&lt;p&gt;Sei que muita coisa ficou "vaga", em especial sobre o HoloAssembly e a HoloVM. Infelizmente não tenho nada funcional para compartilhar. Encontrei parte do código destes projetos em backups antigos, mas não consegui nem rodar eles localmente. Enfim, muito do material que coloquei nesta publicação foram retirados das apresentações da época. &lt;/p&gt;

&lt;p&gt;Mas, para tentar compensar a falta de detalhes aqui, logo que possível vou iniciar um projeto open source de um compilador. Já adianto que este novo projeto será em &lt;a href="https://en.wikipedia.org/wiki/Go_(programming_language)" rel="noopener noreferrer"&gt;Go&lt;/a&gt; e irei utilizar um gerador de parsers bem conhecido.&lt;/p&gt;

&lt;p&gt;Feedbacks são muito bem-vindos :-)&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
