Pour ceux qui ne suivent pas POJ (Pascal sur la JVM) 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 article, nous avons implémenté le support des fonctions.
Dans cet article, allons-nous parler de choses sympas ? Pas tellement mdr. Cette fois, nous allons juste parler de bugs :-)
Alors que 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, à plusieurs reprises, je détaille le fonctionnement interne de la JVM ainsi que certaines de ses instructions (opcodes).
Lorsque j'ai implémenté la déclaration de variable, je n'ai pas prêté attention au fait que, dans la JVM, la première variable de la fonction principale est l'args, un tableau qui contient les arguments passés au programme. Donc, dans ce PR, je réserve implicitement la première position aux arguments.
Les programmes de test Pascal ne contenant que des variables globales, je n'avais pas remarqué d'erreur sérieuse dans la génération JASM. Au moment où j'ai créé des programmes contenant des variables globales et locales, j'ai réalisé que quelque chose n'allait pas mdr.
Du programme Pascal ci-dessous :
program global_var_declaration; var globalvar : integer; begin globalvar := 123; write (globalvar); end.
POJ a généré le JASM suivant :
// 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 } }
Pour tenter d'identifier le problème, j'ai créé un programme Java équivalent au programme Pascal ci-dessus :
public class GlobalVarDeclaration { public static int globalVar; public static void main(String[] args) { globalVar = 123; System.out.println(globalVar); } }
Lorsque j'ai démonté classe, j'ai obtenu l'assemblage :
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: }
À ce stade, j'ai remarqué la déclaration "public static globalVar I" (ligne 2) et les instructions putstatic (ligne 6) et getstatic (ligne 9) . Ce qui était attendu, c'était les instructions astore et istore utilisées par POJ jusqu'à présent. En lisant la documentation de la JVM, j'ai réalisé que POJ déclarait des variables globales comme s'il s'agissait de variables locales d'une fonction pour la JVM :-D
Quoi qu'il en soit, jusqu'à présent, le POJ utilisait (à tort) les opcodes aload/iload/astore/ Istore pour les variables globales, mais l'option correcte serait de déclarer les variables comme publiques (comme à la ligne 2) et d'utiliser getstatic/putstatic.
En conséquence, le code a été refactorisé ici afin que la table des symboles puisse gérer les déclarations locales et globales. Et ici, le code a été refactorisé afin que la table des symboles puisse générer les instructions correctes pour les variables locales et globales.
La génération de code JASM a été modifiée ici pour gérer la nouvelle table de symboles ainsi que pour nettoyer les déclarations locales après la fin d'une fonction ou d'une procédure.
Avec ceci, à partir du programme Pascal ci-dessous :
program GlobalVarDeclaration; var globalvar : integer; begin globalvar := 123; write (globalvar); end.
POJ génère désormais correctement le JASM suivant :
// 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 } }
Dans le prochain article, nous parlerons des contextes et des phrases imbriquées.
Le référentiel avec le code complet et la documentation du projet est ici.
Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.
Copyright© 2022 湘ICP备2022001581号-3