domingo, 13 de octubre de 2013

Unidad 6 Generacion de Codigo Intermedio



6.1 Lenguajes Intermedios


Lenguaje Intermedio. Tipo (1)
 Es una representación más abstracta y uniforme que un lenguaje máquina concreto. Su misión es descomponer las expresiones complejas en binarias y las sentencias complejas en sentencias simples. Ventajas: • Permite una fase de análisis (análisis semántico) independiente de la máquina. • Se pueden realizar optimizaciones sobre el código intermedio (Las complejas rutinas de optimización son independientes de la máquina). Desventajas: • Pérdida de eficiencia (no permite una compilación de una sola pasada). • Introduce en el compilador una nueva fase de traducción.

Lenguaje Intermedio. Tipo (2)
Tipos de lenguajes intermedios: • Árbol sintáctico. • Árbol sintáctico abstracto. 􀂾 Todos los nodos del árbol representan símbolos terminales. 􀂾 Los nodos hijos son operandos y los nodos internos son operadores. • Grafo dirigido acíclico (GDA). • Notación posfija. • Definición de una máquina abstracta. • N-tupla: 􀂾 Cada sentencia del lenguaje intermedio consta de N elementos: (Operador, Operando1, Operando2, … , Operando N?−1) 􀂾 Los más usuales son los tercetos (tripletas) y los cuartetos (cuádruplas), llamados también código de tres direcciones.
Lenguaje Intermedio. Tipo (3)
Tripletas: Ejemplo: d = a + b * c [1] (*, b, c) [2] (+, a, [1]) [3] (=, d, [2]) <operador>, <operando_1>, <operando_2> Cuartetos: Ejemplo: d = a + b * c (*, b, c, temp1) (+, a, temp1, temp2) (=, temp2, —, d)


6.2 Notaciones Lenguajes Intermedios

6.2.1 Infija Lenguajes Intermedios
6.2.2 Postfija Lenguajes Intermedios
6.2.3 Prefija Lenguajes Intermedios
6.3 Representación Código Intermedio

6.3.1 Notación Polaca

La notación polaca es la originada por un Autómata con pila, en la que los operadores siempre preceden a los operandos sobre los que actúan, y que tiene la ventaja de no necesitar paréntesis:
Estandar
Ejemplo 1: 2 * ( 3 + 5 )
Ejemplo 2: 2 * 3 + 5
Polaca
Ejemplo 1: * 2 + 3 5
Ejemplo 2: + * 2 3 5

6.3.2 Código P

Código P o Prolog
Prolog, proveniente del francés Programation et Logique, es un lenguaje de programación lógico e interpretado, bastante popular en el medio de investigación en Inteligencia Artificial.
Se trata de un lenguaje de programación ideado a principios de los años 70 en la universidad de Aix-Marseille por los profesores Alain Colmerauer y Phillipe Roussel. Inicialmente se trataba de un lenguaje totalmente interpretado hasta que, a mediados de los 70, David H.D. Warren desarrolló un compilador capaz de traducir Prolog en un conjunto de instrucciones de una máquina abstracta denominada Warren Abstract Machine, o abreviadamente, WAM. Desde entonces Prolog es un lenguaje semi-interpretado.
Prolog se enmarca en el paradigma de los lenguajes lógicos, lo que lo diferencia enormemente de otros lenguajes más populares tales como Fortran, Pascal, C, etc.
En todos los mencionados, las instrucciones se ejecutan normalmente en orden secuencial, es decir, una a continuación de otra, en el mismo orden en que están escritas, que sólo varía cuando se alcanza una instrucción de control (un bucle, una instrucción condicional o una transferencia).
Los programas en Prolog se componen de cláusulas de Horn que constituyen reglas del tipo “modus ponendo ponens”, es decir, “Si es verdad el antecendente, entonces es verdad el consecuente”. No obstante, la forma de escribir las cláusulas de Horn es al contrario de lo habitual. Primero se escribe el consecuente y luego el antecedente. El antecedente puede ser una conjunción de condiciones que se denomina secuencia de objetivos. Cada objetivo se separa con una coma y puede considerarse similar a una instrucción o llamada a procedimiento de los lenguajes imperativos. En Prolog no existen instrucciones de control. Su ejecución se basa en dos conceptos: la unificación y el backtracking. Gracias a la unificación, cada objetivo determina un subconjunto de cláusulas susceptibles de ser ejecutadas. Cada una de ellas se denomina punto de elección. Prolog selecciona el primer punto de elección y sigue ejecutando el programa hasta determinar si el objetivo es verdadero o falso. En caso de ser falso entra en juego el ‘backtracking’, que consiste en deshacer todo lo ejecutado situando el programa en el mismo estado en el que estaba justo antes de llegar al punto de elección. Entonces se toma el siguiente punto de elección que estaba pendiente y se repite de nuevo el proceso. Todos los objetivos terminan su ejecución bien en “verdadero”, bien en “falso”.
Las listas son colecciones de elementos en Prolog. Una lista se divide en dos partes: Cabeza. Es el primer elemento de la lista. Cola. Es una lista con el resto de los elementos de la lista. La cabeza y la cola de una lista se separan con el símbolo “|”.
Ejemplo de Código Prolog
declaraciones
padrede(‘juan’, ‘maria’). % juan es padre de maria
padrede(‘pablo’, ‘juan’). % pablo es padre de juan
padrede(‘pablo’, ‘marcela’).
padrede(‘carlos’, ‘debora’).
% A es hijo de B si B es padre de A
hijode(A,B) :- padrede(B,A).
% A es abuelo de B si A es padre de C y C es padre B
abuelode(A,B) :-
padrede(A,C),
padrede(C,B).
% A y B son hermanos si el padre de A es también el padre de B y si A y B no son lo mismo
hermanode(A,B) :-
padrede(C,A) ,
padrede(C,B),
A \== B.
% A y B son familiares si A es padre de B o A es hijo de B o A es hermano de B
familiarde(A,B) :-
padrede(A,B).
familiarde(A,B) :-
hijode(A,B).
familiarde(A,B) :-
hermanode(A,B).
consultas
% juan es hermano de marcela?
?- hermanode(‘juan’, ‘marcela’).
yes
% carlos es hermano de juan?
?- hermanode(‘carlos’, ‘juan’).
no
% pablo es abuelo de maria?
?- abuelode(‘pablo’, ‘maria’).
yes
% maria es abuelo de pablo?
?- abuelode(‘maria’, ‘pablo’).
no
Ejemplo sobre Listas Prolog
% Si queremos hallar la longitud de una lista.
% La longitud de una lista vacia es 0.
% La longitud de cualquier lista es la longitud de la cola + 1.
longitud([],0).
longitud([H|T],N):-longitud(T,N0), N is N0 + 1.
?- longitud([a,b,c],L).
   3
?- longitud([a,b,c],4).
   No
% Si queremos determinar si un elemento es pertenece a una lista.
% El elemento pertenece a la lista si coincide con la cabeza de la lista.
% El elemento pertenece a la lista si es se encuentra en la cola de la lista.
pertenece(X,[X|_]).
pertenece(X,[_|R]):- pertenece(X,R).
?- pertenece(b,[a,b,c]).
   Yes
?- pertenece(b,[a,[b,c]]).
   No
?- pertenece([b,c],[a,[b,c]]).
   Yes
% Si queremos eliminar un elemento de la lista.
% Si X es la cabeza de la lista, la cola T es la lista sin X
% Si X no es la cabeza de la lista, conservamos la cabeza de la lista
% como parte de la respuesta y continuamos eliminando X de la cola T.
elimina (X,[X|T],T).
elimina (X,[H|T],[H|T1]):- elimina (X,T,T1).
?- elimina(1,[1,2,3,4],R).
R = [2,3,4]
?- elimina(1,R,[2,3]).
R = [1, 2, 3]
R = [2, 1, 3]
R = [2, 3, 1]
% Si queremos calcular la inversa de una lista.
% La inversa de una lista vacia es una lista vacia.
% La inversa de H|T es la inversa de T concatenada con H.
inversa([],[]).
inversa([H|T],L):- inversa(T,R), concatenar(R,[H],L).
?- inversa([a,b,c,d],[d,c,b,a]).

6.3.3 Triplos Lenguajes Intermedios
6.3.4 Cuádruplos Lenguajes Intermedios

6.4 Esquemas de Generación Lenguajes Intermedios

Cuando una empresa desarrolla un compilador para un lenguaje fuente y un lenguaje objeto determinados, normalmente no es el único compilador que la empresa piensa desarrollar; es más muchos fabricantes de microprocesadores tienen una división de dedicada a desarrollar compiladores para los nuevos chips que construya.
Cuando el número de lenguaje fuente crece hasta un número grande M, y/o cuando el número de lenguajes objeto también crece hasta un número grande N, es necesario encontrar una técnica para evitar tener que diseñar M x N compiladores. La solución consiste en utilizar un lenguaje intermedio o una representación intermedia; de esta forma sólo hay que construir M programas que traduzcan de cada lenguaje fuente al lenguaje intermedio (los front ende), y N programas que traduzcan del lenguaje intermedio a cada lenguaje objeto (los back end).
La matemática (del lat. mathematĭca, y este del gr. τὰ μαθηματικά, derivado de μάθημα, conocimiento) es una ciencia formal que estudia las propiedades y las relaciones que se pueden establecer entre los entes abstractos, como los símbolos, los números y las figuras geométricas.[1]
Aunque la matemática sea la supuesta “Reina de las Ciencias”, algunos matemáticos no la consideran una ciencia natural. Principalmente, los matemáticos definen e investigan estructuras y conceptos abstractos por razones puramente internas a la matemática, debido a que tales estructuras pueden proveer, por ejemplo, una generalización elegante, o una herramienta útil para cálculos frecuentes. Además, muchos matemáticos consideran la matemática como una forma de arte en vez de una ciencia práctica o aplicada. Sin embargo, las estructuras que los matemáticos investigan frecuentemente sí tienen su origen en las ciencias naturales, y muchas veces encuentran sus aplicaciones en ellas, particularmente en la física.
No existe un único lenguaje intermedio en todos los compiladores, sino que cada empresa que diseña compiladores suele tener su propio lenguaje intermedio. La utilización de un lenguaje intermedio permite construir en, mucho menos tiempo un compilador para otra máquina y también permite construir compiladores para otros lenguajes fuente generando códigos para la misma máquina. La matemática es un arte, pero también una ciencia de estudio. Informalmente, se puede decir que es el estudio de los “números y símbolos”. Es decir, es la investigación de estructuras abstractas definidas a partir de axiomas, utilizando la lógica y la notación matemática. Es también la ciencia de las relaciones espaciales y cuantitativas. Se trata de relaciones exactas que existen entre cantidades y magnitudes, y de los métodos por los cuales, de acuerdo con estas relaciones, las cantidades buscadas son deducibles a partir de otras cantidades conocidas o presupuestas.
Véase también: Filosofía de la matemática No es infrecuente encontrar a quien describe la matemática como una simple extensión de los lenguajes naturales humanos, que utiliza una gramática y un vocabulario definidos con extrema precisión, cuyo propósito es la descripción y exploración de relaciones conceptuales y físicas. Recientemente, sin embargo, los avances en el estudio del lenguaje humano apuntan en una dirección diferente: los lenguajes naturales (como el español y el francés) y los lenguajes formales (como la matemática y los lenguajes de programación) son estructuras de naturaleza básicamente diferente.
Por ejemplo, el compilador de C de GNU que se distribuye con Linux es una versión de una familia de compiladores de C para diferentes máquinas o sistemas operativos: Alpha, AIX, Sun, HP, MS-DOS, etc.. Además, GNU ha desarrollado un compilador de FORTRAN y otro de Pascal que, al utilizar el mismo lenguaje intermedio, pueden ser portados a todos los sistemas y máquinas en las que y a existe un compilador de C de GNU con relativamente poco esfuerzo.
La generación de código intermedio transforma un árbol de análisis sintáctico (semántico) en una representación en un lenguaje intermedio, que suele ser código suficientemente sencillo para poder luego generar código máquina.
Una forma de hacer esto es mediante el llamado código de tres direcciones. Una sentencia en código de tres direcciones es: A := B op C, donde A, B y C son operandos y op es un operador binario. También permite condiciones simples y saltos. Por ejemplo, para la siguiente sentencia:
          WHILE (A > B) AND (A < = 2 * B – 5) DO A : = A + B
el código intermedio generado ( código en tres direcciones) será:
       L1 :   IF A > B     GOTO L2
                GOTO L3
       L2 :   T1  : = 2 * B                             (*nivel más alto que ensamblador*)
              T2   :  = T1 – 5                          (*pero más sencillo que Pascal*)
                IF   A < T2   GOTO L4
                GOTO L3
        L4 :  A : = A + B
                GOTO L1
        L3 :  . . . . . . .   
APLICACIONES
La importancia practica de lenguaje en la informática se manifiesta principalmente en el uso cotidiano que hace el profesional informático de compiladores e interpretes, consustancial al la gestión y programación de los sistemas informáticos. Así pues, un conocimiento acerca del funcionamiento interno de estas herramientas básicas resulta fundamental. Pero los conocimientos adquiridos en su estudio encuentren aplicación fuera del campo de la compilación. Es probable que ocas personas realice o mantenga un compilador para un lenguaje de programación, pero mucha gente puede obtener provecho del uso de un gran número de sus técnicas para el diseño de software en general.
En efecto, entre los campos de la informática en los que encuentra aplicación las técnicas aprendidas en COMPILADORES e INTÉRPRETES se puede citar lo siguiente:
Tratamiento de ficheros de texto con información estructurada. Lenguaje como Perl y TEL, o comandos como el sed o egrep de UNIX, incorpora tratamiento de expresiones regulares para la detección y/o modificación de patrones sin texto.
Procesadores de texto. Procesadores como vi o Emacs incorporan también la posibilidad de efectuar búsquedas y sustituciones mediante expresiones regulares. Existen también procesadores (entre ellos los Emacs) capaces de analizar y tratar ficheros de texto de organización compleja.
Diseño e interpretación de lenguaje para formateo y texto y descripción de gráficos. Sistema de formateo de texto (como el HTML o el TEX) o para la especificación de tablas (tbl), ecuaciones (eqn), gráficos (postscript), etc. requieren sofisticados microprocesadores.
Gestión de base de datos. Las técnicas que estamos considerando pueden explotarse tanto en la exploración y proceso de ficheros de información como en la realización de la interfase de usuario.
Traducción de formato de fichero.
Calculo simbólico.
Reconocimiento de formas. Las técnicas de análisis sintáctico son ampliamente utilizadas en la detección de patrones en texto, el reconocimiento automático del habla o la visión por computador.
6.4.1 Expresiones Lenguajes Intermedios
6.4.2 Declaración Variables Constantes Lenguajes Intermedios
6.4.3 Estatuto Asignación Lenguajes Intermedios
6.4.4 Estatuto Condicional Lenguajes Intermedios
6.4.5 Estatuto Ciclos Lenguajes Intermedios

6.4.6 Arreglos Lenguajes Intermedios

(Intermediate language). En computación, un lenguaje intermedio es el lenguaje de una máquina abstracta diseñada para ayudar en el análisis de los programas de computadora. El término viene de su uso en los compiladores, donde un compilador primero traduce el código fuente de un programa, en una forma más apropiada para las transformaciones de mejora del código (forma usualmente llamada bytecode), como un paso intermedio antes de generar el archivo objeto o el código máquina para una máquina específica.
Una variante del significado de “lenguaje intermedio” se da en esos lenguajes de alto nivel que no soportan o no generan un archivo objeto o código máquina, pero sí generan un lenguaje intermedio. Luego ese lenguaje intermedio se transfiere a un compilador que termina de realizar el archivo objeto o el código máquina. Esto se emplea generalmente por cuestiones de optimización y portabilidad.

6.4.7 Funciones Lenguajes Intermedios

Función del Lenguaje, entendemos que es el uso de la lengua que hace un hablante. En simples palabras, las funciones del lenguaje son los diferentes objetivos, propósitos y servicio que se le da al lenguaje al comunicarse, dándose una función del lenguaje por cada factor que tiene éste, en donde la función que prevalece es el factor en donde más se pone énfasis al comunicarse. Diversos lingüistas (Karl Bühler, Roman Jakobson, Michael Halliday…) han propuesto distintas clasificaciones de las funciones del lenguaje: Bühler propuso que existían únicamente tres funciones: • La Representativa (por la cual se trasmiten informaciones objetivamente) • La Expresiva o emotiva (que expresa sentimientos del emisor) • La Conativa, mediante la que se influye en el receptor del mensaje a través de órdenes, mandatos o sugerencias… Este modelo parecía muy incompleto a Jakobson, quien caracterizó mejor las funciones de Bühler y añadió otras tres sobre los ejes de los factores de la comunicación :
Función Apelativa o Conativa Se centra en el receptor. Es la función de mandato y pregunta. Sus recursos lingüísticos son los vocativos, oraciones interrogativas, utilización deliberada de elementos afectivos, adjetivos valorativos, términos connotativos y toda la serie de recursos retóricos. Se da en lenguaje coloquial, es dominante en la publicidad y propaganda política e ideológica en general. Mediante el uso de esta función se pretende causar una reacción en el receptor. Es decir con esta función se pretende que haga algo o que deje de hacer. Por ejemplo cuando decimos “cállate” o “abre la puerta por favor”, etc. El mensaje solicita la atención del destinatario, es decir apela a él, implicita o explicitamente. También se le conoce como función apelativa. Funcion Referencial Es la función del lenguaje en donde se pone énfasis al factor de contexto. Al ser el contexto todo lo extra comunicativo, la función referencial trata solamente sucesos reales y comprobables, ya que no son opiniones ni cosas subjetivas, lo que son es una serie de elementos verificables entre otros Está presente en todos los actos comunicativos. Se da cuando el mensaje que se transmite puede ser verificable, porque reconocemos la relación que se establece entre el mensaje y el objeto (referente) Es aquella que utiliza el lenguaje denotativo (el significado primario de las palabras). Prevalecen los sustantivos y verbos; los textos informativos, científicos y periodísticos. Hay 7 funciones: Expresiva o emotiva, apelativa o conativa, referencial o representativa, situacional, Esta función se centra en el contexto e identifica la relacion entre el mensaje y el objeto del que se habla; es decir, se centra en la tercera persona, la lengua se usa para hablar de algo o alguien, que no somos ni tú ni yo. Así, la función referencial se hace presente en casi todos los mensajes y sirve para evaluar si éstos son objetivos o no.


No hay comentarios:

Publicar un comentario