Pour ceux qui ne suivent pas POJ (Pascal sur la JVM) c'est un compilateur qui transforme un sous-ensemble de Pascal en JASM ( Java Assembly) afin que nous puissions utiliser la JVM comme environnement d'exécution.
Dans le dernier post, les contextes (de analyseur) et les phrases imbriquées ont été discutés. Dans cette publication nous parlerons des changements nécessaires pour permettre la lecture de données à partir d'une entrée standard (stdin), en utilisant la fonction read/readln de Pascal .
Comme nous compilons pour la JVM, il est nécessaire de détailler le fonctionnement de différents points de cette incroyable machine virtuelle. C'est pourquoi, à différents moments, je détaille le fonctionnement interne de la JVM ainsi que certaines de ses instructions (opcodes).
Entrée standard (stdin) est le flux à partir duquel un programme lit ses données d'entrée. Jusqu'à présent, nous ne prenions en charge que stdout (sortie standard).
Dans ce commit un programme Java a été implémenté pour comprendre comment la JVM traite stdin :
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); }
Quand on démonte le fichier class on obtient l'assembly ci-dessous. Les extraits non pertinents ont été omis et l'extrait d'origine (en Java) qui a donné lieu à assembly a été inséré avec ";;":
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 } }
Avec cet exemple, il a été possible d'identifier que pour lire les données de stdin il fallait utiliser l'instruction System.console().readLine() (lignes 11 et 16 ). Et comme readLine() renvoie une chaîne, pour lire des nombres il fallait convertir à l'aide de la fonction Integer.parseInt (ligne 17).
Cela dit, d'après le programme Pascal ci-dessous :
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.
POJ a été ajusté pour générer le JASM suivant :
// 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 } }
Ce commit implémente les modifications nécessaires à l'analyseur POJ.
Voici le PR complet.
Dans la prochaine publication nous compléterons l'un des objectifs de ce projet : le calcul de la factorielle de manière récursive.
Le référentiel avec le code complet et la documentation du projet est ici.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!