Expresiones de Tipos: Tipos Básicos
Tipos atómicos definidos por el lenguaje
Ejemplos:
Enteros
Booleanos
floats
caracteres
type_error
Tipo especial que produce un error
void
Tipo básico que denota “la ausencia de un valor”
Expresiones de Tipo: Nombres
Ya que las expresiones de tipos pueden ser nombradas, un nombre de tipo es una expresión de tipo
Expresiones de Tipo: Productos
Si T1 y T2 son expresiones de tipo, T1 ? T2 es también una expresión de tipo
Expresiones de Tipo: Arrays
Si T es una expresión de tipo, un array(T, I) es también una expresión de tipo
I es una constante entera que denota el número de elementos de tipo T
Ejemplo:
int foo[128];
array(integer, 128)
Expresiones de Tipo: Function Calls
Matemáticamente una función mapea
Elementos de un conjunto (el dominio)
A elementos de otro conjunto (el contradominio)
Ejemplo
int foobar(int a, boolean b, int c)
integer ? boolean ? integer ? integer
Expresiones de Tipo: Otras
Records
Estructuras y clases
Ejemplo
class { int i; int j;}
integer ? integer
Lenguajes Funcionales
Funciones que toman funciones y retornan funciones
Ejemplo
(integer ? integer) ? integer ? (integer ? integer)
Un lenguaje simple con tipos
Un lenguaje que tiene una secuencia de declaraciones seguidas de una sola expresión
P ? D; E
D ? D; D | id : T
T ? char | integer | array [ num ] of T
E ? literal | num | id | E + E | E [ E ]
Programa Ejemplo
var: integer;
var + 1023
Un lenguaje simple con tipos
Un lenguaje que tiene una secuencia de declaraciones seguidas de una sola expresión
P ? D; E
D ? D; D | id : T
T ? char | integer | array [ num ] of T
E ? literal | num | id | E + E | E [ E ]
¿Cuáles son las acciones del parser para este lenguaje?
Acciones del Parser
P ? D; E
D ? D; D
D ? id : T { addtype(id.entry, T.type); }
T ? char { T.type = char; }
T ? integer { T.type = integer; }
T ? array [ num ] of T1 { T.type = array(T1.type, num.val); }
Acciones del Parser
E ? literal { E.type = char; }
E ? num { E.type = integer; }
E ? id { E.type = lookup_type(id.name); }
Acciones del Parser
E ? E1 + E2 { if E1.type == integer and
E2 .type == integer then
E.type = integer
else
E.type = type_error
}
24
Acciones del Parser
E ? E1 [E2 ] { if E2.type == integer and
E1 .type == array(s, t) then
E.type = s
else
E.type = type_error
}
Equivalencia de Tipos
¿Cómo sabemos si dos tipos son iguales?
Mismo entrada de tipo
Ejemplo:
int A[128];
foo(A);
foo(int B[128]) { … }
Dos entradas de tipo distintas en dos tablas de símbolos distintas
Pero deberían ser iguales
Equivalencia Estructural
Si la expresión de tipo de dos tipos tiene la misma construcción, entonces son equivalentes
“Misma Construcción”
Tipos base equivalentes
Mismo conjunto de constructores de tipo son aplicados en el mismo orden (e.d. árbol de tipos equivalente)
Coerción de Tipos
Conversión implícita de un tipo a otro tipo
Ejemplo
int A;
float B;
B = B + A
Dos tipos de coerción
widening conversions
narrowing conversions
Widening conversions
Conversiones sin pérdida de información
Ejemplos:
integers a floats
shorts a longs
Narrowing conversions
Conversiones que pueden perder información
Ejemplos:
integers a chars
longs a shorts
Raro en lenguajes
Type casting
Conversión explícita de un tipo a otro
Tanto widening como narrowing
Ejemplo
int A;
float B;
A = A + (int)B
Typecasting ilimitado puede ser peligroso
Pregunta:
¿Podemos asignarle un solo tipo a todas las variables, funciones y operadores?
¿Qué hay de +, cuál es su tipo?
Overloading
Algunos operadores pueden tener más de un tipo.
Ejemplo
int A, B, C;
float X, Y, Z;
A = A + B
X = X + Y
Complica el sistema de tipos
Ejemplo
A = A + X
¿Cuál es el tipo de + ?
Clases
Una clase es un tipo de datos abstracto
Contiene
Datos (campos)
Acciones (métodos)
Restricciones de acceso
Cada instancia de una clase va a crear un objeto separado
Con su propia copia de las variables instanciadas (compos)
Comparte las acciones (métodos)
Clase Ejemplo
class vehicle {
int num_wheels;
void print_num_wheels( ) { … }
}
(Gp:) campo
(Gp:) método
vehicle A;
A.print_num_wheels( )
(Gp:) El Objeto es un parámetro implícito de la llamada del método
Herencia
Extiende las clases al permitirles relaciones de supertipo/subtipo
Soporta reuso de código incremental
Partes comúnes en un supertipo común
Diferencias individuales en cada subtipo
Ejemplo de Herencia
class SUV extends vehicle {
int rollover_speed;
int get_rollover_speed( ) { … }
void print_rollover_speed( ) { … }
}
La clase SUV es una subclase de la clase vehicle
La clase vehicle es una superclase de la clase SUV
Una instancia (objeto) de la clase SUV contiene
Todos los campos de la clase vehicle
Todos los campos de la clase SUV
Los métodos tanto en SUV como en vehicle son visibles a la clase SUV
Página anterior | Volver al principio del trabajo | Página siguiente |