Download lenguaje de programación

Document related concepts

Programación funcional wikipedia , lookup

Ocaml wikipedia , lookup

Haxe wikipedia , lookup

Lisp wikipedia , lookup

Rust (lenguaje de programación) wikipedia , lookup

Transcript
Agenda Clase 1
Presentación
Evolución histórica
Evolución de los lenguajes de
programación
Clasificación de los lenguajes de
programación
Compilación e interpretación
Temas Exposiciones
Web Servicies
SOA – Arquitectura Orientada a Servicios
PHP
J SP
J avascript
Eclipse (plugins C ++, C , PHP,..)
[Presentación 15min]
C ontenido
●
Qué es?
●
Areas de aplicación
●
●
Ejemplos Básicos
Relaciones con otras herramientas
(versiones, plungins, interfaces)
Evolución Histórica
En los cuarenta las computadoras ocupaban cuartos enteros,
consumían gran cantidad de electricidad y tenían una capacidad de
cómputo similar a la de una calculadora de la actualidad.
En un principio eran programadas en lenguaje de máquina o
secuencia de bits controlados directamente por un procesador que
permiten añadir, comparar y mover datos de un lugar a otro en el
momento apropiado.
Posteriormente, dado el aumento en el tamaño de los programas y lo
engorroso de la programación en lenguaje de máquina, se ideó el
lenguaje ensamblador que son abreviaciones mnemónicas que
corresponden 1 a 1 a las instrucciones de la máquina y que son
traducidas a través de un assembler.
El lenguaje ensamblador evolucionó con macro expansiones
permitiéndole a los programadores definir una secuencia de
instrucciones a través de una abreviación.
Es de notar que la programación dependía de la máquina, ya que
cada una poseía su propio lenguaje ensamblador, y por tanto, los
programadores debían pensar en términos de las instrucciones que
una máquina en específico podía ejecutar.
gran
tamaño
escasa
capacidad de
cómputo y
almacenamiento
Programados en lenguaje de
máquina
Posteriormente surgen
los lenguajes
ensambladores
Tras el desarrollo de las primeras computadoras surgió la
necesidad de programarlas para que realizaran las tareas
deseadas.
Los lenguajes más primitivos fueron los denominados lenguajes
máquina. Como el hardware se desarrollaba antes que el
software, estos lenguajes se basaban en el hardware, con lo que
cada máquina tenía su propio lenguaje y por ello la
programación era un trabajo costoso, válido sólo para esa
máquina en concreto.
Posteriormente, dado el aumento en el tamaño de los programas
y lo engorroso de la programación en lenguaje de máquina, se
ideó el lenguaje ensamblador que son abreviaciones
mnemónicas que corresponden 1 a 1 a las instrucciones de la
máquina y que son traducidas a través de un assembler.
POsteriormente se desarrollaron las primeras herramientas
automáticas generadoras de código fuente. Pero con el
permanente desarrollo de las computadoras, y el aumento de
complejidad de las tareas, surgieron a partir de los años 50 los
primeros lenguajes de programación de alto nivel.
lenguaje de programación es un conjunto de símbolos y reglas
sintácticas y semánticas que definen su estructura y el significado
de sus elementos y expresiones, y utilizado para controlar el
comportamiento físico y lógico de una máquina.
Un lenguaje de programación permite a uno o más programadores
especificar de manera precisa: sobre qué datos una computadora
debe operar, cómo deben ser estos almacenados, transmitidos y
qué acciones debe tomar bajo una variada gama de circunstancias.
Todo esto, a través de un lenguaje que intenta estar relativamente
próximo al lenguaje humano o natural, tal como sucede con el
lenguaje Léxico. Una característica relevante de los lenguajes de
programación es precisamente que más de un programador
puedan tener un conjunto común de instrucciones que puedan ser
comprendidas entre ellos para realizar la construcción del
programa de forma colaborativa.
Con la aparición de los distintos lenguajes, solían aparecer diferentes
versiones de un mismo lenguaje, por lo que surgió la necesidad de
estandarizarlos para que fueran más universales. Las organizaciones
que se encargan de regularizar los lenguajes son ANSI (Instituto de
las Normas Americanas) y ISO (Organización de Normas
Internacionales).
Con el nacimiento de los primeros lenguajes de alto nivel, se hizo
necesario un mecanismo para la traducción de las instrucciones de
estos lenguajes a las que pueden ser entendidas por la máquina, es
por ello que surge el compilador que no es más que un programa del
sistema que lleva a cabo las mencionadas labores de traducción.
Este compilador es más complejo que el lenguaje ensamblador ya
que no hay una correspondencia 1 a 1 entre el código fuente y las
instrucciones de la máquina, además sus programas son más lentos
que los elaborados en lenguaje ensamblador.
Sin embargo, el incremento en la complejidad del hardware y las
mejoras en las tecnologías de los compiladores provocaron que éstos
desarrollaran mejor código que los humanos, con un ahorro
sustancial de esfuerzo, no sólo en las labores de programación sino
también en las de mantenimiento y optimización.
Evolución: el pasar de los años ha propiciado el surgimiento de los
lenguajes y la evolución de los paradigmas de programación,
teniendo por ejemplo en los 60’s y 70’s el paso de la programación
estructurada basada en “go to” (Fortran, Cobol, Basic, etc.) a “loops
while”, instrucciones “case” y otras construcciones similares de alto
nivel; y en los 80’s la evolución de la estructura de bloques anidados
(Algol, Pascal, Ada) a la orientación a objetos (Smalltalk, C++,
Eiffel)
Propósitos Especiales: los lenguajes fueron desarrollados para un
dominio específico, por lo que a pesar de poder realizar varias tareas,
se enfatiza en la especialización. Por ejemplo LISP está orientado al
manejo de datos simbolicos y estructuras de datos complejos, Snobol
y Icon al manejo de Strings, C a la programación de bajo nivel y
Prolog a las relaciones lógicas entre datos.
Preferencia Personal: vinculada a los gustos del programador y su
inclinación a programar con un lenguaje más que con otro.
Poder Expresivo: en esencia todos los lenguajes son equivalentes
(pueden hacer las misma tareas), sin embargo las facilidades que
ofrezca el lenguaje incidirán en la habilidad del programador para
escribir código claro, conciso y mantenible.
Facilidad de Uso para Novatos: mientras más baja sea la curva de
aprendizaje del lenguaje, mayor será su popularidad.
Facilidad de Implementación: se refiere a la facilidad que brinda el
lenguaje para trabajar en máquinas pequeñas con recursos limitados.
Un ejemplo resaltante es Pascal cuyo diseñador Nicklaus Wirth
desarrolló una implementación simple y portátil del lenguaje que
distribuyó gratuitamente en universidades alrededor del mundo.
Excelentes Compiladores: esta excelencia puede considerarse por
una parte a la generación rápida de código de los compiladores cuya
evolución histórica les ha facilitado la tarea, o a las facilidades que
ofrecen ciertos compiladores para aligerar la carga del programador
en proyectos extensos.
Economía, Patronato e Inercia: Se refiere por un lado al respaldo de
un patrocinante poderoso (Cobol y PL/I de IBM y sobre todo Ada
que por cuya complejidad habría muerto de no ser por el respaldo del
Departamento de Defensa de los EE.UU.) y por el otro a una amplia
base de software instalado y experticia de programación cuyo
reemplazo sería sumamente costoso aunque existan mejores
opciones.
Aparte de estas características también constituyen razones de éxito
la claridad conceptual y la eficiencia de implementación, ya que con
ello se cubren las expectativas tanto de implementadores de
lenguajes como de los programadores que harán uso de los mismos.
Clasificación de los
lenguajes
Nivel de abstracción
Forma de ejecución
Paradigma de programación
Lenguajes Maquina
Estan escritos en lenguajes directamente inteligibles por la
maquina (computadora), ya que sus intrucciones son cadenas
binarias (0 y 1). Da la posibilidad de cargar (transferir un
programa a la memoria) sin necesidad de traducción posterior
lo que supone una velocidad de ejecución superior, solo que
con poca fiabilidad y dificuldad de verificar y poner a punto
los programas.
Lenguajes de bajo nivel
Los lenguajes de bajo nivel son lenguajes de programación
que se acercan al funcionamiento de una computadora. El
lenguaje de más bajo nivel es, por excelencia, el código
máquina. A éste le sigue el lenguaje ensamblador, ya que al
programar en ensamblador se trabajan con los registros de
memoria de la computadora de forma directa.
Lenguajes de medio nivel
Hay lenguajes de programación que son considerados por
algunos expertos como lenguajes de medio nivel (como es el
caso del lenguaje C) al tener ciertas características que los
acercan a los lenguajes de bajo nivel pero teniendo, al mismo
tiempo, ciertas cualidades que lo hacen un lenguaje más
cercano al humano y, por tanto, de alto nivel.
Lenguajes de alto nivel
Los lenguajes de programación de alto nivel se caracterizan
por expresar los algoritmos de una manera adecuada a la
capacidad cognitiva humana, en lugar de a la capacidad
ejecutora de las máquinas. En los primeros lenguajes de alto
nivel la limitación era que se orientaban a un área específica
y sus instrucciones requerían de una sintaxis predefinida. Se
clasifican como lenguajes procedimentales. Otra limitación
de los lenguajes de alto nivel es que se requiere de ciertos
conocimientos de programación para realizar las secuencias
de instrucciones lógicas. Los lenguajes de muy alto nivel se
crearon para que el usuario común pudiese solucionar tal
problema de procesamiento de datos de una manera más fácil
y rápida.
Lenguajes compilados
Naturalmente, un programa que se escribe en un lenguaje de alto nivel
también tiene que traducirse a un código que pueda utilizar la
máquina. Los programas traductores que pueden realizar esta
operación se llaman compiladores. Éstos, como los programas
ensambladores avanzados, pueden generar muchas líneas de código de
máquina por cada proposición del programa fuente. Se requiere una
corrida de compilación antes de procesar los datos de un problema.
Los compiladores son aquellos cuya función es traducir un programa
escrito en un determinado lenguaje a un idioma que la computadora
entienda (lenguaje máquina con código binario).
Al usar un lenguaje compilado, el programa desarrollado nunca se
ejecuta mientras haya errores, sino hasta que luego de haber
compilado el programa, ya no aparecen errores en el código
Lenguajes interpretados
Se puede también utilizar una alternativa diferente de los compiladores
para traducir lenguajes de alto nivel. En vez de traducir el programa
fuente y grabar en forma permanente el código objeto que se produce
durante la corrida de compilación para utilizarlo en una corrida de
producción futura, el programador sólo carga el programa fuente en la
computadora junto con los datos que se van a procesar. A
continuación, un programa intérprete, almacenado en el sistema
operativo del disco, o incluido de manera permanente dentro de la
máquina, convierte cada proposición del programa fuente en lenguaje
de máquina conforme vaya siendo necesario durante el proceso de los
datos. No se graba el código objeto para utilizarlo posteriormente.
La siguiente vez que se utilice una instrucción, se le debe interpretar
otra vez y traducir a lenguaje máquina. Por ejemplo, durante el
procesamiento repetitivo de los pasos de un ciclo, cada instrucción del
ciclo tendrá que volver a ser interpretado cada vez que se ejecute el
ciclo, lo cual hace que el programa sea más lento en tiempo de
ejecución (porque se va revisando el código en tiempo de ejecución)
pero más rápido en tiempo de diseño (porque no se tiene que estar
compilando a cada momento el código completo). El intérprete
elimina la necesidad de realizar una corrida de compilación después de
cada modificación del programa cuando se quiere agregar funciones o
corregir errores; pero es obvio que un programa objeto compilado con
antelación deberá ejecutarse con mucha mayor rapidez que uno que se
debe interpretar a cada paso durante una corrida de producción
Imperativo describe la programación en términos del estado del programa y sentencias que cambian dicho
estado. Los programas imperativos son un conjunto de instrucciones que le indican al computador cómo
realizar una tarea.
La implementación de hardware de la mayoría de computadores es imperativa; prácticamente todo el
hardware de los computadores está diseñado para ejecutar código de máquina, que es nativo al computador,
escrito en una forma imperativa. Esto se debe a que el hardware de los computadores implementa el
paradigma de las Máquinas de Turing. Desde esta perspectiva de bajo nivel, el estilo del programa está
definido por los contenidos de la memoria, y las sentencias son instrucciones en el lenguaje de máquina
nativo del computador (por ejemplo el lenguaje ensamblador).
Los lenguajes imperativos de alto nivel usan variables y sentencias más complejas, pero aún siguen el mismo
paradigma. Las recetas y las listas de revisión de procesos, a pesar de no ser programas de computadora, son
también conceptos familiares similares en estilo a la programación imperativa; cada paso es una instrucción,
y el mundo físico guarda el estado
Funcional Los programas escritos en un lenguaje funcional están constituidos únicamente por definiciones
de funciones, entendiendo éstas no como subprogramas clásicos de un lenguaje imperativo, sino como
funciones puramente matemáticas, en las que se verifican ciertas propiedades como la transparencia
referencial (el significado de una expresión depende únicamente del significado de sus subexpresiones), y
por tanto, la carencia total de efectos laterales.
Otras características propias de estos lenguajes son la no existencia de asignaciones de variables y la falta de
construcciones estructuradas como la secuencia o la iteración (lo que obliga en la práctica a que todas las
repeticiones de instrucciones se lleven a cabo por medio de funciones recursivas).
Existen dos grandes categorías de lenguajes funcionales: los funcionales puros y los híbridos. La diferencia
entre ambos estriba en que los lenguajes funcionales híbridos son menos dogmáticos que los puros, al admitir
conceptos tomados de los lenguajes imperativos, como las secuencias de instrucciones o la asignación de
variables. En contraste, los lenguajes funcionales puros tienen una mayor potencia expresiva, conservando a
la vez su transparencia referencial, algo que no se cumple siempre con un lenguaje funcional híbrido.
Lógica La programación lógica consiste en la aplicación del corpus de conocimiento sobre lógica para el
diseño de lenguajes de programación
Orientado a Objetos usa objetos y sus interacciones para diseñar aplicaciones y programas de computadora.
Está basado en varias técnicas, incluyendo herencia, modularidad, polimorfismo, y encapsulamiento. Su uso
se popularizó a principios de la década de 1990. Actualmente son muchos los lenguajes de programación que
soportan la orientación a objetos.
La programación orientada a objetos expresa un programa como un conjunto de estos objetos, que colaboran
entre ellos para realizar tareas. Esto permite hacer los programas y módulos más fáciles de escribir, mantener
y reutilizar.
De esta forma, un objeto contiene toda la información que permite definirlo e identificarlo frente a otros
objetos pertenecientes a otras clases e incluso frente a objetos de una misma clase, al poder tener valores bien
diferenciados en sus atributos. A su vez, los objetos disponen de mecanismos de interacción llamados
métodos que favorecen la comunicación entre ellos. Esta comunicación favorece a su vez el cambio de
estado en los propios objetos. Esta característica lleva a tratarlos como unidades indivisibles, en las que no se
separan ni deben separarse el estado y el comportamiento.
Los métodos (comportamiento) y atributos (estado) están estrechamente relacionados por la propiedad de
conjunto. Esta propiedad destaca que una clase requiere de métodos para poder tratar los atributos con los
que cuenta. El programador debe pensar indistintamente en ambos conceptos, sin separar ni darle mayor
importancia a ninguno de ellos, hacerlo podría producir el hábito erróneo de crear clases contenedoras de
información por un lado y clases con métodos que manejen a las primeras por el otro. De esta manera se
estaría realizando una programación estructurada camuflada en un lenguaje de programación orientado a
objetos.
Un lenguaje imperativo es un tipo de lenguaje de
programación. Es este tipo de lenguajes, las instrucciones se
ejecutan unas tras otras, de manera secuencial, salvo cuando
se encuentran estructuras de control condicionales o bucles.
Hay declaración de variables, tipos y procedimientos, aunque
esto varía notablemente en función del lenguaje utilizado,
pues los hay que exigen las declaraciones mientras que otros
permiten que esos elementos no sean declarados.
Ejemplo de programa en un lenguaje imperativo: Este
sería el código de un programa que determina el factorial de
un número en un lenguaje imperativo inventado:
procedimiento factorial(entero n){
entero resultado = 1;
mientras (n > 0) {
resultado = resultado * n;
n = n - 1; }
devuelve resultado; }
Este procedimiento (o función) recibe un número entero n.
Declara una variable resultado que será el resultado final a
devolver. Inicialmente, tiene como valor el 1. Después llega
una estructura de control denominada bucle, que se ejecuta
mientras la condición expresada entre los paréntesis (n > 0)
sea cierta. Dentro del bucle se multiplica la variable resultado
por n y el valor se deja de nuevo en resultado. La siguiente
sentencia (n = n - 1) es necesaria para ir haciendo el factorial,
así como para salir en algún momento del bucle. Por último,
tras salir del bucle ya podemos devolver el valor final, que
estará en la variable resultado.
Nótese que, si en un principio, la variable n es 0, no se
entrará en el bucle al no ser cierta la condición, por lo que
pasaría directamente a devolver la variable resultado, que
tiene valor inicial 1 (0! = 1).
El objetivo es conseguir lenguajes expresivos y matemáticamente elegantes, en los que no sea
necesario bajar al nivel de la máquina para describir el proceso llevado a cabo por el
programa, y evitando el concepto de estado del cómputo. La secuencia de computaciones
llevadas a cabo por el programa se regiría única y exclusivamente por la reescritura de
definiciones más amplias a otras cada vez más concretas y definidas, usando lo que se
denominan "definiciones dirigidas".
Características
Los programas escritos en un lenguaje funcional están constituidos únicamente por
definiciones de funciones, entendiendo éstas no como subprogramas clásicos de un lenguaje
imperativo, sino como funciones puramente matemáticas, en las que se verifican ciertas
propiedades como la transparencia referencial (el significado de una expresión depende
únicamente del significado de sus subexpresiones), y por tanto, la carencia total de efectos
laterales.
Otras características propias de estos lenguajes son la no existencia de asignaciones de
variables y la falta de construcciones estructuradas como la secuencia o la iteración (lo que
obliga en la práctica a que todas las repeticiones de instrucciones se lleven a cabo por medio
de funciones recursivas).
Existen dos grandes categorías de lenguajes funcionales: los funcionales puros y los híbridos.
La diferencia entre ambos estriba en que los lenguajes funcionales híbridos son menos
dogmáticos que los puros, al admitir conceptos tomados de los lenguajes imperativos, como
las secuencias de instrucciones o la asignación de variables. En contraste, los lenguajes
funcionales puros tienen una mayor potencia expresiva, conservando a la vez su transparencia
referencial, algo que no se cumple siempre con un lenguaje funcional híbrido.
Lenguajes funcionales
Entre los lenguajes funcionales puros, cabe destacar a Haskell y Miranda. Los lenguajes
funcionales híbridos más conocidos son Scala, Lisp, Scheme, Ocaml, SAP y Standard ML
(estos dos últimos, descendientes del lenguaje ML). Erlang es otro lenguaje funcional de
programación concurrente. R también es un lenguaje funcional dedicado a la estadística.[1]
Recientemente Microsoft Research está trabajando en el lenguaje F# (Functional#).
Entre otros lenguajes que se podrían utilizar para programación funcional se podrían incluir a
Perl, pues, aunque es un lenguaje de propósito muy general, se pueden realizar programas
usando exclusivamente funciones definidas por el usuario. Así como Python, como lenguage
que incorpora el paradigma funcional.
La característica principal de la programación funcional es que los cálculos se ven como una
función matemática que hacen corresponder entradas y salidas.
• No hay noción de posición de memoria y por tanto, necesidad de una instrucción de
asignación.
• Los bucles se modelan a través de la recursividad ya que no hay manera de incrementar o
disminuir el valor de una
variable.
Todos los procedimientos son funciones y distinguen claramente los
valores de entrada (parámetros) de los de salida (resultados).
● No existen variables ni asignaciones – las variables han sido
reemplazadas por los parámetros.
● No existen ciclos – éstos han sido reemplazados por las llamadas
recursivas.
El valor de una función depende sólo del valor de sus parámetros y no del
orden de evaluación o de la trayectoria de ejecución que llevó a la
llamada.
● Las funciones son valores de primera clase.
Lenguaje Lógico
Programas escritos en un subc onjunto
de lógica de primer orden
Una base de datos de relaciones
lógicas y detalles que se cumplen
para la aplicación
Lenguaje de programaci´on basado en este esquema que fue introducido
a fines de 1971 (cf. “The Birth of Prolog”,
I Los programas se escriben en un subconjunto de la l´ogica de primer
orden
I El mecanismo te´orico en el que se basa es el m´etodo de resoluci´on
I Para motivar y comprender este mecanismo primero lo vamos a estudiar
en el ´ambito de la l´ogica proposicional
Un programa en Prolog consiste de una base de datos de relaciones
lógicas y detalles que se cumplen para la aplicación. Dicha base de datos
no tiene una estructura impuesta, ni un procedimiento o clase principal.
Los datos y relaciones de un programa en Prolog se escriben en un único
archivo, el cual es consultado por el programa cuando se le hace una
pregunta.
padrede('juan', 'maria').
padrede('pablo', 'juan').
padrede('pablo', 'marcela').
padrede('carlos', 'debora').
% juan es padre de maria
% pablo es padre de juan
% pablo es padre de marcela
% carlos es el padre de debora
hijode(A,B) :- padrede(B,A).
% A es hijo de B si B es padre de A.
abuelode(A,B) :- padrede(A,C), padrede(C,B). % A es abuelo de B si A es
padre de C y C es padre B.
hermanode(A,B) :- padrede(C,A) , padrede(C,B), A \== 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.
familiarde(A,B) :- padrede(A,B).
familiarde(A,B) :- hijode(A,B).
familiarde(A,B) :- hermanode(A,B).
?- hermanode('juan', 'marcela'). % juan es hermano de marcela?
yes
?- hermanode('carlos', 'juan'). % carlos es hermano de juan?
no
Lenguaje Orientado a Objetos
Usa objetos y sus interacciones para
diseñar aplicaciones
Un objeto incluye toda la
información que permite definirlo e
identificarlo.
Orientado a Objetos usa objetos y sus interacciones para diseñar aplicaciones y programas de
computadora. Está basado en varias técnicas, incluyendo herencia, modularidad, polimorfismo, y
encapsulamiento. Su uso se popularizó a principios de la década de 1990. Actualmente son
muchos los lenguajes de programación que soportan la orientación a objetos.
La programación orientada a objetos expresa un programa como un conjunto de estos objetos, que
colaboran entre ellos para realizar tareas. Esto permite hacer los programas y módulos más fáciles
de escribir, mantener y reutilizar.
De esta forma, un objeto contiene toda la información que permite definirlo e identificarlo frente
a otros objetos pertenecientes a otras clases e incluso frente a objetos de una misma clase, al
poder tener valores bien diferenciados en sus atributos. A su vez, los objetos disponen de
mecanismos de interacción llamados métodos que favorecen la comunicación entre ellos. Esta
comunicación favorece a su vez el cambio de estado en los propios objetos. Esta característica
lleva a tratarlos como unidades indivisibles, en las que no se separan ni deben separarse el estado
y el comportamiento.
Los métodos (comportamiento) y atributos (estado) están estrechamente relacionados por la
propiedad de conjunto. Esta propiedad destaca que una clase requiere de métodos para poder
tratar los atributos con los que cuenta. El programador debe pensar indistintamente en ambos
conceptos, sin separar ni darle mayor importancia a ninguno de ellos, hacerlo podría producir el
hábito erróneo de crear clases contenedoras de información por un lado y clases con métodos que
manejen a las primeras por el otro. De esta manera se estaría realizando una programación
estructurada camuflada en un lenguaje de programación orientado a objetos.
Por qué estudiamos lenguajes de
programación?
programación?
Facilita el aprendizaje del lenguaje
Permite entender características del
lenguaje
Ayuda a la escogencia entre alternativas
C ontribuye a hacer buen uso de las
herramientas relacionadas.
C ompilación
Interpretación
Viendo el compilador en alto nivel, éste se encarga de traducir el
código fuente a un programa objeto (típicamente en lenguaje de
máquina).
A su vez el compilador suele ser un programa escrito en lenguaje de
máquina.
Cuando un programa objeto es escrito a un archivo en un formato
que puede ser entendido por el sistema operativo se conoce como
código objeto.
Una de las ventajas de la compilación es que ofrece mejor
desempeño, ya que el proceso de compilación debe llevarse a cabo
una sola vez y el programa puede ser ejecutado en muchas
oportunidades.
Otra de las características de la compilación es que durante ella no se
consideran las decisiones que deben ser realizadas a tiempo de
ejecución.
En las arquitecturas de los microprocesadores modernos (superscalar
RISC) los compiladores pueden generar mejor código que los
programadores en assembler.
Un compilador es un programa informático que traduce un
programa escrito en un lenguaje de programación a otro
lenguaje de programación, generando un programa
equivalente que la máquina será capaz de interpretar.
Usualmente el segundo lenguaje es código máquina, pero
también puede ser simplemente texto. Este proceso de
traducción se conoce como compilación.
Un compilador es un programa que permite traducir el código
fuente de un programa en lenguaje de alto nivel, a otro
lenguaje de nivel inferior (típicamente lenguaje máquina). De
esta manera un programador puede diseñar un programa en
un lenguaje mucho más cercano a como piensa un ser
humano, para luego compilarlo a un programa más manejable
por una computadora.
Normalmente los compiladores están divididos en dos partes:
Front End: es la parte que analiza el código fuente,
comprueba su validez, genera el árbol de derivación y rellena
los valores de la tabla de símbolos. Esta parte suele ser
independiente de la plataforma o sistema para el cual se vaya
a compilar.
Back End: es la parte que genera el código máquina,
específico de una plataforma, a partir de los resultados de la
fase de análisis, realizada por el Front End.
Esta división permite que el mismo Back End se utilice para
generar el código máquina de varios lenguajes de
programación distintos y que el mismo Front End que sirve
para analizar el código fuente de un lenguaje de
programación concreto sirva para generar código máquina en
varias plataformas distintas.
El código que genera el Back End normalmente no se puede
ejecutar directamente, sino que necesita ser enlazado por un
programa enlazador (linker)
El interpretador implementa una máquina virtual cuyo “lenguaje de
máquina” es el lenguaje de alto nivel en el que está escrito el
programa.
El interpretador lee más o menos una línea por vez y la ejecuta.
Como ventaja con respecto al compilador, el interpretador ofrece
mayor flexibilidad y mensajes de error más explicativos.
Adicionalmente, se comienza a ejecutar una vez hechas las
modificaciones sin esperar por el proceso de recompilación.
Muchos lenguajes interpretados emplean un traductor inicial (preprocesador)
que remueve comentarios y espacios en blanco, y agrupa caracteres en
“tokens” para formar palabras clave, identificadores, números y símbolos.
Luego expande abreviaciones al estilo de un macro de “assembler” y
finalmente identifica estructuras sintácticas de alto nivel como “loops” y
subrutinas. Lo que se busca es obtener una forma intermedia, similar al código
fuente, que pueda interpretarse con mayor facilidad.
Si el traductor es “sencillo” es decir, hace una transformación trivial del código
fuente, entonces se considera como un interpretador.
Ahora bien si la traducción es más “compleja”, es decir no hay fuerte similitud
entre el programa intermedio y el fuente, el traductor se considera un
compilador que produce una forma intermedia que puede interpretarse a
posteriori.
Por otro lado, ciertos ambientes de programación ( conjunto de herramientas
integradas al compilador o interpretador que permiten la edición, y debugging
de código) para Pascal, C y otros lenguajes imperativos incluyen interpretación
y compilación.
Se pueden conseguir compiladores (LISP, Prolog, Smalltalk) que permiten
binding tardío por tanto el compilador trabaja en conjunción con un
interpretador. (El binding tardío se ahondará en clases futuras, por ahora basta
con saber que éste implica que las referencias a propiedades y métodos se
resuelven a tiempo de ejecución).
En ocasiones un sistema de programación puede postergar la compilación
hasta el último momento posible (just in time compiler) traduciendo código
binario en lenguaje de máquina inmediatamente antes de cada ejecución del
programa (Java).
En máquinas diseñadas antes de los 80’s las instrucciones a nivel de
ensamblador no estaban implementadas en hardware, y corrían sobre un
interpretador escrito en microcódigo (firmware) almacenado en ROM y
ejecutado por el hardware.
El Linker se encarga de asociar las rutinas de librería apropiadas al
programa final. Nótese que la compilación produce lenguaje de máquina
incompleto ya que quedan por resolver las referencias a librerías
.
Muchos compiladores generan código “assembler” en lugar de lenguaje de
maquina ya que:
- Facilita el “debugging”
- Es más fácil de leer por las personas.
- Aisla al compilador de cambios en el formato de los
archivos del lenguaje de máquina que son mantenidos por las diversas
versiones de Sistemas Operativos.