Aspectos Específicos
1
Aspectos específicos
Lenguajes Imperativos Enfoque principal: estado de la máquina: conjunto de valores almacenados en pjosiciones de memoria Comandos: Sentencias que utilizan el estado actual para calcular el nuevo Sintaxis: S1; S2; S3; ... Lenguajes: FORTRAN, COBOL, C, Pascal,…
2
1
Aspectos específicos
Fortran (1954-57) FORmula TRANslator Desarrollado en IBM bajo supervisión de John Backus especialmente para cálculo científico Cambió drásticamente el uso de los ordenadores hasta entonces Ha evolucionado después, con nuevos conceptos y características
FORTRAN II, FORTRAN IV, FORTRAN 66, FORTRAN 77, FORTRAN 90
Siempre entre los compiladores más eficiente y generando código rápido Aún se usa en aplicaciones científicas, p.e. superordenadores 3
Aspectos específicos
Fortran 0 and 1 FORTRAN 0 – 1954 (not implemented) FORTRAN I - 1957 Designed for the new IBM 704, which had index registers and floating point hardware Environment of development: Computers were small and unreliable Applications were scientific No programming methodology or tools Machine efficiency was most important Impact of environment on design • No need for dynamic storage • Need good array handling and counting loops • No string handling, decimal arithmetic, or powerful input/output (commercial stuff) 4
2
Aspectos específicos
• • • • • • • • • •
Fortran I Features
Names could have up to six characters Post-test counting loop (DO) Formatted I/O User-defined subprograms Three-way selection statement (arithmetic IF) IF (ICOUNT-1) 100, 200, 300 No data typing statements variables beginning with i, j, k, l, m or n were integers, all else floating point No separate compilation Programs larger than 400 lines rarely compiled correctly, mainly due to IBM 704’s poor reliability Code was very fast Quickly became widely used 5
Aspectos específicos
Fortran II, IV and 77 FORTRAN II - 1958 • Independent compilation • Fix the bugs
FORTRAN IV - 1960-62 • Explicit type declarations • Logical selection (IF) statement • Subprogram names could be parameters • ANSI standard in 1966
FORTRAN 77 - 1978 • • •
Character string handling Logical loop control (WHILE) statement IF-THEN-ELSE statement 6
3
Aspectos específicos
Fortran 90 (1990) Added many features of more modern programming languages, including • Pointers • Recursion • CASE statement • Parameter type checking • A collection of array operations, DOTPRODUCT, MATMUL, TRANSPOSE, etc • dynamic allocations and deallocation of arrays • a form of records (called derived types) • Module facility (similar Ada’s package) 7
Aspectos específicos
Pascal (1971) • Diseñado por Wirth. Salió del comité ALGOL 68 • Diseñado para enseñar programación eswtructurada • Simple y sencillo • Introdujo mejoras modestas, como la sentencia case • Ampliamente usado en enseñanza ~ 1980-1995.
8
4
Aspectos específicos
Compiladores para Pascal El desarrollo del lenguaje y del primer compilador para éste fueron independientes
El lenguaje fue desarrollado por Wirth Experimentos sobre la portabilidad llevaron a Ammann al compilador Pascal-P Generaba código P, para una máquina de pila abstracta
Características: Compilador de una pasada Organizado alrededor del A.Sintáctico Analizador descendente recursivo
9
Aspectos específicos
Compiladores para Pascal Organización del compilador Pascal-P
La memoria de la máquina se organiza en las siguientes áreas:
Código Fuente
Analizador léxico, marca errores en una copia del código fuente
Cadena de componente léxicos Traductor predictivo Comprobador de tipos
Código para los procedimientos Constantes Pila para registros de activación Montículo para datos asignados aplicando el operador new
Código P 10
5
Aspectos específicos
Compiladores para Pascal Ventajas del compilador de una pasada
Fue fácil de implementar Generaba poca actividad de entrada/salida El código de un procedimiento se compila en memoria y
se escribe como una unidad a la memoria secundaria
Inconvenientes
Limitaciones en la calidad del código generado Mucha necesidad de memoria
11
Aspectos específicos
C (1972-) Diseñado para programar sistemas en Bell Labs, por Dennis Ritchie. Evolucionó de B, y después de ALGOL 68 Operadores potentes, pero pobre verificación de tipos Muy extendido a través de UNIX y disponibilidad de compiladores gratuitos y de alta calidad, especialmente gcc.
12
6
Aspectos específicos
Compiladores para C Lenguaje de propósito general (Ritchie) Principal lenguaje de programación en UNIX
UNIX está escrito en C
Se van a examinar el diseñado por Ritchie (1979) para PDP-11 y los transportables PCC de Johnson (1979) Compiladores de dos pasadas
PDP-11 tiene una tercera opcional para optimizar el lenguaje ensamblador (elimina proposiciones redundantes o innaccesibles) 13
Aspectos específicos
Compiladores para C Estructura de los compiladores C Código Fuente Analizador léxico y sintáctico Generación de código intermedio Forma postfija o prefija de expresiones o código ensamblador en caso constrario Generación de Código Lenguaje ensamblador Postoptimación Lenguaje ensamblador
14
7
Aspectos específicos
Compiladores para C El compilador PDP-11
Utiliza descenso recursivo para todo excepto las expresiones Expresiones con precedencia de operadores Código intermedio:
El compilador PCC
LALR(1) generado con YACC Código intermedio: Expresiones notación
prefija
Ensamblador demás
construciones
Expresiones notación
postfija
Ensamblador para
estructuras de control
15
Aspectos específicos
Compiladores para Fortran H Permite al usuario no elegir optimización, optimización de registros o completa Escrito por Lowry y Medlock (1969) Se realizan cuatro pasadas
Las dos primeras realizan el a.léxico y a.sintáctico produciendo cuádruplos La siguiente optimiza el código y registros La última genera código objeto a partir de cuádruplos y asignaciones a registros
16
8
Aspectos específicos
Compiladores para Fortran H Estructura de los compiladores H
En el léxico: Devuelve: Los pares operador-
operando son un token operando junto con el token no operando precedente Utiliza precedencia de operadores para las expresiones Optimizaciones simples, sustituir multiplicaciones por dos por desplazamientos
En la optimización: Eliminación de subexpresiones
comunes
Traslado de código
Código Fuente Analizador léxico incluido manejo de COMMON y EQUIVALENCE Pares operador-operando Análisis sintáctico, de flujo de datos Asignación de direcciones a nombres Cuádruplos con asignaciones de registros
Propagación de copias Eliminación de variables de
inducción
Genera código Código máquina relocalizable
Paradigma de Orientación a Objetos
17
Aspectos específicos
Las clases son tipos complejos que agrupan datos con operaciones (métodos) que los usan y modifican Herencia: subclases pueden heredar objetos y métodos de superclases La computación se basa en objetos que se envían mensajes (invocaciones a métodos) Ejemplos: Java, C++, Smalltalk
18
9
Aspectos específicos
Lenguajes Orientados a Objetos Características
Métodos Enlace objeto-método Estático Dinámico
Herencia Sobrecarga y polimorfismo Herencia múltiple Coerciones Objetos genéricos 19
Aspectos específicos
Implementación de Clases Ejemplo C++ #include <stdio.h> class A { public: int a; virtual int geta() { return a; } virtual void seta(int b) { a = b; } }; main() { A o; }
a
seta
geta
“Registro” de A: a tiene el dato entero seta, geta son punteros al código de la clase
20
10
Aspectos específicos
Compilación de lenguajes OO El compilador conoce el tipo (clase) de cada variable objeto
Las invocaciones a métodos se trasladan a llamadas ordinarias Se mantiene la invocación a funciones basada en pila
Todos los objetos de una clase comparten la tabla de despacho class A { public: dispatch ptr a int a; virtual int geta() { return a;} virtual void seta(int b){ a = b; } geta
Compilación: o1.a o1.geta() o1.seta(i)
o1->a o1->geta(o1) o1->seta(o1,i)
seta
o1->a (*(o1-> dtptr[0]))(o1) (*(o1->dtptr[1]))(o1,i)
21
Aspectos específicos
Compilación de lenguajes OO Llamadas a métodos Enlace Estático El objeto al que se aplica el método se pasa por
referencia a éste como primer argumento
obj.m(x,y) -> m(&obj, x, y)
El atributo “this” típico en lenguajes OO Aplicación de un método de clase base a
clases derivadas
La representación de los objetos de la clase base tiene que estar incluida en la representación de la clase derivada
Registro de Activación m
y x &Obj VD ED Vars …
22
11
Ejemplo C++ #include <stdio.h> class A { public: int a; virtual int geta() { return a; } virtual void seta(int b) { a = b; } };
MONTÍCULO: objs
Aspectos específicos
o1
o2
o1.a
A::geta
&A::geta
…
&A::seta
A::seta
o2.a
…
&A::geta &A::seta …
SEGMENTO DE CÓDIGO: clases
4 main() { A o1, o2; o1.seta(4); o2.seta(5) }
&o1
R.A. o1.seta(4)
…
PILA: llamadas
&main 5 &o2
R.A. o2.seta(4)
… &main
23
…
Aspectos específicos
Herencia en OO Una clase hereda los atributos y métodos de otra, y añade los suyos propios
Podría implementarse con enlace estático A B
Campos de A Campos de B
Class B: A {…} Sin funciones virtuales
Caso general: Xn hereda de Xn-1 , que hereda de. . . X1 Contenido de objeto de Xn : dispatch ptr
X1 atribs
X1 metodos
X2 atribs
X2 metodos
...
Xn atribs
. . . Xn metodos
24
12
Aspectos específicos
Herencia en OO Sobreescritura de métodos: una clase puede re-implementar métodos heredados
Implica cambios en los enlaces al código de métodos (tiempo de compilación) Podría implementarse con enlace estático
Ej.: class B : A { public: int b; virtual int getb() {return b;} virtual void setb(int c) {b = c + a;} virtual void seta(int c) {a = c+1;} };
dispatch ptr
a
b
A::seta (Class A* this, int c) {…} B::seta (Class B* this, int c) {…}
B::seta A::geta B::setb B::getb
25
Aspectos específicos
Herencia en OO Polimorfismo: una variable de clase base puede referirse a clase heredada Ej.: class B* b = new B(…); class A *a=b;
b &A::seta &A::geta &B::getb
Lo mismo ocurre con llamadas a métodos void f(A* x) { ... } ... B y; ... f(y);
puntero a A dentro de B puntero a B a
class
&B::setb …
*a= conv_ptrB_2_ptrA(b)
upcasting: en tiempo de compilación 26
13
Aspectos específicos
Herencia en OO Enlace dinámico: si b es realmente es de clase B, invoca a los métodos de B Ej.:
puntero a A dentro de B puntero a B a
b &A::seta
class B* b = new B(…); class A *a=b; a.seta(4);
&A::geta &B::getb &B::setb
¡No puede predecirse en tiempo de compilación!
&B::seta …
class C* c; if (random()>0.5) c=b; else c=new A(…); c.seta(4);
27
Aspectos específicos
Enlace dinámico Solución: tablas virtuales de despacho dinámico
Campos de A TVA
A
Se precisa información dinámica de tipos (distinguir A de A en B) Estructura de clases conocida
A: geta A::seta Tabla virtual de A
C++ No necesita
representación de clases en tiempo de ejecución, Smalltalk sí
Class A {…} A con funciones virtuales
A B
Campos de A TVA_B Campos de B TVB
Class B: A {…} A:geta B:seta B::getb B::setb Tabla virtual de B 28
14
Aspectos específicos
Tablas virtuales Tablas virtuales de despacho dinámico
Identificar la clase del objeto para poder decidir que método se tiene que aplicar Transformar tipo de this en ejecución
Ej.: class B* b = new B(…); class A *a1=new A(…); class A *a2=b; a1.seta(4); a2.seta(4)
a1->dtptr->A::seta(a1, 4); a2->dtptr->B::seta(convert_ptrA_2_ptrB(a2),4);
downcasting 29
Aspectos específicos
Herencia múltiple Una clase hereda los atributos y métodos de otra, y añade los suyos propios class C { field c1; field c2; virtual method virtual method } class D { field d1; virtual method virtual method } class E : C,D { field e1; method m4(); method m5(); };
puntero a E m1(); m2();
m3(); m4();
puntero a C dentro de E
puntero a D dentro de E
c1
&C::m1
c2
&C::m2
TV
&D::m3
d1
&E::m4
TV
&E::m5
e1 TV
upcast downcast
convert_ptrE_2_ptrC(e) -> e convert_ptrE_2_ptrD(e) -> e + sizeof(C) convert_ptrC_2_ptrE(e) -> e convert_ptrD_2_ptrE(e) -> e - sizeof(C) 30
15
Aspectos específicos
Resumen Compilación Lenguajes OO Análisis sintáctico
Estructura de clases y sintaxis
Análisis semántico
Enlace estático Coerción de tipos Invocación de métodos
Paquete de ejecución
Creación dinámica de objetos Despacho dinámico para métodos con polimorfismo
Optimización
Reducir la sobrecarga de llamadas Java: final, C++: virtual,… 31
Aspectos específicos
Lenguajes funcionales Paradigma de lenguaje funcionales (o aplicativos)
Programas como funciones que toman argumentos y devuelven valores (incluyendo otras funciones) La programación consiste en construir funciones que calculen la respuesta, aplicar la función y componer la respuesta
Historia
1930’s 1950’s 1960’s 1970’s 1980’s 1990’s
Lambda calculus (Church) Lisp (McCarthy) semantics, deconstruction FP (Backus) Miranda (Turner), ML (Milner) Haskell 32
16
Aspectos específicos
LISP (1959) • LISt Processing language (Designed at MIT by McCarthy) • AI research needed a language that: • Process data in lists (rather than arrays) • Handles symbolic computation (rather than numeric) • One universal, recursive data type: the s-expression • An s-expression is either an atom or a list of zero or more s-expressions • Syntax is based on the lambda calculus • Pioneered functional programming • No need for variables or assignment • Control via recursion and conditional expressions • Status • Still the dominant language for AI • COMMON LISP and Scheme are contemporary dialects • ML, Miranda, and Haskell are related languages 33
Aspectos específicos
Functional Programming Common Lisp: consolidation of LISP dialects spurred practical use, as did the development of Lisp Machines. Scheme: a simple and pure LISP like language used for teaching programming. Logo: Used for teaching young children how to program. ML: (MetaLanguage) a strongly-typed functional language first developed by Robin Milner in the 70’s Haskell: polymorphicly typed, lazy, purely functional language.
34
17
Aspectos específicos
Aspectos de Lenguajes Funcionales Idea básica: un programa es una función con entrada y salida El programador sólo especifica qué hay que calcular, no se preocupa de como, donde o cuando hacerlo
No hay sentencias, bucles, estructuras de control Sólo se preocupa del algoritmo eficiente, no de aspectos de bajo nivel: reducir llamadas, gestionar la memoria, etc.
Complicaciones con respecto a imperativos: mayhor abstracción, notación matemática, generalidad
Listas Definición con búsqueda de patrones (Pattern matching) Tipos y funciones polimórficas Funciones de orden superior (Higher-order) Evaluación tardía (Lazy evaluation) 35
Aspectos específicos
Aspectos de Lenguajes Funcionales Listas: elemento esencial. Notación (Haskell)
notación explícita: [] [1, 2, 3] [1..100] notación con operador aditivo “:” (1: (2: (3: [])))
Especificación con notación de conjuntos (List comprehension) [s=n^2 | n <- [1..100], odd n] qsort (x:xs)= qsort[y|y<-xs, y<x]++[x]++ qsort[y|y<-xs, x>=x]
Operadores <-, ++,
36
18
Aspectos específicos
Aspectos de Lenguajes Funcionales Funciones definidas con patrones fac 0 = 1 fac n = n *
fac (n-1)
No se precisan paréntesis para función
Tipos polimórficos length [] = 0 length (x:xs) = 1 +length xs take 0 xs = [] take n [] = [] take n (x:xs) = x: take (n-1) xs
No depende del tipo de cada elemento
37
Aspectos específicos
Aspectos de Lenguajes Funcionales Funciones de orden superior
Las funciones pueden ser argumentos de entrada y salida (diferencia con leng. imperativos)
diff f = f1 where f1 x= (f (x+h)-f x)/h where h=0.001 Nueva función: diff diff diff exp - x
Creación de funciones con currying (H.B. Curry) Función de n argumentos recibe m parámetros: nueva
función de n-m argumentos deriv f x = (f (x+h)-f x) / h where h=0.001 función de un argumento: deriv sqrt
38
19
Aspectos específicos
Aspectos de Lenguajes Funcionales Evaluación retardada (lazy evaluation)
Las funciones dependen de argumentos que se evalúan cuando son necesarios para seguir)
take n [1..]
¡[1 ..] es una lista infinita! En tiempo de ejecución se evalúan n primeros elementos
39
Aspectos específicos
Compilar Lenguajes Funcionales Análisis sintáctico
Notación listas, especificación Definición funciones
Análisis semántico
Inferencia de tipos polimórficos
Paquete de ejecución
Funciones de orden superior Evaluación retardada
Programa fuente
Traducción sintaxis Inferencia de tipos
Núcleo Funcional
Optimización
Generación de código Código generado (C)
Paquete de ejecución
Compilador C Código máquina
40
20
Aspectos específicos
Traducción a núcleo funcional Representación del programa con estructuras de control y funciones explícitas
Se utiliza código de leng. imperativo (C): llamadas a funciones y estructuras de control Se sustituye la notación de conjuntos por llamadas explícitas Se mantiene la semántica de funciones de orden superior y evaluación retardada
Transformaciones Traducción de listas a notación explícita
[1..100] (1: (2: (3 :…) (llamada a funciones de libería)
Pattern matching a estructuras de tipo if () else if () … Especificaciones sobre listas a llamadas a funciones de orden
superior: [expresion | calificador1, …, calificador]
41
Aspectos específicos
Paquete de Ejecución. LLamadas Llamadas a funciones
…
La traducción de especificaciones genera llamadas anidadas Funciones de orden superior y evaluación retardada Representación de funciones con currying
dirección retorno <sin enlace acceso> enlace de control
RA main RA padre
parám: n dirección retorno enlace de acceso enlace de control
La implementación con pila es insuficiente
RA hijo1
dirección retorno enlace de acceso enlace de control
fp
RA hijo2
parám: n …
enlace de acceso (acceso estático o léxico vs acceso dinámico) 42
21
Aspectos específicos
Paquete de Ejecución. LLamadas Ejemplo llamada a funciones de orden superior fun f(x) = let fun g(y)=x+y in g end val h=f(3) val j=f(4) val z=h(5) val w=j(7)
43
Aspectos específicos
Paquete de Ejecución. LLamadas Función de primer orden reverse reverse :: [a] -> [b] reverse [] = [] reverse (x:s) = reverse(s) : x
reverse [1,2,3] = [3,2,1]
L = [] reverse L = [3] reverse L = [2,3] reverse L = [1,2,3]
pila
44
22
Aspectos específicos
Paquete de Ejecución. LLamadas Función de orden superior map:: (a->b) -> ([a]->[b]) map f [] = [] map f (x:s) = (f x) : map f s g:: int -> (int->int) g x = f where f v = x+v
map (g 4) [10,11,12] = [14,15,16]
Problema: hay que guardar x como parte del entorno de la función devuelta. Funciones locales activas
fuera de su entorno de definición
g x=4
pila
45
Aspectos específicos
Paquete de Ejecución. LLamadas Cierre: puntero a código y al entorno de esé código
Solución:
< ,
La función invocada (g 4) devuelve puntero a su entorno de llamada g
fn(y:int) => x+y
fn(y:int) => x+y Y=10
env =
map f=
>
g x=4
L=[10,11,12];
pila
En montículo 46
23
Aspectos específicos
Paquete de Ejecución. LLamadas Solución alternativa a montículo:
EP
Pila de Contexto
Usar dos pilas: Pila de contexto con los
CSP
bloques de activación Pila de argumentos
Se evita que los parámetros impidan la eliminación del registro de activación antes de la última llamada Los parámetros se deben copiar de la pila de argumentos a la de contexto
AP Pila de Argumentos
EP: apuntador al ámbito activo CSP: apuntador a la cabeza de la pila de contexto AP: apuntador a la cabeza de la pila de argumentos 47
Aspectos específicos
Paquete de Ejecución. Reducción de grafo Es el intérprete de la representación intermedia en el núcleo funcional
Función “eval”. Toma las funciones construidas en tiempo de ejecución
@
El reductor de grafo resuelve las funciones de orden superior y evaluación retardada
Manipula nodos que representan llamadas parciales a funciones: ejecución suspendida Cada llamada de n argumentos es un subgrafo con n hijos
@ @ f
e1
e2
en
f e1 e2 … en
Cuando están evaluados todos los hijos se tiene una expresión reducible
Motor de reducción de grafos 48
24
Aspectos específicos
Optimización en lenguajes funcionales Esencial para obtener prestaciones aceptables Sobre la representación intermedia: núcleo funcional
Constant folding Eliminación de subexpresiones comunes Las llamadas directas (f g) se transfieren directamente sin nodos de aplicación Análisis de argumentos que pueden evaluarse en tiempo de compilación Optimización de llamadas recursivas Recursión en cola (la última llamada no consume pila)
49
25