POJ (JVM 上の Pascal) をフォローしていない人のために説明すると、これは サブセット を Pascal から JASM に変換するコンパイラーです ( Java アセンブリ) を使用して、JVM を実行環境として使用できるようにします。
前回の投稿では、エラー キャプチャ、string 型の関係演算子のサポート、Pascal の プロシージャ の定義 (および使用) の可能性がいくつか改善されました。
この出版物では、Pascal 関数 (関数) のサポートについて説明します。プロジェクトの最後の目標、つまり標準入力から数値を読み取り、その階乗を計算するまであと少しです。
JVM 用にコンパイルしているので、この素晴らしい仮想マシンのさまざまな点の機能を詳しく説明する必要があります。したがって、私はさまざまな機会に、JVM の内部機能とその命令 (オペコード) の一部について詳しく説明します。
これまで、Pascal の プロシージャ を定義して呼び出す方法がありました。この PR から、Pascal の 関数 を定義して呼び出すこともできます。
このコミットでは、JVM が関数の定義と呼び出しをどのように処理するかを理解するために Java プログラムが実装されました。以下の Java プログラムから:
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!"; } }
クラスを逆アセンブルすると、次のアセンブリが得られます。
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: }
この例では、次のことを識別できました。
つまり、以下の Pascal プログラムから:
program function_call_wo_params; function myfunction : string; begin myfunction := 'Hello from myfunction!'; end; begin writeln('Hello from main!'); writeln(myfunction()); end.
POJ は次の JASM を生成するように調整されました:
// 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 } }
最も注意深い人は、上記の「astore 100」に気づき、次のように考えたに違いありません:
このコミットは、シンボル テーブルと パーサー で "function" タイプのサポートを実装します。
上記の例では、関数には引数がありませんでした。このコミットでは、引数を持つ関数に対して期待される結果が実装されました。これは以下の Pascal プログラムからのものです:
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 は次の JASM を正しく生成しました:
// 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 } }
次の出版物では、コンテキスト、見つかったバグ、ネストされた文、データ入力について説明し、このプロジェクトの最後の目的である階乗の再帰計算を締めくくります。
プロジェクトの完全なコードとドキュメントが含まれるリポジトリはここにあります。
以上がパスカル関数のサポートの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。