Examen I - LDC - Universidad Simón Bolívar

Anuncio
Universidad Simón Bolívar
Departamento de Computación y Tecnología de la Información
CI4722 – Lenguajes de Programación III
Abril-Julio 2010
Carnet:
Nombre:
Examen I
(35 puntos)
Antes de empezar, revise bien el examen, el cual consta de cuatro preguntas.
Pregunta 0
Pregunta 1
Pregunta 2
Pregunta 3
Total
8 puntos
7 puntos
10 puntos
10 puntos
35 puntos
Pregunta 0 — 8 puntos
Siguiendo los esquemas de generación de código utilizados en clase (basados tanto en el texto de Scott, “Programming
Language Pragmatics”, con gramáticas de árboles abstractos, como en el texto de Aho et al., “Compilers”, con
herencia de etiquetas para expresiones booleanas), deseamos manejar una variante de las típicas instrucciones
break y continue.
En sus versiones básicas estándar, la instrucción break finaliza la iteración actual, mientras la instrucción continue
reinicia la iteración actual, correspondiendo esto a reevaluar la expresión booleana que controla la terminación de una
iteración-while y decidir según el resultado si se continúa iterando o no. En la variante que queremos implementar,
tanto break como continue reciben como parámetro un entero positivo que determina a cuál de muchas iteraciones
anidadas se refiere la instrucción. Así, en un punto del programa que se encuentre bajo al menos n iteraciones
anidadas, break n finaliza la n-ésima iteración actual contando desde el punto del programa donde aparece el
break hacia el exterior, mientras continue n reinicia la n-ésima iteración actual contando de la misma manera.
El parámetro debe ser estrictamente positivo. Note que break 1 y continue 1 corresponden a la versión básica
estándar de estas instrucciones.
Construya entonces esquemas de generación de código para estas nuevas instrucciones, utilizando las mismas convenciones manejadas en clase (tomadas, como se señaló anteriormente, de los textos de Scott y de Aho et al.). Puede
agregar nuevos atributos sobre la gramática de árboles abstractos si Ud. lo considera necesario.
Considere sólo las estructuras de control de la gramática de árboles abstractos que se presenta a continuación, y
considere que el esquema de generación de código para expresiones booleanas se mantiene tal como fue presentado
en clase (tomado del texto de Aho et al.). En el árbol del programa principal se omite adrede el componente de
tabla de símbolos, por ser irrelevante para el tema de esta pregunta. La gramática es:
PRINC : AProg
→
AInstr
SEC : AInstr
→
AInstr AInstr
COND1 : AInstr
→
AEBool AInstr
COND2 : AInstr
→
AEBool AInstr AInstr
ITER : AInstr
→ AEBool AInstr
BRK : AInstr
→ int (n)
CNT : AInstr
→ int (n)
,
donde PRINC se refiere al programa principal (ignorando su tabla de símbolos), SEC es secuenciación, COND1 es
un condicional con una sola rama (esto es, sin else, o con un skip en el else, según Ud. prefiera verlo), COND2 es
un condicional con dos ramas (típico condicional con else), ITER es una iteración estilo while, BRK se refiere a
la instrucción break, y CNT se refiere a la instrucción continue. En las últimas dos producciones puede suponerse
que los enteros son estrictamente positivos y válidos según su ubicación en el programa, ya que, de lo contrario, el
programa habría sido rechazado por las fases anteriores del front end.
Nota: Puede ignorar el atributo correspondiente al próximo registro a ser utilizado en evaluación de resultados
temporales.
Pregunta 1 — 7 puntos
Considere el pasaje de parámetros por valor-resultado a un subprograma, utilizando la pila para enviar y recibir
parámetros. Se desea que, dado un árbol de expresión con l-value correspondiente a un parámetro real, Ud. indique
el código que se debe generar para empilar y desempilar a éste.
Ahora bien, sabemos que el l-value puede cambiar entre el inicio y el final del subprograma, por lo cual es importante
conocer en qué momento debe ser evaluado éste según la definición del lenguaje. Suponga entonces que la definición
del lenguaje señala que el l-value debe ser utilizado como se indica a continuación: (i) al inicio, su valor antes de
entrar al subprograma, usando éste para pasar el parámetro real al formal; y (ii) al final, su valor luego de salir del
subprograma, usando éste para pasar el parámetro formal al real.
Construya entonces funciones empilar y desempilar que reciban los siguientes dos parámetros: pr : ALVal , el
árbol de expresión con l-value del parámetro real a pasar; y px : int , el típico atributo “próximo registro” (tomado
de los esquemas de generación de código presentados por el texto de Scott, “Programming Language Pragmatics”);
y que devuelvan un string correspondiente al código deseado.
Suponga que el parámetro para el que se está manejando el empilamiento/desempilamiento es de tipo entero, que
un entero ocupa 4 bytes, y que sp es el nombre del registro que se usa como stack pointer. Suponga también que
cuenta con un subprograma genCod (in lv : ALVal ; in px : int ; out cd : string ) , el cual, dado el árbol lv y
el “próximo registro” px , devuelve el código cd que evalúa a lv .
Por último, puede suponer, como de costumbre, que el registro de bajo nivel correspondiente a “próximo registro”
está disponible. Si necesitase más registros, debe considerar la posibilidad de que no haya más disponibilidad y
manejar este hecho apropiadamente.
Pregunta 2 — 10 puntos
Suponga que se tiene el siguiente fragmento de código fuente
x := x + a[i] * b[i];
y := y + a[i] * b[i];
x := x * y
en un contexto con las siguientes variables globales:
int x, y;
int[10] a, b;
int i;
Suponga también que estamos utilizando el mismo esquema de generación de código intermedio que fue utilizado
en clase (basado en el texto de Scott, “Programming Language Pragmatics”), en el que: se asume que se dispone
de una cantidad infinita de registros virtuales v0, v1, v2, etcétera, para almacenar resultados temporales; en el
código generado no se incluye verificación de errores de indexación inadecuada de arreglos; las variables globales
son referenciadas por su nombre; etcétera.
Responda entonces lo siguiente:
(a) Muestre el código de nivel intermedio que se genera para el fragmento de código fuente dado arriba.
(b) Tomando al código generado en (a) como un bloque básico, aplique a éste la técnica de eliminación local de
redundancia vista en clase (presentada en el texto de Scott bajo el nombre de “numeración local de valores”).
Muestre el código resultante y los contenidos finales de los diccionarios utilizados.
Nota: La suma y la multiplicación tienen la precedencia usual.
Pregunta 3 — 10 puntos
Utilizando el mismo lenguaje y las mismas convenciones del texto de Nielson et al., “Principles of Program Analysis”,
se tiene el siguiente programa:
[ j := 0 ]0 ;
[ k := j ]1 ;
while [ k < 10 ]2 do ( [ j := j + 1 ]3 ; [ k := k + 1 ]4 );
[ n := k ]5
.
Considere el problema LV de variables vivas (“live variables”) presentado en el texto de Nielson et al., y suponga
que a la salida del programa la única variable viva es n (lo cual es equivalente a suponer que estamos procesando el
cuerpo de una subrutina que sólo maneja variables locales y cuyo único parámetro de salida es n).
Considere ahora una variante LV’ de este problema bajo la cual una variable a la que se le hace una asignación
está “realmente viva” si el valor que se le está asignando realmente contribuirá al resultado final del programa. Esta
variante del problema refina el análisis para aumentar las posibilidades de detección de “código muerto” (asignaciones
innecesarias que pueden ser eliminadas).
Responda entonces lo siguiente:
(a) Muestre el sistema de ecuaciones del problema LV’ correspondiente al programa dado.
(b) Resuelva el sistema de ecuaciones de LV’ dado por Ud. en (a), utilizando alguno de los algoritmos de punto
fijo analizados en clase (tomados de los textos de Nielson et al., “Principles of Program Analysis”, y de Aho
et al., “Compilers”). Muestre los resultados temporales de la aplicación de su algoritmo.
(c) Indique qué asignaciones pueden ser eliminadas por ser consideradas “código muerto” según los resultados
obtenidos para LV’ en (b). Justifique su respuesta.
Descargar