Maison  >  Article  >  développement back-end  >  Résolution de quelques bugs

Résolution de quelques bugs

王林
王林original
2024-07-24 14:23:311011parcourir

Resolução de alguns 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).

Bug concernant les paramètres passés au programme via la ligne de commande

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.

Bug lors du traitement des variables locales et globales

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
    }
}

Prochaines étapes

Dans le prochain article, nous parlerons des contextes et des phrases imbriquées.

Code de projet complet

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Article précédent:Producteur/ConsommateurArticle suivant:Producteur/Consommateur