Maison > Article > développement back-end > Résolution de quelques bugs
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 implémenté le support des fonctions de Pascal.
Dans ce post, est-ce qu'on va parler de choses sympas ? Pas tellement mdr. Cette fois, nous allons juste parler de bugs :-)
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).
Lorsque j'ai implémenté la déclaration de variable, je n'ai pas fait 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.
Comme les programmes Pascal de test ne contenaient 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.
Extrait 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é la classe, j'ai obtenu l'assemblage suivant :
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'étaient 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 à la JVM :-D
Quoi qu'il en soit, jusqu'à présent 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.
Avec cela, 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, 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.
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!