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).
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!"; } }
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: }
Anhand dieses Beispiels konnte Folgendes identifiziert werden:
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.
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 } }
Dem Aufmerksamsten dürfte oben das „astore 100“ aufgefallen sein und gedacht haben:
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.
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 } }
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.
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!