For those who are not following POJ (Pascal on the JVM) it is a compiler that transforms a subset from Pascal to JASM (Java Assembly) so that we can use the JVM as an execution environment.
In the last post we had some improvements in error capture, support for relational operators for the string type and the possibility of defining (and using) Pascal's procedures.
In this publication we will cover support for Pascal functions (functions). Not long before we can complete the last objective of the project: reading a number from standard input and calculating its factorial.
As we are compiling for the JVM, it is necessary to detail the functioning of various points of this incredible virtual machine. Therefore, at various times I detail the internal functioning of the JVM as well as some of its instructions (opcodes).
Until now we had a way to define and invoke Pascal's procedures. From this PR it is also possible to define and invoke Pascal's functions.
In this commit, a Java program was implemented to understand how the JVM deals with defining and calling functions. From the Java program below:
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!"; } }
When we disassemble the class we get the following 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: }
With this example it was possible to identify that:
That said, from the Pascal program below:
program function_call_wo_params; function myfunction : string; begin myfunction := 'Hello from myfunction!'; end; begin writeln('Hello from main!'); writeln(myfunction()); end.
POJ has been adjusted to generate the following 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 } }
The most attentive must have noticed the "astore 100" above and thought:
This commit implements support for the "function" type in the symbol table and in the parser.
In the examples above, the functions had no arguments. In this commit, the expected result for functions with arguments was implemented. With this from the Pascal program below:
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 correctly generated the following 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 } }
In the next publications we will talk about contexts, bugs found, nested sentences, data entry and conclude the last of the objectives of this project: calculating the factorial recursively.
The repository with the project's complete code and documentation is here.
The above is the detailed content of Support for Pascal functions. For more information, please follow other related articles on the PHP Chinese website!