Apuntes de Programación y estructuras dedatos. Tipos de datos
Nikos Mylonakis, Fernando Orejas y Ana Cristina Zoltan
Dept. Llenguatges i Sistemes Informatics Universitat Politecnica de Catalunya
Barcelona
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.1/36
Introducción a la comprobación detipos
• Un tipo se puede definir como una propiedad deun conjunto de valores
• Ejemplos: booleanos, enteros, entero_par,entero_impar, tablas, tuplas, etc
• Los tipos también se pueden asociar a todas lasconstrucciones del lenguaje, por ejemplo lasoperaciones, las instrucciones y los subprogramas
• Los tipos se introducen en los LPs por motivos deseguridad.
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.2/36
• Los tipos determinan cómo se pueden utilizar lasentidades del LP
• Ejemplo 1: Si x es entero lo podemos sumar a unentero pero no lo podemos utilizar en unaoperación lógica o como una acción
• Ejemplo 2: Si A:tabla [1..100] de entero la expresiónA[50] es correcta pero A[120] no
• Para detectar los errores de uso de las diferentesentidades de un LP los LP realizan unacomprobación de tipos
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.3/36
• Ejemplo 1: Para que x + y sea correcta x e y hande ser bien enteros bien reales
• Ejemplo 2: Para que A[50] sea correcta A ha deser de tipo tabla y 50 ha de estar entre el subrangode la tabla.
• La comprobación de tipos puede ser estática (entiempo de compilación) o dinámica (en tiempo deejecución)
• Hay comprobaciones de tipos que sólo se puedenrealizar en tiempo de ejecución.
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.4/36
• La comprobación de tipos dinámica hace que losprogramas se ejecuten más lentamente
• En algunos LP las comprobaciones dinámicas sonopcionales. Java las realiza siempre
• Las ventajas de la comprobación de tipos sonfiabilidad (si hay errores se detectan lo más prontoposible) y eficiencia (la memoria asignada a lasvariables se puede gestionar con una pila si no seutilizan punteros)
• Las desventajas son que a veces se imponenrestricciones innecesarias y que es pesado tenerque declarar todo
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.5/36
Clases de sistemas de tipos
• Los sistemas de tipos en los LP pueden sermonomórficos (toda entidad sólo tiene un únicotipo) o polimórficos ( una entidad puede tener másde un tipo).
• La notación algorítmica que utilizamos esmonomórfica aunque puede haber sobrecarga deoperadores y Java es polímorfico (por la relaciónclase-subclase)
• Hay dos clases de polimorfismo: polimorfismo desubclase y polimormismo parámetrico
• Ejemplo de polimorfismo parámetrico: listas decualquier tipo ([α]) en Haskell donde α denotacualquier tipo Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.6/36
• Otra decisión de diseño de los sistemas de tipo LPes la equivalencia de tipos
• Ejemplo : x:=y requiere la comprobación de queambos tipos son equivalentes
• Hay dos clases de equivalencia: por nombre y porestructura
• La equivalencia por nombre requiere que los dostipos tengan el mismo nombre
• La equivalencia por estructura requieren que losdos tipos tengan la misma estructura
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.7/36
Ejemplo:
tipo
T = tabla [1..100]de entero
T ′ = tabla [1..100]de entero
ftipo
var
t1, t2 : T ;
t3 : T ′;
t4 : tabla [1..100]de entero
fvar
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.8/36
• Si hay equivalencia por nombre t1 := t2 es correctopero t1 := t3 y t1 := t4 no.
• Si hay equivalencia estructural t1 := t2, t1 := t3 yt1 := t4 son correctas
• En Java la equivalencia de tipos es por nombre• La equivalencia estructural varía según el LP
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.9/36
• Otro tema relacionado con la equivalencia de tiposson las coerciones
• Las coerciones son conversiones ímplicitas detipos
• Ejemplo: En C se realiza una coerción al realizarx = y si x es real y y entero
• En Java no existen coerciones• Siempre se permite realizar conversiones
explícitas
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.10/36
Concepto de subclase
• Se dice que existe una relación de subclase entreSC y C (SC es subclase de C) si siempre quepodemos utilizar elementos de la clase C tambiénpodemos utilizar elementos de la subclase SC
• La relación de subclase no es lo mismo que larelación de subconjunto en teoría de conjuntos
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.11/36
tipo
t = tupla
A : entero;
B : booleano;
ftupla
st = tupla
A : entero;
B : booleano;
C : caracter;
ftupla
ftipo
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.12/36
• Los valores de st no están incluidos en t pero encambio sí que puede existir una relación desubclase
• El motivo es porque las operación de acceso a uncampo de las tuplas hace que siempre que seutilice un elemento de t se puede utilizar unelemento de st pues los campos de t estánincluidos en st.
• En algunos LP como en Java para que puedeexistir relación de subclase se tiene que declararexplícitamente
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.13/36
Reglas de inferencia en sistema detipos
• Si los tipos son propiedades de conjuntos devalores, la lógica es una buena herramienta paratratarlas
• Un sistema de tipos quedará definido por unconjunto de reglas para inferir si una ciertaconstrucción del LP tiene su tipo correcto
• Las reglas de inferencia tendrán la forma
premisa1 . . . premisaN
conclusion
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.14/36
• Ejemplo de reglas lógicas
A BA ∧ B
A ⇒ B AB
• Las premisas y conclusiones de las reglas de unsistema de tipos para determinar el tipo de unaexpresión podrían ser de la forma Expr : T (Expr
tiene el tipo T )• Ejemplo de estas reglas serían
E1 : entero E2 : enteroE1 + E2 : entero
E1 : entero E2 : enteroE1 ≤ E2 : booleno
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.15/36
• El problema está en que la comprobación de tiposrequiere un conjunto de declaraciones deconstantes y variables ademas de la aridad de lasoperaciones predefinidas
• Por tanto las reglas requieren de entorno Γ quecontiene una lista con todas las declaracionesdefinidas y predefinidas
• Nosotros no veremos las reglas de generación delentorno pero si veremos el formato general de lasreglas para comprobar el tipo de las expresiones
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.16/36
Γ ∪ {x : T} ⊢ x : T
Γ ∪ {f : T1 × . . . × TN → T} ⊢ f : T1 × . . . × TN → T
Γ ⊢ f : T1 × . . . × TN → T Γ ⊢ E1 : T1 . . . Γ ⊢ EN : TN
Γ ⊢ f(E1, . . . , EN) : T
• Los operadores unarios y binarios tendrían reglasespecíficas por su posición infija y prefija
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.17/36
Las reglas para las instrucciones serían:
Γ ⊢ x : T Γ ⊢ E : TΓ ⊢ x := E : Instr
Γ ⊢ I1 : Instr Γ ⊢ I2 : InstrΓ ⊢ I1; I2 : Instr
Γ ⊢ E : booleano Γ ⊢ I1 : Instr Γ ⊢ I2 : InstrΓ ⊢ SiE entonces I1 sinoI2 : Instr
Γ ⊢ E : booleano Γ ⊢ I : InstrΓ ⊢ mientrasE hacer I fmientras : Instr
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.18/36
• La comprobación de tipos de los subprogramasrequeriría un nuevo tipo (por ejemplo Subpr)
• El entorno se tendría que actualizar con la lista deparámetros y variables locales
• A continuación se pasaría a comprobar que el tipodel cuerpo del subrprograma es una instrucción
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.19/36
• Finalizada la comprobación el entorno se tieneque actualizar con el nombre del subprograma y eltipo de sus parámetros para comprobar que lasllamadas a los subprogramas son correctas
• Debido a que pueden haber llamadas recursivasesta actualización se ha de hacer antes decomprobar el tipo del cuerpo del subprograma
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.20/36
Ejercicio: Comprobar el tipo de la siguiente función
funcion f(x, y : entero) retorna b : booleano
x := x + 1;
y ::= y + 2;
b := x ≤ y
retorna b
ffuncion
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.21/36
Algoritmos de comprobación detipos
• Los compiladores de los LP no implementansistemas deductivos de comprobación de tipos porser ineficientes
• Los compiladores utilizan una tabla de símbolospara guardar la información que tenemos en elentorno de las reglas
• La representación del programa es mediante unárbol sintáctico
• La comprobación de tipos requiere realizar unrecorrido recursivo del árbol sintáctico desde lashojas hasta la raíz asociando un tipo a cada nodo
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.22/36
Reglas de inferencia con subtipo
• Recordemos que un tipo st es subtipo de un tipo tsi cualquier elemento de st puede ser utilizado enun contexto en el que se utiliza t
• Las reglas de inferencia con subtipos tienen reglasadicionales como la reflexividad y la transitividadde la relación de subtipos y la regla desubsumción.
• La regla para subsumir nos dice que cuando unelemento es de un tipo st, ese elemento tambiéntiene los tipos de los supertipos de st, esto es, detodos los tipos t de los cuales st es subtipo
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.23/36
La formalización de las reglas es la siguiente
Γ ⊢ T < T
Γ ⊢ T1 < T2 Γ ⊢ T2 < T3Γ ⊢ T1 < T3
Γ ∪ {ST < T} ⊢ ST < T
Γ ⊢ expr : ST Γ ⊢ ST < T
Γ ⊢ expr : T
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.24/36
• Veamos cómo se implementa la comprobación detipos con subtipos
• El funcionamiento general es el mismo teniendouna tabla de símbolos y un árbol sintáctico al quehay que comprobar su tipo
• La tabla de símbolos contiene el menor subtipoasociado a las variables, constantes y parámetrosde las operaciones y las relaciones de subtiposentre los tipos
• El proceso recursivo es el mismo de las hojas a laraíz pero con comprobaciones adicionales
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.25/36
• Si tenemos que f : T1 × . . . × TN → y al realizar lacomprobación de f(E1, . . . , EN) tenemos queE1 : T1′, . . . , EN : TN ′ si TJ ′ < TJ para todo J entre1 y N el tipo de f(E1, . . . , EN) será correcto y detipo T .
• Si hay sobrecarga se tienen que tratar todas lasalternativas posibles
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.26/36
El sistema de tipos de Java
• El sistema de tipos de Java es polimórfico (porrelación de subclase/subtipo)
• No realiza coerciones implícitas• Permite sobrecarga si no hay ambiguedades• Ejemplo g : t1 × t2 → ts, g : t1′ × t2′ → ts′,
t1 < t1′, t2′ < t2 y a : t1, b : t2′ , la expresión g(a, b) daerror cuando es ambigua. Si hiciesemos x = g(a, b)y x : ts podríamos desambiguar pero en Java daerror
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.27/36
• Recordamos que en Java la asociación de tipos esestática pero la asociación de métodos esdinámica con ciertas restricciones
• En Java se puede asignar a una variable x declase C un valor de una subclase de C SC pero x
continua siendo de la clase C y x sólo puedeacceder a los atributos declarados en C
• Con respecto de los métodos, por asociacióndinámica si hay una redefinición de un método deC en SC una llamada a ese método con la variablex utilizaría el de SC
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.28/36
• La relación de subclase en Java se definemediante la cláusula extends entre clases como yavimos y sólo se puede heredar de una superclase(herencia simple)
• En Java también se permite dejar sin definirciertos métodos de una clase. En estos casos laclase se denomina abstracta
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.29/36
• Mediante la herencia podremos completar la clasedefiniendo los métodos no definidos
• Así podríamos implementar en Java el ejemplo delprograma del cálculo de los salarios de lostrabajadores de una empresa
• En Java también existen interfaces y son similaresa las clases abstractas con la particularidad quepermiten la herencia múltiple
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.30/36
• En Java tenemos dos clases de tipos: losprimitivos y los referencia subclase de la clasegeneral Object
• Los primitivos denotan un conjunto de valores yson por ejemplo int, boolean, byte, float, long, etc
• Los tipos referencia incluyen los strings, arrays ylas clases definidas por el usuario
• Los tipos referencia denotan una posición dememoria que contiene un valor del tiporeferenciado
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.31/36
• Una decisión de diseño de Java que se le criticade insegura es que si B es subclase de Aentonces los arrays de B (B[]) son subclase de losarrays de A (A[])
• Si generamos una tabla de 10 posiciones declases de B mediante la inicializaciónB[] b = newB[10] y declaramos a como un array deA A[] a
• Como los arrays de B son subclase de los arraysde A podemos realizar la asignación a=b,
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.32/36
• Ahora podríamos hacer la asignacióna[4] = new A() y por tanto el array b contendría unvalor de A
• La implementación de Java no permite ejecutarlo• Por este y otros motivos esta relación de subclase
en arrays no se considera una buena decisión dediseño
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.33/36
El sistema de tipos de C++
• El sistema de tipos de C++ también es polimórfico(por relación de subclase/subtipo)
• C++ sí que realiza coerciones implícitas• También permite sobrecarga si no hay
ambiguedades
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.34/36
• En C++ la asociación de tipos es estática y laasociación de métodos redefinidos también esdinámica
• Para ello se tienen que definir los subprogramascomo virtuales y los objetos como referencias asus clases.
• Si no se definen como virtuales se considera elsubprograma sobrecargado
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.35/36
• La relación de subclase en C++ se definemediante el símbolo : y una lista de superclasesseparadas por comas. Por tanto se permiteherencia multiple.
• Como ya vimos en el anterior capítulo se puedeponer operadores de acceso private, public oprotected.
• En C++ también se permite dejar sin definir losmétodos virtuales de una clase.
Nikos Mylonakis, UPC (Spain) March 4, 2010 – p.36/36