Está en la página 1de 5

Universidad Simón Bolívar

Departamento de Computación y Tecnología de la Información


CI3641  Lenguajes de Programación I

Guía Corta: Diagramas de T


(Aplicados a Traductores, Intérpretes y Bootstrapping)

1. Deniciones básicas

A continuación se presentan las deniciones básicas de máquinas, intérpretes y traductores,


necesarias para la elaboración de ejemplos más complicados. Se incluye una representación gráca
para las mismas correspondiente a los llamados Diagramas de T.

1.1. Máquinas

Una Máquina para M es, en un sentido muy general, una herramienta que permite entender
y ejecutar código escrito en un lenguaje particular M. En este caso, diremos que tal código es
ejecutable en M.

Representaremos grácamente una máquina como un clavo identicado con el lenguaje de


la misma, mostrado en la Figura 1.

Figura 1: Representación gráca de una máquina para M.

1.2. Intérpretes

Un Intérprete A es similar a una máquina, en el sentido que permite entender y ejecutar


para
código escrito en un lenguaje particular A. Sin embargo, un intérprete debe ejecutarse sobre
una máquina ya existente. Un intérprete puede ejecutarse sobre una máquina M , siempre que el
mismo está escrito en M .

Representaremos grácamente un intérprete como un tubo identicado en el nivel superior


con el lenguaje que interpreta y en el nivel inferior con el lenguaje en el cual está escrito, mostrado
en la Figura 2.

1
Figura 2: Representación gráca de una intérprete para A, escrito en M.

Tomando esto en cuenta, es posible ver un intérprete para A escrito en M como una función
que recibe una máquina para M y devuelve entonces una máquina para A. Esto puede apreciarse
grácamente en la Figura 3.

Figura 3: Intérprete como creador de una nueva máquina para A, a través de M.

1.3. Traductores y Compiladores

Un Traductor de A hacia B es una herramienta que permite transformar código escrito en A


a un código equivalente escrito en B . Al igual que los intérpretes, los traductores deben ejecutarse
sobre una máquina ya existente. Un traductor puede ejecutarse sobre una máquina M , siempre
que el mismo esté escrito en M. Un traductor donde el lenguaje destino y el lenguaje en el que
está escrito son el mismo se conoce como un Compilador.

Representaremos grácamente un traductor como una T identicado en el nivel superior


izquierdo con el lenguaje fuente, en el nivel superior derecho con el lenguaje destino y en el nivel
inferior con el lenguaje en el cual está escrito, mostrado en la Figura 4.

Figura 4: Traductor desde el lenguaje A, hacia al lenguaje B, escrito en M.

Al ejecutar un traductor sobre una máquina que lo soporte, el mismo esperará una entrada
escrita en el lenguaje fuente y arrojará esa misma entrada en el lenguaje destino. Tal entrada puede
ser cualquier programa, los cuales se representarán grácamente como cuadrados identicados
con el lenguaje en el que están escritos. Un ejemplo de traducción es mostrado en la Figura 5.

Figura 5: Programa escrito en A, traducido a B a través de un traductor.

2
2. Traductor de Traductores

Un traductor de A B , es útil para traducir cualquier programa escrito en A a un


hacia
programa equivalente escrito en B . En particular, un traductor es un programa. Por lo tanto, es
posible tomar traductores escritos en un lenguaje S y traducirlos a un lenguaje T si se tiene otro
traductor que pueda realizar tal transformación. Un ejemplo de esto se encuentra representado
grácamente en la Figura 6.

Figura 6: Traductor de A a B, escrito en S, traducido a T.

2.1. Bootstrapping

El término bootstrapping proviene de una creencia pirata, la cual consistía en que era posible
levantarse del piso y otar al jalarse uno mismo las trenzas de las botas. Su equivalente en términos
de compiladores, sería intentar construir un compilador para un lenguaje en el mismo lenguaje
y esperar que funcione. Sin embargo, al agregar un intérprete para el lenguaje, tal hazaña es
posible. La gura 7 muestra la construcción de una compilador ejecutable en M para un lenguaje
A usando solamente los siguientes elementos:

Una máquina M.

Un traductor de A hacia M, escrito A.

Un intérprete para A en M.

Figura 7: Bootstrapping de un compilador para A, a través de M.

3
2.2. El Caso de Pascal

Escribir un compilador para un lenguaje de alto nivel, en un lenguaje ensamblable es una tarea
sumamente difícil. Además, tal implementación es inútil al cambiar la arquitectura del sistema.
Era necesario plantear una solución que permitiese facilidad de codicación y portabilidad. En
1970, Niklaus Wirth diseñó el lenguaje de programación Pascal. Con el objetivo de distribuir
Pascal a la mayor cantidad de potenciales usuarios, Pascal fue entregado como un conjunto de
aplicaciones conocidas como sistema PascalP.

El sistema PascalP incluía las siguientes componentes:

Un traductor de Pascal al lenguaje Pcode, escrito en Pascal.

El mismo traductor, pero escrito en Pcode.

Un intérprete para Pcode, escrito en Pascal.

Al recibir este conjunto de programas, la única responsabilidad del recipiente era traducir el
intérprete brindado (manualmente) al lenguaje de su propia arquitectura. Esto sigue siendo una
tarea complicada, pero es mucho más sencilla que escribir un compilador directamente y más aún
dado que ya existe un modelo escrito en Pascal del cual guiarse. La gura 8 muestra este proceso,
suponiendo que ya se tradujo el intérprete al lenguaje M de la arquitectura disponible.

Figura 8: Traductor de Pascal a Pcode del sistema PascalP.

Una vez traducido el programa en cuestión, se puede utilizar el intérprete de Pcode para
ejecutarlo.

Esta solución es suciente si se quiere poder ejecutar los programas escritos en Pascal. Sin
embargo, al hacerse siempre a través de un intérprete, el rendimiento de los programas puede verse
fuertemente afectado. Si la velocidad de ejecución es un requerimiento importante, el recipiente
del sistema PascalP puede entonces implementar un traductor de Pascal a el lenguaje M de
la arquitectura, basándose en el traductor a Pcode. Implementar tal traductor puede parecer
complicado, sin embargo el mismo puede implementarse en Pascal (en vez del lenguaje de la
máquina) y ya se tiene un modelo de traducción a Pcode con el cual guiarse.

En primer lugar, se debe tomar el traductor de Pascal a M , escrito en Pascal y traducirlo a P


code, con el procedimiento presentado en la Figura 8. Luego, se puede utilizar este nuevo traductor
para completar el proceso. La gura 9 muestra dicho procedimiento, donde los programas ahora
pueden ejecutarse en M directamente.

4
Figura 9: Compilador de Pascal a través del sistema PascalP.

Ya los programas pueden ejecutarse en M directamente, sin embargo el compilador debe


ejecutarse en el intérprete. Si consideramos tal compilación como un programa más, podemos
hacerle bootstrap y obtener un compilador nativo. La gura 10 muestra este procedimiento, donde
el compilador es ahora nativo (escrito en M ).

Figura 10: Bootstrap de un compilador de Pascal a través del sistema PascalP.

3. Ejercicios sugeridos
En ambos ejercicios se busca construir una herramienta particular. Explique, de forma clara
y concisa, como deben utilizarse los recursos disponibles para conseguir la herramienta deseada.
(En ambos casos cuenta con una máquina M inicialmente).

1. Se desea implementar un traductor de un lenguaje L, hasta otro lenguaje T, que debe


ejecutarse sobre una máquina para M. Actualmente se cuenta con los siguientes recursos:

Un intérprete para T , ejecutable en M .


Un traductor para L, escrito en T , que genera código M .
Un traductor para L, escrito en L, que genera código T .

2. Se desea implementar un intérprete del lenguaje A, que debe ejecutarse en una máquina
para M. Actualmente se cuenta con los siguientes recursos:

Un intérprete para B , ejecutable en M .


Un intérprete para A, ejecutable en B .

Un traductor para B , escrito en A, que genera código para M.


Un traductor para A, escrito en B , que genera código para B.

Ricardo Monascal / Febrero 2014

También podría gustarte