Tarea 7__López
FUNCIONES Y ESTRUCTURAS
La generación
de código para las funciones es la parte mas complicada porque depende de la
maquina objeto y de la organización del entorno de ejecución. La traducción de
funciones implica dos etapas:
·
La definición de la función. Una definición
de función crea un nombre, parámetros y código del cuerpo de la función pero no
se ejecuta la función en ese punto.
·
La llamada a la función desde una
parte del programa (trataremos a los procedimientos como funciones que no de vuelven
valores). Una llamada crea los valores actuales para los parámetros y realiza
un salto al código de entrada de la función que se ejecuta y retorna al punto
de la llamada.
Supongamos
que el sub árbol sintáctico correspondiente a una función tiene como raíz un
nodo de tipo n_ call, llamada a función, con
una serie de hijos que corresponden a los argumentos, que en general, serán
expresiones E1; : : :
;En a evaluar para obtener el valor actual de los n-argumentos.
A
continuación se incluye una implantación para generar el código de
3-direcciones correspondiente a la llamada de la función en primer lugar.
Posteriormente analizaremos el caso de la definición de la función. Supondremos
que se han comprobado previamente las condiciones semánticas de la llamada (número
y tipo de argumentos).
Ejemplo
de llamada a la función
La llamada a una función de dos argumentos genera el siguiente código intermedio:
Se hace
uso de una pila en donde se apilan los valores actuales de los parámetros de la
función para después, como veremos en Siguiente
apartado, en la implantación del cuerpo de la función,
Nota:
Respecto a la dirección de la llamada a la función (índice de la instrucción
del código de entrada a la función), se podrá conocer en el caso de que el código
para la función ya se hubiera generado antes de la llamada (por ejemplo, se podrá
haber almacenado en la entrada de la tabla de símbolos correspondiente a esa función
en un campo definido para ese propósito).
En el
caso de que aun no se haya generado el código para la dedición de la función tendremos
que hacer un relleno de retroceso en todas las llamadas a esa función. Una
forma será para cada función almacenar los índices de las instrucciones donde
se hace una llamada dicha función (por ejemplo, en un vector de índices) y Una
vez definida la función que ya se conoce la dirección de entrada recorremos el
vector de índices y rellenamos con la dirección adecuada en todas las
proposiciones de llamadas a esa función.
No hay comentarios:
Publicar un comentario