Código Intermedio. Compiladores II 1

Documentos relacionados
Unidad II: Análisis semántico

Generación de Código Intermedio

Tema: Análisis de código intermedio

Unidad VI Generación de Código Intermedio. M.C. Juan Carlos Olivares Rojas

GENERACIÓN DE CÓDIGO INTERMEDIO ÁRBOLES DE SINTAXIS ABSTRACTA (ASA)

ÍNDICE UNIDAD 2: GENERACION DE CODIGO INTERMEDIO

Un. VI. Generador de código intermedio.

Unidad 5 Análisis semántico

Tema 7. Generación de código

Diseño de Compiladores I. Estructura General de un Compilador

Lenguajes y Compiladores Traducción Dirigida por la Sintaxis

Procesadores de lenguaje Tema 7 Generación de código intermedio

OPTIMIZACIÓN DE CÓDIGO

COMPILADORES E INTERPRETES

Lenguajes de programación

Compiladores e intérpretes Introducción

Semántica: principales usos. Semántica: principales enfoques. Semántica Operacional. Sintaxis abstracta de un lenguaje (sujeto) Semántica Operacional

AMBIENTES DE COMPILACION

Tema: Análisis Léxico

Tema 1 INTRODUCCIÓN A LOS LENGUAJES DE PROGRAMACIÓN

Todo programa en 'C' consta de una o más funciones, una de las cuales se llama main.

GENERACIÓN DE CÓDIGO INTERMEDIO CÓDIGO DE TRES DIRECCIONES

PROCESADORES DE LENGUAJE EXAMEN FINAL 8-JUNIO-07

Procesadores de Lenguajes. Análisis sintáctico. Gramáticas libres de contexto

Uno de los conceptos más útiles en ciencias de la computación es la pila.

Análisis semántico Tabla de símbolos, chequeo de tipos y representaciones internas

Construyendo Programas más Complejos

Tiempo de Compilación. Programa fuente. Secuencia. de caracteres. Scanner. Secuencia. de símbolos Parser. Compilador.

Introducción general al Lenguaje C (2010/2011)

GENERACIÓN DE CÓDIGO INTERMEDIO EJEMPLOS PARA DISTINTAS ESTRUCTURAS DE DATOS

Controla el flujo de tokens reconocidos por parte del analizador léxico. 4.2 Introduccion a las gramaticas libres de contexto y arboles de derivacion

CÓMO DESARROLLAR Y PROBAR PROGRAMAS?, COMPRUÉBALO!

Compiladores: Análisis Semántico. Pontificia Universidad Javeriana Cali Ingenieria de Sistemas y Computación Prof. Gloria Inès Alvarez V.

GENERACIÓN DE CÓDIGO

Índice general 7. Presentación 15

Java para no Programadores

Programación 1 Tema 2. Lenguaje de programación y ejecución de un programa

Teoría de autómatas. Un enfoque práctico. Recortables. Thelma Cantú María Gpe. Mendoza

Análisis semántico Tabla de símbolos, chequeo de tipos y representaciones internas

Java para no Programadores

Estructura de Datos. Temario Unidad VI. Árboles Árboles Binarios

UNIDAD 2. ESTRUCTURAS DE DATOS SECUENCIALES. 1. Pilas (Stacks)

Lenguajes y Compiladores Introducción. Compiladores 1

Árboles de Decisión Árboles de Sintaxis

Lenguaje de programación. COMPILADORES Unidad I: Introducción al proceso de compilación

Fundamentos PHP. El término puntuación nos referimos a la sintaxis usada en PHP para la terminación de una línea de código (;)

UNIDAD V. Analisis Semantico. 5.1 Introduccion. Analizador Semántico. Verifica que el significado de las construcciones del lenguaje tengan sentido.

Programación de Sistemas. Unidad 6. Macro Procesador

Tema 2 Conceptos básicos de programación. Fundamentos de Informática

Elementos léxicos del lenguaje de programación Java

Introducción a OCaml. October 19, 2015

LENGUAJES DE PROGRAMACIÓN. Solución al Ejercicio de Autocomprobación 1

FASES DE UN COMPILADOR

TP 3: intérprete de C en LISP (alias máquina virtual de C en LISP )

INTRODUCCION AL LENGUAJE C PARA SISTEMAS EMBEBIDOS

INDICE Parte I Algoritmos y herramientas de programación Capitulo 1. Computadoras y lenguajes de programación Actividades de Programación Resueltas

Examen de Procesadores de Lenguaje

Estructuras de Datos. La pila es un objeto dinámico en constante cambio.

Componentes Básicos. InCo. InCo Componentes Básicos 1 / 28

Definición de la sintaxis (1) Definición de la sintaxis (2) Definición de la sintaxis (3)

Tema: Análisis Semántico

UNIDAD IV Programación Funcional. Lic. Jesús Germán Andrés PAUTSCH - FCEQyN - UNaM

Programación Web Tema 3.2 Java Script Estructura del Lenguaje. Ramón Alcarria ETSI en Topografía, Geodesia y Cartografía - UPM

Tema II: Introducción al Lenguaje Funcional

LENGUAJE. Tema 2 Elementos de un programa

Estructuras de datos y algoritmos

Estructuras de Datos

Unidad I Introducción a la programación de Sistemas. M.C. Juan Carlos Olivares Rojas

Reconstrucción de Código. Joxean Koret

Concepto de compilador Intérprete Fases de un Compilador Herramientas de construcción de Compiladores

AGENDA Curso Java Básico

COMPILADORES. Tema 4. Análisis semántico

RECORRIDO EN ARBOLES

2. DISEÑO DEL REPERTORIO DE INSTRUCCIONES MÁQUINA

Introducción. El proceso de traducción

INDICE. Prólogo de la Segunda Edición

INTRODUCCIÓN AL ANÁLISIS ASCENDENTE. V id asig num. La siguiente figura muestra la tabla de análisis SLR de la gramática anterior:

Tema: Autómata de Pila

Introducción a la. Programación con

Análisis semántico: Comprobación de tipos

Lección 2 Introducción al lenguaje C

ALGORITMO. Podemos encontrar muchas definiciones de algoritmo en los textos de programación, todas ellas muy similares:

Tipos algebraicos y abstractos. Algoritmos y Estructuras de Datos I. Tipos algebraicos

16 Análisis sintáctico I

PROGRAMA: COMPUTACION I

Estructuras de Control

Compiladores e Intérpretes

Transcripción:

Código Intermedio Compiladores II 1

Usos del Código Intermedio Múltiples lenguajes y compiladores n+m módulos -> n*m compiladores Optimización Representación de fácil modificación Modelos de generación de código o Máquinas abstractas FAM, G-machine, máquina de Warren Compiladores transportables PASCAL /P-Code, JAVA Interpretación rápida OAKLisp, CLISP Depuración Intérpretes de C u otros lenguajes Compiladores II 2

Notación polaca Inversa (postfija) Se utiliza principalmente para la representación de expresiones aritméticas Expresión a notación polaca inversa Algoritmo Representar la expresión en forma de árbol sintáctico Recorrer el árbol en postorden Ejemplo: a+b*c-d Código: a b c * + d - - + d a * b c Compiladores II 3

Extensión a instrucciones de control de flujo Ejemplo: Fuente: if <cond> then <instr1> else <instr2> No se puede traducir a: <cond> <instr1> <instr2> If ya que solo se ha de evaluar una de las instrucciones Código generado <cond> etiqueta1 Salta si falso <instr1> etiqueta2 Salta etiqueta1: <instr2> etiqueta2: Código más típico <cond> Salta Si falso Etiqueta1 <Instr1> Salta Etiqueta2 Etiqueta1: <Instr2> Etiqueta2: Compiladores II 4

Pros y Contras de la Notación Polaca Inversa Generación de código: Simple No utiliza registros Optimización Es difícil de reordenar ya que hay que considerar el contenido de la pila Interpretación rápida Es muy fácil de interpretar ya que solo necesita una pila Transportable: Si, ya que todos los procesadores implementan una pila. Compiladores II 5

n-tuplas En la notación de n-tuplas cada instrucción es una n-tupla. Tripletas <operador>, <operando1>, <operando2> El resultado se asocia al número de tripleta Tripletas indirectas Son tripletas donde el orden de ejecución se especifica a parte. Cuadruplas <operación>, <operando1>, <operando2>, <resultado> Compiladores II 6

Tripletas Tripleta: <operador>, <operando1>, <operando2> el resultado se asocia al número de tripleta Ejemplo: W*X+(Y+Z) 1. *, W, X 2. +, Y, Z 3. +, (1), (2) Control de flujo: IF X>Y THEN Z=X ELSE Z=Y+1 1. >, X, Y 2. Saltar si falso, (1), 5 3. =, Z, X 4. Saltar,, 7 5. +, Y, 1 6. =, Z, (5) 7.... Problema: La optimización supone mover tripletas y hay que recalcular las referencias Compiladores II 7

Tripletas Indirectas Tripletas indirectas. Solucionan el problemas de la reordenación mediante indirección Ejemplo: Fuente: A=B+C*D/E F=C*D Operaciones Tripletas 1. (1) (1) *, C, D 2. (2) (2) /, (1), E 3. (3) (3) +, B (2) 4. (4) (4) =, A, (3) 5. (1) (5) =, F, (1) 6. (5) Compiladores II 8

Cuádruplas Cuádrupla: <operación>, <operando1>, <operando2>, <resultado> Ejemplo: (A+B)*(C+D)-E +, A, B, T1 +, C, D, T2 *, T1, T2, T3 -, T3, E, T4 T1, T2, T3, T4 son variables temporales. Las cuádruplas facilitan la aplicación de muchas optimizaciones, pero hay que tener un algoritmo para la reutilización de las variables temporales (reutilización de registros del procesador). Compiladores II 9

Fácil creación: Árboles sintácticos abstractos Se crea a partir del árbol sintáctico. Se elimina la información innecesaria. Símbolo no terminales Ejemplo: (a*b)/(c+d) / * + a b c d Compiladores II 10

Fácil optimización: Árboles sintácticos abstractos El árbol representa directamente la estructura del lenguaje fuente, y por tanto, las modificaciones que haríamos en el fuente son fáciles de realizar en el árbol. Como el árbol representa la estructura del lenguaje es fácil aplicarle las propiedades de este para optimizar. Propiedad conmutativa. Propiedad asociativa. etc. Compiladores II 11

Ejemplos de Árbol en CoSeL Un árbol sintáctico esta formado por las estructuras apply con el contenido: Función: operador raíz Arg(0), Arg(1)... Argumentos del operador Ejemplo: VerArbol(`( Fun f(n)=> if (n<=2) 1 else f(n-2)+f(n-1) )) Fun +- [] +- => +- f +- n +- If_Else +- <= +- n +- 2 +- 1 +- + +- f +- - +- n +- 2 +- f +- - +- n +- 1 Compiladores II 12

Buscar las Variables en un Árbol Fun Variables(arbol)=> { if (TypeP(Symbol,arbol)) [arbol] else if (TypeP(Apply,arbol)) { Var lv=[]; // lista de variables for (i<-arbol:index) lv=lv Variables(arbol.arg(i)); lv } else [] } variables(`( a=b+c; d=a*2;)) [d,a,c,b] Compiladores II 13

Buscar las Variables Modificadas en un Árbol Fun VariablesModificadas(arbol)=> { if (ApplyFunP(arbol,`\=,2) && TypeP(Symbol,arbol.arg(0))) { [arbol.arg(0)] } else if (TypeP(Apply,arbol)) { Var lv=[]; for (i<-arbol:index) lv=lv VariablesModificadas(arbol.arg(i)); lv } else [] } VariablesModificadas(`(a=b+c;d=a*2;)) [d,a] Compiladores II 14

Eliminar Expresiones Redundantes (NO FUNCIONA CORRECTAMENTE) Type Redundante(variable,expresion); Fun EliminarRedundantes(arbol)=> { Var ExpR=[]; Fun Eliminar(a)=> { Search (r<-expr,r.expresion==a) r.variable else { if (TypeP(apply,a)) { Var na=newapply(a.function,a.nargs); for (i<-a:index) na.arg(i)=eliminar(a.arg(i)); na; } else a; } } Compiladores II 15

Eliminar Expresiones Redundantes (NO FUNCIONA CORRECTAMENTE) } Fun Buscar(a)=> { if (ApplyFunP(a,`\=,2)) { Var ne=eliminar(a.arg(1)); ExpR=Redundante(a.Arg(0),ne)::ExpR; << <a.arg(0)> = <ne> >> } else if (TypeP(Apply,a)) { Var na=newapply(a.function,a.nargs); for (i<-a:index) na.arg(i)=buscar(a.arg(i)); na; } else a } Buscar(arbol); Compiladores II 16

Eliminar Expresiones Redundantes Ejemplo EliminarRedundantes(`( a=b+c; d=(b+c)*5; e=c+b; ))) Resultado a=b+c; d=a*5; e=c+b; Árbol de la entrada ; +- = +- a +- + +- b +- c +- ; +- = +- d +- * +- + +- b +- c +- 5 +- = +- e +- + +- c +- b Árbol del resultado ; +- = +- a +- + +- b +- c +- ; +- = +- d +- * +- a +- 5 +- = +- e +- + +- c +- b Compiladores II 17

Tipo de datos Type Cons(Head,Tail) Type List=Cons [] Listas en CoSeL Construcciones equivalentes [1,2,3]==cons(1,cons(2,cons(3,[]))) Cons(h,t)==h::t [1,2,3]==1::2::3::[] [h1,h2...::t]==h1::h2::...::t Compiladores II 18

Operaciones [1,2,3].Head==1 Listas en CoSeL [1,2,3].Tail==[2,3] [1,2,3].Head(0)==1 [1,2,3].Head(1)==2 [1,2]++[2,3]==[1,2,2,3] (append) [1,2] [2,3]==[1,2,3] (unión) [1,2] & [2,3]==[2] (intersección) [1,2] - [2,3]==[1] (resta) Listas por comprensión [x x<-1..5]==[1,2,3,4,5] [x x<-[1,2,3,4,5],x%2==0]==[2,4] Compiladores II 19

Árboles Estructura Nodo del arbol: Type apply(function,arg...) Hoja: Cualquier tipo de datos que no sea apply Construcción Árbol en forma de literal `(1+2+A) apply(\+,apply(\+,1,2),a) == 1+2+A Árbol en forma de patrón Var a=10; << 1+A+<A> >> apply(\+,apply(\+,1,a),10) == 1+A+10 Árbol construido directamente Var a=10; apply(`\+,apply(`\+,1,`a),a) apply(\+,apply(\+,1,a),10) == 1+A+10 Compiladores II 20

Estructuras de Control Instrucciones de control de flujo Típicas if (condición) instrucción if (condición) sentencia else sentencia switch (selector) {casos} while (condición) instrucción do instrucción while (condición) Break [condición] Continue [condición] No típicas for (generadores) instrucción Search (generadores) instrucción Search (generadores) sentencia else sentencia Found (generadores) sentencia Compiladores II 21

Generadores variable <- lista Estructuras de Control variable <- vector : Index variable <- apply : Index variable <- mínimo.. máximo variable <-~ mínimo.. máximo Compiladores II 22

Código Enhebrado Es una representación útil para la interpretación independiente de máquina. Código enhebrado directo: El código es una secuencia de direcciones de rutinas que implementan las instrucciones. Algunas rutinas son estándar (Add), pero otras las ha de generar el compilador para que puedan tratar los operandos (Push). Estas últimas limitan la transportabilidad. código Push B Contador de programa virtual Push C Add Pop B Bucle de interpretación For (;;) (*pc++)(); Compiladores II 23

Código Enhebrado con Parámetros Código enhebrado indirecto: El código es una secuencia de apuntadores a funciones seguidos de los argumentos que pueda necesitar la función. Contador de programa virtual push b push c add pop c argumento argumento argumento Bucle de interpretación For (;;) (*PC)(); Función void pushliteral() { *--SP=PC[1]; PC=PC+2; } Compiladores II 24

Código para máquinas abstractas Un objetivo de los compiladores es ser adaptables y portables a nuevas máquinas. Una de las formas de conseguirlo es con la generación de código para máquinas abstractas. Aplicaciones: Modelos de compilación WAM modelo de compilación de PROLOG G-machine modelo de compilación de lenguajes funcionales con evaluación perezosa. FAM modelo de compilación de lenguajes funcionales con evaluación estricta. Compiladores II 25

Código para máquinas abstractas Compiladores portables Compilador ha código intermédio + intérprete. Compilador ha código intermedio + compilador de código intermedio a código máquina n+m módulos -> n*m compiladores Compiladores II 26

Resumen Códigos para la ejecución Notación polaca inversa Código enhebrado Códigos para la optimización Árbol sintáctico abstracto Tuplas Tripletas Tripletas indirectas Cuadruplas Códigos para la explicación Códigos de máquinas abstractas Compiladores II 27