Maison > développement back-end > Golang > le corps du texte

Prise en charge des fonctions Pascal

王林
Libérer: 2024-07-16 08:03:50
original
500 Les gens l'ont consulté

Suporte às funções do Pascal

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

Prise en charge des fonctions Pascal (fonctions)

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!";
    }
}
Copier après la connexion

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: }
Copier après la connexion

Avec cet exemple, il a été possible d'identifier que :

  • Pour invoquer une méthode, la JVM a utilisé l'instruction "invokestatic FunctionCall.myMethod()java/lang/String" (ligne 8) où :
    • invokestatic est l'instruction qui reçoit en argument la signature complète de la méthode à appeler ;
    • FunctionCall est le nom de la classe ;
    • myMethod()java/lang/String est la signature complète de la méthode avec ses paramètres (dans cet exemple aucun) et le type de retour (dans cet exemple java/lang/String) ;
  • L'instruction areturn (ligne 17) termine la fonction et laisse la chaîne de retour sur la pile.

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.
Copier après la connexion

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
    }
}
Copier après la connexion

Les plus attentifs ont dû remarquer le "astore 100" ci-dessus et penser :

  • Pourquoi stocker le retour de la fonction dans une variable locale ? Cela est dû au fait qu'en Pascal la valeur de retour d'une fonction peut être définie N fois pendant la fonction, mais on ne peut empiler qu'un seul résultat dans la JVM ;
  • Pourquoi en position 100 ? Les variables locales d'une fonction ou d'une procédure commencent à la position 0, donc la position 100 a été arbitrairement choisie pour stocker le retour ;
  • Mais ne serait-il pas possible d'optimiser pour que dans cet exemple seule l'instruction ldc "Hello from myfunction!" soit générée suivie de l'instruction areturn ? Oui, ce serait le cas, mais POJ ne met pas en œuvre la phase d'optimisation qui existe dans les compilateurs de marché, ce qui pourrait être mis en œuvre à l'avenir.

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.
Copier après la connexion

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
    }
}
Copier après la connexion

Prochaines étapes

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.

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!

source:dev.to
Déclaration de ce site Web
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!