"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > Résolution de quelques bugs

Résolution de quelques bugs

Publié le 2024-08-19
Parcourir:502

Resolução de alguns bugs

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).

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

Bug lors du traitement des variables locales et globales

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

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.

Déclaration de sortie Cet article est reproduit sur : https://dev.to/alexgarzao/resolucao-de-alguns-bugs-3a1i?1 En cas d'infraction, veuillez contacter [email protected] pour le supprimer.
Dernier tutoriel Plus>

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