Para aquellos que no siguen POJ (Pascal en la JVM) es un compilador que transforma un subconjunto de Pascal a JASM (Java Assembly) para que podamos usar la JVM como entorno de ejecución.
En la última publicación implementamos soporte para las funciones de Pascal.
En esta publicación, ¿vamos a hablar de cosas interesantes? No tanto jajaja. Esta vez solo vamos a hablar de errores :-)
Como estamos compilando para la JVM, es necesario detallar el funcionamiento de varios puntos de esta increíble máquina virtual. Por ello, en diversos momentos detallo el funcionamiento interno de la JVM así como algunas de sus instrucciones (opcodes).
Cuando implementé la declaración de variables no presté atención al hecho de que, en la JVM, la primera variable en la función principal es args, una matriz que contiene los argumentos pasados al programa. Entonces, en este PR reservo la primera posición implícitamente para args.
Como los programas Pascal de prueba contenían solo variables globales, no había notado un error grave en la generación JASM. En el momento en que creé programas que contenían variables globales y locales me di cuenta de que algo no estaba bien jajaja.
Del siguiente programa Pascal:
program global_var_declaration; var globalvar : integer; begin globalvar := 123; write (globalvar); end.
POJ generó el siguiente 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 } }
Para intentar identificar el problema, creé un programa Java equivalente al programa Pascal anterior:
public class GlobalVarDeclaration { public static int globalVar; public static void main(String[] args) { globalVar = 123; System.out.println(globalVar); } }
Cuando desarmé la clase obtuve el siguiente ensamblaje:
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: }
En este punto noté la declaración "public static globalVar I" (línea 2) y las instrucciones putstatic (línea 6) y getstatic (línea 9). Lo que se esperaba eran las instrucciones astore y istore utilizadas por POJ hasta ahora. Al leer la documentación de JVM me di cuenta de que POJ estaba declarando variables globales como si fueran variables locales de una función para la JVM :-D
De todos modos, hasta ahora el POJ estaba usando (erróneamente) los opcodes aload/iload/astore/ Istore para variables globales, pero la opción correcta sería declarar las variables como públicas (como en la línea 2) y usar getstatic/putstatic.
Como resultado, el código fue refactorizado aquí para que la tabla de símbolos pueda manejar declaraciones locales y globales. Y aquí el código fue refactorizado para que la tabla de símbolos pueda generar las instrucciones correctas para las variables locales y globales.
La generación de código JASM se ha cambiado aquí para manejar la nueva tabla de símbolos, así como para limpiar las declaraciones locales después de que finaliza una función o procedimiento.
Con esto, del programa Pascal a continuación:
program GlobalVarDeclaration; var globalvar : integer; begin globalvar := 123; write (globalvar); end.
POJ ahora genera correctamente el siguiente 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 } }
En el próximo post hablaremos sobre contextos y oraciones anidadas.
El repositorio con el código completo y la documentación del proyecto está aquí.
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3