Paradigma de los lenguajes de programación.

Anuncio
Precedentes (I)
TEMA 2.
DISEÑO Y PARADIGMAS DE LOS
LENGUAJES DE PROGRAMACIÓN.
Precedentes (II)
• El diseño de lenguajes es un problema
complejo
• En los lenguajes de programación hay
muchos errores de diseño
– C
• Se han considerado ideas erróneas
– FORTRAN
– C++
• el programador sabe lo que hace
– Obtener direcciones de variables locales
– Printf no comprueba el tipo y número de los
argumentos
• se puede extender C al paradigma orientado
a objeto (demasiados compromisos de
compatibilidad)
• Uso intensivo de apuntadores a objetos
• Lenguaje demasiado complicado
• uso del GOTO
• declaración implícita de variables
– COBOL
• Sentencias demasiado largas
• Farragoso de escribir y leer
• Uso del GOTO
– APL
• si puede significar algo, lo significa
– LISP
• una sintaxis simple es más fácil de aprender
• Los paréntesis dificultan escribir programas
• La lectura es compleja por una sintaxis
demasiado homogénea
Compiladores I (13/08/2003 07:52)
- 2.1 -
Compiladores I (13/08/2003 07:52)
- 2.2 -
– Un lenguaje se puede utilizar para todo tipo
de desarrollo de software
• Aun con muchos errores de diseño es
importante estudiar los lenguajes de
programación existentes ya que aportan
muchas ideas
Compiladores I (13/08/2003 07:52)
- 2.3 -
1
Consideraciones Preliminares
Fuentes de Ideas
• ¿Cual es el propósito del lenguaje?
– No hay un lenguaje bueno para todo
– Aplicación específica
• Bases de datos, sistemas expertos, cálculo
numérico, programación simbólica, diseño
algorítmico, etc.
• ¿Es necesario diseñar un nuevo lenguaje?
– Ya existe un lenguaje apropiado
• El nuevo lenguaje se diferencia de los
existentes
– Se consume demasiado tiempo en el diseño
e implementación de un nuevo lenguaje
• Es demasiado fácil diseñar un lenguaje
incompleto
• Lenguaje demasiado especializado
• Sacrificar características del lenguaje por un
compilador simple.
– Otras opciones
• Lenguaje natural (COBOL)
– Fácil de leer y escribir
– Ambiguo
– Solo se puede implementar un subconjunto
• Lenguajes matemáticos (APL)
– No ambiguos
– Crípticos
– La programación no es matemáticas
• Lenguajes de programación
– Errores de diseño (pasado)
• Comunicación humana
• Prevención y detección de errores
• Usabilidad
• Efectividad
• Compilabilidad
• Eficiencia
• Independencia de la máquina
• Simplicidad
• Hay que valorar cada característica de un
lenguaje existente antes de incluirla en el
nuevo lenguaje
• Uniformidad
• Ortogonalidad
• Generalización y especialización
• Otras filosofías de diseño
• Pruebas y experimentos
– Programar con el lenguaje antes de haber
acabado su diseño
• Sirve para detectar los problemas del diseño
y tomar decisiones difíciles.
• Un modulo o librería de funciones
• Ampliar un lenguaje de programación
Compiladores I (13/08/2003 07:52)
Objetivos y Filosofías de Diseño
- 2.4 -
Compiladores I (13/08/2003 07:52)
- 2.5 -
Compiladores I (13/08/2003 07:52)
- 2.6 -
2
Comunicación humana (I)
Comunicación humana (II)
• Se busca una comunicación eficiente entre
el programador y el ordenador
• Un buen nivel de comunicación se da
cuando los programas son leíbles
– No ha de ser necesaria una documentación
externa al programa (minimizar)
– Es más importante que un programa sea
leíble que escribible
• Un programa se escribe una vez, pero se lee
muchas durante su depuración,
documentación y mantenimiento.
• Tendencia actual a separar la interfaz de la
implementación de un módulo
Prevención y detección de errores
– El lenguaje ha de representar los patrones
de pensamiento humanos
• No hay que crear una sintaxis pensada
exclusivamente para
• El programador comete errores
– Hay que prevenir los errores
• El programador es su fuente
– un modelo de cómputo teórico (λ-calculus)
– un conjunto de instrucciones de la máquina
– facilitar la compilación (forth)
– El programador no sabe lo que hace y el
compilador ha de limitar sus acciones
(EUCLID, PASCAL)
– Hacer imposible cierto tipo de errores
– El programador no es un ordenador
• Ejecutar datos -> control de flujo limitado
• Errores en el uso de datos -> Tipado fuerte
• Apuntadores erróneos -> Gestión de
memoria implícita (LISP, PROLOG, ML,
etc).
• Que el compilador entienda una estructura
es posible que el programador no
– Evitar incluso la posibilidad de escribirlas
– Reducir el conocimiento contextual
– El programador no funciona con una pila
como el programa compilado.
– La sintaxis ha de reflejar la semántica
– Hay que facilitar su detección,
identificación y corrección
• Redundancia
– Tener que declarar antes de utilizar.
– Evitar coerciones inductoras de errores
• Reducir las manipulaciones implícitas
– Coerciones (coerciones de PL/I o C)
• float a int por su perdida de precisión
– ON de BASIC para eventos o excepciones
– Constructores y destructores de C++
(necesarios, pero complican el seguimiento
del flujo de ejecución)
Compiladores I (13/08/2003 07:52)
- 2.7 -
• Comprobaciones en tiempo de ejecución
– Indice de array fuera de limites
– Control sobre los apuntadores a NULL
Compiladores I (13/08/2003 07:52)
- 2.8 -
Compiladores I (13/08/2003 07:52)
- 2.9 -
3
Lenguaje Utilizable y Efectivo
Otras filosofías de diseño
• Un lenguaje ha de ser fácil de utilizar
– Un lenguaje ha de ser fácil de aprender y
recordar
• Evitar la necesidad de consultar el manual
(C++ no cumple)
• Lenguaje simple (C++ no cumple)
• Aprendizaje incremental (PROLOG no
cumple, LISP si cumple)
– El comportamiento del lenguaje ha de ser
predecible
• el uso de void* de C++ es incomprensible
• Efectividad
– Los detalles de implementación no han de
oscurecer las intenciones del programador
• Soportar abstracción
• Modularidad: Separar especificación de
implementación
– Los Efectos de un cambio han de quedar
localizados
– Evitar los trucos (programas ilegible)
Compiladores I (13/08/2003 07:52)
- 2.10 -
Diseño Detallado
• Compilabilidad
– Se ha de poder compilar programa en un
tiempo reducido
– Se ha de poder depurar o aplicar otras
herramientas de análisis
• Eficiencia: La ejecución ha de ser rápida
• Independencia de la máquina
• Estructura de las expresiones
• Estructuras de datos
• Estructuras de control
• Estructura de compilación
• Estructura de la entrada/salida
• Simplicidad
• Uniformidad: lenguaje predecible
• Ortogonalidad
– Todas las características del lenguaje se
han de poder combinar
• Generalización y especialización
– La generalización dice que algo similar
también es correcto, pero es difícil de
implementar
– Hay que especializar para facilitar la
implementación sin perder la utilidad del
lenguaje
Compiladores I (13/08/2003 07:52)
- 2.11 -
Compiladores I (13/08/2003 07:52)
- 2.12 -
4
Ejemplos:
Lenguajes de Programación y su Diseño
• El lenguaje C
– Aplicación: programación de sistemas
– Programador: experto
– Sacar el mayor rendimiento posible del
ordenador
• PASCAL
– Aplicación: docencia
– Programador: inexperto
• LISP
– Aplicación: procesamiento simbólico
– Desarrollo rápido
• PROLOG
– Aplicación: procesamiento simbólico
– Programación lógica
– Desarrollo rápido
El Lenguaje C (I)
El Lenguaje C (II)
– En contra de la velocidad
• Lenguaje pensado para el desarrollo de
sistemas operativos (unix)
– Rendimiento/velocidad de ejecución
– Programador experto
– Código compacto
• Redimiento/Velocidad de ejecución
– Operaciones básicas simples
– Apuntadores
• Cálculos en coma flotante con la máxima
precisión posible
• Programador experto
– Amplio uso de coerciones
• Implícitas
– char -> int -> double
– double <- int <.- char
– void * -> tipo*, tipo* -> void *
• uso para los strings y arrays
• Estructuras de datos referenciadas por
apuntadores (paso por referencia explícito)
- 2.13 -
Compiladores I (13/08/2003 07:52)
– El programador puede convertir cualquier
tipo de datos en cualquier otro.
• int -> void*
– Gestión de memoria explícita
– En las primeras versiones las funciones
solo retornan datos que puedan ir en un
registro del procesador
– Optimización explícita
– Flujo de ejecución
• break y continue
• goto local
• long jump
– Obtención de direcciones
• Incremento y decremento
• Operaciones con asignación incluida
• variables register
Compiladores I (13/08/2003 07:52)
• Explícitas
• Se puede obtener la dirección de cualquier
variable aunque esta sea local
- 2.14 -
Compiladores I (13/08/2003 07:52)
- 2.15 -
5
El Lenguaje C (III)
El Lenguaje C (IV)
– Prioridades de operadores complejas
• Casi cualquier combinación de operadores
es aceptada por el compilador
• Otras cuestiones
– Falta de un método por defecto para la
gestión de excepciones
• Códigos de error retornados por las
funciones de la librería que continuamente
ha de verificar el programa
– Faltan comentarios de una línea
– Palabras clave con diferentes significados
según el contexto
PASCAL
– Sintaxis de los comentarios confundible
(A=b/*p)
• Código compacto
– La mayor parte de las instrucciones se
traducen a unas pocas instrucciones de
código máquina
– Faltan instrucciones de alto nivel
• Docencia
– Estructura muy rígida de los programas
– Un buen nivel de abstracción
– Transportable
– Lenguaje simplificado
• Falta de módulos y librerías
• Librería básica muy limitada
• Strings
– Tratamiento por apuntadores
– Gestión explicita de la memoria
– Considerar continuamente si la reserva de
memoria es suficiente
• Todo lo que hace el programa se indica
explícitamente
– Pensado para la resolución de problemas
por subdivisión
• No hay copia de datos compuestos
• static
– Asignación array a array
– Semántica ambigua
– Escritura farragosa de los programas
– Minimización del uso de coerciones
• Definiciones anidables de funciones y
procedimientos
• Incrementos en una expresión
– Métodos para la escritura de programas
transportables soportados por el
programador
– Tipado fuerte
• Compilación condicional
• sizeof
Compiladores I (13/08/2003 07:52)
- 2.16 -
Compiladores I (13/08/2003 07:52)
- 2.17 -
Compiladores I (13/08/2003 07:52)
- 2.18 -
6
LISP
PROLOG
• Sintaxis demasiado simple
– Difícil escritura y lectura de los programas
• Comprobaciones semánticas en tiempo de
ejecución
– Variables declaradas
– Tipos de datos
• Enfoque pragmático
– Programación imperativa y funcional
• Orientado a optimizar el desarrollo frente a
la velocidad de ejecución
– Gestión de memoria implícita
– Uso de listas para todo
– Amplia librería de funciones
C++
• Programación declarativa y lógica
• Implementación del cálculo de predicados
– Faltan funciones (λ-prolog)
• Difícil modularidad
– Un método de programación demasiado
alejado de la programación habitual
– Gramática de operadores extensible
– Totalmente transportable
– Modulariza las búsquedas
• Orientación a objeto de C
– Mantener la compatibilidad con C
• Uso masivo de apuntadores
• Tratamiento de excepciones no soportado
por las librerías estándar
– Rendimiento
• Complica el lenguaje
– Static en métodos
– Métodos virtuales y no virtuales
– Templates
• Convierte los bucles de una búsqueda en
una secuencia lineal de aplicación de
predicados
• Destructores por gestión de memoria
explícita
• Apuntadores y referencias
• Otros
– comentarios de una línea fáciles de escribir
y leer (repetición de //)
– Implementación parcial de las coerciones
• Diseño por etapas
– Funciones repetidas
• setq y setf
– Parches para mantener compatibilidad
• forma de creación de los places
Compiladores I (13/08/2003 07:52)
- 2.19 -
Compiladores I (13/08/2003 07:52)
- 2.20 -
Compiladores I (13/08/2003 07:52)
- 2.21 -
7
ADA
Opciones en el Diseño (I)
• Lenguaje pensado para grandes proyectos
de software
– Facilitar el uso de librerías
• Interfaz separa de la implementación del
módulo
• Control exhaustivo sobre la interfaz
– Fácil lectura y detección de posibles bugs
• Sintaxis de las instrucciones de control de
flujo con marcadores claros de inicio y fin
(If then else end if)
• Etiquetas visibles <<etiqueta>>
• Coerciones explicitas
– Reducción de los errores
• Definición de excepciones para controlar
errores de ejecución
– Acceso a array fuera de rango
– Un case del que no se selecciona ninguna
opción
• Atributos asociados a las variables:
– un array tiene asociado el atributo de su
tamaño
Compiladores I (13/08/2003 07:52)
- 2.22 -
Opciones en el Diseño (II)
• Sintaxis de control de flujo
– Instrucción compuesta
• C, PASCAL (for (;;) ; {...}
– Instrucciones de control de flujo con claros
marcadores de inicio y fin
• ADA
– Instrucción vacía
• Explicita ADA ( null)
• Implícita C, PASCAL (; o nada)
• Gestión de memoria
– Explicita: C, PASCAL, ADA
• Lenguaje orientado a
– Instrucción: ADA, PASCAL
– Expresión: C, funcionales
• Velocidad
– Implícita: LISP, PROLOG, Java,
funcionales
• Marcadores de las estructuras sintácticas
– Si: PASCAL, ADA
– No: C, C++
• Expresiones
– Riqueza de operadores C, C++
– Pobreza de operadores PASCAL, ADA
Compiladores I (13/08/2003 07:52)
• Sistema de tipos
– No tipado: LISP, BASIC
– Tipado: C, PASCAL, ADA, etc.
• Código genérico
– Datos marcados con su tipo en ejecución
– Tipos paramétricos
– templates
- 2.23 -
• Simplicidad
• Gestión de errores de ejecución
– Responsabilidad del programador: C, C++
– Responsabilidad del lenguaje ADA
– Excepciones sin declarar C++
– Excepciones declaradas Java
Compiladores I (13/08/2003 07:52)
- 2.24 -
8
Opciones en el Diseño (III)
• Estructura declaraciones
– Rígida: PASCAL, ADA
– Poco rígida: C
– Libre: C++
• Ámbitos
– Expresión LISP
– Instrucción compuesta C, C++, Java
– Función C, C++, PASCAL, ADA
– Espacios de nombres
– Clases
– Paquetes
– Módulos
• Coerciones
– Explicitas: ADA
– Pocas implícitas: PASCAL
– Muchas implícitas: C, C++
Compiladores I (13/08/2003 07:52)
- 2.25 -
9
Descargar