martes, 21 de febrero de 2017

COMPILADORES: Análisis Semántico

Un compilador toma como su entrada un programa escrito en lenguaje fuente y produce un programa equivalente escrito lenguaje objeto. Un compilador se compone internamente de varias etapas o fases que ser realizan operaciones lógicas:

Análisis Semántico: Semántica de un lenguaje dar sentido a sus construcciones, como los tokens estructura y sintaxis. Semántica ayudan a interpretar los símbolos, sus tipos y sus relaciones con los demás. Análisis semántico los jueces si la sintaxis estructura construida en el programa de origen se deriva el significado o no.
CFG + semantic rules = Syntax Directed Definitions
Por ejemplo:
int a = value”;
No debe emitir un error léxico y la sintaxis en fase de análisis, ya que es léxico y estructuralmente correcto, pero se debe generar un error semántico como del tipo de asignación es diferente. Estas normas están definidas por la gramática de la lengua y evaluado en análisis semántico. Las siguientes tareas deben realizarse en análisis semántico:
  • Resolución de Ámbito
  • Comprobación de tipos
  • Matriz de control

Errores Semanticos 

Hemos mencionado algunos de los errores que la semántica analizador semántico se espera para reconocer:
  • No coinciden los tipos
  • Variable no declarada
  • Identificador reservado uso indebido.
  • Declaración de variables múltiples en un ámbito.
  • Acceder a una variable fuera de alcance.
  • Parámetro formal y real no coincide.

Gramatica Atributo

Atributo gramática es una forma especial de libres de contexto gramática donde algunas de las informaciones adicionales (atributos) se añade a una o más de sus terminales con el fin de proporcionar información sensible al contexto. Cada atributo tiene bien definido el dominio de los valores, como integer, float, caracteres, cadenas y expresiones.
Atributo gramática es un medio para proporcionar semántica en el contexto de libre gramática y puede ayudar a especificar la sintaxis y la semántica de un lenguaje de programación. Atributo gramática (cuando se considera como un árbol de análisis) puede pasar valores o información entre los nodos de un árbol.
Ejemplo:
E  E + T { E.value = E.value + T.value }
La parte derecha de la CFG contiene la semántica las normas que especifican el modo en que la gramática debe ser interpretado. Aquí, los valores de las terminales E y T se suman y el resultado se copian en el no-terminal E.
Semántica atributos pueden ser asignados a sus valores de su dominio en el momento de análisis y evaluación en el momento de la cesión o condiciones. Sobre la base de la forma los atributos obtienen sus valores, que pueden dividirse en dos categorías: atributos sintetizados y atributos heredados.

Atributos sintetizados

Estos atributos obtener los valores de los atributos de sus nodos secundarios. Para ilustrar, asumir las siguientes producciones:
S  ABC
Si S es tomar los valores de sus nodos secundarios (A,B,C), entonces se dice que es un atributo sintetizado, como los valores de ABC se sintetizan para S.
Como en nuestro ejemplo anterior (E → E + T), el nodo padre E obtiene su valor de su nodo hijo. Sintetiza los atributos nunca tomar valores entre sus nodos padres o cualquier nodos relacionados.

Atributos heredados

A diferencia de los atributos sintetizados, atributos heredados puede tomar valores entre padres y/o hermanos. Tal como se muestra en la siguiente producción,
S  ABC
Puede obtener los valores de S, B y C. B puede tomar valores de S, A, y C. Asimismo, C puede tomar valores de S, A y B.
Expansión: se produce cuando un no-terminal se ha ampliado a los terminales, como por una regla gramatical
Atributos Heredados
Reducción: Cuando un terminal se reduce a su correspondiente no-terminal según las reglas de gramática. Los árboles se analizan Sintaxis de arriba a abajo y de izquierda a derecha. Reducción cada vez que se produce, sus reglas semánticas correspondientes (acciones).
Análisis semántico utiliza la sintaxis dirige las traducciones para realizar las tareas antes mencionadas.
Analizador semántico recibe AST (Abstract Syntax Tree) de su etapa anterior (sintaxis).
Analizador semántico concede información sobre los atributos de AST, que son llamados atribuido AST.
Los atributos son dos tupla valor, <nombre de atributo, valor de atributo>
Por ejemplo:
int value  = 5;
<type, integer”>
<presentvalue, 5”>
Para cada producción, damos una regla semántica.

S-atribuyó SDT

Si un TRATO ESPECIAL Y DIFERENCIADO sólo utiliza atributos sintetizados, se llama como S-atribuidas al SDT. Estos atributos son evaluados usando S-atribuidas SDTS que tienen sus acciones semánticas escrito después de la producción (a la derecha).
S-atribuido SDT
Tal como se ha descrito anteriormente, los atributos de S-atribuidas SDTs son evaluados en la parte inferior de análisis, como los valores de los nodos padres dependen de los valores de los nodos secundarios.

L-atribuyó SDT

Esta forma de SDT de ambos atributos sintetizados y heredados con la restricción de no tomar los valores de derecha hermanos.
En L-atribuidas SDTs, un no-terminal pueden obtener los valores de su padre, hijo, y nodos relacionados. Tal como se muestra en la siguiente producción
S  ABC
S puede tomar valores de A, B y C (sintetizada). UNA puede tomar valores de S. B puede tomar valores entre S y A. C se puede obtener los valores de S, A y B. No Hay terminal puede obtener los valores de los hermanos a su derecha.
Los atributos de L-atribuidas SDTs son evaluados por primero en profundidad y de izquierda a derecha el análisis.
L-atribuido SDT

COMPILADORES: Análisis Sintáctico

Un compilador toma como su entrada un programa escrito en lenguaje fuente y produce un programa equivalente escrito lenguaje objeto. Un compilador se compone internamente de varias etapas o fases que ser realizan operaciones lógicas

 Análisis Sintáctico: Obtiene la cadena de tokens del analizador léxico y verifica que puede ser generada por la gramática que describe el lenguaje fuente



El análisis sintáctico es un análisis a nivel de sentencias, y es mucho más complejo que el análisis léxico. Su función es tomar el programa fuente en forma de tokens, que recibe del analizador léxico, y determinar la estructura de las sentencias del programa. Este proceso es similar a determinar la estructura de una frase en Castellano, determinando quien es el sujeto, predicado, el verbo y los complementos.

El análisis sintáctico agrupa a los tokens en clases sintácticas (denominadas no terminales en la definición de la gramática), tales como expresiones, procedimientos, etc.
El analizador sintáctico o parser obtiene un árbol sintáctico (u otra estructura equivalente) en la cual las hojas son los tokens, y cualquier nodo que no sea una hoja, representa un tipo de clase sintáctica (operaciones). Por ejemplo el análisis sintáctico de la siguiente expresión:
(A+B)*(C+D)
Con las reglas de la gramática que se presenta a continuación dará lugar al árbol sintáctico de la figura 3:
<expresión> ::= <término> <más términos>
<más términos>::= +<término> <más términos>| - <término> <más términos> | <vacío>
<término> ::= <factor> <más factores>
<más factores>::= * <factor> <más factores>|/ <factor> <más factores> | <vacío>
<factor> ::= ( <expresión> ) | <variable> | <constante>
La estructura de la gramática anterior refleja la prioridad de los operadores, así los operadores “+” y “-” tienen la prioridad más baja, mientras que “*” y “/” tienen una prioridad superior. Se evaluaran en primer lugar las constantes, variables y expresiones entre paréntesis.
Los árboles sintácticos se construyen con un conjunto de reglas conocidas como gramática, y que definen con total precisión el lenguaje fuente.
Al proceso de reconocer la estructura del lenguaje fuente se conoce con el nombre de análisis sintáctico (parsing). Hay distintas clases de analizadores o reconocedores sintácticos,
pero en general se clasifican en 2 grandes grupos: A.S. Ascendentes y A.S. Descendentes.
La principal tarea del analizador sintáctico no es comprobar que la sintaxis del programa fuente sea correcta, sino construir una representación interna de ese programa y en el caso en que sea un programa incorrecto, dar un mensaje de error.


Para ello, el analizador sintáctico (A.S.) comprueba que el orden en que el analizador léxico le va entregando los tokens es válido. Si esto es así significará que la sucesión de  símbolos que representan dichos tokens puede ser generada por la gramática correspondiente al lenguaje del código fuente.

Ejemplo: Entrada: “num*num+num Gramática: E ::= E + T | T T ::= T * F | F F ::= num (E: expresión, T: término, F: factor)


lunes, 20 de febrero de 2017

COMPILADORES: Análisis Léxico

Un compilador toma como su entrada un programa escrito en lenguaje fuente y produce un programa equivalente escrito lenguaje objeto. Un compilador se compone internamente de varias etapas o fases que ser realizan operaciones lógicas:

·         Analizador léxico: Lee la secuencia de caracteres de izquierda a derecha del programa fuente  y agrupa las secuencias de caracteres en unidades con significado propio(componente léxico o tokens). Las palabras clave, identificadores operadores constantes numéricas, signos de puntuación, como separadores de sentencias, llaves, paréntesis, etc. Son diversas clasificaciones de componentes léxicos.
l  
Lee los caracteres del programa fuente de izquierda a derecha, y los agrupa en tokens


👉 Funciones del Analizador Léxico 

  • Convierte el programa fuente en una cadena de tokens 
  • Para reconocer el token usa un patrón, una regla que describe como se forman las cadenas que corresponden a un token. 
  • Salta comentarios y espacios en blanco (tabuladores, saltos de línea...) 
  • Tener el registro de la línea del archivo fuente que está siendo analizada 
  • Genera mensajes de error léxico, y se recupera del error 
  • Convierte los valores literales al tipo que corresponda 
  •  Si la entrada debe obedecer a un formato, verifica el formato  
👉 Tokens y Lexemas 


Token
Lexema
q Elemento básico del lenguaje q Unidad léxica indivisible
q Identifica una entidad lógica dentro del lenguaje
q Incluyen: Palabras Reservadas, Constantes, Operadores, Signos de Puntuación e Identificadores
q La cadena original que se identifica como token  
q No hay correspondencia 1-1 entre token-lexema
q La cadena original que se identifica como token
q No hay correspondencia 1-1 entre token-lexema


EJEMPLO:



👉 Palabras Reservadas
  • Identificador es una palabra que inicia con una letra, y es seguida por letras o dígitos 
  • Las palabras clave cumplen con este mismo patron de construcción 
  • Se hace necesario un mecanismo que permita decidir cuando una cadena es una palabra clave o un identificador 
  • Solución sencilla: Palabras Reservadas (que no pueden ser usadas como identificadores)

👉 Manejo de Buffers 

  • Cuando se implementa el scanner es necesario manejar un buffer de entrada para hacer mas eficiente la lectura de la cadena de entrada 
  • Generalmente se define un buffer del tamaño de un bloque de disco
  •  Se maneja un apuntador que marca el inicio del lexema que se está analizando, y un apuntador que marca el carácter que está siendo analizado 
 Posibilidades: 

 Un buffer


 Par de Buffers



Sentinelas: marcar el final del buffer con EOF. Entonces EOF significa: 
  • Llegó al final del 1er. buffer : debe cargar el segundo 
  • Llegó al final del 2o. Buffer: debe cargar el primero
  • Llegó al final del archivo 


miércoles, 8 de febrero de 2017

Instalar compilador GCC en Ubuntu

Pasos para instalar el compilador gcc/g++ 4.9 en Ubuntu :

  1. sudo add-apt-repository ppa:ubuntu-toolchain-r/test
  2. sudo apt-get update
  3. sudo apt-get install g++-4.9


Programas.


 ➤PROGRAMA 1

Realiza un código que imprima tu nombre


 🔎 Programa

#include <iostream.h>
#include <conio.h>
void main (void) {
char Saludo[4];
Saludo[0] = 'n';
Saludo[1] = 'a';
Saludo[2] = 't';
Saludo[3] = 'o';

for(int i=0;i<5;i++){
cout<<Saludo[i]<<endl;
}


getch();
}



 🔎 Programa compilado 











 ➤PROGRAMA 2

Realizar un programa en C++ que cuente los caracteres ingresados por teclado.


 🔎 Programa
#include <iostream>

using namespace std ;
int main ()
{
    int cont_car = 0; // contador de caracteres
    int cont_com = 0; // contador de comas
    cout << "Ingrese una frase hasta '. ': " ;
    char c ;
    cin.get(c); // lee un caracter
    while (c !='.') {
        cont_car++ ;
        if (c == ',')
            cont_com ++;
        cin.get(c); // lee un caracter
    }
    cout << "Cantidad de caracteres: " << cont_car << endl
         << "Cantidad de comas: " << cont_com << endl ;
    cin.get(c);
}

 🔎 Programa compilado 






martes, 7 de febrero de 2017

MAQUINA VIRTUAL

UNIDAD 1 ARQUITECTURA DE LOS COMPILADORES E INTEPRETES
Unidad de competencia
Determina la estructura general de los compiladores e intérpretes con base en la funcionalidad de sus etapas y fases

Una máquina virtual no es más que un software capaz de cargar en su interior otro sistema operativo haciéndole creer que es un PC de verdad. Tal y como su nombre indica, el concepto es tan sencillo como crear una máquina (PC, consola, móvil o lo que sea) que en vez de ser física es virtual o emulada.

¿Qué es una máquina virtual?
Una vez nos ha quedado claro que una máquina virtual no es realmente ninguna máquina llena de engranajes con un casco de realidad virtual, sino un software, entremos más en detalle sobre qué son las máquinas virtuales.
Lo primero que debes saber es que hay dos tipos de máquinas virtuales diferenciadas por su funcionalidad: las de sistema y las de proceso, si bien la gran mayoría de las veces que oigas hablar de una máquina virtual casi seguro que se estarán refiriendo a las de sistema.

Máquinas virtuales de sistema
Una máquina virtual de sistema es aquella que emula a un ordenador completo. En palabras llanas, es un software que puede hacerse pasar por otro dispositivo -como un PC- de tal modo que puedes ejecutar otro sistema operativo en su interior. Tiene su propio disco duro, memoria, tarjeta gráfica y demás componentes de hardware, aunque todos ellos son virtuales.
Que sus componentes sean virtuales no quiere decir necesariamente que no existan. Por ejemplo, una máquina virtual puede tener unos recursos reservados de 2 GB de RAM y 20 GB de disco duro, que obviamente salen de algún sitio: del PC donde está instalada la máquina virtual, también llamado a veces el hipervisor, el host o el anfitrión. Otros dispositivos podrían realmente ser inexistentes físicamente, como por ejemplo un CD-ROM que en verdad es el contenido de una imagen ISO en vez de un lector de CD de verdad.


Máquinas virtuales de proceso
Una máquina virtual de proceso es menos ambiciosa que una de sistema. En vez de emular un PC por completo, ejecuta un proceso concreto, como una aplicación, en su entorno de ejecución. Suena algo esotérico, pero lo usas cada vez que ejecutas una aplicación basada en Java o basada en .NET Framework.
Esto es de utilidad a la hora de desarrollar aplicaciones para varias plataformas, pues en vez de tener que programar específicamente para cada sistema, el entorno de ejecución (es decir, la máquina virtual) es el que se encarga de lidiar con el sistema operativo.
Las máquinas virtuales de proceso te permiten disfrutar de aplicaciones que se comportan de forma igual en plataformas tan distintas como Windows, Mac o Linux, pero tú como usuario normalmente no les prestarás mucha atención. Por eso, salvo que seas programador, generalmente cuando se habla de máquinas virtuales nos estamos refiriendo a las de sistema.



Para qué se usan las máquinas virtuales
Todo esto está muy bien, pero ¿para qué querría alguien crear un PC virtual dentro de su PC? Aunque así de entrada pudiera parecer una idea algo trivial, la verdad es que las máquinas virtuales tienen una gran variedad de utilidades tanto en el entorno profesional como en el del consumidor final. Estos son los principales usos:
Para poder probar otros sistemas operativos. Instalar un sistema operativo en tu PC es un proceso largo, aburrido y difícil de revertir si no estás satisfecho con los resultados. Así, cuando hay una nueva versión de Windows es más fácil y seguro probarla instalándola en una máquina virtual que en tu disco duro. Si algo va mal, la borras y se acabó, sin arriesgarte a perder mucho tiempo o tus datos.
Para ejecutar programas antiguos. ¿Qué pasa cuando tu negocio depende de un software que no se actualiza desde hace 20 años? Si no puedes modernizar el software no te queda otra que seguir cargándolo en un sistema operativo de su época. Con una máquina virtual este sistema antiguo puede funcionar en hardware actual en vez de en una chatarra de PC. Lo mismo se puede aplicar a juegos antiguos que han dejado de funcionar en hardware o software moderno.
Para usar aplicaciones disponibles para otros sistemas. También es posible que necesites una máquina virtual para ejecutar aplicaciones que han sido desarrolladas para otro sistema operativo distinto al que estás usando. Por ejemplo, para usar una aplicación para Linux desde Windows, o vice versa.
Para probar una aplicación en distintos sistemas. Como desarrollador de una aplicación te interesa que funcione correctamente en la mayor cantidad de configuraciones posibles, y eso incluye distintas versiones de sistemas operativos. Una opción es tener media docena de PC instalados con distintas versiones de Windows... o simplemente uno con máquinas virtuales de cada versión.
Como seguridad adicional. Al estar aislada del resto, una máquina virtual te proporciona una seguridad adicional en tareas precisas en las que quieres estar seguro de que una aplicación no tendrá acceso al resto de tus datos. Es por eso que se suelen usar para hacer cosas tan peligrosas como instalar virus y malware para estudiarlos.
Para aprovechar su gran dinamismo. Por su naturaleza las máquinas virtuales son muy útiles en ocasiones donde necesitas un extremo dinamismo en el sistema. Puedes guardar estados (copias exactas de sus datos), ampliarlas, moverlas a un hardware totalmente distinto y seguirán funcionando sin problemas. Por esto son imprescindibles por ejemplo en empresas con servidores web que hospedan multitud de máquinas con las páginas web de sus clientes

INTERPRETES

UNIDAD 1 ARQUITECTURA DE LOS COMPILADORES E INTERPRETES
Unidad de competencia
Determina la estructura general de los compiladores e intérpretes con base en la funcionalidad de sus etapas y fases


¿Qué es un intérprete?
Un intérprete ejecuta el programa sin traducirlo.
El funcionamiento de un intérprete se caracteriza por traducir y ejecutar, de una en una, las instrucciones del código fuente de un programa, pero, sin generar como salida código objeto.
Analiza el programa fuente y lo ejecuta directamente, o sea en el ejemplo del traductor humano, éste sería un traductor humano que conforme a lo que está escuchando va ejecutando, sin generar ningún escrito, es decir que sobre la marcha va traduciendo.
                                                                



¿Como funciona un interprete? 

Intérprete, que analiza el programa fuente y "lo ejecuta directamente", sin generar ningún código equivalente. Su acción equivale a la de un intérprete humano, que traduce las frases que oye sobre la marcha, sin producir ningún escrito permanente. Intérpretes y compiladores tienen diversas ventajas e inconvenientes que los hacen complementarios:
Un intérprete facilita la búsqueda de errores, pues la ejecución de un programa puede interrumpirse en cualquier momento para estudiar el entorno (valores de las variables, etc.). Además, el programa puede modificarse sobre la marcha, sin necesidad de volver a comenzar la ejecución.
El proceso que realiza un intérprete es el siguiente: lee la primera instrucción del código fuente, la traduce a código objeto y la ejecuta; a continuación, hace lo mismo con la segunda instrucción; y así sucesivamente, hasta llegar a la última instrucción del programa, siempre y cuando, no se produzca ningún error que detenga el proceso.

Un intérprete permite utilizar funciones y operadores más potentes, como por ejemplo ejecutar código contenido en una variable en forma de cadenas de caracteres. Usualmente, este tipo de instrucciones es imposible de tratar por medio de compiladores. Los lenguajes que incluyen este tipo de operadores y que, por tanto, exigen un intérprete, se llaman interpretativos. Los lenguajes compilativos, que permiten el uso de un compilador, prescinden de este tipo de operadores. En pocas palabras "el compilador sólo traduce; el intérprete decodifica y ejecuta.

Ventajas del intérprete frente al compilador:
•             El programa se puede ejecutar de inmediato, sin esperar a ser compilado.
•             Puede ser interrumpido con facilidad.
•             puede ser rápidamente modificado y ejecutado nuevamente.
•             Resultan muy apropiados durante la fase de desarrollo de un programa, ya que la compilación no permite la ejecución paso a paso del programa y con ello impide la edición seguimiento y depuración del programa.
Desventajas del intérprete frente al compilador:
•             La ejecución es más lenta, pues cada instrucción debe ser traducida a código máquina tantas veces como sea ejecutada.
•             No son adecuados en la fase de explotación del programa ya que el proceso de interpretación se ha de repetir cada vez que se ejecuta el programa, mientras que con la compilación, una vez obtenido el programa en leguaje máquina éste puede ser ejecutado sin necesidad de compilarlo de nuevo.
Son lenguajes interpretados:
•             PHP
•             ASP (hasta la versión 3)
•             HTML
•             JavaScript
•             Haskell
•             Prolog




COMPILADORES

UNIDAD 1 ARQUITECTURA DE LOS COMPILADORES E INTEPRETES
Unidad de competencia: Determina la estructura general de los compiladores e intérpretes con base en la funcionalidad de sus etapas y fases.


Introducción
Tanto los compiladores como los intérpretes son programas de gran complejidad. Afortunadamente, se sabe suficiente acerca de cómo estructurarlos y hay suficientes herramientas formales para que la complejidad se reduzca a niveles razonables.
¿Qué es un compilador?
·         Un compilador es un programa traductor
·         Compilar consiste en traducir un programa escrito en un cierto lenguaje a otro.
·         Un compilador es un pequeño programa informático, que se encarga de traducir (compilar) el código fuente de cualquier aplicación que se esté desarrollando
¿Para qué es un compilador?
·         Los compiladores se utilizan en todos los aspectos prácticos de la computación
·         Las técnicas utilizadas en la construcción de compiladores se aplican en otros contextos:
·         Procesamiento de información estructurada
·         Conversión de archivos
·         Compilación de circuitos
·         Los compiladores son programas muy complejos que utilizan de estructuras de datos y algoritmos útiles

¿Cuáles son las propiedades de un compilador?
·         Genera código correcto siempre
·         Satisface completamente las especificaciones de los lenguajes fuente y objetivo
·         Debe aceptar programas de tamaño arbitrario (solo limitado por la memoria disponible).
·         Velocidad de compilación, tamaño del compilador, calidad de los reportes de error
·



Fases de un compilador
  • ·         Entrada del programa fuente
  • ·         Lee el programa eficientemente
  • ·         Lo convierte en un flujo de caracteres
  • ·         Puede utilizar otros archivos, si estos fueron incluidos
  • ·         Coopera con el sistema operativo y el analizador léxico


ANÁLISIS LÉXICO:
  • ·         Identifica los tokens del flujo de entrada y determina su clase y representación
  • ·         Puede interpretar algunos tokens (identificar macros o palabras reservadas)


ANÁLISIS SINTÁCTICO:
  • ·         Convierte el flujo de tokens a un árbol de sintáctico
  • ·         Estos árboles no son una representación eficiente
  • ·         Se usan los arboles sintácticos abstractos

·
ANÁLISIS SEMÁNTICO
  • ·         Se recolecta información del programa
  • ·         Tipos de datos
  • ·         Etiquetas (goto)
  • ·         Se hace anotaciones a los nodos del ´árbol sintáctico abstracto con los resultados


GENERACIÓN DE CÓDIGO INTERMEDIO:

  • ·         Traduce las construcciones específicas del lenguaje fuente en el árbol semántico abstracto con anotaciones a construcciones más generales
  • ·         Debe ser “fácil” generar código de maquina a partir del código intermedio para maquinas diferentes
  • ·         Generalmente incluye expresiones e instrucciones de control de flujo (condiciones, saltos)


OPTIMIZACIÓN DE CÓDIGO INTERMEDIO:
  • ·         Intenta mejorar la eficiencia del código intermedio
  • ·         Se puede hacer incorporación de constantes
  • ·         Se puede remplazar la llamada a una rutina con el contenido de la rutina.


GENERACIÓN DE CÓDIGO EN LENGUAJE OBJETIVO:

  • ·         Se re-escribe el árbol semántico abstracto con anotaciones como una lista de instrucciones en lenguaje objetivo
  • ·         Toma instrucciones del árbol semántico abstracto con anotaciones
  • ·         Asigna los registros que se utilizaran para almacenar datos
  • ·         Acomoda las instrucciones en el orden correcto


OPTIMIZADOR DE CÓDIGO EN LENGUAJE OBJETIVO:

  • ·         Remplaza secuencias de instrucciones en lenguaje objetivo por secuencias equivalentes que son más rápidas o más cortas.
  • ·         Depende de las propiedades del lenguaje objetivo


OPTIMIZADORES:

  • ·         La implementación de optimizadores es la última fase en el desarrollo de un compilador
  • ·         Las optimizaciones no son necesarias para un compilador, la correctitud si
  • ·         Es más fácil acelerar un programa correcto que corregir un programa rápido

·