
Para quem não está acompanhando o POJ (Pascal on the JVM) é um compilador que transforma umsubset de Pascal para JASM (Java Assembly) de forma que possamos usar a JVM como ambiente de execução.
Na últimapostagem foi abordado contextos (doparser) 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 (stdin), isso utilizando a funçãoread/readln doPascal.
Como estamos compilando para a JVM faz-se necessário detalhar o funcionamento de vários pontos desta incrível máquina virtual. Com isso, em vários momentos eu detalho o funcionamento interno da JVM bem como algumas das suas instruções (opcodes).
Lendo dados destdin (entrada padrão)
Standard input (stdin) é o stream do qual um programa lê seus dados de entrada. Até o momento tínhamos suporte aostdout (saída padrão) apenas.
Nestecommit foi implementado um programa em Java para entendermos como a JVM lida comstdin:
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); }
Quando desassemblamos o arquivoclass obtemos oassembly abaixo. Trechos irrelevantes foram omitidos, bem como o trecho original (em Java) que deu origem aoassembly foi inserido com ";;":
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/Console11: invokevirtual java/io/Console.readLine()java/lang/String12: putstatic InputData.name java/lang/String13:14: ;; age = Integer.parseInt(System.console().readLine());15: invokestatic java/lang/System.console()java/io/Console16: invokevirtual java/io/Console.readLine()java/lang/String17: invokestatic java/lang/Integer.parseInt(java/lang/String)I18: putstatic InputData.age I19:20: ;; System.out.println("You entered string " + name);21: getstatic java/lang/System.out java/io/PrintStream22: getstatic InputData.name java/lang/String23: 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)V26:27: return }}
Com este exemplo foi possível identificar que para ler dados dastdin era necessário utilizar a instruçãoSystem.console().readLine() (linhas 11 e 16). E comoreadLine() retorna uma string, para lermos números era necessário converter com o uso da funçãoInteger.parseInt (linha 17).
Dito isso, a partir do programa Pascal abaixo:
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.
O POJ foi ajustado para gerar o seguinte JASM:
// Code generated by POJ 0.1public 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 }}
Estecommit implementa as alterações necessárias no parser do POJ.
Aqui está o PR completo.
Próximos passos
Na próxima publicação vamos concluir um dos objetivos deste projeto: cálculo do fatorial de forma recursiva.
Código completo do projeto
O repositório com o código completo do projeto e a sua documentação estáaqui.
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse