cursoprogsist
TRANSCRIPT
-
8/3/2019 CURSOProgSist
1/213
CURSO:
PROGRAMACION DESISTEMAS
Dr. Ramn Zatarain Cabada
-
8/3/2019 CURSOProgSist
2/213
ELEMENTOS DEL CURSO
Programa del Curso..... PDF
Datos del Profesor . RZC
Contenido del Curso. Diaps Proyectos . Archs
Software y Herramientas
-
8/3/2019 CURSOProgSist
3/213
Unidad I
Introduccin a la Programacinde Sistemas
-
8/3/2019 CURSOProgSist
4/213
1.1 Qu es y que estudia la P. de S. ?
Son los programas que residen en unsistema de computacin. Su funcin es
proporcionar al usuario o programador unainterfase mas eficiente y practica con relacinal hardware de la maquina.
La P. de S. estudia como estn
implementados cada uno de los programasde un Sistema (vernotas).
-
8/3/2019 CURSOProgSist
5/213
1.2 Herramientas desarrolladas
con la P de SEjemplos:
Compiladores (javac)
Ensambladores (Masm)
Interpretes (Visual Basic)
Ligadores (Link)
Cargadores
Sistema Operativo (Windows)
Utileras de Sistemas (Debugger)
-
8/3/2019 CURSOProgSist
6/213
1.3 Lenguajes
Naturales (Traductores de Ingles-Espaol,Ingles-Ruso, etc)
Artificiales (Compiladores de LP como Java,C++, Ada, etc.)
-
8/3/2019 CURSOProgSist
7/213
1.4 Traductor y su Estructura
Ensambladores . (notas)
Compiladores. (notas)
Intrpretes...... (notas)
-
8/3/2019 CURSOProgSist
8/213
1.5 Generador de Cdigo para Compiladores(Compilador de Compiladores)
Definicin: Un compilador de compiladores o generador deParsers es una utilera para generar el cdigo fuente de unparser, intrprete o compilador a partir de una descripcin delenguaje anotado en la forma de gramtica (usualmente BNF)
mas cdigo que es asociado con cada una de las reglas de lagramtica que debe ser ejecutada cundo esas reglas seanaplicadas por el parser. Esas piezas de cdigo son algunasveces llamadas rutinas de acciones semnticas ya que ellasdefinen la semntica de las estructura sintctica y que esanalizada por el parser. Dependiendo del tipo de parser que ser
generado, las rutinas pueden construir un rbol de parsing (oAST) o generar cdigo ejecutable directamente (notas).
-
8/3/2019 CURSOProgSist
9/213
Unidad II
Introduccin al Diseo deLenguajes de Programacin
-
8/3/2019 CURSOProgSist
10/213
Visin del Problema.
Consideraciones Preliminares.
Objetivos y filosofas del diseo de los
lenguajes de programacin.
Diseo detallado.
Caso de estudio.
-
8/3/2019 CURSOProgSist
11/213
Unidad IIIAnlisis de Lxico
-
8/3/2019 CURSOProgSist
12/213
3.1 Introduccin a los Autmatas Finitos
y Expresiones Regulares
(ver apuntes de Lenguajes y Autmatas).
-
8/3/2019 CURSOProgSist
13/213
3.2 Analizador de Lxico. Descompone la entrada en palabras individuales llamadas tokens. El
analizador de lxico (scanner) toma una cadena de caracteres queforman la entrada y produce una cadena de nombres o identificadores,palabras claves o reservadas (PC) signos o marcas de puntuacin,operadores aritmticos y lgicos, constantes (nmeros, cadenas, etc.)
y otros. Tambin el scanner tiene como funcin desechar espacios enblanco y comentarios entre los tokens, otra funcin podra ser crear latabla de smbolos.Ejemplo:TIPO EJEMPLOSID foo n14 lastNUM 73 0 00 515REAL 66.1 .5 10. 1e67
IF if COMMA ,NOTEQ!=LPAREN (
-
8/3/2019 CURSOProgSist
14/213
Analizador de Lxico (cont.)
Tokens de puntuacin como IF, VOID yRETURN son llamadas palabras reservadas
y en la mayora de los lenguajes no puedenusarse como identificadores.
-
8/3/2019 CURSOProgSist
15/213
3.3 Manejo de Buffers
El analizador de lxico (scanner) y el analizador desintxis (parser) forman un duo productor-consumidor. El scanner produce tokens y el parser
los consume.La implementacin de la lectura de los caracteresde la entrada (disco) es usualmente hecha por unbuffer (memoria) que contendr una buena parte de
la entrada, desde donde el scanner ir formando lostokens. Esto agiliza la entrada que de otra formaleera carcter por carcter desde el disco.
-
8/3/2019 CURSOProgSist
16/213
3.4 Creacin de la Tabla deSmbolos.
ChecarnotasLa tabla de smbolos es una estructura de datosmuy importante en casi todo el proceso decompilacin. En ella se guarda durante las primerasfases de compilacin los nombres de losidentificadores (smbolos) usados en el programafuente, adems de los atributos de cada uno deestos identificadores. Estos identificadores ysmbolosjunto con sus atributos sern usados
posteriormente para realizar funciones como elchequeo de tipos, la asignacin de memoria,generacin de cdigo objeto etc.
-
8/3/2019 CURSOProgSist
17/213
EjemploEjemplo.-Programa X1;
Var X, Y: Integer;Z: Real;
Arreglo: Array [1100] of int
Procedure compara (a, b: Integer)Var n, m: integer;Begin
--------
EndBegin
--------End
-
8/3/2019 CURSOProgSist
18/213
3.5 Manejo de Errores de Lxico
Errores posibles detectados en el anlisis delxico son:
Patrones de tokens que no coincidan con algnpatrn vlido. Por ejemplo el token #### serainvlido en algunos L.P.
Caracteres invlidos para el alfabeto del el
lenguaje. Longitud de ciertos tokens demasiado larga.
-
8/3/2019 CURSOProgSist
19/213
3.6 Generadores de CdigoLxico
La construccin de un scanner puedeautomatizarse por medio de un generador de
analizadores de lxico. El primer programa de este tipo que se hizo
popular fue Lex (Lesk, 1975) que generabaun scanner en lenguaje C.
Hoy en da existen muchos programas deeste tipo: Flex, Zlex, YooLex, JavaCC,SableCC, etc.
-
8/3/2019 CURSOProgSist
20/213
Ejemplo: Javacc
Javacc (Java Compiler Compiler) es un generadorde scanners y parsers (https://javacc.dev.java.net/).
Toma como entrada especificaciones de lxico
(expresiones regulares) y sintxis (gramtica decontexto libre) y produce como salida un analizadorde lxico y un parser recursivo decendente.
Se puede usar como pre-procesador de Javacc, ajjtree y a JTB para la construccin del rbolsintctico.
-
8/3/2019 CURSOProgSist
21/213
(cont.)
Miparser. jj javacc Miparser.jj Miparser.javaParseException.javaTokenMgrError.javaotros archivosjava
javac Miparser.java
Miparser.class java Miparser
-
8/3/2019 CURSOProgSist
22/213
(cont.)
PARSER_BEGIN(PS1)
class PS1 {}PARSER_END(PS1)
/* Para la expresin regular de la derecha lo de la izquierda ser retornado */
TOKEN: {||
||
}
SKIP: {|" "|"\t"
|"\n"|"\r"}
void Start():{}{ ( | | | )* }
EJEMPLO DE ESPECIFICACION PARA GENERAR UN SCANNER
-
8/3/2019 CURSOProgSist
23/213
Unidad IVAnlisis de Sintxis
-
8/3/2019 CURSOProgSist
24/213
4.1 Introduccin a las gramticasLibres de Contexto y rboles de
derivacin
El tipo de gramticas usadas en los LP son llamadas gramticas de contexto libre, las cules,junto con rboles de derivacin, fueron estudiadas en el curso de Lenguajes y Autmatas.
Un ejemplo de una gramtica para un LP simple es la siguiente:
1) SS;S 2) S id := E 3) S print (L)4) E id 5) E num 6) E E + E 7) E (S,E)
8) L E 9) L L , E
(ver ejemplo de derivaciones y rboles de parsing)
A continuacin veremos un ejemplo de una gramtica para Java en formato BNF (liga).
-
8/3/2019 CURSOProgSist
25/213
(cont.)
Gramtica Ambigua. Una gramtica es ambigua sipuede derivar una oracin (cadena) con dosdiferentes rboles de parsing. La sig. Gramtica esambiga:
Eid Enum E E*E E E/E
EE+E E E-E E (E)
ya que tiene dos rboles de parsing para la mismaoracin (rboles para id:=id+id+idcon primeragramtica y rboles para 1-2-3 con segunda en sigslice).
-
8/3/2019 CURSOProgSist
26/213
(cont.)S
Id := E
E + E
E + E id
Id id
S
Id := E
E + E
id E + E
id id
-
8/3/2019 CURSOProgSist
27/213
(cont.)
E
E - E
E - E 3
1 2
E
E - E
1 E - E
2 3
-
8/3/2019 CURSOProgSist
28/213
4.2 Diagramas de Sintaxis
Un mtodo alternativo al BNF para desplegarlas producciones de ciertas gramticas es eldiagrama de sintaxis. sta es una imagende la producciones que permite al usuario verlas sustituciones en forma dinmica, es decir,verlas como un movimiento a travs del
diagrama.Ejemplo en Java (liga)
-
8/3/2019 CURSOProgSist
29/213
4.3 Precedencia de Operadores
En los dos ejemplos vistos en seccin 4.1, los dosrboles de parsing para 1-2-3 significaba diferentescosas: (1-2)-3=-4 versus 1-(2-3)=2. Similarmente,(1+2)x3 no es lo mismo que 1+(2x3). Es por eso
que gramticas ambiguas son problemticas paraun compilador. Afortunadamente, una gramticaambigua puede convertirse en una no ambigua. Porejemplo, si queremos encontrar una gramtica noambigua para el lenguaje de la segunda gramtica
de seccin 4.1, lo podemos hacer por medio de dosoperaciones: primero, aplicar orden de precedenciaa los operadores y segundo aplicar asociatividadpor la izquierda. Con esto, tenemos la sig.gramtica:
-
8/3/2019 CURSOProgSist
30/213
(cont.)
SE$ nota: $es EOF- marker
EE+T EE-T ET
T-->T*F TT/F TF
Fid Fnum F(E)
Esta gramtica acepta el mismo lenguaje que la
de seccin 4.1 pero solo produce un rbol de
parsing por oracin. Esta gramtica no podra producir
rboles como los siguientes:
X
+ ?Y
+
?U
?V *
+
-
8/3/2019 CURSOProgSist
31/213
4.4 Analizador Sintctico En esta fase se analiza la estructura de la frase del programa. El parser es el programa que funciona como ncleo del compilador.
Alrededor del parser funcionan los dems programas como el scanner, elanalizador semntico y el generador de cdigo intermedio. De hecho sepodra decir que el parser comienza el proceso de compilacin y su primertarea es pedir al escner que enve los tokens necesarios para llevar acabo el anlisis sintctico, del estatuto, expresin o declaracin dentro de
un programa. Tambin el parser llama rutinas del anlisis semntico para revisar si el
significado del programa es el correcto. Por ultimo el parser genera cdigo intermedio para los estatutos y
expresiones si no se encontraron errores en ellos.
-
8/3/2019 CURSOProgSist
32/213
(cont.)
Existen diferentes tcnicas o mtodos para realizar un anlisissintctico Parsing. Estas tcnicas se dividen en dos tipos:
Descendentes Ascendentes
Las tcnicas descendentes realizan su anlisis partiendo desde elsmbolo inicial de la gramtica y realizando derivaciones hastallegar a producir las hojas o tokens.Por otra parte las tcnicas ascendentes realizan su anlisis
partiendo de las hojas o tokens y mediante una serie deoperaciones llamadas reducciones terminan en la raz o smboloinicial de la gramtica.Por lo general las tcnicas descendentes son mas sencillas deimplementar que las ascendentes, pero por otra parte son menoseficientes
-
8/3/2019 CURSOProgSist
33/213
4.4.1 Analizador descendente (LL).
Parsing Predictivo Algunas gramticas son sencillas de analizarse sintcticamente
usando un algoritmo o mtodo cuyo nombre es recursivodescendente. En esta tcnica cada produccin de la gramticase convierte en una clusula de una funcin recursiva.
Un parserPredictivo es aquel que predice que camino tomaral estar realizando el anlisis sintctico. Esto quiere decir que elparser nunca regresara a tomar otra decisin ( back tracking )para irse por otro camino, como sucede en las derivaciones.Para poder contar con un parser predictivo la gramtica debe detener ciertas caractersticas, entre ellas la mas importante es que
el primer smbolo de la parte derecha de cada produccin leproporcione suficiente informacin al parser para que esteescoja cual produccin usar. Normalmente el primer smbolomencionado es un Terminal o token.
-
8/3/2019 CURSOProgSist
34/213
(cont.)
Esta tcnica se utiliz o populariz en los aos 70 a partir delprimer compilador de pascal implementado con ella. Acontinuacin ilustraremos esto escribiendo un parser recursivodescendente para la siguiente gramtica:
S ifE then S else SS begin S LS print EL endL ; S L
Enum = num
Nuestro Parser tendra 3 mtodos (uno por cada produccin)
-
8/3/2019 CURSOProgSist
35/213
Programa del ParserFinal int if = 1, then = 2, else = 3, begin = 4, end = 5, print = 6, semi = 7,
num = 8, EQ = 9
int tok = get token ( );
void advance ( ) { tok = get token ( ); }void eat ( int t) { if ( tok == 1) advance ( ); else error ( ); }
void S ( ) { switch ( tok ) {case If: eat ( if ); E ( ); eat ( then ); S ( );
eat ( else ); S ( ); break;case begin: eat ( begin ); S ( ); L ( ); break;case print: eat ( print ); E ( ); break;default: error;}}
void L ( ) { switch ( tok ) {case end: eat ( end ); break;case semi: eat ( semi ); S ( ); L ( ); break;default: error ( );}}
void E ( ) { eat ( num ); eat ( EQ ); eat ( num ); }
-
8/3/2019 CURSOProgSist
36/213
(cont.)
Un parser predictivo que examina la entrada de izquierda aderecha (left-to-right) en un paso y realiza su derivacin por laizquierda es llamado Parser LL.
Cuando el parser solo necesita mirar el siguiente token para
hacer su funcin (llokahead(1)), recibe el nombre de ParserLL(1). Un parser podra necesitar mirar K tokens por adelantado para
tomar desiciones. En este caso recibe el nombre de parserLL(K).Ejemplo: (parte de una gramtica)
IF-STM ifEXPthen STM else STM| ifEXPthen STM
-
8/3/2019 CURSOProgSist
37/213
Eliminacin de Recursin por la izquierda
Suponer que queremos construr un Parserpredictivo para la gramtica de seccin 4.3.
S
E$ E
E+T E
E-T E
TT-->T*F TT/F TF
Fid Fnum F(E)
Producciones como E E + T contienen recursin por la izquierda.Parsers descendentes no pueden manejar recursin por la izquierdaen una gramtica. Para eliminar este tipo de recursin utilizamos lasiguiente transformacin:
-
8/3/2019 CURSOProgSist
38/213
(cont.)
En general, si tenemos producciones X X Ky X Edonde Eno comience con Xpodemos aplicar la siguiente transformacin:
X XK X EXX XK X EXX E X KX
XE X
KXX P
-
8/3/2019 CURSOProgSist
39/213
(cont.)
Aplicando la transformacin a la gramtica anterior,obtenemos la nueva equivalente gramtica (sinrecursin por la izquierda):
S E$E T E E + T E E - T E E P
T F T T * F T T / F T T P
F idF num F (E)
-
8/3/2019 CURSOProgSist
40/213
Factorizacin por la izquierda Otro problema en una gramtica ocurre cuando dos producciones
para el mismo no terminal comienza con el mismo smbolo. Porejemplo:
IF-STM if EXP then STM else STM
IF-STM if EXP then STM
En dicho caso podemos factorizar por la izquierda la gramtica. Elresultado sera el sig:
IF-STM if EXP then STM X
X P
X else IF-STM
las producciones anteriores facilitarn el trabajo del parserpredictivo.
-
8/3/2019 CURSOProgSist
41/213
4.4.2 Analizador ascendente(LR yLALR).
La debilidad de las tcnicas descendentes LL(k) es quedeben predecir que producciones usar, despus dehaber mirado los primeros ktokens de la cadena deentrada.
Una tcnica ascendente mas poderosa es la tcnicaLR(K), la cual pospone la decisin hasta que ha vistolos tokens de la entrada correspondientes a la partederecha de la produccin (adems de k mas tokenstambin).
LR(K) quiere decir parser de izquierda a derecha,derivacin por la derecha y lookahead(k). Estatcnica fue introducida por primera vez en 1965 porKnuth.
-
8/3/2019 CURSOProgSist
42/213
(cont.)
Un Parser LR(K) est compuesto de: La cadena de entrada
Una pila
Una tabla de Parsing LR
El parser obtiene los tokens de la entrada ydependiendo de el token actual y de lo que
est en el tope de la pila, ejecuta una de dosacciones (shift-reduce) con la ayuda de latabla de parsing
-
8/3/2019 CURSOProgSist
43/213
Algoritmo de Parsing LR (aho,Sethi y Ullman)
Tomar el primer token de w$ /* w es la cadena */Repeat forever begin
Sea s el estado en el tope de la pila y a el token actual;ifaccin[s,a] = shift s then begin
push a primero y sedpus s al tope de la pila;obten el siguiente token de la cadena de entrada
else ifaccin[s,a] = reduce A->B then beginpop 2*|B| smbolos fuera de la pila;Sea s ahora el estado en el tope de la pila;Push A y despus goto[s,A] al tope de la pila;Imprime la produccin A->B
end
else ifaccin[s,a] = accept thenreturnelse error()
end
-
8/3/2019 CURSOProgSist
44/213
Ejemplo: Parser LR(K)
S4 s7 g2s3 a
S4 s7 g5s6
r1 r1 r1S20 s10 s8 g11
s9S4 s7 g12
123
45
678910111213
1415161718192021
2223
id num print ; , + := ( ) $ S E L
S20 s10 g15 g14r5 r5 r5 r5 r5r2 r2 s16 r2s3 s18r3 r3 r3
s19 s13
r8 r8S20 s10 s8 g17
r6 r6 s16 r6 r6S20 s10 s8 g21S20 s10 s8 g23
r4 r4 r4 r4 r4s22
r7 r7 r7 r7 r7r9 s16 r9
TABLA DE PARSING
-
8/3/2019 CURSOProgSist
45/213
Ejemplo (cont.):PILA ENTRADA ACCION
1 a:=7;B:=c+(d:=5+6,d)$ shift1 id4 := 7;B:=c+(d:=5+6,d)$ shift1 id4 := 6 7;B:=c+(d:=5+6,d)$ shift
1 id4 := 6 num10 ;B:=c+(d:=5+6,d)$ reduceE->num
1 id4 := 6 E11 ;B:=c+(d:=5+6,d)$ reduceS->id:=E
.
.
.
.
.
.
.
$ accept1 S2
.
.
.
..
.
.
.
.
.
..
.
.
-
8/3/2019 CURSOProgSist
46/213
Parsing LALR
La tcnica de parsing LALR (LookAhead-LR) evita el usode tablas muy grandes, como las manejadas en latcnica de parsing LR.
Esta tcnica fue inventada por DeRemer en 1971. Casi cualquier construccin sinctica de un LP puede
ser expresado de manera conveniente por unagramtica LALR.
Generadores de Parsers famosos como YACC (YetAnother Compiler-Compiler-Johnson) producen unparser LALR.
Para una gramtica de un LP como Pascal una tabla deparsing LALR ocupara varios cientos de estados,mientras que una tabla LR seran miles de estados.
-
8/3/2019 CURSOProgSist
47/213
4.5 Administracin de tablas desmbolos.
Como se estudi en la unidad anterior,durante el anlisis de lxico se inicia laconstruccin de la tabla de smbolos.
Esto ocurre al detectarse las declaracionesen el programa fuente.
Sin embargo tambin el parser ayuda arealizar esta tarea pues el es quien llama alas respectivas rutinas semnticas para querealicen funciones relacionada con la tablade smbolos (ver figura).
-
8/3/2019 CURSOProgSist
48/213
4.6 Manejo de errores sintcticos y surecuperacin.
Dentro del cdigo del parser predictivo estudiado enclase se puede observar que el parser llama unmetodo error para el manejo de erroressintcticos, que es cuando el parser obtiene un
token no esperado. Cmo se maneja el error para esta clase de
parsers? Una forma simple es ejecutar unaexcepcin y parar la compilacin. Esto como que noes muy amigable par el usuario.
La mejor tcnica es desplegar un mensaje de errory recuperarse de este, para que otros posibleserrores sintcticos puedan ser encontrados en lamisma compilacin.
-
8/3/2019 CURSOProgSist
49/213
(cont.)
Un error sintctico ocurre cuando la cadena detokens de entrada no es una oracin en el lenguaje.La recuperacin del error es una forma de encontraralguna oracin correcta, similar a la cadena detokens.
Esto se puede realizar por medio de borrar,reemplazar o insertar tokens.
Por ejemplo la recuperacin de un error en S,
podra ser al insertar un token if,begin o print(opretender que existe en la cadena), desplegar elmensaje del error y continuar la compilacin.
-
8/3/2019 CURSOProgSist
50/213
Ejemplo:
void S ( ) { switch ( tok ) {case If: eat ( if ); E ( ); eat ( then ); S ( );
eat ( else ); S ( ); break;case begin: eat ( begin ); S ( ); L ( ); break;case print: eat ( print ); E ( ); break;default: print(se esperaba if, begin o print);
}}
Un problema que puede ocurrir al insertar un token faltante es que el programacaiga en un ciclo infinito, por eso a veces es preferible y mas seguro borrar eltoken, ya que el ciclo terminar cuando el EOF sea encontrado. Esta tcnica
trabaja muy cercanamente con la tabla de parsing (cuando el parser seimplementa con tablas).En un parser del tipo LR o LALR, la tabla de parsing tiene 4 acciones: shift,reduce, accept y error (entrada nula). Cuando el parser encuentra una accinerror, se para el proceso de anlisis y se reporta la falla.
-
8/3/2019 CURSOProgSist
51/213
4.7 Generadores de cdigo paraanalizadores sintcticos
Como se vio al final del captulo 3, Javacc es un generadorde scanners y de parsers (https://javacc.dev.java.net/).
Javacc produce un parser del tipo descendente (recursivo) oLL(k) donde k (lookahead) puede ser cualquier nmero entero
positivo. El parser producido puede correr en cualquier plataforma que
cuente con el compilador de Java. En el ejemplo siguiente del uso de Javacc, utilizamos de
nuevo la gramtica presentada anteriormente (seccin 4.4.1)
para un parser predictivo. Ejecutamos Javacccon la anteriorgramtica y obtendremos un parser recursivo descendentepara dicha gramtica.
Ejemplo: gramtica para estatutos
-
8/3/2019 CURSOProgSist
52/213
Ejemplo: gramtica para estatutosbegin, if y print
PARSER_BEGIN(MiniParser)public class MiniParser {
public static void main(String[] args) {MiniParser parser;try {// RGC: added line
if( args.length == 0 )parser= new MiniParser(System.in);
// RGC: added lineselse
parser= new MiniParser( new java.io.FileInputStream( args[0] ) ) ;
}// RGC: End
parser.Program();} catch (ParseException e) {
System.out.println(e.getMessage());}//RGC: added linescatch( Exception e ) {
System.out.println(e.getMessage());} //RGC :End
}}PARSER_END(MiniParser)
SKIP : {" "
| "\t"| "\n"| "\r"}
-
8/3/2019 CURSOProgSist
53/213
-
8/3/2019 CURSOProgSist
54/213
Unidad VAnlisis Semntico
-
8/3/2019 CURSOProgSist
55/213
5.1 Analizador semntico
Un compilador no solo tiene que revisar la sintaxis decdigo fuente, si no tambin la semntica de este.
Al igual que en los lenguajes naturales (espaol, ingles,etc.) en los lenguajes de programacin existen reglassemnticas para definir el significado de los programas,estatutos, expresiones, etc.
Por ejemplo un error semntico es usar (en pascal java) un identificador que no fue anteriormentedeclarado.
Otro ejemplo de error semntico en un programa escuando este es compilado y y no se detectan errorespero el momento de ser ejecutado este programa nofunciona correctamente.
-
8/3/2019 CURSOProgSist
56/213
-
8/3/2019 CURSOProgSist
57/213
5.3 Conversin de tipos.
Algunas veces los tipos de una expresin o estatuto sondiferente.
Por ejemplo en la asignacin,a = b * c;
el tipo del resultado de evaluarb*ces diferente al de elidentificadora. El compilador algunas veces con ciertos diferentes tipos puede
hacer una conversin interna en forma implcita para solucionarel problema. Otras veces el programador explcitamente es elque hace la conversin (casting).
Ejemplo:float dinero;int cambio;dinero = (float) cambio;
-
8/3/2019 CURSOProgSist
58/213
En un parser recursivo-descendente, el cdigo de las acciones semnticases mezclado dentro del flujo de control de las acciones del parser. En unparser especificado en javaCC, las acciones semnticas son fragmentos decdigo de programa en java unido a las producciones gramticales.
Cada smbolo terminal y noterminal puede asociarse con su propio tipo devalor semntico.Por ejemplo en la siguiente gramtica para YACC de una calculadorasimple, el tipo asociado con exp e INTpodra serint:
%token INT PLUS MINUS TIMES UMINUS%start exp%left PLUS MINUS
%left TIMES%left UMINISexp: INT | exp PLUS exp | exp MINUS exp | exp TIMES exp 1
MINUS exp %prec UMINUS
5.4 Acciones agregadas en un Analizadorsintctico descendente (top-down).
-
8/3/2019 CURSOProgSist
59/213
(cont.)
Los otros tokens no necesitaran tener unvalor.
Por otra parte el tipo asociado a un token
debe por supuesto coincidir con el tipo detoken que el scanner retorne.
Para una regla ABCD, la accin semnticadebe retornar un valor cuyo tipo es elasociado al noterminal A. Pero puedeconstrur este valor de los valores asociadosa los terminales y noterminales B, C, D.
-
8/3/2019 CURSOProgSist
60/213
Recursivo-descendente
En un parser recursivo-descendente, las accionessemnticas son los valores retornados por lasfunciones de parsing, o los efectos laterales deesas funciones o ambos.
Por cada smbolo terminal y noterminal, asociamosun tipo (desde el lenguaje de implementacin del LPdel compilador) de valor semntico representandofrases derivadas desde ese smbolo.
El siguiente programa es un intrprete recursivo
descendente para una parte de la gramtica en lacual eliminamos la recursin por la izquierda (porconveniencia la volvemos a mostrar):
-
8/3/2019 CURSOProgSist
61/213
(cont.)
S E$ E T E E + T E E - T E E P
T F T T * F T T / F T T P
F id F num F (E)
Los tokens ID y NUM deben ahora acarrear valores de tipo string e int,respectivamente. Asumiremos que existe una tabla lookup que mapeaidentificadores a enteros. El tipo asociado con E, T, F, etc., es int, y la accinsemntica es fcil de implementar.
-
8/3/2019 CURSOProgSist
62/213
Interprete
class Token2 {int kind; Object val;Token2(int k, Object v){kind=k;val=v;
}}final int EOF=0, ID=1, NUM=2, PLUS=3,
MINUS=4,LPAREN=5, RPAREN=6, TIMES=7;int lookup(String id) { . }int F_follow[] = {PLUS,TIMES,RPAREN,EOF};
int F() {switch(tok.kind) {case ID: int i=lookup((String)(tok.val));advance()return i;case NUM: int i=((integer)(tok.val)).intVal();
advance();return i;case LPAREN: eat(LPAREN);
int i=E();eatOrSkipTo(RPAREN,F_follow);return i;
case EOF:default: print("1 esperaba ID,NUM, o parent izq");//skipto(F_follow); return 0;
}}
int T_follow[]= {PLUS,RPAREN,EOF};
int T() {switch(tok.kind) {case ID:case NUM:case LPAREN: return Tprime(F());default: print("2 esperaba ID, NUM o parent izq");
//skipto(T_follow);
return 0;}}
int Tprime(int a) {switch (tok.kind) {case TIMES: eat(TIMES); return Tprime(a*F());case PLUS:case RPAREN:case EOF: return a;default: print("3 esperaba ID, NUM o parent izq");
//skipto(T_follow);return 0;
}}
void eatOrSkipTo(int expected, int[] stop) {if (tok.kind==expected)
eat(expected);else {print("4 esperaba ID, NUM o parent izq");
//skipto(stop);}}
Acciones semnticas
-
8/3/2019 CURSOProgSist
63/213
-
8/3/2019 CURSOProgSist
64/213
-
8/3/2019 CURSOProgSist
65/213
(cont.)
Otro ejemplo es en el rbol de parsing:
L
E + T
T * F F
F 4 8
2
Cuyo rbol sintctico abstracto sera:+
* 8
2 4
-
8/3/2019 CURSOProgSist
66/213
Ejemplo:
La gramtica siguiente nos muestra una sintaxisabstracta de un lenguaje para expresiones:
EE+E EE-E EE*E
EE/E Eid Enum Esta gramtica es imprctica para un parser ya que
es ambigua pues no tiene precedencia deoperadores.
Sin embargo, esta gramtica no es para el parser.El analizador semntico podra usarla el cual no semolesta por la ambiguedad puesto que ya tiene suarbol.
-
8/3/2019 CURSOProgSist
67/213
rboles de Sintaxis en Java
En Java las estructuras de datos para elrbol de sintaxis contienen una claseabstracta para cada noterminal y unasubclase para cada produccin. As, lasclases de el programa siguiente son lasclases de la sintaxis abstracta para la
gramtica de la diapositiva anterior.
-
8/3/2019 CURSOProgSist
68/213
public abstract class ExpCh4 {public abstract int eval();
}class PlusExp extends ExpCh4 {
private ExpCh4 e1,e2;public PlusExp(ExpCh4 a1, ExpCh4 a2)
{e1=a1; e2=a2;}public int eval() {
return e1.eval()+e2.eval();
}}class MinusExp extends ExpCh4 {
private ExpCh4 e1,e2;public MinusExp(ExpCh4 a1, ExpCh4 a2)
{e1=a1; e2=a2;}public int eval() {
return e1.eval()-e2.eval();}
}class TimesExp extends ExpCh4 {private ExpCh4 e1,e2;public TimesExp(ExpCh4 a1, ExpCh4 a2)
{e1=a1; e2=a2;}public int eval() {
return e1.eval()*e2.eval();}
}
class DivideExp extends ExpCh4 {private ExpCh4 e1,e2;public DivideExp(ExpCh4 a1, ExpCh4 a2)
{e1=a1; e2=a2;}public int eval() {
return e1.eval()/e2.eval();}}class Identifier extends ExpCh4 {
private String f0;public Identifier(String n0) {f0=n0;}public int eval() {
return (7); //return lookup(f0);}
}class IntegerLiteral extends ExpCh4 {private String f0;public IntegerLiteral(String n0) {f0=n0;}public int eval() {
return (4);//return Integer.parseInt(f0);
}}
Programa de clases para Exp
-
8/3/2019 CURSOProgSist
69/213
Gramtica con acciones semnticas para
-
8/3/2019 CURSOProgSist
70/213
Gramtica con acciones semnticas pararboles sintcticos
PARSER_BEGIN(InterSinTree)class InterSinTree {}
PARSER_END(InterSinTree)
TOKEN: {
|
|
}
SKIP: {|" "|"\t"|"\n"|"\r"
}
ExpCh4 Start():{ ExpCh4 e; }{ e=Exp()
{System.out.println(e.eval()); return e; }}
ExpCh4 Exp():{ ExpCh4 e1,e2; }{ e1=Term()
("+" e2=Term() { e1=new PlusExp(e1,e2);}|"-" e2=Term() { e1=new MinusExp(e1,e2);})*{ return e1;}
}ExpCh4 Term():
{ ExpCh4 e1,e2; }{ e1=Factor()
("*" e2=Factor() { e1=new TimesExp(e1,e2);}|"/" e2=Factor() { e1=new DivideExp(e1,e2);})*{ return e1;}
}
ExpCh4 Factor() :{ Token t; ExpCh4 e; }{ (t=
{return new Identifier(t.image); } |t=
{return new IntegerLiteral(t.image); } |"(" e=Exp() ")" {return e; })
}
-
8/3/2019 CURSOProgSist
71/213
VISITADORES
Es una tcnica de patrones (opuesta a la orientadaa objetos) que se puede usar para implementar elrbol sintctico del compilador o intrprete. Unvisitador es un objeto que contiene un mtodo visitpor cada clase de rbol sintctico. Cada clase derbol sintctico debe contener un mtodo accept.Cada mtodo accept sirve como enganche paracada diferente tipo de operacin sobre el rbol y es
llamado por un visitador donde tiene una tarea:pasar el control de ida y venida (back and forth)entre el visitador y las clases del rbol sintctico.
-
8/3/2019 CURSOProgSist
72/213
(cont.)
A continuacin veremos un ejemplo delintrprete de expresiones anterior pero ahoraimplementado con visitadores. Cada visitador
implementa la interfase Visitor. Cadamtodo accept toma un visitador comoargumento y cada mtodo visit toma un
objeto de un nodo del rbol sintctico comoargumento.
-
8/3/2019 CURSOProgSist
73/213
Sintxis Abstracta para MiniJava
En la siguiente figura (siguiente diapositiva) mostramos las clasesde la sintaxis abstracta para minijava. Solo los constructores sonmostrados en la figura. Cada una de las clases de listas seimplementa en la misma forma. Por ejemplo:
public class ExpList {
private Vector list;public ExpList() {
list=new vector();
}
Public void addElement (Exp n) {
list.addElement(n);
}
public Exp elementAt(int i) {
return (exp)list.elementAt(i);
}
public int size() {
return list.size();
}
}
-
8/3/2019 CURSOProgSist
74/213
Package syntaxtree;
Program(MainClass m, ClassDeclList cl)MainClass(Identifier i1, Identifier i2, Statement s)
Abstract class ClassDecl
ClassDeclSimple(Identifier i, VarDeclList vl, MethodDeclList ml)ClassDeclExtends(Identifier i, identifierj, VarDeclList vl, MethodDeclList ml)
VarDecl(Type t, Identifier i)
MethodDecl(Type t, Identifier i, FormalList fl, VarDeclList vl, StatementList,Exp e)Formal(Type t, Identifier i)
Abstract class Type
IntArrayType() BooleanType() IntegerType() IdentifierType(String s)
Abstract class StatementBlock(StatementList sl)If(Exp e, Statement s1, Statement s2)While(Exp e, Statement s)Print(Exp e)Assign(Identifier i, Exp e)ArrayAssign(Identifier i, Exp e1, Exp e2)
(cont figura)
-
8/3/2019 CURSOProgSist
75/213
(cont. figura)
Abstract class Exp
And(Exp e1, Exp e2)LessThan(Exp e1, Exp e2)Plus(Exp e1, Exp e2) Minus(Exp e1, Exp e2) Times(Exp e1, Exp e2)ArrayLoockup(Exp e1, Exp e2)ArrayLength(Exp e)Call(Exp e, Identifier i, ExpList el)IntegerLiteral(int i)
True()False()IdentifierExp(String s)This()NewArray(Exp e)NewObject(Identifier i)Not(Exp e)
Identifier(String s)
List classes
ClassDeclList() ExpList() FormalList() MethodDeclList()StatementList() VarDeclList()
-
8/3/2019 CURSOProgSist
76/213
Arbol Sintctico
Cada una de las clases que no son listastiene un mtodo acceptpara usarse con elpatrn visitador. La interface Visitador se
muestra en la siguiente diapositiva.
public interface Visitor {
-
8/3/2019 CURSOProgSist
77/213
public interface Visitor {public voidvisit(Program n);publicvoid visit(MainClass n);publicvoid visit(ClassDeclSimplen);publicvoid visit(ClassDeclextends n);public voidvisit(VarDecl n);publicvoid visit(MethodDecl n);public voidvisit(Formaln);
publicvoid visit(IntArrayType n);publicvoid visit(BooleanType n);publicvoid visit(IntegerType n);publicvoid visit(IdentifierType n);public voidvisit(Block n);public voidvisit(If n);public voidvisit(While n);public voidvisit(Print n);public voidvisit(Assignn);publicvoid visit(ArrayAssign n);public voidvisit(And n);
publicvoid visit(LessThan n);public voidvisit(Pluss n);public voidvisit(Minus n);public voidvisit(Times n);publicvoid visit(ArrayLoockup n);publicvoid visit(ArrayLengthn);public voidvisit(Call n);publicvoid visit(IntegerLiteral n);public voidvisit(True n);public voidvisit(False n);publicvoid visit(IdentifierExpn);
public voidvisit(This n);public voidvisit(NewArray n);public voidvisit(NewObjectn);public voidvisit(Not n);publicvoid visit(Identifier n);
}
VisitadorMiniJava
-
8/3/2019 CURSOProgSist
78/213
(cont. Arbol Sintctico)
Podemos construir un rbol sintctico usando expresiones newanidadas. Por ejemplo el rbol sintctico para el estatuto MiniJava:
x = y.m(1,4+5);
usara el siguiente cdigo:
ExpList el= new ExpList();
el.addElement(newIntegerLiteral(1));
el.addelement(new Plus(newIntegerLiteral(4),
newIntegerLiteral(5)));
Statement s = newAssign(newIdentifierx ),
new Call(new identifierExp(y ),newIdentifier(m),
el));
-
8/3/2019 CURSOProgSist
79/213
5.6 Administracin de la tabla de
-
8/3/2019 CURSOProgSist
80/213
smbolos
El anlisis semntico conecta las definiciones de lasvariables con sus usos, checa que cada expresintenga un tipo correcto y traduce la sintaxis abstractaa una representacin mas simple para generar
cdigo mquina. Esta fase es caracterizada por el mantener la tabla
de smbolos (tambin llamada environment) la cualmapea identificadores con sus tipos y localidades.
Cada variable local en un programa tiene un mbito
(scope) dentro del cual es visible. Por ejemplo, enun mtodo MiniJava m, todos los parmetrosformales y variables locales declarados en m sonvisibles solo hasta que finalice m.
-
8/3/2019 CURSOProgSist
81/213
-
8/3/2019 CURSOProgSist
82/213
Ejemplo:1 Class C {2 int a, int b; int c;3 public void m() {4 System.out.println(a+c);5 int j=a+b;
6 String a=hello;7 System.out.println(a);8 System.out.println(j);9 System.out.println(b);10 }11 }
Suponer que compilamos esta clase en el ambiente z0. Las declaraciones decampo en lnea 2 nos da la tabla z1 igual a z0+ {aint,bint,cint}. Losidentificadores en lnea 4 pueden encontrarse (look up) en ambiente z1. Enlnea 5, la tabla o ambiente z2=z1+{jint} es creada; y en lnea 6,z3=z2+{astring} es creada.
-
8/3/2019 CURSOProgSist
83/213
Implementacin de la Tabla
Existen dos opciones: El estilo funcionaldonde cuando z1 existe y z2es creado, z1sigue existiendo. Y el imperativo en donde z1
es destruido al crearse z2. Mientras z2existeno podemos mirarz1. Pero al morirz2, z1 denuevo existe.
Mlti l T bl d S b l
-
8/3/2019 CURSOProgSist
84/213
Mltiple Tablas de Smbolos
En algunos LP pueden existir variosambientes a la vez: Cada mdulo, o clase oregistro en el programa tiene una tabla desmbolos zpropia. Ejemplos (ML y Java).
Structure M = structstructure E= struct
val a= 5;endstructure N= struct
val b=10val a=E.a+b
endstructure D = struct
val d=E.a+N.aend
end
Package M;class E {
static int a=5;}Class N {
static int b=10;
static int a=E.a+b;}Class D {
static int d=E.a+N.a;}
-
8/3/2019 CURSOProgSist
85/213
(cont.)
Al anlizar los 2 programas anteriores, sea z0 elambiente base conteniendo funciones predefinidas,y seaz1={aint}z2={Ez1}z3={bint,aint}z4={Nz3}
z5={d
int}z6={Dz5}z7=z2+z4+z6
-
8/3/2019 CURSOProgSist
86/213
(cont.)
En ML, N es compilado usando el ambientez0+z2 para buscar los identificadores en latabla;D es compilado usando z0+z2+z4 y el
resultado del anlisis es {Mz7}. En Java, referencias adelantads son
permitidas (dentro de N la expresin D.d
sera legal), asi E,N y D son compilados en elambiente z7.
-
8/3/2019 CURSOProgSist
87/213
-
8/3/2019 CURSOProgSist
88/213
(cont.)
Considere z+{at2} cuando zya contieneat1. La funcin insertdeja at1 en elbucket y pone at2 antes en la lista.Entonces, cuandopop se realiza despus delambito de a, zes restaurado.
-
8/3/2019 CURSOProgSist
89/213
SIMBOLOS
Para evitar comparaciones innecesarias decadenas podemos convertir cada cadena aun smbolo, y as todas las diferentes
ocurrencias de cualquier cadena seconviertan a un mismo objeto smbolo. El mdulo smbolo implementa los smbolos
y tiene estas propiedades: Comparar smbolos por igualdad o por mayor es
rpido (comparacin por apuntador o por entero). Extraer una llave hash de tipo entero es rpido
-
8/3/2019 CURSOProgSist
90/213
(cont.)
Los ambientes son implementados en la clase Symbol.Tablecomo Tables mapeando Symbols a ligados (bindings).
Para eso se manejan ligaduras para diferentes propsitos en elcompilador ligadura para tipos, para variables, para funciones,etc.
Entonces, una ligadura es un Objeto. Para implementar la clase Symbol, usaremos el mtodo intern()
(java.lang.String), para darnos un objeto nico a partir de unacadena de caracteres.
Para el uso de la tabla de smbolos usaremosjava.util.Hashtable. La funcin beginScope recuerda el estadoactual de la tabla y endScope restaura la tabla a donde estabaen el mas reciente beginScope que no ha terminado.
-
8/3/2019 CURSOProgSist
91/213
(cont.)
Cuando la atadura xb es metido a la tabla (table.put(x,b)),xesdispersado a un ndice i, y un objeto binderxb es puesto en lacabeza de la lista ligada para el bucket i.
Si la tabla ya tiene una ligaduraxb, esto permanecera en elbucket, pero escondido porxb. Esto es importante ya quesoportara la implementacin de undo (beginScope y endScope).
Tambin deber existir una pila auxiliar, que muestre en queorden los smbolos son metidos (pushed) a la tabla de smbolos.Cuando xb es encontrado, entoncesxes metido a la pila(beginScope). Entonces, para implementar endScope, los
smbolos deben sacarse de la pila.
-
8/3/2019 CURSOProgSist
92/213
Chequeo de Tipos en MiniJava
Con que se llena una tabla de smbolos? Esto es,Qu es la ligadura o binding?
Para realizar el chequeo de tipos de programasMiniJava, la tabla de smbolos debe contener todala informacin declarada: Cada nombre de variable y nombre de parmetro formal
debe ser ligado a su tipo. Cada nombre de mtodo debe ser ligado a sus
parmetros, tipo de resultado y variables locales. Cada nombre de clase debe ser ligado a su variable ydeclaraciones de mtodos.
Liga a pgina con mas informacin.
-
8/3/2019 CURSOProgSist
93/213
-
8/3/2019 CURSOProgSist
94/213
(cont.)
Los tipos primitivos en MiniJava son int y boolean;todos los otros tipos son arreglo de enteros onombres de clases.
Por simplicidad todos los tipos son string, en lugar
de smbolos; esto nos permite checar igualdad detipos por medio de comparacin de strings. El chequeo de tipos de un programa MiniJava
ocurre en dos fases. Primero, construimos la tablade smbolos y despus checamos los tipos de los
estatutos y las expresiones. Lo hacemos en dosfases porque en MiniJava (igual que en Java) lasclases son mutuamente recursivas.
-
8/3/2019 CURSOProgSist
95/213
(cont.)
La primera fase de el checador de tipos se puedeimplementarse por medio de un visitador que visitelos nodos del rbol sintctico de MiniJava yconstruya la tabla de smbolos.
Por ejemplo el mtodo visitador en el siguienteprograma maneja declaraciones de variables. Esteagrega el nombre de la variable y el tipo a laestructura de datos para la clase actual que mas
tarde ser agregada a la tabla de smbolos. El mtodo visitador checa si la variable ya fue
declarada anteriormente.
-
8/3/2019 CURSOProgSist
96/213
Mtodo Visitador
Class ErrorMsg {boolean anyErrors;void complain (String msg) {anyErrors = true;System.out.println(msg);
}
}// Type t;// Identifier i;Public void visit(VarDecl n) {Type t = n.t.accept(this);String id= n.i.toString();
if (currMethod ==null) {if (!currClass.addVar(id,t))
error.complain(id + is already defined in + currClass.getId());} else if (!currentMethod.addVar(id,t))
error.Complain(id + is already defined in + currClass.getId( ) + . + currMethod.getId( ));
-
8/3/2019 CURSOProgSist
97/213
(cont.)
La segunda fase del checador de tipos puede ser implementadapor un visitador que cheque tipos de todas los estatutos yexpresiones.
El tipo del resultado de cada mtodo visitador es String, querepresenta los tipos de MiniJava.
La idea es que cuando el visitador visita una expresin, entoncesretorna el tipo de esa expresin.
El siguiente mtodo (siguiente diapositiva) es el visitador queimplementa la adicin (plus) e1 + e2. En MiniJava ambosoperandos deben ser de tipo entero (el checador revisa esto) y el
resultado debe ser entero (el checador retorna este tipo).
Mtodo Visitador para
-
8/3/2019 CURSOProgSist
98/213
Mtodo Visitador paraexpresiones Plus
// Exp e1, e2;Public Type visit(Plus n) {
if (! (n.e1.accept(this) instanceOf IntegerType) )error.complain(Left side of LessThan must be of type integer);
if (! (n.e2.accept(this) instanceOf IntegerType) )error.complain(Right side of LessThan must be of type integer);
return new IntegerType( );}
5 7 Manejo de errores semnticos
-
8/3/2019 CURSOProgSist
99/213
5.7 Manejo de errores semnticos.
Cuando el checador de tipos detecta un error detipos o un identificador no declarado, debe imprimirel mensaje de error y continuar.
Esto debido a que normalmente el programador
prefiere que le describan todos los errores posiblesdel programa fuente. Esto quiere decir, que si un error de tipos es
encontrado, no debe producirse un programa objetopor parte del compilador.
As, las siguientes fases no deben ejecutarse. Hasta esta etapa (chequeo de tipos), la parte del
compilador se conoce con el nombre de front End.
-
8/3/2019 CURSOProgSist
100/213
REGISTROS DE ACTIVACION
En casi cualquier LP, una funcin (mtodo)puede tener variables locales que soncreadas cuando se llama la funcin (al entrar
a esta). Diferentes invocaciones a la funcin pueden
existir a la vez, y cada invocacin tiene su
propia instanciacin de variables.
(cont )
-
8/3/2019 CURSOProgSist
101/213
(cont.)
En el siguiente mtodo de JavaInt f(int x) {
int y=x+x;if (y
-
8/3/2019 CURSOProgSist
102/213
-
8/3/2019 CURSOProgSist
103/213
MARCOS DE PILA
Debido a que se trabaja con bloques de datos porfuncin un push y pop no funciona.
Entonces la pila es tratada como si fuera un granarreglo, con un registro especial- el stack pointer
que apunta a una localidad. Todas las localidades despus del apuntador son
basura y todas las que estn antes estnasignadas.
El rea en la pila dedicada a las variables locales,
parmetros, direccin de retorno y otras variablestemporales para una funcin es llamada el registrode activacin o marco de pila de la funcin.
-
8/3/2019 CURSOProgSist
104/213
(cont.)
El diseo de la estructura de los marcos esde acuerdo con la arquitectura y el LP que secompila.
Aunque normalmente el constructor de laarquitectura define un diseo de marcostandard para todos los compiladores para
esa arquitectura.
Ejemplo: Un marco de pila
-
8/3/2019 CURSOProgSist
105/213
Argumentosde entrada
ApuntadorDel marco
ArgumentosDe salida
ApuntadorDe pila
Argumento nArgumento 1Liga esttica
Argumento mArgumento 1Liga esttica
Variables
locales
Direccin retorno
Temporales
Registros salvados
Marcoactual
Marco anterior
Marco siguiente
Direcciones de Memoriamas altas
Marco de Pila
-
8/3/2019 CURSOProgSist
106/213
Marco de Pila
Los argumentos de entrada son los pasados por elllamador (tcnicamente son parte del marco anteriorpero pueden accesarse usando un desplazamientodel apuntador de marco).
Cuando la funcin actual llama otras funciones,puede usar el espacio de los argumentos de salidapara pasar parmetros.
La direccin de retorno es creada por la instruccinCALL.
Las variables locales tambin tienen su espacio. Las variables mantenidas en registros algunas
veces son salvadas a memoria.
-
8/3/2019 CURSOProgSist
107/213
El Apuntador de Marco (FP)
Suponer que una funcin g() llama la funcin f(a1,an).Diremos que ges el llamador (caller) y fel llamado (callee). Alentrar a f, el apuntador de la pila (SP) apunta al primerargumento que g pasa a f. Al entrar, fcoloca un marco solo conrestar el tamao del marco de el SP.
El viejo SP se convierte en el actual FP y el viejo FP es salvadoen el marco.
Cuando FP termina, solo copia FP de regreso a SP y regresa elvalor viejo salvado de FP.
Si los marcos son siempre del mismo tamao entonces no es
necesario contar con FP y todo se simplifica sumando orestando la constante framesize a SP.
-
8/3/2019 CURSOProgSist
108/213
Registros
Por eficiencia, es importante mantener las variableslocales, resultados intermedios y otros valores enregistros en lugar de la pila de marcos.
Si funcin fllama a gy ambas hacen uso de registror, entonces rdebe ser salvado (dentro de la pila demarcos) antes de que lo use gy restaurado (desdela pila) despus de que termine g.
de quien es responsabilidad de salvarr? de fog? si lo salva f se dice que r es un registro caller-save; si lo salva g se llama callee-save.
-
8/3/2019 CURSOProgSist
109/213
Pase de Parmetros
Estudios actuales han mostrado queraramente una funcin pasa mas de 4parmetros.
Debido a esto, la mayora de las mquinasdefinen que los primeros k argumentos (conk=4) se pasan en registros y el resto en
memoria.
-
8/3/2019 CURSOProgSist
110/213
Direcciones de Retorno
Si gllama a f, entonces si la instruccin calldentro de gest en direccin a, el lugar deretorno en ges a+1, la siguiente instruccin
del call. En mquinas modernas la direccin de
retorno es pasada a un registro en lugar de la
memoria. En funciones hoja la direccin no necesita
ponerse en la pila.
-
8/3/2019 CURSOProgSist
111/213
Registros vs. Memoria
Registros siempre deben usarse en asignacin amenos que: La variable sea pasada por referencia
La variable es accesada por una funcin anidada dentrode la funcin actual.
El valor es demasiado grande para un registro.
La variable es un arreglo, donde es necesario realizararitmtica de direcciones.
El registro que contiene la variable es necesitado paraotros propsitos.
Existen demasiadas variables locales y valores temporales
-
8/3/2019 CURSOProgSist
112/213
Ligas Estticas (Static Links)
En LP que admiten funciones anidadas (Pascal,MLy Java) las funciones de mas adentro pueden usarvariables declaradas en funciones de mas afuera
(Estructuras de Bloque). En el siguiente programa (sig. Diapositiva) la
funcin write hace referencia a la variable de afueraoutpute indenthace referencia a n y output. Para
cumplir con esto, indentdebe tener acceso no soloa su propio marco (para iy s) sino tambin a losmarcos de show(porn) yprettyprint(poroutput).
Programa de funciones Anidadas
-
8/3/2019 CURSOProgSist
113/213
og a a de u c o es dadas
Type tree= {key: string, left: tree, right: tree}
Function prettyprint(tree:tree): string=let
var output :=
function write(s:string) =output :=concat(output,s)
function show(n:int, t:tree) =let function indent(s:string)=
(for i:= 1 to ndo write( );output:=concat(output,s);write( );
in if t=nil then indent(.)else (indent(t.key);
show(n+1,t.left);show(n+1,t.right))end
in show(0,tree); outputend
-
8/3/2019 CURSOProgSist
114/213
-
8/3/2019 CURSOProgSist
115/213
(cont.) Lnea 21:prettyprintllama show, pasando el apuntador del marco del propio
prettyprintcomo una liga esttica de show. Lnea 10: showguarda su liga esttica (la direccin del marco deprettyprint)
dentro de su propio marco. Lnea 15: showllama indent, pasando su propio apuntador de marco como liga
esttica de indent.
Lnea 17: showllama a show,pasando su propia liga esttica (no su propioapuntador de marco) como la liga esttica. Lnea 12: indentusa el valorn del marco de show. Para hacer esto, trae un
desplazamiento apropiado de la liga esttica de indent(que apunta al marco deshow).
Lnea 13: indentllama a write. Debe pasar el apuntador de marco deprettyprintercomo la liga esttica. Para obtener esto, primero trae undesplazamiento de su propia liga esttica (desde el marco de show), la liga
esttica que haba sido pasada a show. Lea 14: indentusa la variable outputdel marco deprettyprint. Para hacer esto,
comienza con su propia liga esttica, entonces trae a show, y luego trae aoutput.
-
8/3/2019 CURSOProgSist
116/213
Unidad VI
Generacin de CdigoIntermedio
6 1 Lenguajes intermedios
-
8/3/2019 CURSOProgSist
117/213
6.1 Lenguajes intermedios.
El cdigo intermedio en una estructura de cdigocuya complejidad est entre un cdigo fuente en unlenguaje de alto nivel y el cdigo mquina.
Cdigo fuente Cdigo intermedio Cdigo Objeto
Un compilador produce primero un cdigointermedio, pues producir directamente el cdigo
objeto resulta sumamente complicado e ineficiente.
-
8/3/2019 CURSOProgSist
118/213
(cont.)
Ventajas de producir cdigo intermedio: Ms fcil de producir cdigo objeto despus,
si se parte de un cdigo intermedio. Facilita y hace eficiente la optimizacin de
cdigo (algunos tipos de optimizacin). El cdigo intermedio es transportable (puede
usarse en diferentes arquitecturas) ya que nohace referencia a componentes de lamquina.
6 2 Notaciones
-
8/3/2019 CURSOProgSist
119/213
6.2 Notaciones.
Infija. Es la notacin habitual. El orden es primeroperando, operador, segundo operando.
Ejemplo: a/b/c
La notacin infija tiene el problema de que enexpresiones con ms de un operador existeambiguedad sobre cual es el orden de evaluacin.Por ejemplo, la expresin 8/4/2 se puede interpretar
como (8/4)/2 o bien como 8/(4/2). Las otrasnotaciones (prefija y postfija) no sufren esteproblema.
-
8/3/2019 CURSOProgSist
120/213
(cont.) Postfija. El orden es primer operando, segundo operando, operador.
Ejemplo: La expresin X+Y-X*Yen notacin Postfija es XY+XY*-
Por lo general la notacin postfija se emplea en mquinas de pilas ya que la pila facilita laejecucin. Al analizar una notacin postfija de izquierda a derecha, cada vez que se detecta unoperando se mete a la pila. La ocurrencia de un operador con m' operandos significa que elensimo operando estar m-n posiciones por debajo del tope de la pila. Despus se sacan losoperandos de la pila y se mete el resultado de la operacin.
Por ejemplo, suponer que X=1 y Y=2.
Las operaciones seran:push 1 (meter 1)push 2' + ' requiere de 2 operandos, se sacan, se suman y se mete el resultado (3)push 1push 2
' * ' se mete el resultado(2)' - ' se mete el resultado (1)
Notacin prefija: El orden es operador, primer operando, segundo operando.
6.3 Representacin de cdigointermedio
-
8/3/2019 CURSOProgSist
121/213
intermedio.
Existen muchas clases de representaciones
intermedias. Algunas de las mas comunesson: Notacin polaca.
Cdigo P (Pascal).
Triples y Cuadruples.
Bytecodes (Java) MSIL (C#)
-
8/3/2019 CURSOProgSist
122/213
Notacin Polaca
Tambin conocida como notacin postfija. Seutiliza como se dijo anteriormente enmquinas de Pila.
Ejemplos:Pascal Notacin Polaca
a+b-c ab+c-
a+b*c abc*+a+b*c+d abc*+d+
-
8/3/2019 CURSOProgSist
123/213
Cdigo P
Se us como cdigo intermedio y objeto en lasprimeras implementaciones de Pascal.
El cdigo P era interpretado en una mquina
abstracta. Algunas implementaciones de Basic y Pascal usan
cdigo P el cual despus es traducido a cdigonativo por un compilador Just-in-Time.
La mquina P est orientada a usarse en una pila(stack-oriented).
-
8/3/2019 CURSOProgSist
124/213
Ejemplo:
Insn. Stack Stack Description
before after adi i1 i2 i1+i2 add two integers
Adr r1 r2 r1+r2 add two reals
dvi i1 i2 i1/i2 integer division
ldci i1 i1 load integer constant
mov a1 a2 movenot b1 ~b1 boolean negation
Triples y Cuadruplos
-
8/3/2019 CURSOProgSist
125/213
(Cdigo de 3 Direcciones)
Ha sido uno de los mas populares. Susinstrucciones constan de 3 direcciones o registrospara 2 argumentos u operandos y el resultado.
Su formato es:resultado:= argumento1 operador argumento2
Donde resultado, argumento1 y argumento2 puedenser constantes, identificadores y variables
temporales definidos por el compilador mientras queoperador representa una operacin arbitraria. Estaforma se denomina Cudruplo.
(cont.)
-
8/3/2019 CURSOProgSist
126/213
( )
EJEMPLO: Z:= X + Y X * Y
ADD X Y V AR1
MUL X Y V AR2
SUB V AR1 VAR2 VAR3
STORE VAR3 Z
(cont.)
-
8/3/2019 CURSOProgSist
127/213
(cont.)
EJEMPLO: (Estructure de Control):
If (a==b)
a=0;
else
a=1; En cuadruplos tendramos:
1 - A B t1
2 JnZ t1 5
3 = 0 A
4 JP 6
5 = 1 A
6
(cont.)
-
8/3/2019 CURSOProgSist
128/213
( )
En el cdigo de 2 direcciones se evita el uso sevariables temporales. El formato es:Operador argumento1 argumento2EJEMPLO: Z = X + Y - X * Y
1. ADD X Y
2. MUL X Y
3. SUB (1) (2)
4. STORE (3) ( Z)
Donde los nmeros entre parntesis representanapuntadores a la secuencia de operaciones de 2 direcciones.
Java Bytecodes
-
8/3/2019 CURSOProgSist
129/213
Java Bytecodes
El bytecode es un cdigo intermedio ms abstracto que el cdigomquina. Habitualmente viene a ser un archivo binario quecontiene un programa ejecutable similar a un mdulo objeto ocdigo mquina producido por el compilador.
El bytecode recibe su nombre porque generalmente cada cdigo
de operacin tiene una longitud de un byte, si bien la longitud delcdigo de las instrucciones vara.
Cada instruccin tiene un cdigo de operacin entre 0 y 255seguido de parmetros tales como los registros o las direccionesde memoria. Esta sera la descripcin de un caso tpico, si bien
la especificacin del bytecode depende ampliamente dellenguaje.
(cont.)
-
8/3/2019 CURSOProgSist
130/213
( )
Como cdigo intermedio, se trata de una forma de salidautilizada por los implementadores de lenguajes para reducir ladependencia respecto del hardware especfico y facilitar lainterpretacin.
Menos frecuentemente se utiliza el bytecode como cdigo
intermedio en un compilador. Algunos sistemas, llamadostraductores dinmicos o compiladores just-in-time (JIT) traducenel bytecode a cdigo mquina inmediatamente antes de suejecucin para mejorar la velocidad de ejecucin.
Los programas en bytecode suelen ser interpretados por un
intrprete de bytecode (en general llamado mquina virtual, dadoque es anlogo a un ordenador).
(cont.)
-
8/3/2019 CURSOProgSist
131/213
( )
Su ventaja es su portabilidad: el mismo cdigo binario puede serejecutado en diferentes plataformas y arquitecturas. Es la mismaventaja que presentan los lenguajes interpretados.
Sin embargo, como el bytecode es en general menos abstracto,ms compacto y ms orientado a la mquina que un programapensado para su modificacin por humanos, su rendimientosuele ser mejor que el de los lenguajes interpretados.
A causa de esa mejora en el rendimiento, muchos lenguajesinterpretados, de hecho, se compilan para convertirlos enbytecode y despus son ejecutados por un intrprete debytecode.
Entre esos lenguajes se encuentran Perl, PHP y Python. Elcdigo Java se suele trasmitir como bytecode a la mquinareceptora, que utiliza un compiladorjust-in-time para traducir elbytecode en cdigo mquina antes de su ejecucin.
La Mquina Virtual de Java(JVM)
-
8/3/2019 CURSOProgSist
132/213
(JVM)
La siguiente liga nos lleva a la informacin delo que es la JVM y mas sobre Javabytecodes.
b l d E bl d
-
8/3/2019 CURSOProgSist
133/213
rboles de Ensamblador
Un paso antes de generarEnsamblador Real
Permite mas fcil optimizacin de cdigo
Primero vamos a estudiar la implementacinde asignacin de memoria en el cdigogenerado (stack y heap).
-
8/3/2019 CURSOProgSist
134/213
Por ejemplo, la funcin:
-
8/3/2019 CURSOProgSist
135/213
Int foo() {
int a;
intb;
/* body of foo */
}
a
b
Registros
salvados
FP
SP
Tendra el registro de activacin
Existen dos apuntadores. FP queapunta al inicio del RA actual y SP queapunta a la primera localidad vaca. Elvalor retornado de una funcin espuesto en un registro especial en lugar
de la pila. Cuando una funcin esllamada los valores de los parmetrosde entrada son puestos en la pila, ycuando la funcin retorna un valor, elvalor es almacenado en el registro deresultado.
(cont.)
-
8/3/2019 CURSOProgSist
136/213
Como el FP siempre apunta al comienzo delRA actual, podemos acceder a las variableslocales usando un offsetdesde el FP.
Los parmetros de funciones son
almacenados en RA de la funcin que llama,no la que es llamada. Los parmetros deentrada a una funcin pueden ser accesadospor medio del FP, usando un offset en ladireccin opuesta a las variables locales. Elformato completo de un RA es mostrado enla siguiente diapositiva.
Formato completo de RA
-
8/3/2019 CURSOProgSist
137/213
Input Parameter n
Input Parameter 2
Input Parameter 1
Local Variables
Saved Registers
FP
SP
Previous Activation Record
Current Activation Record
Considere el siguiente programa:
-
8/3/2019 CURSOProgSist
138/213
g gvoid foo(int a, intb);
void foo(int c, int d);
void main() {
int u;
int v;
/* LabelA */
bar(1,2);
}
voidbar(int a, intb) {
int w;
int x;
foo(3,4);
}
void foo(int c, int d) {
int y;
int z;
/* Label B */
}
En label A de el programa, la pila de RA se mirara de laforma siguiente
-
8/3/2019 CURSOProgSist
139/213
g
u
v
Saved Registers
FP
SP
ActivationRecord formain
La variable local upuede accesarse examinando la localidad dememoria apuntada por FP. La variable vpuede accesarseexaminando (FP-wordsize). Algo para aclarar es que la pilacrece de direcciones altas a bajas.
En etiqueta B los RA semiraran as: u
-
8/3/2019 CURSOProgSist
140/213
v
Saved Registers
b
a
w
x
Saved Registers
d
c
y
z
Saved Registers
FP
SP
Activation Record
for main
Activation Recordfor bar
Activation Recordfor foo
(cont )
-
8/3/2019 CURSOProgSist
141/213
(cont.)
La variable yen funcin foo puede accesarse alexaminar la localidad de memoria apuntada porFP.La variable z en foo puede accesarse examinandola localidad (FP-wordsize). El parmetro de entradac en funcin foo puede accesarse examinando lalocalidad (FP+wordsize), mientras que el parmetrod puede accesarse con (FP+2*wordsize).
Algo importante es que la funcin llamadora esresponsable de poner los parmetros actuales y dequitarlos cuando acabe la funcin llamada.
Ensamblador Abstracto
-
8/3/2019 CURSOProgSist
142/213
El ensamblador abstracto es dividido en rboles deestatutos y rboles de expresiones. rboles deestatutos no tienen valores pero los de expresionessi lo tienen.
Existen cinco diferentes tipos de rboles deexpresiones: Constante. Consiste de un valor de la constante (solo
enteros). Registro. Una cadena que especifica el registro. Operador. Dos rboles de expresin para los operandos, y
el operador: +,-,*,/,,=,=,&&,||,!.
(cont.)
-
8/3/2019 CURSOProgSist
143/213
CallExpression. Contiene una etiqueta de lenguaje ensamblador y
un rbol de expresin por cada uno de los parmetros en la llamadade la funcin (function call). La etiqueta es la direccin del inicio dela funcin llamada. Por ejemplo la funcin foo(3,4,5) serepresentara por el rbol de expresin:
CallExpresion(foo)
Constant(4)Constant(3) Constant(5)
El ensamblador abstracto en este caso no contiene instruccionesexplcitas para asignar los parmetros actuales a la pila. Cuandose tradusca el ensamblador abstracto de una callExpression aensamblador real, se incluye el cdigo para hacer la copia de losparmetros actuales a la pila.
Memoria. Solo se denota la direccin de memoria.
-
8/3/2019 CURSOProgSist
144/213
Ejemplo:Memory
Constant(1006)
Casi nunca se manejan direcciones absolutas sino que estas sonrelativas al FP. Por ejemplo para referirse a la localidad de memoria deuna variable local con un desplazamiento (oofset) de 4 del FP esrepresentado con el rbol:
Memory
Operator(-)
Register(FP) Constant(4)
Existen 8 tipos de rboles de estatutos:
-
8/3/2019 CURSOProgSist
145/213
Move. Tienen dos subrboles elsubrbol izquierdo es el destino delmove, y el derecho es el valor a mover. El izquierdo necesita ser un rbol de
expresin de registro (mover un dato a un registro) o un rbol de expresinde memoria (mover un dato a memoria). La parte derecha puede ser unaexpresin arbitraria.
Label (Etiqueta). Se usan como destinos de jumps y calls. Jump. Saltos incondicionales contienen una etiqueta. Conditional Jump. Contienen un subrbol de expresin y una etiqueta de
lenguaje ensamblador. Si la expresin es verdadera se hace unatransferencia de control a una etiqueta. Si es falsa, entonces habr un no-
op. Sequential. Tiene dos subrboles. Representa la ejecucin del izquierdo
seguido del derecho. CallStatement. Contienen una rbol de etiqueta, y un rbol expresin de
cada uno de los parmetros actuales. Calls representan void functioncalls.
Empty. Son no-ops y son removidos cuando se traduce a ensamblador
real. Return. No retorna un valor (como Java). Solo cambia el flujo de control. Un
return de Java se implementa incluyendo cdigo que retorne el valor de lafuncin (en el registro resultado) adems del ensamblador abstracto delreturn.
Ejemplos: (asumiremos que wordsize=4 y que un entero seguarda en una palabra)
-
8/3/2019 CURSOProgSist
146/213
void foo(int a, int b) {
int x;
int y;
boolean z;
x= 1;
y = a * b;y++;
bar(y, x + 1, a);
x= function(y+1, 3);
if (x > 2)
z = true;else
z = false;
}
X=1;
-
8/3/2019 CURSOProgSist
147/213
Move
Memory Constant(1)
Register(FP)
-
8/3/2019 CURSOProgSist
148/213
Y++;
-
8/3/2019 CURSOProgSist
149/213
Move
Memory
Operator (-)
Constant(4)
Operator(+)
Memory Constant(1)
Operator (-)
Register(FP) Constant(4)
Register(FP)
bar(y,x+1,a);
-
8/3/2019 CURSOProgSist
150/213
CallStatement(bar)
Memory
Operator (-)
Constant(4)Register(FP)
Operator (+)
Memory Constant(1)
Register(FP)
Memory
Operator (+)
Constant(4)Register(FP)
x=function(y+1,3);
-
8/3/2019 CURSOProgSist
151/213
Move
Memory
Register(FP)
Callexpression(function)
Constant(3)
Constant(1)
Operator(+)
Memory
Operator(-)
Register(FP) Constant(4)
if (x > 2) z = true; else z = false;
S ti l
-
8/3/2019 CURSOProgSist
152/213
Sequential
ConditionalJump(iftrue)
Operator(>)
Memory Constant(2)
Sequential
Sequential
Sequential
Sequential
Label(ifend)
Jump(ifend)
Label(iftrue)
Move
Move
Constant(0)Memory
Operator(-)
Register(FP) Constant(8)
Constant(1)Memory
Operator(-)
Register(FP) Constant(8)
Register(FP)
Creacin de Ensamblador Abstracto
-
8/3/2019 CURSOProgSist
153/213
Variables Variables base
La variablexy yse representaran con losrboles:
void foo() {
int x;
int y;
/* Body of foo */
}
Memory
Register(FP)
Memory
Operator(-)
Register(FP) Constant(4)
Variables Arreglo: Son almacenadas en el
-
8/3/2019 CURSOProgSist
154/213
heap, y usando un apuntador a la base del
arreglo el cual se almacena en la pila.La siguiente funcin o mtodo
void foo arrayallocation() {
int x;
int A[];
int B[];
A = new int [5];
B = new int [5];
/* Body of function */
}
La variable local x es almacenada en la pila,igual que la direccin base del arreglo A y delarreglo B
-
8/3/2019 CURSOProgSist
155/213
arreglo B.
Saved Registers
Stack Heapx
AB
FP
SP
A[0]
A[1]
A[2]
A[3]
A[4]
B[0]
B[1]
B[2]
B[3]B[4]
Cmo debemos representarel arreglo A[3]
-
8/3/2019 CURSOProgSist
156/213
el arreglo A[3]
Register(FP)
Memory
Operator(-)
Memory Operator(*)
Operator(-)
Constant(WORDSIZE)
Constant(WORDSIZE) Constant(3)
Y A[x] ?
-
8/3/2019 CURSOProgSist
157/213
Memory
Operator(-)
Memory Operator(*)
Operator(-)
Register(FP) Constant(WORDSIZE)
Constant(WORDSIZE) Memory
Register(FP)
Y para A[B[2]] ?
M
-
8/3/2019 CURSOProgSist
158/213
Memory
Operator(-)
Memory Operator(*)
Operator(-)
Register(FP) Constant(WORDSIZE)
Constant(WORDSIZE) Memory
Operator(-)
Memory
Operator(-)
Register(FP) Constant(2*WORDSIZE)
Operator(*)
Constant(WORDSIZE)Constant(2)
Arreglos Multidimensionales se manejan demanera similar.Ejemplo:
-
8/3/2019 CURSOProgSist
159/213
Ejemplo:
void twoDarray {
int i;
int c [ ] [ ] ;
C = new int [3] [ ] ;
for (i=0; i
-
8/3/2019 CURSOProgSist
160/213
La variable C sera representada as:
-
8/3/2019 CURSOProgSist
161/213
Memory
Operator(-)
Register(FP) Constant(WORDSIZE)
La variable C[2] as:
-
8/3/2019 CURSOProgSist
162/213
Memory
Operator(-)
Memory Operator(*)
Operator(-)
Register(FP) Constant(WORDSIZE)
Constant(WORDSIZE) Constant(2)
La variable c[2] [1]
-
8/3/2019 CURSOProgSist
163/213
Memory
Operator(-)
Memory Operator(*)
Operator(-)
Memory Operator(*)
Constant(WORDSIZE) Constant(1)
Operator(-)
Register(FP) Constant(WORDSIZE)
Constant(2)Constant(WORDSIZE)
-
8/3/2019 CURSOProgSist
164/213
Cul es el rbol de ensambladorpara s.y ?
-
8/3/2019 CURSOProgSist
165/213
Memory
Register(FP)
l rbol de s:
Para obteneryde s:
Memory
Memory
Operator(-)
Constant(WORDSIZE)
Register(FP)
El rbol de la variable s.x: Memory
Memory
-
8/3/2019 CURSOProgSist
166/213
Memory
Register(FP)
El rbol para .A[3]: Memory
Operator(-)
Memory Operator(*)
Operator(-)
Memory Constant(2*WORDSIZE)
Constant(WORDSIZE)
Constant(3)
Register(FP)
Estatutos
Estatutos de Asignacin
-
8/3/2019 CURSOProgSist
167/213
Estatutos de Asignacin
=
es representada por el rbol de ensamblador:
Move
-
8/3/2019 CURSOProgSist
168/213
Ejemplo:
Void main() {
int x;
int y;
y =x + 4;
}
Move
Memory Operator(+)
Operator(-)
Constant(4)
Memory
Register(FP)Register(FP)
Constant(4)
Estatuto If
-
8/3/2019 CURSOProgSist
169/213
if () else
se puede traducir en
If () goto IFTRUE
goto IFENDIFTRUE:
IFEND:
-
8/3/2019 CURSOProgSist
170/213
Estatutowhile:while ()
-
8/3/2019 CURSOProgSist
171/213
( )
se puede traducir en
WHILESTART:
if (not ) goto WHILEEND
gotoW
HILESTARTWHILEEND:
aunque es mas eficiente
goto WHILETEST
WHILESTART:
WHILETEST:
if () goto WHILESTART
WHILEEND:
Estatuto for:
for (;;)
-
8/3/2019 CURSOProgSist
172/213
for (;;)
es equivalent a:
while () {
}
Entonces queda como:
goto FORTESTFORSTART:
FORTEST:
-
8/3/2019 CURSOProgSist
173/213
Definiciones de Funcin o Mtodos:
El ensamblador abstracto debe:
-
8/3/2019 CURSOProgSist
174/213
El ensamblador abstracto debe: Guardar el viejo SP, FP y registros de direccin de retorno en la pila.
Apuntar el FP al inicio del RA actual.Apuntar el SP al final del RA actual. Incluir el ensamblador para el cuerpo de la funcin. Restaurar el viejo SP, FP y registros de direccin de retorno (el FP al ltimo si seusa para referenciar los datos en la pila). Retornar del mtodo, con una instruccin de ensamblador abstracto return. Incluir etiquetas despus del cuerpo para instrucciones return desde adentro delcuerpo
El cdigo ensamblador queda as:
Creacin de rboles de EnsambladorAbstracto (AAT) en Java
-
8/3/2019 CURSOProgSist
175/213
( )
Para construir AAT en Java, primerodefinimos una interfase para construir AATspara estatutos y para expresiones.
Entonces, se agregan en el anlisissemntico llamadas a las funciones definidasen la interfase.
De esta forma, el analizador semnticoconstruir los AATs al igual que checar porlos errores semnticos.
-
8/3/2019 CURSOProgSist
176/213
-
8/3/2019 CURSOProgSist
177/213
-
8/3/2019 CURSOProgSist
178/213
Igual, el ensamblador abstracto para el estatuto b = 2; y c= a + 1, puede crearse con:
-
8/3/2019 CURSOProgSist
179/213
AATEstatement s1, s2;
s1 = bt.assignmentStatemen(bt.baseVariable(0), bt.constantExpression(2));
s2 = bt.assignment(bt.BaseVariable(-4), bt.operatorExpression(bt.baseVariable(4), bt.constantExpression(1),
AATOperator.PLUS));
Finalmente, dadas las definiciones anteriores, el ensamblador abstracto para el estatutoif (a > 2) b = 2 else c= a + 1; puede crearse con:
AATstatement s3;
s3 = bt.ifStatement(e1,s1,s2);
-
8/3/2019 CURSOProgSist
180/213
-
8/3/2019 CURSOProgSist
181/213
-
8/3/2019 CURSOProgSist
182/213
-
8/3/2019 CURSOProgSist
183/213
VIII Generacin de Cdigo
-
8/3/2019 CURSOProgSist
184/213
La funcin de un generador de cdigo esbsicamente la traduccin de la salida del anlisissintctico y semantico (el cdigo intermedio) a unasecuencia equivalente de instrucciones que puedenejecutarse en la maquina destino.
El cdigo debe ser correcto y optimo. El generador de cdigo toma las desiciones
bsicas: Asignar Registros.- Registros generales, Prop. Especficos,
pares, impares, registros ndices, etc. Seleccin de Instrucciones.- La mejor secuencia de
instrucciones (la optima). Por ejemplo elegir INC en lugarde MOV ADD.
En el caso de nuestro compilador una vez que se ha creado un
-
8/3/2019 CURSOProgSist
185/213
En el caso de nuestro compilador, una vez que se ha creado un
rbol de ensamblador, el prximo paso es crear cdigoensamblador para una mquina especfica.
Generaremos cdigo ensamblador por medio de usar tiles pararellenar huecos, con el rbol de ensamblador abstracto.
Vamos a crear un conjunto de tiles o rellenos cada uno de loscuales pueden cubrir una porcin pequea de un rbol deensamblador abstracto.
Para generar el ensamblador real para un rbol de ensamblador
especfico, primero cubriremos el rbol con tiles, asegurndoseque todas las partes del rbol estn cubiertas y que no existantiles traslapados. Despus, se producir el ensambladorasociado con cada tile.
Cdigo Ensamblador ObjetoUsaremos un subconjunto del ensamblador para MIPS
Instruction Description
-
8/3/2019 CURSOProgSist
186/213
lw rt, (base) Add the constant value to the register base to get an address. Load the contents of this address into theregister rt. Rt = M[base + ]
sw rt, (base) Add the constant value to the register base to get an address. Store the contents of rt into this address.M[base + ] = rt
add rd, rs, rt Add contents of register rs and rt, put result in register rd.
sub rd, rs, rt Subtract contents of register rt from rs, put result in register rd.
addi rt, rs, Add the constant value to register rs, put result in register rt.
mult rs, rt Multiply contents of register rs by register rt, put the low order bits in register LO and the high bits in register HI
div rs, rt Dive contents of register rs by register rt, put the quotient in register LO and the remainder in register HI
mflo rd Move contents of the special register LOW into the register rd.
j Jump to the assembly label .
jal jump and link. Put the address of the next instruction in the return register, and then jump to the address .Used for function and procedure calls.
jr rs Jump to the address stored in register rs. Used in conjunction withjal to return from function and procedure calls
slt rd, rs, rt if rs < rt, rd = 1, else rd = 0
beq rs, rt, if rs == rt, jump to the label
bne rs, rt, if rs rt,jump to the label
bltz rs, if rs < 0,jump to the label
Bgez rs, if rs 0, jump to the label
Register that we will use for code generation
-
8/3/2019 CURSOProgSist
187/213
MnemonicName
SPIMName
Description
$FP $fp Frame pointer points to the top of the current activation record
$SP $sp Stack Pointer Used for the activation record stack
$ESP $esp Expression Stack Pointer The next expression stack holds temporary values forexpression avaluations
$result $v0 Result Register Holds the return value for functions
$return $ra Result Register Holds the return address for the current function
$zero $zero Zero register This register always has the value 0
$ACC $t0 Accumulator Register Used for expressioncalculation
$t1 $t1 General Purpose Register
$t2 $t2 General Purpose Register
$t3 $t3 General Purpose Register
TilingSimple
-
8/3/2019 CURSOProgSist
188/213
Usaremos una pila para guardar valores temporales enexpresiones. Esta pila estar adems de la pila normal de RA.
Primero describiremos una forma de producir cdigo ineficiente. Despus veremos como producir cdigo mas eficiente. Tilingsimple est basado en un recorridopost-orderdel rbol de
ensamblador abstracto. Esto es, despus de cubrir el rbol con tiles, emitiremos cdigo para
cada tile en una formapost-order. Primero emitiremos recursivamente tiles para cada uno de los sub-
rboles del rbol de ensamblador, de izquierda a derecha.
Despus, emitiremos el cdigo para el tile de la raz del rbol.
Ejemplos:
-
8/3/2019 CURSOProgSist
189/213
Tiling Simple para rboles de Expresiones.El cdigo asociado con el tile colocar el valor de la expresin en el tope de lapila de expresiones.
Expresiones de ConstantesConsidere el siguiente rbol:
Constant(5)El cdigo asociado con este tile necesita poner un 5 en el tope de la pila deexpresiones.
addi$t1, $zero, 5 % Load the constant value 5 into the register $t1
sw $t1, 0($ESP) % Store $t1 on the top of the expression stack
addi$
ESP,$
ESP, -4 % Update the expression stack pointer
En general, el tile para cualquier valor constante x es:
addi$t1, $zero, x % Load the constant value into x the register $t1
sw $t1, 0($ESP) % Store $t1 on the top of the expression stack
addi$ESP, $ESP, -4 % Update the expression stack pointer
Operaciones de Aritmtica Binaria
-
8/3/2019 CURSOProgSist
190/213
+
Constant(3) Constant(4)
En lugar de tratar de cubrir todo el rbol con un tile, usaremos tres. Laconstante 4 y 5 pueden cubrirse cada una con un tile de constante, yusaremos un tile + para cubrir la suma.
+
Constant(3) Constant(4)
Cmo debe ser el cdigo para +?Recordemos que emitimos cdigo en post-order (subrbolizquierdo, subrbol derecho y luego raz). Podemos asumir
-
8/3/2019 CURSOProgSist
191/213
que los valores de los operandos de la izquierda y laderecha de el + ya estn en la pila cuando el cdigo de el tile+ es emitido. Ntonces, todo lo que necesitamos es hacer essacar (pop off) esos valores , hacer la suma y meter (push)el resultado de regreso a la pila. El cdigo para el tile + es:
lw $t1, 8(ESP) % Load the first operand into temporary $t1
lw $t2, 4(ESP) % Load the second operand into temporary $t2
add $t1, $t1, $t2 % Do the addition. Storing result in $t1
sw $t1, 8(ESP) % Store the result on the expression stackadd $ESP, $ESP, 4 % Update the expression stack pointer
-
8/3/2019 CURSOProgSist
192/213
RegistrosConsidere el rbol de expresin
Register(FP)
-
8/3/2019 CURSOProgSist
193/213
Esto ocupa un tile.
sw $FP, 0($ESP)addi $ESP, ESP, -4
Combinando otros tiles discutidos antes, el rbol
-
Register(FP) Constant(8)
Puede ser los tiles:-
Register(FP) Constant(8)
Produciendo el rbol
sw $FP 0($ESP) % Store frame pointer on the top of the expression stack
-
8/3/2019 CURSOProgSist
194/213
sw $FP, 0($ESP) % Store frame pointer on the top of the expression stack
addi $ESP, $ESP, -4 % Update the expression stack pointer
addi $t1, $zero, 8 % Load the constant value 8 into the register$t1
sw $t1, 0($esp) % Store $t1 on the top of the expression stack
addi $ESP, $ESP, -4 % Update the expression stack pointer
lw $t1, 8($ESP) % Load the first operand into temporary $t1
lw $t2, 4($ESP) % Load the second operand into temporary $t2
sub $t1, $t1, $t2 % Do the subtraction, storing result in $t1
sw $t1, 8($ESP) % Store the result on the expression stack
add $ESP, $ESP, 4 % Update the expression stack pointer
Operaciones relacionalesARBOL ABSTRACTO:
-
8/3/2019 CURSOProgSist
195/213
>
Constant(3) Constant(4)
>
Constant(3) Constant(4)
TILES:
El cdigo para > es:
lw $t1, 8($ESP)lw $t2 4($ESP)
-
8/3/2019 CURSOProgSist
196/213
lw $t2, 4($ESP)
slt $t1, $t2, $t1sw $t1, 8($ESP)addi $ESP, $ESP, 4
Thus, one posibility for the code for the == tile is:
lw $t1, 8($ESP)lw $t2, 4($ESP)slt $t3, $t2, $t1 % $t3= (x < y)slt $t2, $t1, $t2 % $t2 = (y < x)add $t1, $t1, $t2 % $t1 = (x < y) I I (y
-
8/3/2019 CURSOProgSist
197/213
Lw $t1, 4 ($ESP) % Pop the address to dereference off the top of the
% expression stacklw $t1, 0($t1) % Dereference the pointer sw $t1, 4($ESP) % Push the result back on the expression stack
Memory
-
Register(FP) Constant(12)
Los tiles son: Memory
-
Register(FP) Constant(12)
Ejemplo: El rbol de expresinPara una variable simple es.
Que resulta en el siguiente ensamblador:
sw $FP, 0($ESP) % Store frame pointer on the top of the expression stack
addi $ESP, $ESP, -4 % Update the expression stack pointer
addi $t1, $zero, 12 % Load the constant value 12 into the register $t1
-
8/3/2019 CURSOProgSist
198/213
sw $t1, 0($ESP) % Store $t1 on the top of the expression stackaddi $ESP, $ESP, -4 % Update the expression stack pointer
lw $t1, 4($ESP) % Load the first operand into temporary $t1
lw $t2, 8($ESP) % Load the second operand into temporary $t2
sub $t1, $t1, $t2 % Do the subtraction, storing result in $t1
sw $t1, 8($ESP) % Store the result on the expression stack
add $ESP, $ESP, 4 % Update the expression stack pointer
lw $t1, $4($ESP) % Pop the address to dereference off the top of
% the expression stack
lw $t1, $0($t1) % Dereference the pointer
sw $t1, 4($ESP) % Push the result back on the expression stack
El resultado de este cdigo es: El valor que estaba en memoria (FP 12) es empujado (pushed onto)
en el tope de la pila de expresiones.
-
8/3/2019 CURSOProgSist
199/213
-
8/3/2019 CURSOProgSist
200/213
-
8/3/2019 CURSOProgSist
201/213
Tiles de rboles de Estatutos
Mientras que el cdigo de ensamlador para rboles de expresionesmete (push) el valor de la expresin en el tope de la pila de
-
8/3/2019 CURSOProgSist
202/213
mete (push) el valor de la expresin en el tope de la pila de
expresiones, el cdigo ensamblador para rboles de estatutosimplementa el estatuto descrito por el rbol.
rboles de EtiquetasEl subrbol Label(label1) puede ser cubierto con solo un tile. Elcdigo para ese tile es:
Label1:
rboles para MoveEl lado izquierdo de un MOVE necesita que sea un registro o unalocalidad de memoria.Ejemplo:
Move
Register(r1) Constant(8)
Ser dividido en los tiles:
Move
-
8/3/2019 CURSOProgSist
203/213
Register(r1) Constant(8)
Considere el tile del MOVE registro:
Move
Register(r1)
Cuando el cdigo para este tile es ejecutado, el valor que es cargadoal registro est ya en el tope de la pila de expresiones. Entonces, todolo que necesitamos hacer es sacar el valor de la pila de expresiones ymeterlo al registro.
El tile del MOVE tiene el siguiente cdigo asociado:
lw $r1, 4($ESP) % load the rhs of the move into a register
-
8/3/2019 CURSOProgSist
204/213
addi $ESP, $ESP, 4 % update expression stack pointer
Todo el cdigo para el rbol es:
addi $t1, $zero, 8 % Store the constant 8 in a register sw $t1, 0($ESP) % Push the value on the expression stack
addi $ESP, $ESP, -4% Update the expression stack pointer
lw $r1, 4($ESP) % load the rhs of the move into a register
addi $ESP, $ESP, 4 % update expression stack pointer
Veamos ahora un MOVE a memoria. Consideremos el siguiente rbol:
Move
Constant(4)Memory
-
8/3/2019 CURSOProgSist
205/213
Register(FP)
El rbol puede tener los tiles:
Move
Constatnt(4)Mem
Register(FP)
El tile MOVE a memoria es:
Move
Necesita sacar dos valores del tope de la pila el destino del MOVE yel valor a almacenarse.
lw $t1, 8($ESP)
lw $t2 4($ESP)
-
8/3/2019 CURSOProgSist
206/213
lw $t2, 4($ESP)
sw $t2, 0($t1)
addi $ESP, $ESP, 8
Todo el rbol se puede implementar con el sig. Cdigo:
sw $FP 0($ESP)addi $ESP, $ESP, -4
addi $t1, $ZERO, 4
sw $t1, 0($ESP)
addi $ESP, $ESP, -4
lw $t1, 8($ESP)
lw $t2, 4($ESP)
sw $t2, 0($t1)
Addi $ESP, $ESP, 8
-
8/3/2019 CURSOProgSist
207/213
El cdigo que emitimos para el subrbol de la expresin jumpcondicional pone el valor de la expresin en el tope de la pila deexpresiones. Asi, necesitamos sacar la expresin del tope de la pila deexpresiones, y saltar a la etiqueta jumplab si la expresin es
-
8/3/2019 CURSOPro