Práctica 4: Compilador MINICOMP
Versión 1. Literales de tipo real.
El objetivo de esta versión es entender con detalle la generación de código que se hace en la versión inicial del compilador en algunos de los nodos del AST, viendo lo que se hace para trabajar con datos enteros y tratando de hacer lo mismo con datos reales.
Amplía Minicomp para que admita literales reales. Un literal real se ajustará a la siguiente definición regular (se utiliza aquí la notación para definiciones regulares de la página 98 del libro "Compiladores: principios, técnicas y herramientas"; Metacomp no la acepta así, debes convertirla en una expresión regular equivalente):
dígito -> [0-9]
exp -> [eE][-+]?dígito+
real -> dígito+\.dígito+exp?
Observa que algo como, por ejemplo,
Realiza las modificaciones necesarias para que todos los operadores aritméticos de Minicomp, excepto el operador resto (%), puedan aplicarse también a operandos de tipo real, así como para permitir la escritura de expresiones de tipo real.
En las operaciones binarias con un operando real y uno entero (salvo %), realiza una conversión implícita del operando de tipo entero en un operando de tipo real. Supongamos, por ejemplo, que durante las comprobaciones semánticas del nodo que representa una de dichas operaciones, tras hacer recursivamente las de cada hijo, se detecta que el tipo del hijo izquierdo es entero y el tipo del hijo derecho es real. Te aconsejamos crear, en ese momento, un nuevo nodo NodoEnteroAReal que pase a ser el hijo izquierdo, y que tenga un único hijo, el que era el hijo izquierdo. Ese nuevo nodo será el responsable de hacer la conversión de tipos y obtener un resultado de tipo real a partir del resultado de tipo entero de su hijo. De ese modo, durante la generación de código, el operador binario no debe preocuparse de hacer conversiones: si hacen falta, habrá un nodo encargado de ello. Eso lo podrás aplicar en la versión 2 y posteriores en otros sitios en que haya que realizar una conversión de tipos implícita (para conversiones explícitas, si las tuviéramos, la creación de esos nodos la haríamos como la de todos los demás nodos, durante el análisis sintáctico).
No es necesario que contemples de momento la posibilidad de utilizar comparaciones entre reales ni reales en otros contextos.
Aquí tienes un ejemplo de programa válido:
secuencia escribe 3.0e-21 * 5.0 / 2; nl; fin
Ten en cuenta que para trabajar con reales necesitamos poder reservar y liberar los registros reales $f0, $f1, etc., sin confundirlos con los registros enteros. Para ello, puedes usar un objeto diferente de la clase BancoRegistros.
Ten en cuenta también que no se trata de cambiar alegremente todos los registros enteros por registros reales. Debes pensar bien para qué se usan. Por ejemplo:
- Las direcciones de memoria siempre son números enteros, aunque sean la dirección de un dato de tipo real.
- Tenemos también cadenas, que se manejan utilizando su dirección (un entero).
- El código de operación que se pone en el registro $sc para syscall es un entero, incluso para escribir reales.
Última actualización: 16 de abril de 2010.