Lenguajes de Programación Tema 2. Semántica básica Pedro García López pgarcia@etse.urv.es/
Copyright © University Rovira i Virgili Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; provided its original author is mentioned and the link to http://libre.act-europe.fr/ is kept at the bottom of every non-title slide. A copy of the license is available at: http://www.fsf.org/licenses/fdl.html
Indice 2.1 Introducción 2.2 Valores y variables 2.3 Tipos de datos 2.4 Abstracciones 2.5 Encapsulación
2.1 Introducción Variables y asignación -- Storage fetch & update Estructuras de datos Storage structs Estructuras de control Saltos (JUMPS) Procedimientos Subrutinas Genericidad Reutilización Bloques, modulos Encapsulación Abstraccion
2.2 Valores y variables Las variables, los procedimientos o las constantes tienen nombres asignados por el programador Los valores son cualquier entidad almacenable como enteros, reales o arreglos. Las localizaciones son lugares o zonas de memoria donde se almacenan estos valores. El significado de un nombre queda determinado por las propiedades o atributos asociados con el mismo
Atributos const int n = 5 Ejemplo: Esta declaración convierte a n en una constante entera con valor 5, es decir, asocia al nombre n el atributo de tipo de datos contante entera y el atributo de valor 5
Atributos El proceso de asociación de un atributo a un nombre se conoce como ligadura (binding). Dependiendo del momento de asociación la ligadura puede ser estática (tiempo de compilación) o dinámica (tiempo de ejecución). y = new int; int n = 5; a = ‘pedro’ a = 3
Tabla de símbolos © 2003 Brooks/Cole - Thomson Learning™ © 2003 Brooks/Cole - Thomson Learning™ La tabla de símbolos (symbol table) almacena las ligaduras de atributos a nombres El entorno (environment) almacena las ligaduras de nombres a localizaciones de memoria.
Declaraciones, bloques y alcance La declaración es el método esencial para establecer ligaduras. Las declaraciones están asociadas comúnmente con constructores del lenguaje como los bloques. Las declaraciones pueden tambien asociarse a estructuras de datos como registros, o en agrupaciones más amplias como paquetes, módulos y namespaces.
Ámbito X Y Z
Ámbito Alcance estático o dinámico en la tabla de símbolos. const s=2; function scaled (d: Integer); begin scaled:= d*s; end; procedure q; const s = 3; begin (2) ... scaled(h) ... end begin (1) ... scaled(h) ... end;
Variables y asignación Una variable es un objeto cuyo valor almacenado puede cambiar durante la ejecución. x = y © 2003 Brooks/Cole - Thomson Learning™
Variables y asignación Asignación por copia o clonación (semántica de almacenamiento), por referencia o compartición (semántica de apuntador). Un alias ocurre cuando el mismo objeto está vinculado a dos nombres diferentes al mismo tiempo. Los alias pueden presentar efectos colaterales. © 2003 Brooks/Cole - Thomson Learning™
Variables y asignación Referencias perdidas free y malloc Basura, memoria asignada en el entorno que se ha convertido en inaccesible para el programa. El recolector de basura: Garbage collector
2.3 Tipos de datos Un tipo de datos es un conjunto de valores, junto con un conjunto de operaciones sobre dichos valores y con ciertas propiedades. Lenguajes fuertemente tipados (tipado estático) frente a lenguajes debilmente tipados (tipado dinámico) La verificación de tipos es el proceso que comprueba la consistencia del uso de tipos de un programa
Tipado estático (ventajas) Mejora la eficiencia de la ejecución Mejora la eficiencia de traducción Mejora la capacidad de escritura y la detección de errores Mejora la seguridad y confiabilidad Mejora la legibilidad Elimina ambigüedades La verificación de tipos estáticos es una herramienta de diseño Mejora la consistencia y corrección de la interfaz
Preguntas En grupos de 2 a 3 personas contestad a las siguientes cuestiones: Justificad y explicad cada uno de los puntos de la transparencia anterior. Justificad el uso del tipado dinámico con ejemplos
Clasificación de tipos Tipos primitivos (integer, boolean, char) Producto cartesiano (record, struct) Unión disjunta (union) Mapping (array, function) Set Enumerados Tipos recursivos y apuntadores Strings Tipos compuestos
Tipos en C © 2003 Brooks/Cole - Thomson Learning™
Tipos en Java © 2003 Brooks/Cole - Thomson Learning™
Tipos en Ada © 2003 Brooks/Cole - Thomson Learning™
Monomorfismo y polimorfismo Monomorfismo: Cada constante, variable, resultado de función o parámetro formal debe ser declarado de un tipo concreto. Ventajas: simplicidad, chequeo estático de tipos. Inconvenientes: Va contra la reusabilidad del código. Es poco flexible. Va contra el código genérico. Polimorfismo: Cuando una abstracción opera de forma uniforme sobre valores de diferentes tipos. Ventajas: potencia, elegancia, flexibilidad, reusabilidad, código generico. Inconvenientes: eficiencia, chequeo dinámico.
Sistemas de Tipos Sobrecarga (overloading): la capacidad de que un operador o identificador denote distintas abstracciones simultáneamente. Ej: write. Ventajas: simplicidad, polimorfismo aparente. Inconvenientes: Duplicidad de código, poco elegante para determinados problemas. Herencia y sistemas de tipos(inheritance): referente a los tipos, subtipos, supertipos y en particular la capacidad de los subtipos de heredar operaciones de sus supertipos. Dualidad Modulo-tipo
Sistemas de Tipos Monomorfismo Ej: PASCAL type CharSet = set of Char; function disjoint (s1,s2:CharSet):Boolean; begin disjoint := (s1*s2 = []) end var chars: CharSet; ... if disjoint (chars, [‘a’,’e’,’i’,’o’,’u’]) then ... ¿ Puede usarse disjoint sobre Integer o Color ?
Sistemas de Tipos Sobrecarga Ej: PASCAL Operadores: +,-, *. write(int), write (String), write (Character) File of Integer, File of Character, File of X eof(f) generico !!! PASCAL es inconsistente: las abstracciones definidas por el usuario solo pueden ser monomorficas mientras para solucionar problemas de genericidad utiliza la sobrecarga.
Sistemas de Tipos Sobrecarga (tipos) Dadas f1: S1 -> T1 y f2: S2 -> T2 Sobrecarga independiente del contexto (Pascal y ML). Requiere que S1 y S2 sean diferentes Sobrecarga dependiente del contexto(Ada). Requiere que S1 sea distinto de S2 o bien que T1 sea distinto de T2. function “/”( m,n: Integer) return Float is begin return Float(m)/ Float(n); end;
Sistemas de Tipos Polimorfismo (paramétrico) function second(x:a, y:b) = y; - second (13,true): Politipo: a x b -> b donde a y b son tipos. Ejemplos:Integer x Boolean -> Boolean y String x String -> String. Ej. PASCAL function disjoint (s1,s2:set of a):Boolean; begin disjoint := (s1*s2 = []) end
Sistemas de Tipos Polimorfismo (paramétrico). ML. Ejemplos: - fun id (x: a) = x; datatype a list = nil |cons of (a* a list) fun hd (l: a list) = ... fun tl ( l: a list) = ... fun length (l: a list) = Case l of Nil => 0 | cons (h,t) => 1 + length (t)
Sistemas de tipos Polimorfismo paramétrico: Generics en Ada Templates en C++ Ejemplos: Pila<T>, maximo(x:T, y:T) Polimorfismo paramétrico restringido Ejemplo. Pila<Persona>
Sistemas de Tipos Inferencia de tipos Monomórfica: fun even (n) = (n mod 2 = 0); Infiere un entero Polimórfica: fun id(x) = x Infiere un politipo. Casting (coercions): Conversion forzosa entre tipos distintos.
Sistemas de Tipos Polimorfismo de inclusión (Herencia) Tipos y subtipos Asignación polimórfica Ligadura dinámica Conclusiones: Polimorfismo está íntimamente relacionado con el código generico, reutilización y extensibilidad.
Preguntas En grupos de 2 a 3 personas contestad a las siguientes cuestiones: ¿ Qué tipos de polimorfismo soporta Ada ? ¿ Qué tipos de polimorfismo soporta C ? ¿ Qué tipos de polimorfismo soporta Java ? Añadid para cada tipo de polimorfismo en cada lenguaje al menos una línea de código que lo demuestre.
2.4 Abstracciones Secuenciadores Saltos Escapes Excepciones
Abstracciones Clases Funcional Procedural Parámetros Mecanismos de copia Mecanismos de referencia Principio de correspondencia
Abstracciones Clases (procedural y funcional) Parametrización Binding y parametrización Descomposición de problemas Abstracciones Caja negra
Abstracciones Abstracciones funcionales function power (x:Real; n:Integer):Real; begin if n = 1 then power := x else power:= x * power ( x , n-1) end
Abstracciones Abstracciones funcionales fun power (x:real; n:integer)= if n = 1 then x else x * power ( x , n-1) end Vista del implementador Vista Usuario
Abstracciones Abstracciones procedurales type WordSequence = array [...] of Word; procedure sort (var words : WordSequence); Vista del implementador Vista Usuario Asignación Algoritmo Abstracciones funcionales Expresiones Abstracciones procedurales Comandos
Abstracciones Parámetros Parámetro formal Parámetro actual Argumento Copia Referencia (Definitional) Paso de parámetros
Abstracciones Mecanismos de copia Valor Resultado Valor-resultado Mecanismo Entrada Salida Valor X:=argumento - Resultado - argumento:= X Valor-resultado X:=argumento argumento:=X
Abstracciones Principio de correspondencia: Para cada tipo de declaración existe un correspondiente paso de parámetros y vice versa. Declaración Parámetro formal Parámetro actual const I=E const I :T expression E of type T var I:= E I : T expression E of type T var I = V var I : T variable access Vof type T
Abstracciones Ordén de Evaluación Eager evaluation Normal-order evaluation Lazy evaluation Ejemplos: a) fun sqr (n:int) = n* n b) sqr(getint(f))
2.5 Encapsulación Tipos abstractos de datos (TADs) Paquetes y módulos Ocultación de Información Objetos y clases Genericidad Abstracciones genéricas Type parameters
Tipos de datos definidos por el usuario Los lenguajes deben ofrecer un mecanismo para construir tipos que disponga de : Un método para definir un tipo de datos y a la vez las operaciones sobre dicho tipo.Las operaciones deben quedar asociadas directamente con el tipo. Las definiciones no deben depender de detalles de implementación Un método para reunir en un solo lugar los detalles de implementación del tipo y sus operaciones, así como restringir el acceso a dichos detalles a los programas que utilizan el tipo de datos.
Tipos abstractos de datos Encapsulación: recolección en una sola localización de todas las definiciones relacionadas con el tipo de datos, restringiendo el uso del tipo a las operaciones definidas en dicha localización. Ocultación de información: separación de los detalles de implementación de las definiciones, y posibilidad de restringir el acceso a determinados detalles de la implementación.
Semántica Algebraica Especificación de un tipo abstracto Teoría denotada por la especificación Algebra que satisface la teoría La especificación algebraica consiste de dos partes: la signatura y los axiomas. La signatura define los tipos, operaciones y funcionalidad. Los axiomas son sentencias lógicas que describen el comportamiento de las operaciones
Semántica Algebraica specification TRUTH-VALUES sort Truth-Value operations true : Truth-Value false : Truth-Value not_ : Truth-Value -> Truth-Value _^_ : Truth-Value,Truth-Value -> Truth- Value _v_ : Truth-Value,Truth-Value -> Truth-Value _=>_ : Truth-Value,Truth-Value -> Truth-Value
Semántica Algebraica variables t,u:Truth-Value equations not true = false not false = true t ^ true = t t ^false = false t ^ u = u ^ t t v true = true t v false = false t v u = u v t t => u = (not t) v u end specification
Semántica Algebraica specification LISTS include NATURALS formal sort Component sort List operations empty-list : List cons (_,_) : Component , List -> List head _ : List -> Component tail _ : List -> List length _ : List -> Natural
Semántica Algebraica variables c:Component l: List equations head cons (c,l) = c tail cons(c,l) = l tail empt-list = 0 length empty-list = 0 length cons(c,l) = succ(length l) end specification
TADs Tipos abstractos de datos (ML) abstype rational = rat of (int * int) with val zero = rat(0,1); val one = rat (1,1); fun op // (m:int, n:int) = ... and op ++(rat(m1,n1):rational, rat(m2,n2):rational) = rat(m1*n2 + m2*n1, n1*n2) and op == ( ...) end
Módulos Un módulo es una unidad de programación con una interfaz pública y una implementación privada; todos los servicios disponibles de un módulo quedan descritos en su interfaz pública y se exportan a otros módulos, así como todos los servicios requeridos por un módulo deben importarse de otros módulos. © 2003 Brooks/Cole - Thomson Learning™
Compilación por separado en C y C++ C no tiene mecanismos modulares pero si tiene características de compilación por separado y de control de nombres para imitar módulos. © 2003 Brooks/Cole - Thomson Learning™
C y módulos Las directivas include proveen algo de documentación con respecto a las dependencias, pero esta información no puede ser utilizada por el compilador o enlazador. Todos los sistemas en C requieren que el usuario lleve un control del código fuente obsoletoy proceder manualmente a recompilar y volver a enlazar. (make) C++ tiene el mismo problema debido a una decisión de diseño (Stroustup) de compatibilidad con C.
Espacios de nombres Namespace en C++ y package en Java Permite la introducción explícita de un alcance nombrado a fin de evitar choques de nombres entre bibliotecas compiladas por separado. package myqueue; import myqueue.Queue; Myqueue.Queue
Paquetes Abstracción -> Encapsulación -> Modularidad Librerias de rutinas (c) -> Modulos (Modula 2) -> paquetes (Ada) -> clases (Smalltalk) Modularidad, TAD (tipos abstracto de datos), ocultación de información. Paquetes package I is D end I; structure I = struct D end
Paquetes Ocultación de información Ada: package body trig is ... package trig is function sin(x:Float) return Float; function cos(x:Float) return Float; end trig; package body trig is ... end trig Favorece la programación por contrato (caja negra) Favorece la separación de interfaz de implementación independizando ésta.
Paquetes Clases y objetos (Ada) package directory_object is procedure insert ( newname: in Name; newnumber: in Number); procedure lookup ( oldname: in Name; oldnumber: out Number, found: out Number); end directory_object; directory_object.insert(me, 6041); ... directory_object.lookup(me, mynumber,ok);
Paquetes Clases y objetos (Ada) generic package directory_class is procedure insert ( newname: in Name; newnumber: in Number); procedure lookup ( oldname: in Name; oldnumber: out Number, found: out Number); end directory_object; package homedir is new directory_class; package workdir is new directory_class; workdir.insert(me,6050); homedir.insert(me,2323);
OOP Clases y objetos (Java OOP) class Directory { ... } Directory homedir = new Directory(); Directory workdir = new Directory(); homedir.insert(2323); Workdir.insert(1212);
Genericidad Genericidad: polimorfismo paramétrico generic capacity: in Positive; package queue_class is .... end queue_class; package body queue_class is items: array (1.. Capacity) of Character; package line_buffer is new queue_class (120);
Genericidad Genericidad (tipos) generic capacity: in Positive; type Item is private; package queue_class is procedure append (newitem: in Item); procedure remove (olditem: out Item; end queue_class; package line_buffer is new queue_class (120, Character); line_buffer.append(‘*’);
Problemas de los TADs Los módulos no son tipos. Los módulos son entidades estáticas. procedure Quser is package IntQueues is new Queues(Integer); use IntQueues; package FloatQueues is new Queues(Float); use FloatQueues; fq: FloatQueues.Queue; iq: IntQueues.Queue; begin fq := enqueue(fq,3.1); iq := enqueue(iq,3);
Problemas en los TAD Problemas de inicialización, asignación, igualdad, copia y control de memoria. Problemas de contrato y parametrización restringida (with en Ada). Las definiciones de los módulos no incluyen especificación de la semántica de las operaciones incluidas. La especificación algebraica incluye ecuaciones que explican la semántica. Eiffel resuelve esto mediante precondiciones, postcondiciones e invariantes.
Preguntas En grupos de 2 a 3 personas contestad a las siguientes cuestiones: De los problemas anteriores, ¿ cuales resuelve Java (explicad como) y cuales no ? ¿ Soporta Java encapsulación y ocultación de información ? ¿ como ? ¿ Soporta Java la compilación separada ? ¿ Gestiona Java automáticamente las dependencias entre módulos (clases) ? Ejemplo: detección de imports no usados, recompilación automática de dependencias al modificar una clase.