Tema 5 - Lenguajes de programación TEMA 5: Lenguajes de Compilación y depuración. 15/03/2011 programación. Tipología y evolución. Índice 1 INTRODUCCIÓN___________________________________________________________________1 2 TIPOS DE LENGUAJES_____________________________________________________________2 2.1 Niveles de abstracción del lenguaje__________________________________________________2 2.2 Características del lenguaje de programación__________________________________________3 2.2.1 Entorno de programación_______________________________________________4 2.3 Paradigmas de programación_______________________________________________________4 3 LA COMPILACIÓN E INTERPRETACIÓN____________________________________________5 3.1 Enlace_________________________________________________________________________5 4 DEPURACIÓN DE PROGRAMAS_____________________________________________________6 5 EVOLUCIÓN HISTÓRICA DE LOS LENGUAJES DE PROGRAMACIÓN_________________7 1 Introducción La misión de un sistema informático es procesar datos. Lee unos datos de entrada y realiza operaciones aritméticas y lógicas sobre estos datos para obtener otros datos que son el resultado buscado. El control de las operaciones que debe realizar el sistema informático lo realizan los programas. Un programa se compone de un conjunto de instrucciones comprensibles por el ordenador, cada instrucción indica una operación al ordenador: leer/guardar un dato, un salto en el flujo del programa, una operación aritmética... El formato de instrucciones que un ordenador puede interpretar se denomina “lenguaje máquina”. Este lenguaje es muy difícil de manejar por parte de las personas que quieran escribir un programa. Por ello, se han ido diseñando programas de mayor nivel de abstracción que reduzcan el esfuerzo necesario para programar. Para que ejecutar los programas escritos en lenguajes de alto nivel de abstracción, primero se traducen al lenguaje de bajo nivel que el sistema informático es capaz de interpretar. Página 1 de 7 Tema 5. Lenguajes de programación 2 15/03/2011 Tipos de lenguajes Existen multitud de lenguajes diferentes con características dispares. Los principales criterios de clasificación son: 2.1 Niveles de abstracción del lenguaje El aumento de los niveles de abstracción de los lenguajes de programación ha seguido, más o menos, un orden temporal. Es por ello que se clasifican en generaciones. 1ª Generación Es la programación usando lenguaje máquina, como he indicado en la introducción, es una forma costosa de programar. El motivo es que está diseñado para ser ejecutado por parte de la CPU del ordenador, y no para su uso por parte de las personas. La única mejora era utilizar cargadores que permitían utilizar codificación octal o hexadecimal en vez de binario. 2ª Generación Se sustituye el lenguaje máquina por lenguaje ensamblador. Es un lenguaje idéntico al lenguaje máquina pero tiene un léxico más fácil de usar. Sustituye la codificación numérica por el uso de codificación alfanumérica, más fácil de recordar (pnemónicos). La traducción a lenguaje máquina es directa, cada instrucción ensamblador da lugar a una instrucción lenguaje máquina. Los programas en ensamblador se traducen a lenguaje máquina para que puedan ser ejecutados. 3º Generación o lenguajes de programación El siguiente paso fue crear lenguajes con un mayor nivel de abstracción, más fáciles de entender y usar que los anteriores. Tienen sintaxis algebraicas, compactas y fáciles de usar por parte de los usuarios. Estos lenguajes se denominan lenguajes de programación o de alto nivel. Cada instrucción de alto nivel se traduce en una serie de instrucciones de bajo nivel. El lenguaje de alto nivel es más productivo e independiente de la máquina. Actualmente todavía siguen siendo los más utilizados. Las ventajas de usar estos lenguajes son: ► Hacen transparente las características del computador al programador. Por ejemplo: El programador no tiene porque saber el número de registros de la CPU. ► Portabilidad: Un programa en lenguaje de alto nivel es independiente de la máquina. Es por ello que es más fácil de llevarlo a otro tipo de máquinas. Sólo es necesario que se disponga de un traductor adecuado y que tenga los recursos externos necesarios (p.e. librerías) ► Permiten hacer los programas de manera más concisa. Las instrucciones de un lenguaje de alto nivel “hacen más cosas” que uno de bajo nivel. Se necesitan menos instrucción para codificar lo mismo. ► Permiten programar en términos del problema a resolver. Por ejemplo, se puede dar nombres simbólicos a los datos y funciones, en vez de referenciarlos a través de sus posiciones de memoria. Los lenguajes de alto nivel no sólo han conseguido facilitar el desarrollo y mantenimiento de los programas (reducir el coste del software), sino que han permitido desarrollar programas de gran complejidad, imposibles, en la práctica, de desarrollar en lenguaje máquina o ensamblador. Página 2 de 7 Tema 5. Lenguajes de programación 15/03/2011 4ª Generación Son los paquetes software que permiten ser adaptados para proporcionar nuevas funcionalidades sin necesidad de muchos conocimientos técnicos. Se incluyen hojas de cálculo, bases de datos, procesadores de texto avanzados... También se incluye en esta generación las herramientas software para programar de forma visual. (Por ejemplo: El DreamWeaver) 5ª Generación Son los lenguajes declarativos. El programador se concentra en definir el problema y no en solucionarlo. El ordenador deriva la solución a partir de la definición del problema a resolver. Por ejemplo: Prolog. La evolución de los LP no ha sido lineal tal como se suele representar. Las tres últimas generaciones están evolucionando en paralelo. 3ª generación 4ª generación 5ª generación 1ª generación 2ª generación Evolución temporal 2.2 Características del lenguaje de programación Existe una serie de características de los lenguajes de programación que facilitan la tarea de programar. Estas características son: I. Claridad de la sintaxis: La sintaxis afecta a la facilidad en que un programa pueda estar escrito, probado y mantenido. Una sintaxis críptica permite una programación fácil (en caso de un programador experto) pero dificulta el testeo y el mantenimiento. Como ejemplos tenemos el COBOL, un lenguaje extenso y claro, engorroso de programar y el lenguaje C, un lenguaje que puede especificar muchas operaciones en unas pocas instrucciones. II. Claridad y riqueza de conceptos: Los lenguaje de programación contienen conceptos abstractos que facilitan la programación. Por ejemplo, concepto como los tipos de datos, los conjuntos... Cuanta más riqueza y claridad de conceptos, el lenguaje es más productivo. El problema de los lenguajes con gran riqueza de conceptos abstractos es que dificultan el desarrollo de compiladores eficientes. III. Fiabilidad: Un lenguaje deba ayudar a minimizar los errores de programación. Los errores sintácticos y semánticos deben ser detectados cuanto antes mejor. Lo ideal es detectarlos en tiempo de compilación. Como ejemplos tenemos el lenguaje C, un lenguaje que da mucha libertad pero es poco fiable pues es propenso a que los errores pasen desapercibidos. En el lado contrario está ADA. IV. Uniformidad: Un lenguaje debe evitar inconsistencias en su diseño, que aumentan la dificultad de su aprendizaje y uso. Por ejemplo: En Pascal, todas las operaciones de control de flujo (If, While..) empiezan por begin, excepto la instrucción CASE. Se debe buscar la ortogonalidad de las operaciones, por ejemplo: cualquier tipo de dato debe poder ser un parámetro de una función. Página 3 de 7 Tema 5. Lenguajes de programación V. 15/03/2011 Orientación del lenguaje. El tipo de abstracciones que posee el lenguaje pueden ayudar a programar aplicaciones de un determinado tipo. Existen lenguajes de propósito general y lenguajes de propósito específico. Por ejemplo el lenguaje LISP, es un lenguaje especializado en tratamiento de listas. 2.2.1 Entorno de programación Además de las propiedades inherentes al propio lenguaje, es muy importante el entorno de programación. La presencia de herramientas y recursos de programación permite que un lenguaje técnicamente pobre sea más productivo que un lenguaje mejor que con menos soporte. Como recursos de un lenguaje podemos encontrar: Las librerías API. Las librerías son un conjunto de código que proporciona una serie de funcionalidades disponibles a la hora de programar. Disponer de estas funcionalidades evita tener que desarrollarlas. Por ejemplo: la gran librería de Java, que proporciona la funcionalidad necesaria para hacer programas distribuidos fácilmente. Las herramientas de ayuda al desarrollo de software (CASE) . Agrupan a un conjunto de herramientas que facilitan el desarrollo de los programas. Por ejemplo, depuradores, editores de código… Actualmente, estas herramientas suelen venir todas juntas integradas en los denominados IDEs – Integrated Developement Enviorement-. 2.3 Paradigmas de programación Los lenguajes de programación se diferencian en como afrontan la solución al problema. Hay cuatro formas de afrontarlo: 1. Lenguajes imperativos: Es el enfoque tradicional, similar al código máquina. Programar consiste en desarrollar una serie de instrucciones que manipulan los datos para calcular la solución al problema planteado. Ejemplo: Pascal, COBOL... 2. Lenguajes orientados a objetos: Se observa la aplicación como un conjunto de entidades (objetos) interrelacionados. Se clasifican los objetos en clases, cada clase tiene su datos de estado (atributos) y su comportamiento (métodos). La solución se obtiene manipulando los objetos. 3. Lenguajes declarativos: Se define el problema a resolver y el ordenador se encarga de buscar la solución a partir de la definición. 4. Lenguajes funcionales: El lenguaje provee de una serie de funciones especializadas, que el programador combina para obtener la solución-. Actualmente, en los proyectos profesionales sólo se utilizan lenguajes imperativos y orientados a objetos. El resto de lenguajes se utilizan en entorno académicos, salva contadas excepciones. Página 4 de 7 Tema 5. Lenguajes de programación 3 15/03/2011 La compilación e interpretación Un programa escrito en lenguaje de alto nivel, debe ser convertido a lenguaje máquina para que pueda ser ejecutado. El proceso de traducción consta de dos actividades: a) El análisis del código del programa, para saber qué hace. b) La síntesis del nuevo programa en código máquina. Los traductores se dividen en: Interpretes: Realizan la traducción del programa instrucción a instrucción. Compiladores: Realizan la traducción de forma global. Los compiladores, al realizar la traducción de forma global, pueden optimizar mejor el código generado. Así generar programas más rápidos, pequeños y eficientes (consumen menos recursos). La traducción sólo se realiza una vez, se guarda en un fichero el código ejecutable. Su inconveniente es que, al realizar la traducción, consumen muchos recursos (tiempo y memoria). La interpretación permite al intérprete controlar la ejecución del programa (más seguridad) y ejecutar el programa sin necesidad de esperar a traducirlo todo. Además permiten detener la ejecución del programa en cualquier punto y conservar el estado de la ejecución del programa (PC, valor de la variables...), esto facilita la depuración del programa. Su inconveniente es que la ejecución del programa es menos eficiente y la necesidad de contar con el traductor para ejecutar el programa. El diseño de los compiladores y de los lenguajes de programación está íntimamente ligado. Cuando se diseña un lenguaje de programación se tiene en cuenta dos objetivos: Aumentar la productividad de los programadores, creando lenguajes que faciliten la programación. Facilitar la generación de ejecutables eficientes por parte del compilador o el intérprete. Normalmente ambos objetivos se contraponen. Un lenguaje muy abstracto que facilite su programación, dificultará que sus ejecutables sean eficientes, y viceversa. 3.1 Enlace La mayoría de lenguajes actuales permiten dividir el código en diferentes partes que pueden interrelacionarse. Cada módulo puede ser compilado por separado y luego unirse para generar un ejecutable. El proceso de unión de las partes compiladas y resolver sus interrelaciones se denomina “enlace” (lincado coloquialmente). Con el enlace se facilita el desarrollo y mantenimiento de los programas, además de reducir el tiempo de generación de nuevos ejecutables al realizar modificaciones a los programas. Hay dos tipos de enlaces: • Dinámico: Se realiza en tiempo de ejecución. El SO o el entorno de ejecución se encarga de realizar las relaciones. (librerías dinámicas). Sus ventajas es tener ficheros ejecutables más pequeños y que podemos modificar la implementación de las librerías sin tener que recompilar los programas. • Estáticas: Se realiza en tiempo de compilación. Los módulos se combinan para hacer un solo fichero ejecutable. (librerías estáticas). Evita problemas de versiones de librerías al ejecutar el programa. Página 5 de 7 Tema 5. Lenguajes de programación 15/03/2011 Fases de la compilación Código fuente Análisis léxico Análisis sintáctico Análisis semántico Se identifican los tokens que componen el programa (el léxico). Se utilizan, para ello, expresiones regulares Se analizan las relaciones entre los tokens (la sintaxis). El orden debe ser correcto. La sintaxis del LP se define mediante una gramática. Se analiza que el significado del código sea coherente. Se utilizan gramáticas de atributos. Código intermedio Optimización Un código puente en la traducción. De bajo nivel similar al código máquina. Independiente de la máquina. Se analiza el código generado para eliminar el código superfluo y reordenarlo para hacerlo más eficiente. Código intermedio optimizado Generar código Se traduce el código intermedio a código máquina. Se realiza una optimización para aprovechar la arquitectura de la máquina. Ejemplo: Reorden de instrucciones en procesadores superescalares Código objeto Enlace Se unen los códigos objeto que forman el programa y se resuelven sus relaciones. Código ejecutable 4 Depuración de programas Muchos de los errores de programación se detectan al compilar el programa, pero otros se detectan al ejecutarlo. Los errores en la ejecución son difíciles de localizar en el código del programa. Para localizarlos se depura el programa. La técnica más elemental para depurar un programa es insertar instrucciones en el programa que informen del estado de la ejecución (localización del flujo del programa y el valor de las variables relevantes). Existen programas que facilitan depurar el código, sin necesidad de insertar instrucciones extra. Se denominan depuradores o debuggers. Estos programas permiten seguir el estado de la ejecución de los programas, muchas veces de forma visual. Los depuradores pueden ser de dos tipos: Simbólicos: Permiten examinar el código ejecutable como si fuera el código fuente. Consumen muchos recursos. Estos depuradores necesitan que el compilador haya insertado en el ejecutable información extra para la depuración. Es usado durante el proceso de desarrollo. Página 6 de 7 Tema 5. Lenguajes de programación 5 15/03/2011 Absolutos: Manejan información de bajo nivel: muestran los registros de la CPU, posiciones de memoria, etc. Consumen muchos menos recursos, pero la información que suministran es de más difícil de interpretar. Es utilizado para tareas de Ingeniería Inversa. Evolución histórica de los lenguajes de programación El primer lenguaje ampliamente utilizado fue el FORTRAN (FORmula TRANformation) en 1956. Es un lenguaje con sintaxis de estilo matemático, destinado a programas científicos y matemáticos. Demostró que la idea de un lenguaje de alto nivel era viable y aportó el concepto de desarrollo y compilación por módulos. El siguiente lenguaje en triunfar fue el COBOL (1959) que introdujo los conceptos de ficheros y declaración de variables. Es un lenguaje de sintaxis extensa y fácil de entender, destinado a programar aplicaciones de gestión, cuyo código tendría que ser revisado por personal no técnico. Luego surgió el ALGOL (1960), que aportó los conceptos de estructuras en bloques y procedimientos recursivos. Todos estos lenguajes son lenguajes imperativos. Durante la década de los 60, se realizaron multitud de estudios al diseño de lenguajes de alto nivel y sobre sus compiladores, en especial en materias como la teoría de autómatas, en técnicas de especificación de lenguajes y la verificación de programas. Surgieron nuevos paradigmas en el diseño de lenguajes. Como los lenguajes orientado a objetos, el primero fue el SIMULA, leguajes funcionales (LISP) y lenguajes declarativos (PROLOG). De estos nuevos paradigmas, sólo los lenguajes orientado a objetos han obtenido una gran cuota de uso, quedando relegado los otros dos paradigmas prácticamente a entornos académicos. A finales de los 70, surge el concepto de la crisis del software, ante el gran porcentaje de proyectos que fracasan. Se abandonan en gran medida los esfuerzos en el diseño de lenguajes de programación, para centrarse en el estudio de los métodos, las técnicas y las herramientas necesarias que ayuden al desarrollo de software. Estas materias se conocen como Ingeniería del software. De estos estudios surge el concepto de programación estructurada, para dar un orden a la hora de programar. La programación estructurada ha influido en todos los lenguajes de programación. El lenguaje PASCAL es el ejemplo más claro de lenguaje estructurado. Han ido apareciendo nuevos lenguajes orientados a nuevos entornos de aplicación, por ejemplo el lenguaje Java o C# para programar aplicaciones distribuidas. Estos lenguajes presentan pocas novedades en si mismos, marcando la diferencia respecto al resto en los recursos que acompañan al lenguaje: librerías, entornos de desarrollo, de ejecución... Página 7 de 7