Principios de diseño de lenguajes
Objetivo
El alumno describirá los procedimientos y gramáticas empleadas en el diseño de los lenguajes de programación.
Figura 1.1: Preguntas incómodas
1.1. Los lenguajes en la estructura y operación de una
compu-tadora
Un programa es una serie de instrucciones que una computadora puede entender y ejecutar. Un lenguaje de programación es un lenguaje artificial utilizado para escribir dichos programas. Posteriormente éstos se introducirán en la memoria de la computadora y ejecutará todas las operaciones que se incluyan.
Los lenguajes de programación constan de:
} Vocabulario del lenguaje, un conjunto finito de símbolos.
} Sintaxis, un conjunto finito de reglas para la construcción de las sentencias “correctas”. } Semántica, que asocia un significado a cada posible instrucción.
Así, podemos decir que un lenguaje de programación consta de un conjunto de símbolos y un conjunto de reglas válidas para componerlos, de manera que formen un mensaje con significado para la computadora.
Al diseñar un lenguaje de programación, es necesario considerar tres aspectos básicos:
} Laestructura y operación de la computadora dónde se van a ejecutar los programas escritos
en el lenguaje.
} El modelo de ejecución o computadora virtual con que se implementará el lenguaje en la máquina real.
} Elmodelo de cómputo (paradigma) que el lenguaje soportará.
Un lenguaje de programación se implementa construyendo untraductor, el cuallee los programas expresados en dicho lenguaje y entrega programas en lenguaje de máquina que pueden ser ejecuta-dos directamente por alguna computadora, la computadora que ejecuta los programas traduciejecuta-dos puede ser unacomputadora física:hardware o unacomputadora virtual:software.
Figura 1.2: Arquitectura (Zuse) von Neumann
1.2. Computadoras virtuales
Para facilitar la programación, lo común es expresar los programas en un lenguaje de alto nivel, el cual es muy cercano al lenguaje del programador y muy distante del lenguaje de máquina (bajo nivel). El lenguaje de máquina es distinto para cada tipo dehardware.
El problema que se enfrenta al implementar un lenguaje es, cómo hacer que se ejecuten progra-mas en un lenguaje de alto nivel en diferentes computadoras, independientemente de su lenguaje de máquina. Para resolver este problema existen dos soluciones básicas: traducción (compilación) y simulación porsoftware.
Figura 1.3: Máquina virtual
1.2.1. Traducción (compilación)
Se puede construir un traductor que toma programas en el lenguaje de alto nivel y produce programas equivalentes en el lenguaje de máquina de la computadora real.
Un traductor es un procesador de lenguajes que toma programas en un cierto lenguaje fuente y los transforma en programas funcionalmente equivalentes codificados en otro lenguaje objeto. Por ejemplo: ensambladores y compiladores.
Figura 1.4: Proceso de compilación
1.2.2. Simulación por software
En lugar de traducir los programas de un lenguaje de alto nivel a un lenguaje de máquina, se puede simular una computadora cuyo lenguaje de máquina sea el lenguaje de alto nivel. Para
hacer esto se construye un conjunto de programas en el lenguaje de máquina de la computadora anfitrión que representan los algoritmos (y estructuras de datos) necesarios para la ejecución de programas en el lenguaje de alto nivel.
Figura 1.5: Interpretación directa
A diferencia de un traductor, el simulador ejecuta el programa directamente, no lo traduce. En la práctica pocas veces se usan la traducción o la simulación puras, mas bién se trabaja con una combinación de ambas.
Un programa se descompone en varios subprogramas independientes que se compilan por separado, luego en la fase de carga se combinan con otras rutinas (operaciones simuladas por software) en tiempos de ejecución, y se ejecuta por simulación.
Traductor (software) Código fuente Enlazador Traductor (software) Código fuente Errores de sintáxis Errores de sintáxis Código objeto Código objeto Librerías auxiliares en tiempo de ejecución Código ejecutable Computadora virtual (Simulada completa o parcialmente) Intérprete (hardware o software) Operaciones (hardware o software) Datos de ejecución Salida de resultados Mensajes de error
TRADUCCIÓN CARGA EJECUCIÓN
Figura 1.6: Estructura de implementación de un lenguaje de programación
Una cuestión importante en la implementación de un lenguaje es saber si la representación del programa durante su ejecución será la del lenguaje de máquina de la computadora real o una
virtual. Esto establece dos tipos de implementaciones de lenguajes:
1. Compilados. Los programas en estos lenguajes se traducen al lenguaje de máquina de la computadora real antes de ejecutarse, y la simulación se usa en las rutinas auxiliares en tiempo de ejecución que simulan operaciones primitivas que no tienen representación directa en el lenguaje de máquina. Por ejemplo: C, C++, Pascal, Ada, FORTRAN, etc.
2. Interpretados. El traductor produce un código intermedio, y un software intérprete lo ejecuta ya que el hardware no lo puede ejecutar directamente. Por ejemplo: LISP, Prolog, Smalltalk, ML, Java, Python, BASIC, etc.
1.2.3. Jerarquía de computadoras
La computadora virtual que se utiliza cuando se hace un programa en algún lenguaje de alto nivel, esta formada por una jerarquía de computadoras virtuales.
La figura siguiente muestra la jerárquía de computadoras para un programa desarrollado en C.
Computadora de hardware real
(Implementada por dispositivos físicos)
Computadora virtual de firmware
(Instrucciones en lenguaje de máquina implementadas por microcódigo ejecutado por la computadora real)
Computadora virtual del system operativo
(Implementadas por programas en el lenguaje máquina que se ejecutan en la computadora virtual de firmware)
Computadora virtual de C
(Implementadas por rutinas de librerías auxiliares en tiempo de ejecución cargadas en el programa compilado)
Computadora virtual desarrollada por el programador
(Implementada por el modelo de ejecución desarrollado en lenguaje C, para ejecutarse en la computadora virtual de C) Datos de entrada Datos de salida
Figura 1.7: Jerarquía de computadoras virtuales de un programa en C
1.3. Sintaxis
La sintaxis de un lenguaje de programación es el aspecto que ofrece el programa, proporcio-nar las reglas de sintaxis para un lenguaje de programación significa decir como se escriben los enunciados, declaraciones y otras construcciones de lenguaje.
1.4. Semántica básica
La semántica de un lenguaje de programación es el significado que se le da a las diversas construcciones sintácticas, la semántica de un lenguaje de programación está muy relacionada con el paradigma que implementa dicho lenguaje.
Cuando un lenguaje de programación se implementa en una computadora particular, primero sedeterminala computadora virtual que representa una interpretación de la semántica del lenguaje y luego se construye esa computadora virtual a partir de los elementos de hardware y software que suministra la computadora subyacente. Por ejemplo, se puede determinar que una operación de suma de enteros se implemente directamente porhardware y que una raíz cuadrada se simule en la computadora virtual.
También se debe determinar qué se va a hacer durante la traducción del programa y qué durante su ejecución. Ya que algunas representaciones de estructuras de datos u operaciones en la computadora virtual, sólo se pueden usar si el traductor las definió dentro de la estructura en tiempos de ejecución.
Programa: Desarrollar un programa que obtenga la representación C1 y C2 de un número entero que se encuentra en base10 y viceversa.
1.5. Enlace y tiempo de enlace
Se denominaenlace de un elemento de programa a una característica o propiedad particular a la elección de dicha propiedad de entre un conjunto de propiedades posibles. El momento durante la formulación o procesamiento del programa en el que se hace está elección se conoce como tiempo de enlace de esa propiedad para ese elemento.
Los lenguajes de programación cuentan con distintas variedades de enlaces y tiempos de enlace.
1.5.1. Tiempo de ejecución
Enlaces que se llevan a cabo durante la ejecución de programa, como son los enlaces de las variables a sus valores o localidades particulares de almacenamiento. Hay dos categorías:
1. Al entrar a un subprograma o bloque. En casi todos los lenguajes las clases importan-tes de enlaces sólo pueden ocurrir en el momento de entrar a un subprograma durante la ejecución. Por ejemplo, en C y Pascal el enlace de parametros formales a reales sólo puede ocurrir al entrar a un subprograma.
2. En puntos arbitrarios durante la ejecucion. Ciertos enlaces pueden ocurrir en cualquier punto durante la ejecución de un programa. Por ejemplo, el enlace de variables a valores a través de asignación, o como en LISP y ML que permiten enlazar nombres a localidades de almacenamiento en puntos arbitrarios del programa.
1.5.2. Tiempo de traducción o compilación
1. Enlaces elegidos por el programador. El programador elige nombres de variables y tipos de las mismas, estructuras de enunciados, etc., que representan enlaces durante la traducción.
2. Enlaces elegidos por el traductor. Ciertos enlaces son elegidos por el traductor del lenguaje sin que el programador intervenga. Por ejemplo, la asignación de las localidades relativas de almacenamiento de un objeto de datos.
3. Enlaces elegidos por el cargador. Un programa se compone generalmente de varios subprogramas que se deben de fusionar en un programa ejecutable único. El traductor enlaza variables a direcciones relativas dentro del espacio de almacenamiento designado para cada subprograma. Durante el tiempo de carga (o tiempo de vinculación, link) las direcciones relativas deben de ser asignadas a las direcciones reales de la máquina real donde se ejecuta el programa.
1.5.3. Tiempo de implementación del lenguaje.
Ciertos aspectos de la definición de un lenguaje pueden ser iguales para todos los programas que se ejecutan usando una implementación particular del mismo, pero pueden variar entre las distintas implementaciones. Por ejemplo, sí un programa usa una característica que se ha definido durante la implementación, no se puede asegurar que correrá en otra implementación del mismo lenguaje.
1.5.4. Tiempo de definición del lenguaje.
Casi toda la estructura de un lenguaje de programación se fija cuando el lenguaje se define, en el sentido de la especificación de las alternativas disponibles para un programador cuando escribe un programa. Por ejemplo, todos los tipos de datos, estructuras de programa, etc., suelen fijarse en el tiempo de definición del lenguaje.
1.5.5. Importancia de los tiempos de enlace
Muchas de las diferencias más importantes y sutiles entre lenguajes implican diferencias en cuanto a tiempos de enlace. Se dice que un lenguaje, donde casi todos los enlaces se efectúan durante la traducción y al principio del procesamiento de un programa, tieneenlace temprano; un lenguaje conenlace tardío, demora casi todos los enlaces hasta el tiempo de ejecución.
Las ventajas y desventajas del enlace temprano respecto al enlace tardío giran en torno al conflicto entre eficiencia y flexibilidad.
} En lenguajes donde se persigue la eficiencia de ejecución, como FORTRAN, Pascal y C,
es común proyectar el lenguaje de manera que se puedan efectuar tantos enlaces como sea posible durante la traducción.
} En los casos donde la flexibilidad es lo se persigue, como en ML y LISP, casi todos los enlaces
se retrasan hasta el tiempo de ejecución para que puedan adaptarse a los datos introducidos durante la ejecución.
} En un lenguaje diseñado para ofrecer a la vez ejecución eficiente y flexibilidad, como Ada,
se suele disponer de múltiples opciones que permiten elegir tiempos de enlace.
Un lenguaje se diseña de tal modo que un enlace particular se puede efectuar, por ejemplo, durante la traducción, pero el momento efectivo en el cual el enlace se lleva a cabo está definido de hecho sólo por la implementación del lenguaje.
1.6. Paradigmas de lenguajes
Además de conocer la máquina virtual que va a proporcionar el almacenamiento de datos en tiempo de ejecución y las operaciones para la ejecución de un programa traducido y el hardware dónde se va a correr realmente el programa traducido a código ejecutable, se tiene que analizar el modelo de computación que maneja el lenguaje de programación. Es decir, el modelo de compu-tación se plantea preguntas como: ¿Cómo se ejecuta el programa? ¿Qué clase de construcciones suministra el programa?
Existen dos modelos básicos de computación que describen a los lenguajes de programación actuales: elimperativo y eldeclarativo.
Lenguajes de Programación
Imperativos Declarativos
Estructurados Orientados a
Objetos Funcionales Lógicos
C Pascal COBOL php ... C++ Java C# php5 ... Haskell LISP Dr. Scheme Dr. Racket ... Prolog CLIPS ... Python
Figura 1.8: Paradigmas de lenguajes de programación
1.6.1. Lenguajes imperativos
Los lenguajes imperativos o deprocedimientoson lenguajes controlados por mandatos u orien-tados a enunciados (instrucciones).
Un programa se compone de una serie de enunciados, y la ejecución de cada enunciado hace que el intérprete cambie el valor de una localidad o más en su memoria, es decir, que pase a un nuevo estado.
La memoria consiste en una colección de celdas, y la ejecución del enunciado (por ejemplo, sumar dos variables para obtener una tercera) se puede representar como acceder a las localidades de memoria (las celdas), combinar los valores contenidos en las celdas en alguna forma y guardar el resultado en la nueva localidad. El desarrollo de programas consiste en construir los estados de máquina sucesivos (valores en las celdas) que se necesitan para llegar a la solución.
En general, este modelo procede del hardware de la computadora convencional que ejecuta instrucciones en forma secuencial (arquitectura von Neumann).
1.6.1.1. Lenguajes estructurados en bloques (procedimientos)
Un lenguaje con bloques de programa, divide el estado en bloques que representan subrutinas y datos comunes. Los bloques se pueden pensar como un archivo plano, donde cada bloque sigue a sus predecesores.
El término estructuras en bloques se refiere a los ámbitos anidados. Es decir, los bloques pueden estar anidados dentro de otros bloques, y pueden contener sus propias variables. El estado representa una pila con una referencia al bloque actualmente activo en la parte superior. En los lenguajes estructurados en bloques, el procedimiento es el principal bloque de construcción de los programas.
Figura 1.9: Programa estructurado
1.6.1.2. Lenguajes orientados a objetos
Son aquellos lenguajes basados en objetos que soportaban clases de objetos y la herencia de atributos de un objeto padre por parte de sus hijos. Un objeto es un grupo de procedimientos que comparten un estado. Puesto que los datos son también parte de un estado, los datos y todos los procedimientos o funciones que se le aplicarán son encapsulados en un solo objeto.
1.6.1.3. Lenguajes para la programación concurrente
La programación concurrente está asociada con más de un CPU funcionando simultáneamente en paralelo, compartiendo o no datos. Sin embargo, los CPU múltiples no son esenciales para este paradigma. Lo esencial es que el trabajo sobre un problema en particular pueda ser compartido.
La programación concurrente se divide en dos categorías,sistemas distribuidos ysistemas con memoria compartida.
1.6.1.3.1. Sistemas distribuidos El término distribuido se refiere a lenguajes para sistemas acoplados débilmente que soportan que un programa se ejecute de manera simultánea y se comu-nique a través de paso de mensajes mediante un canal de comunicación, tal como un enlace de punto a punto o una red de área local.
1.6.1.3.2. Sistemas de memoria compartida o fuertemente acoplados Permite que más de un proceso en ejecución tenga acceso a la misma ubicación de memoria. Un lenguaje asociado con el sistema debe sincronizar el uso compartido de memoria, de modo que sólo un proceso escriba
a una variable compartida a la vez, y de modo que un proceso pueda esperar hasta que ciertas condiciones se satisfagan por completo antes de continuar la ejecución. La memoria compartida tiene la ventaja de la velocidad, porque no se necesita pasar mensajes.
1.6.2. Lenguajes declarativos
Un lenguaje declarativo es aquel en el que un programa especifica una relación o función. Cuando se programa en el estilo declarativo, no se hacen asignaciones a variables del programa. El intérprete o compilador para el lenguaje en particular administra la memoria independientemente del programador.
1.6.2.1. Lenguajes Funcionales
Los lenguajes funcionales en vez de examinar la serie de estados a través de los cuales debe pasar la máquina para obtener una respuesta, se preguntan: ¿Cuál es la función que se debe aplicar al estado de máquina inicial accediendo al conjunto inicial de variables y combinándolas en formas específicas para obtener una respuesta?
El desarrollo de programas procede a través del desarrollo de funciones a partir de funciones previamente desarrolladas para construir funciones más complejas que manipulan el conjunto inicial de datos hasta que la función final se puede usar para calcular una respuesta a partir de los datos iniciales.
Así, la programación funcional proporciona la capacidad para que un programa (función) se modifique a sí mismo, es decir,aprenda. LISP , Scheme y ML son lenguajes funcionales manejan este modelo de programación.
1.6.2.2. Lenguajes de Programación Lógica
La programación lógica está basada en el cálculo de predicados, el cual proporciona axiomas y reglas de modo que se pueden deducir nuevos hechos a partir de otros hechos conocidos.
Un programa basado en la lógica se compone de una serie de axiomas o hechos, reglas de inferencia y un teorema o cuestión por demostrarse. La salida es verdadera si los hechos soportan o apoyan la cuestión, y es falsa en el caso contrario. Prolog es el ejemplo típico de este tipo de lenguajes.
1.6.3. Lenguajes de base de datos
Las propiedades que distinguen a los lenguajes diseñados para tratar con bases de datos son la persistencia y la administración de cambios. Las entidades de base de datos no desaparecen después de que finaliza un programa, sino que permanecen activas durante tiempo indefinido como fueron estructuradas originalmente. Puesto que la base de datos, una vez organizada, es permanente, estos lenguajes también deben soportar los cambios. Los datos pueden cambiar y así también pueden hacerlo las relaciones entre objetos o entidades de datos.
Un sistema de administración de base de datos incluye un lenguaje de definición de datos (DDL) para describir una nueva colección de hechos, o datos, y unlenguaje de manipulación de datos (DML) para la interacción con las bases de datos existentes. SQL es un ejemplo de este tipo de lenguajes.
Tarea:
} Leer los artículos relacionados con “Computational Thinking”: (1)http://bit.ly/1fD8eWT (2) http://bit.ly/2auRCqh y hacer un breve comentario (1 cuartilla por integrante del equipo), no resumen, puedes hacer referencia entre otros muchos a los siguientes puntos:
• ¿Qué relación tiene con el curso?
• ¿Estás de acuerdo con lo que se expone?
• ¿Todas las personas piensan que cualquier persona se beneficiaría al saber algo de sus