Maquina de Pila Abstracta
Maquina de Pila Abstracta
Maquina de Pila Abstracta
Tema 1
Lenguajes interpretados
1. INTRPRETES
1. Intrpretes
2. La mquina
de pila abstracta
un lenguaje
de programacin
2 Compiladores 2
3. Lee el oprador +, extrae los dos primeros valores de la pila, los suma e
inserta el resultado (6)
4. Lee el valor 5 y lo inserta en la pila
5. Lee el operador *, y extrae los dos primeros valores de la pila, ejecuta la
operacin e inserta el resultado (30).
La mquina abstracta trabaja con nmeros enteros y soporta las instrucciones
aritmticas habituales; cada uno de estos operadores aritmticos (+, -, *, /) define
una operacin que se ha de aplicar sobre los dos primeros valores de la cima de la
pila. Cuando la mquina lee un operador, extrae los dos primeros valores de la pila,
aplica la operacin e introduce en resultado en la pila.
El conjunto de instrucciones est formado por 18 elementos. En binario se
pueden codificar utilizando 5 bits, con lo que se pueden generar 32 elementos (2 5);
por tanto, en una codificacin de 5 bits, todava dispondramos de 14 posiciones
libres para ampliar el conjunto de instrucciones.
Dado que un intrprete para la mquina de pila abstracta se podra
implementar para muchas mquinas diferentes, es muy importante que la
especificacin recoja aspectos propios del hardware como el tamao en bits de los
datos o el tamao de la memoria. Es responsabilidad del intrprete compatibilizar
estas especificaciones con el hardware especfico sobre el cual se ejecuta. Por ello
los intrpretes para lenguajes de programacin portables en diferentes plataformas
tambin se llaman mquinas virtuales.
Es posible implementar un intrprete obviando algunas de estas cuestiones si
se programa mediante un lenguaje portable como Java. Un intrprete programado
en Java ya es portable porque el mismo lenguaje asegura un mismo
comportamiento del cdigo sobre distintas plataformas: por ejemplo, un entero en
Java siempre tendr un tamao de 32 bits, sea cual sea la mquina sobre la cual se
ejecute el programa.
Compiladores 2 3
2. Analizadores sintcticos de
XML
EN 3.
XML
se puede escribir
Procesadores XSLT
Estas hojas en cascada crecen y evolucionan con la web, pero a pesar de ello, el
lenguaje HTML est limitado desde el comienzo para la representacin de pginas
web; en stas y otras muchas situaciones es necesario un lenguaje para
representar datos estructurados: el XML.
El lenguaje XML (extensible markup language) es el formato universal
para documentos estructurados y datos en la web. Un documento XML puede ser
perfectamente presentado en la web con formato tanto de forma como de
contenido, y adems una persona o un programa podrn automticamente obtener
datos del mismo que pueden ser de nuevo procesados.
Por tanto XML puede servir para representar y transportar
informacin estructurada como la que se puede guardar en una base de datos,
tambin sirve para representar informacin.
El XML es ms restrictivo que el HTML, pero se permite que diferentes
comunidades pueden intercambiar documentos siempre que se pongan de acuerdo
en el nombre de los elementos a incluir y la forma de organizarlos; varias
4 Compiladores 2
Compiladores 2 5
tienen propsitos y orgenes diferentes, pero con ellas se puede realizar cualquier
tipo de tratamiento sobre documentos XML.
La API SAX
SAX es el acrnimo de Simple API for XML. SAX es software de libre
distribucin, totalmente gratuito y con cdigo abierto. SAX lee un documento XML
de manera secuencial y a lo largo del proceso de lectura efecta un anlisis
sintctico y genera un conjunto de eventos cada vez que identifica algo
significativo.
Con respecto al tratamiento de errores, SAX desencadena
eventos que notifican errores cuando identifica durante el proceso de
anlisis, alguna circunstancia anmala, como un elemento que no tiene
etiqueta de cierre o el valor de un atributo que no est entre comillas.
Todos los mtodos reciben como parmetro la excepcin
SAXParseException. Este objeto contiene el nmero de lnea en el que
se ha detectado el problema, el URI del documento y la informacin
tpica de todas las excepciones java (como la descripcin del error y el rastro de la
pila de llamadas a mtodos. SAX genera tres tipos de errores:
1. Warnings: Que constituyen ms bien notificaciones de anomalas o situaciones
extraas.
2. Errores no fatales: Que son errores que no impiden que el analizador pueda
continuar adelante.
3. Errores fatales: Que provocan que el anlisis deba finalizar.
Tanto los warnings como los errores no fatales suelen estar asociados a errores
provocados por documentos no vlidos, mientras que los errores fatales
normalmente son errores provocados por documentos mal formados que no se
ajustan a la sintaxis XML.
SAX resulta muy til para procesos de bsqueda de elementos o de acceso a
informacin especfica dentro del documento XML. Es muy rpido y no gasta
memoria; adems, cuando se localiza el elemento buscado, permite parar el
proceso de anlisis.
SAX no permite un acceso aleatorio a un documento XML, sino que lee el
documento de un modo secuencial y va lanzando acontecimientos mientras dura
este proceso de lectura: si una vez ledo el documento se quisiera volver a acceder
a la informacin de un elemento determinado, no habra otro remedio que volver a
analizar el documento desde el principio hasta encontrar el elemento en cuestin.
La API DOM
Para poder acceder rpidamente y tantas veces como se quiera a la
informacin de los elementos del documento XML, sera necesario construir una
representacin en memoria, esto es justo lo que hace un analizador DOM. DOM
define una estructura de rbol con mtodos y propiedades para poder navegar por
la estructura y obtener los datos almacenados.
Los analizadores sintcticos basados en DOM retornan
un rbol DOM a las aplicaciones que los utilizan. En caso de
producirse errores durante el anlisis, tambin informan de ello
a la aplicacin.
Un analizador sintctico basado en DOM consta
bsicamente de dos partes: el analizador propiamente dicho
(que se encarga de leer el documento y crear el rbol DOM) y
un conjunto de clases de apoyo que implementan la jerarqua
DOM (y permiten navegar y acceder a la informacin
almacenada en memoria).
6 Compiladores 2
Compiladores 2 7
8 Compiladores 2
La principal
diferencia entre
compiladores de lenguajes de diferentes
TEMA
3 GENERACIN
AVANZADA
paradigmas se encuentra en el tipo de cdigo que se genera: mientras que los
imperativos y los orientados al objeto generan cdigo a nivel de ensamblador o
inferior,
el resto de DE
paradigmas
suelen generar cdigo C o C++.
1. PARADIGMAS
PROGRAMACIN
Tema 1
Generacin avanzada
Programacin funcional
1. Paradigmas de programacin
Los lenguajes funcionales, como Lisp, Mirando o Haskell, se basan en la 2. Gestin del contexto
3. Representacin y gestin de
idea de que un programa es una funcin con un parmetro de entrada y un
los datos del lenguaje fuente
resultado. La ejecucin del programa se convierte entonces en la aplicacin de la
4. Rutinas y mtodos
funcin en la entrada para obtener como resultado la salida.
5. Gestin de errores en tiempos
Estos lenguajes se caracterizan porque:
de ejecucin
Promueven un estilo declarativo en el que los
programadores han de especificar slo qu se debe
calcular y dejan al compilador y al sistema de
ejecucin decidir cmo, dnde y cundo lo han de
realizar.
Incluyen construcciones de programacin para
conseguir el nivel de abstraccin requerido (por ejemplo, funciones de alto
nivel) que complican el compilador y el sistema de ejecucin.
Incluyen facilidades sintcticas gestionadas en el analizador lxico y el
sintctico: regla de fuera de juego, notacin de listas, listas exhaustivas y
agrupacin de patrones.
Presentan aspectos fundamentales como tipos polimrficos, transparencia
referencial, funciones de alto orden o evaluacin diferida.
Se ha verificado que se obtiene una reduccin de cdigo de 10 a 1 entre los
lenguajes imperativos y los funcionales, lo que reduce mucho el esfuerzo de
programacin.
Programacin lgica
La programacin lgica se basa en la especificacin de relaciones entre
trminos de hechos que utilizan estas relaciones y de las reglas para inferir nuevos
hechos a partir de los ya existentes. Las reglas y los hechos juntos se denominan
clusulas.
El punto clave de la programacin lgica es la posibilidad de inferir hechos
especficos preguntando a las clusulas, combinndolas de distintas maneras,
retrocediendo cuando no conducen a ningn sitio y, a menudo, tambin cuando se
llega al lugar deseado.
Los compiladores lgicos habitualmente generan cdigo C. De todos
modos, como la expresin ms natural de la vuelta atrs utiliza rutinas imbricadas,
se suele usar alguna versin de C que las admita, como GNU C. Incluso existen
algunos compiladores que aumentan un nivel y generan directamente cdigo
Prolog.
Programacin paralela y distribuida
Los sistemas paralelos y distribuidos consisten en mltiples procesadores
que se pueden intercomunicar. Los lenguajes de programacin para estos sistemas
soportan construcciones especficas para gestionar la concurrencia y la
comunicacin. Las dos arquitecturas ms significativas son:
Multiprocesador: En estas estructuras todos los recursos acceden, como
mnimo, a un espacio de memoria compartido y se suelen comunicar leyendo y
escribiendo datos en este espacio comn. Se pueden construir, por ejemplo,
conectando mltiples procesadores a un nico bus (existen otras tipologas
mucho ms sofisticadas).
Compiladores 2 9
10 Compiladores 2
Compiladores 2 11
12 Compiladores 2
Compiladores 2 13
rutinas a medida que se van creando, aunque, como se ver, en algunos casos la
pila puede resultar insuficiente y es necesario utilizar la memoria montculo. Esta
estructura de pila permite una gestin implcita de la activacin de las rutinas y
facilita mucho la programacin del compilador.
Cuando una rutina es llamada se crea un registro de activacin para guardar
los datos y se transfiere el flujo de controla su primera instruccin de cdigo. En
este momento se dice que la rutina se ejecuta.
Las rutinas que se ejecutan o que se encuentran suspendidas, tienen un
registro de activacin creado y estn activas. En caso de que una rutina est activa
ms de una vez simultneamente, ser una rutina recursiva, pero en un momento
dado, slo puede estar en ejecucin una nica invocacin.
Cuando una rutina se acaba, se elimina su registro de activacin y cuando la
ltima activacin de la rutina se ha acabado y se han eliminado todos los registros
de activacin de la rutina, sta se convierte en inactiva.
Sobre una rutina se puede realizar una llamada, que crea un registro de
activacin y transfiere el flujo de control del programa al cdigo de la rutina.
Como se ha visto, una parte de la secuencia de acciones que se llevan a cabo
en la llamada de una rutina se realiza en la parte de la rutina invocadora y otra, en
la parte de la rutina invocada. La reserva de espacio para el registro de activacin
ser la primera accin que se llevar a cabo y se puede realizar utilizando una pila
o una memoria montculo. Si se utiliza una pila, la reserva es ms o menos
automtica y los componentes se ponen en la pila en el orden correcto. Si se utiliza
la memoria montculo, se ha de reservar un trozo secuencial de memoria de una
longitud suficiente para guardar todo el registro de activacin. Como la situacin
normal es la primera, asumiremos que se utilizada una pila.
En una pila se pueden llevar a cabo las dos acciones siguientes:
Push: Poner un elemento en la cima.
Pop: Sacar el ltimo elemento entrado en la cima.
Existen distintos mecanismos posibles para realizar el paso de parmetros: el
ms sencillo es el paso por valor: el valor actual del parmetro se utiliza como valor
inicial del parmetro formal correspondiente. Despus de retornar, la rutina que ha
realizado la llamada no ve ningn cambio en el valor del parmetro. Muchos
lenguajes soportan una forma de parmetros de salida que permite a una rutina
que las modificaciones en los valores de los parmetros actuales sean reflejados en
los correspondientes parmetros formales:
Paso por referencia: Se copia la direccin del parmetro actual en el registro de
activacin.
Paso por valor-resultado: Se copia la direccin del parmetro actual en el
registro de activacin. Una variable local sustituye al parmetro en las
sentencias del cdigo de la rutina. Esta variable se inicializa con el valor del
parmetro. El cambio de valor se efecta a la vuelta: cuando finaliza la rutina,
el valor de la variable local se copia en el parmetro original.
rea de variables locales
Una vez transferido el control, la rutina invocada crea la parte de variables
locales donde residirn las variables locales y temporales del compilador.
Normalmente, el compilador determina su longitud considerando el rea como un
registro en el que las variables locales de la rutina forman los campos. Tambin ha
de tener en cuenta los requerimientos de longitud y alineacin de la memoria.
Tal como ocurra con los parmetros, algunos datos pueden tener
componentes dinmicos; en este caso, se debern guardar en la memoria
montculo o en el rea de asignacin dinmica del registro de activacin, como se
explicar a continuacin.
14 Compiladores 2
Pila de trabajo
Esta pila se utiliza para guardar resultados annimos de expresiones.
Tambin se pueden guardar lmites de sentencias for (aunque es ms normal
guardarlas en variables temporales). Analizando el cdigo de la rutina, el
compilador puede decidir fcilmente la longitud mxima de la pila e incorporarla
como un bloque fijo detrs del rea de las variables locales.
rea de memoria dinmica
Si el lenguaje objeto permite registros de activacin que puedan modificar
su longitud dinmicamente, se puede incorporar una parte separada de memoria
dinmica para las variables locales y para los parmetros con componentes
dinmicos. Como sta es la nica parte del registro de activacin de la que no se
puede saber la longitud en tiempo de compilacin, se debe situar al final del
registro.
Las principales ventajas que supone utilizar reas de memoria dinmica son
que no ser necesario eliminar las variables cuando la rutina finalice, y que se
mejora la velocidad, ya que la gestin se efecta utilizando el registro SP. El
inconveniente es que el rea de pila de trabajo ya no podr utilizar el SP, sino que
se deber simular el funcionamiento por software.
Retorno de valores
Si la rutina invocada tiene que retornar un valor, se pueden seguir
diferentes esquemas para que se percate de ello la rutina invocadora:
Si el valor es un tipo de datos simple, se guarda el resultado en el registro de
resultado de funcin.
Si el valor no cabe de manera natural en el registro, la situacin se complica y
ser necesario aplicar una de las 3 soluciones siguientes:
o Si el compilador conoce la longitud del resultado, puede reservar
espacio en el rea de variables temporales de la rutina invocadora y
pasar su direccin como parmetro extra a la rutina invocada.
o La rutina invocada puede reservar espacio dinmicamente en el
registro de resultado de funcin y retornar un apuntador a esta
direccin.
o El resultado de puede dejar en la memoria dinmica del registro de
activacin de la rutina invocada o en una variable local, y poner un
apuntador a ella en el registro de resultado de funcin.
La secuencia de llamada y retorno
La secuencia de pasos que se llevan a cabo al invocar una rutina es la
siguiente:
Crear un registro de activacin.
Evaluar los parmetros y guardarlos en el registro de activacin.
Llenar el rea de administracin del registro de activacin: apuntador marco de
la rutina invocadora (enlace dinmico), direccin de retorno, apuntador lxico y
quiz algunos registros de la mquina.
Transferir el control a la rutina invocada.
Hacer que el apuntador de marco apunte al nuevo registro de activacin de la
rutina invocada.
Actualizar el apuntador de pila reservando espacio suficiente para el rea de
variables locales.
Si hay parte de memoria dinmica, se llena a medida que se va requiriendo.
La secuencia de pasos necesaria para el retorno es la siguiente:
Si la rutina invocada retorna un valor, lo debe guardar en el rea designada
para esto.
Si se han guardado los registros de la mquina en el rea de administracin,
hay que restaurarlos tal como fueron guardados.
Compiladores 2 15
Junio 2007