Unterstützung für Pascal-Funktionen

王林
Freigeben: 2024-07-16 08:03:50
Original
500 Leute haben es durchsucht

Suporte às funções do Pascal

Für diejenigen, die POJ (Pascal auf der JVM) nicht befolgen: Es handelt sich um einen Compiler, der eine Teilmenge von Pascal in JASM umwandelt ( Java Assembly), damit wir die JVM als Ausführungsumgebung verwenden können.

Im letzten Beitrag hatten wir einige Verbesserungen bei der Fehlererfassung, Unterstützung für relationale Operatoren für den Typ string und die Möglichkeit, Pascals Prozeduren zu definieren (und zu verwenden).

In dieser Veröffentlichung behandeln wir die Unterstützung für Pascal-Funktionen (Funktionen). Nicht mehr lange bevor wir das letzte Ziel des Projekts erreichen können: eine Zahl aus der Standardeingabe lesen und ihre Fakultät berechnen.

Während wir für die JVM kompilieren, ist es notwendig, die Funktionsweise verschiedener Punkte dieser unglaublichen virtuellen Maschine im Detail zu beschreiben. Daher erläutere ich an verschiedenen Stellen die interne Funktionsweise der JVM sowie einige ihrer Anweisungen (Opcodes).

Unterstützung für Pascal-Funktionen (Funktionen)

Bisher hatten wir eine Möglichkeit, Pascals Prozeduren zu definieren und aufzurufen. Von dieser PR aus ist es auch möglich, Pascals Funktionen zu definieren und aufzurufen.

In diesem Commit wurde ein Java-Programm implementiert, um zu verstehen, wie die JVM mit der Definition und dem Aufruf von Funktionen umgeht. Aus dem Java-Programm unten:

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!";
    }
}
Nach dem Login kopieren

Wenn wir die Klasse zerlegen, erhalten wir die folgende Assembly:

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: }
Nach dem Login kopieren

Anhand dieses Beispiels konnte Folgendes identifiziert werden:

  • Um eine Methode aufzurufen, verwendete die JVM die Anweisung „invokestatic FunctionCall.myMethod()java/lang/String“ (Zeile 8), wobei:
    • invokestatic ist die Anweisung, die als Argument die vollständige Signatur der aufzurufenden Methode erhält;
    • FunctionCall ist der Name der Klasse;
    • myMethod()java/lang/String ist die vollständige Signatur der Methode mit ihren Parametern (in diesem Beispiel keine) und dem Rückgabetyp (in diesem Beispiel java/lang/String) ;
  • Anweisung areturn (Zeile 17) beendet die Funktion und belässt die Rückgabezeichenfolge auf dem Stapel.

Das heißt, aus dem Pascal-Programm unten:

program function_call_wo_params;

function myfunction : string;
begin
    myfunction := 'Hello from myfunction!';
end;

begin
    writeln('Hello from main!');
    writeln(myfunction());
end.
Nach dem Login kopieren

POJ wurde angepasst, um den folgenden JASM zu generieren:

// 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
    }
}
Nach dem Login kopieren

Dem Aufmerksamsten dürfte oben das „astore 100“ aufgefallen sein und gedacht haben:

  • Warum die Funktionsrückgabe in einer lokalen Variablen speichern? Dies liegt daran, dass in Pascal der Rückgabewert einer Funktion N-mal während der Funktion festgelegt werden kann, wir aber in der JVM nur ein Ergebnis stapeln können;
  • Warum auf Position 100? Die lokalen Variablen einer Funktion oder Prozedur beginnen an Position 0, daher wurde Position 100 willkürlich gewählt, um die Rückgabe zu speichern;
  • Aber wäre es nicht möglich, so zu optimieren, dass in diesem Beispiel nur die Anweisung ldc „Hello from myfunction!“ generiert wurde, gefolgt von der Anweisung areturn? Ja, das wäre es, aber POJ implementiert nicht die Optimierungsphase, die es in Marktcompilern gibt, etwas, das in Zukunft implementiert werden könnte.

Dieser Commit implementiert die Unterstützung für den Typ „Funktion“ in der Symboltabelle und im Parser.

In den obigen Beispielen hatten die Funktionen keine Argumente. In diesem Commit wurde das erwartete Ergebnis für Funktionen mit Argumenten implementiert. Hiermit aus dem Pascal-Programm unten:

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.
Nach dem Login kopieren

POJ hat den folgenden JASM korrekt generiert:

// 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
    }
}
Nach dem Login kopieren

Nächste Schritte

In den nächsten Veröffentlichungen werden wir über Kontexte, gefundene Fehler, verschachtelte Sätze und Dateneingabe sprechen und das letzte Ziel dieses Projekts abschließen: die rekursive Berechnung der Fakultät.

Vollständiger Projektcode

Das Repository mit dem vollständigen Code und der Dokumentation des Projekts finden Sie hier.

Das obige ist der detaillierte Inhalt vonUnterstützung für Pascal-Funktionen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!