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 implemented support for Pascal's functions.
In this post, are we going to talk about cool things? Not so much lol. This time we're just going to talk about bugs :-)
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 workings of the JVM as well as some of its instructions (opcodes).
When I implemented the variable declaration, I didn't pay attention to the fact that, in the JVM, the first variable in the main function is the args, an array that contains the arguments passed to the program. With that in this PR I reserve the first position implicitly for args.
As the test Pascal programs only contained global variables, I had not noticed a serious error in the JASM generation. The moment I created programs that contained global and local variables I realized that something wasn't right lol.
From the Pascal program below:
program global_var_declaration; var globalvar : integer; begin globalvar := 123; write (globalvar); end.
POJ generated the following JASM:
// Code generated by POJ 0.1 public class global_var_declaration { public static main([java/lang/String)V { ;; globalvar := 123; bipush 123 istore 1 ;; write (globalvar); getstatic java/lang/System.out java/io/PrintStream iload 1 invokevirtual java/io/PrintStream.print(I)V return } }
To try to identify the problem, I created a Java program equivalent to the Pascal program above:
public class GlobalVarDeclaration { public static int globalVar; public static void main(String[] args) { globalVar = 123; System.out.println(globalVar); } }
When I disassembled the class I got the following assembly:
1: public class GlobalVarDeclaration { 2: public static globalVar I 3: 4: public static main([java/lang/String)V { 5: bipush 123 6: putstatic GlobalVarDeclaration.globalVar I 7: 8: getstatic java/lang/System.out java/io/PrintStream 9: getstatic GlobalVarDeclaration.globalVar I 10: invokevirtual java/io/PrintStream.println(I)V 11: 12: return 13: } 14: }
At this point I noticed the declaration "public static globalVar I" (line 2) and the instructions putstatic (line 6) and getstatic (line 9). What was expected were the astore and istore instructions used by POJ so far. Reading the JVM documentation I realized that POJ was declaring global variables as if they were local variables of a function for the JVM :-D
Anyway, until now POJ was (wrongly) using the opcodes aload/iload/astore/istore for global variables, but the correct thing would be to declare the variables as public (as in line 2 ) and use getstatic/putstatic.
With this, the code was refactored here so that the symbol table can handle local and global declarations. And here the code was refactored so that the symbol table can generate the correct instructions for local and global variables.
JASM code generation has been changed here to handle the new symbol table as well as clean up local declarations after a function or procedure ends.
With this, from the Pascal program below:
program GlobalVarDeclaration; var globalvar : integer; begin globalvar := 123; write (globalvar); end.
POJ now correctly generates the following JASM:
// Code generated by POJ 0.1 public class global_var_declaration { public static globalvar I public static main([java/lang/String)V { ;; globalvar := 123; bipush 123 putstatic global_var_declaration.globalvar I ;; write (globalvar); getstatic java/lang/System.out java/io/PrintStream getstatic global_var_declaration.globalvar I invokevirtual java/io/PrintStream.print(I)V return } }
In the next post we will talk about contexts and nested sentences.
The repository with the project's complete code and documentation is here.
The above is the detailed content of Resolution of some bugs. For more information, please follow other related articles on the PHP Chinese website!