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 nous avons eu quelques améliorations dans la capture d'erreurs, la prise en charge des opérateurs relationnels pour le type string et la possibilité de définir (et d'utiliser) les procédures de Pascal.
Dans cette publication, nous couvrirons la prise en charge des fonctions Pascal (fonctions). Peu de temps avant que nous puissions atteindre le dernier objectif du projet : lire un nombre à partir d'une entrée standard et calculer sa factorielle.
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).
Jusqu'à présent, nous avions un moyen de définir et d'invoquer les procédures de Pascal. A partir de ce PR, il est également possible de définir et d'invoquer les fonctions de Pascal.
Dans ce commit, un programme Java a été implémenté pour comprendre comment la JVM gère la définition et l'appel des fonctions. Depuis le programme Java ci-dessous :
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!"; } }
Quand on démonte la classe on obtient le assemblage suivant :
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: }
Avec cet exemple, il a été possible d'identifier que :
Cela dit, d'après le programme Pascal ci-dessous :
program function_call_wo_params; function myfunction : string; begin myfunction := 'Hello from myfunction!'; end; begin writeln('Hello from main!'); writeln(myfunction()); end.
POJ a été ajusté pour générer le JASM suivant :
// 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 } }
Les plus attentifs ont dû remarquer le "astore 100" ci-dessus et penser :
Ce commit implémente la prise en charge du type "fonction" dans la table des symboles et dans le analyseur.
Dans les exemples ci-dessus, les fonctions n'avaient aucun argument. Dans ce commit, le résultat attendu pour les fonctions avec arguments a été implémenté. Avec ceci du programme Pascal ci-dessous :
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.
POJ a correctement généré le JASM suivant :
// 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 } }
Dans les prochaines publications nous parlerons des contextes, des bugs trouvés, des phrases imbriquées, de la saisie de données et conclurons le dernier des objectifs de ce projet : calculer 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!