Diseño de compiladores Recordando la clase anterior

Documentos relacionados
Introducción a C# y la plataforma.net. Pablo Zaidenvoren 2013

Unidad Didáctica 2. Elementos básicos del lenguaje Java Tipos, declaraciones, expresiones y asignaciones

Estructuras de control selectivas

Compiladores e Intérpretes Análisis Semántico IV

Unidad Didáctica 3. Tipos genéricos. Fundamentos de Programación Departamento de Lenguajes y Sistemas Informáticos

Introducción a C# y la plataforma.net

PROGRAMACIÓN ORIENTADA A OBJETOS (L40629) Sabino Miranda-Jiménez

Carlos Montenegro. Programación Orientada a Objetos Proyecto Curricular de Ingeniería de Sistemas

Estructura de un programa en Java. Tipos de datos básicos. class miprimerprograma{ // comentario, no es parte del programa

Examen Teórico Convocatoria de Junio de 2012

Comprender las diferencias entre tipos de datos primitivos similares, y aprender a elegir el tipo más conveniente en cada caso.

Algoritmos y programas. Algoritmos y Estructuras de Datos I

Curso de Java Introducción a la Programación II

Compiladores e Intérpretes

Introducción a Java. Introducción a Java. Programación I

ANÁLISIS SEMÁNTICO VERIFICACIÓN DE TIPOS

Compiladores: Análisis Semántico. Pontificia Universidad Javeriana Cali Ingenieria de Sistemas y Computación Prof. Gloria Inès Alvarez V.

Centro Asociado Palma de Mallorca. Antonio Rivero Cuesta

Algoritmos y Estructuras de Datos Iteradores. Guillermo Román Díez

VARIABLES, CONSTANTES Y EXPRESIONES ASIGNACIÓN. TIPOS ELEMENTALES. PRECEDENCIA DE LOS ESTRUCTURAS DE CONTROL. CONDICIONAL E

Java. Introducción a la Programación Orientada a Objetos

Unidad IV. Este tipo de codificación nos es permitido gracias a la sobrecarga, la cual se aplica a métodos y constructores.

PROGRAMACIÓN GENÉRICA

Procesadores de lenguaje Tema 5 Comprobación de tipos

JavaScript Básico. Elementos Básicos: Comentarios: Literales: Valores que puede tomar una variable o una constante.

Introducción a Java LSUB. 30 de enero de 2013 GSYC

Elementos léxicos del lenguaje de programación Java

Algoritmos y Estructuras de Datos Ingeniería en Informática, Curso 2º SEMINARIO DE C++ Sesión 3

Introducción a C# y la plataforma.net. Pablo Zaidenvoren 2010

Tema 3: Herencia en C# Programación Orientada a Objetos Curso 2008/2009 Begoña Moros Valle

Los tipos de datos primitivos

18. Interfaces Declaración de una interfaz

Tema 4: Corrección y Robustez en C++ Programación Orientada a Objetos Curso 2008/2009 Begoña Moros Valle

2.2 Nombres, Ligado y Ámbito

INTERACCION ENTRE OBJETOS

Introducción a la computación. Carlos Lopez Pombo

Introducción a Java. Fernando Cerezal López. 24 Noviembre 2005

int[] nombrearray1; int nombrearray2[];

Qué es Java? Un lenguaje de programación Un entorno de desarrollo Un entorno de aplicación Un entorno de despliegue Es similar en sintaxis de C + +.

Construcciones del Lenguaje Java

CURSO : ESTRUCTURA DE DATOS DOCENTE : ING. JUAN ZEVALLOS VALLE

4/14/2010. Objetivos. Que es JAVA. JAVA como plataforma. Reglas Sintácticas y de Codificación Básicas de JAVA

Para crear un arreglo de cualquier tipo de elementos la sintaxis es:

Programación Tema 4: Métodos. Programación DIT-UPM

Programación orientada a objetos. Resumen de Temas Unidad 5: Herencia

Clases Abstractas e Interfaces

Métodos CON valor de retorno

ESTRUCTURA DE DATOS Y ALGORITMOS Titulación: Ingeniero Técnico en Informática de Gestión Curso: 2º Nombre y apellidos: Nota:

Diseño y Programación Orientados a Objetos 29 de Abril de Primer Certamen

3.3 Conceptos Básicos del Lenguaje Java

CAPÍTULO IV: 4.1 Introducción a la. Programación Funcional

Programación II Objetos en Java

Instituto Tecnológico de Celaya

Lenguajes de Programación. Capítulo 4. Expresiones.

Clases abstractas e interfaces en Java

Índice del capítulo. Capítulo 4. Expresiones. Las expresiones. Indice de la sección. Lenguajes de Programación. Introducción. 2.

Análisis semántico: Comprobación de tipos

Paradigmas de lenguajes de programación. Introducción a la programación imperativa. Lenguaje C. Programación imperativa

ARRAYS O ARREGLOS. EJEMPLOS CON OBJETOS Y TIPOS PRIMITIVOS. CAMPO LENGTH. RESUMEN TIPOS DE COLECCIONES JAVA. (CU00669B)

Swift. Angela María Muñoz Medina Liseth Briceño Albarracín Nicolás Larrañaga Cifuentes

PARTE TEÓRICA - TEST [2,5 PUNTOS]:

INICIACIÓN A LA PROGRAMACIÓN LENGUAJE JAVA con BlueJ

CLAVE EXAMEN: a cd. c u r s o r = c u r s o r. g e t S i g u i e n t e ( ) ; p o s i c i o n ++;

Aspectos de los LP. Diseño de compiladores. Estático vs. Dinámico. Estático vs. Dinámico. Scope. Scope 24/03/2015

Programación Tema 3: Tipos y expresiones simples. Programación DIT-UPM

Plantillas (Templates) Agustín J. González ELO-329

Estructura de Datos Unidad 1: Repaso del Lenguaje Java

Algoritmos y Estructuras de Datos: Ordenación y Colas con Prioridad. Guillermo Román Díez

Algoritmos y Estructuras de Datos Tema 2: Diseño de Algoritmos

LENGUAJES DE PROGRAMACIÓN. Solución al Ejercicio de Autocomprobación 1

Entiendo los métodos de Java equals y hashcode

HERENCIA (2ª parte) En Java todas las clases derivan de otra, aunque no se diga explícitamente.

12. Tipos de atributos

IMPLEMENTACIÓN DE PILAS CON LISTAS EN C++

Componentes Básicos. InCo. InCo Componentes Básicos 1 / 28

Java para programadores

Algoritmos y Estructuras de Datos Ingeniería en Informática, Curso 2º SEMINARIO DE C++ Sesión 1

Unidad Didáctica 1. Introducción a la Programación Orientada a Objetos (POO) Conceptos de clase, objeto e interfaz. Atributos y métodos

Memoria en C++ Punteros - Referencias Clases Y ahora, a trabajar! Memoria Dinámica en C++

abril de 2017 Desarrollo de aplicaciones en Java Tipos de datos primitivos Tipos de datos Elementos de aplicaciones simples

Variables. Una variable no es más que un nombre simbólico que identifica una dirección de memoria: vs.

Apuntes de Programación y estructuras de datos. Control de datos

Estructuras de control: Las variables: Fuertemente tipado: Tipado dinámico: Variables booleanas: Qué son las estructuras de control?

Tema 2: Programación basada en Objetos

REPRESENTACIÓN DE DATOS

Lenguajes de programación. Algoritmos y Estructuras de Datos I. Lenguajes compilados. Lenguajes compilados

Agradecimientos. Nota de los autores. 1 Problemas, algoritmos y programas 1

Sobrecarga de Operadores II

Programación orientada a objetos

Prefacio 25 Organización de la Unidad Didáctica Cómo utilizar el libro Objetivos docentes... 27

Asignación Dinámica de Memoria. Agustín J. González Versión original de Kip Irvine ELO 326: Seminario II 2do. Sem. 2001

Características de JavaScript

Ejercicio 1 (proyecto prlistas, paquete listas)

Sesión 2: Introducción a Java

Lenguajes de Programación I

Centro Asociado Palma de Mallorca. Antonio Rivero Cuesta

EJERCICIO Y EJEMPLO RESUELTO: USO DE LA INTERFACE COMPARABLE Y MÉTODO COMPARETO DE JAVA. COMPARAR OBJETOS (CU00913C)

Transcripción:

Diseño de compiladores Recordando la clase anterior Control de Tipos public class Clase1 implements Interfaz1 private string entero1; void metodo1() int[] x = new string; x[5] = entero1 * y; void metodo1() Tipo de datos equivocado public class Clase1 implements Interfaz1 private string entero1; void metodo1() int[] x = new string; x[5] = entero1 * y; void metodo1() Variable no declarada (y) No podemos multiplicar strings int fibonacci(int n) return metodo1() + fibonacci(n 1); int fibonacci(int n) return metodo1() + fibonacci(n 1); public class Clase1 implements Interfaz1 private string entero1; Que es un tipo? void metodo1() int[] x = new string; x[5] = entero1 * y; void metodo1() int fibonacci(int n) return metodo1() + fibonacci(n 1); No podemos sumar void La noción de tipo varia de lenguaje en lenguaje Hay cierto consenso en que: Es un conjunto de valores Es un conjunto de operaciones sobre esos valores Los errores de tipos ocurren cuando se realizan operaciones sobre valores que no soportan dichas operaciones 1

Chequeo de tipos Chequeo estático Analizamos el programa en tiempo de compilación para probar que no hay errores de tipo Idea: No dejar que pasen cosas malas en runtime Chequeo dinámico Chequeamos las operaciones en runtime, antes de hacerlas Mas preciso que el control estático, pero menos performante Sin control de tipos Mucha suerte! Sistemas de tipos Las reglas que determinan las operaciones permitidas en tipos, forman un sistema de tipos Sistemas fuertemente tipados NUNCA permiten un error de tipos Java, Phyton, Javascript, LISP, Haskell, etc. Sistemas débilmente tipados PERMITEN errores de tipos en runtime C, C++ Cual es mejor? Control de tipos (estático) Es un debate sin fin Los sistemas dinámicos facilitan la prototipación, mientras que los sistemas estáticos suelen tener menos fallas Los lenguajes fuertemente tipados son mas robustos, los lenguajes débilmente tipados, son mas rápidos En general implica 2 pasos Inferir los tipos de datos de las expresiones a partir de los tipos de datos de los componentes de las mismas Confirmar que los tipos de datos de las expresiones concuerdan con lo que se espera en ciertos contextos Conceptualmente son dos pasos diferentes, aunque suelen realizarse a la vez Ejemplo Ejemplo while (shiftbits(x + 5) <= 10) if (2.0 + 3.0) while (shiftbits(x + 5) <= 10) if (2.0 + 3.0) while (5 == null) while (5 == null) La expresión esta bien en termino de tipos Pero el tipo de la expresión no permite usarla en donde esta usada 2

Ejemplo while (shiftbits(x + 5) <= 10) if (2.0 + 3.0) while (5 == null) La expresión tiene un error de tipos + + INT 200 150 200 150 + + INT INT INT INT INT 200 150 200 150 3

= x Identificador = y Identificador true BoolConstant = = x Identificador = x Identificador = y Identificador true BoolConstant y Identificador true BoolConstant Reglas de inferencia Si x es un identificador que refiere a un objeto que tiene tipo T, entonces la expresión x tiene tipo T Si e es una constante entera, entonces e tiene tipo INT Si los operandos e1 y e2 de la expresión e1+e2 tienen tipos INT, entonces la expresión e1+e2 tiene tipo INT Control de tipos, como pruebas Podemos pensar el control de tipos, como la verificación de afirmaciones acerca de los tipos de las expresiones Comenzamos con un conjunto de axiomas a los que luego aplicamos reglas de inferencia para determinar el tipo de las expresiones Un sistema de tipos puede pensarse como un sistema de pruebas 4

Notación formal / Sistemas de tipos Esto se especifica con la siguiente sintaxis: Precondiciones PostCondiciones Esto se lee así: Si las precondiciones son verdaderas, podemos inferir las postcondiciones Notación formal / Sistemas de tipos Escribimos: e : T Si la expresión e tiene tipo T El símbolo significa Podemos inferir que Axiomas Algunas reglas de inferencia i es una constante INT s es una constante STRING i : INT s : STRING true : bool false : bool d es una constante DOUBLE d : DOUBLE Algunas reglas mas complejas Algunas reglas mas complejas Si podemos mostrar que e1 y e2 tienen tipo INT e1 : INT e2 : INT e1 : DOUBLE e2 : DOUBLE e1 : INT e2 : INT e1 : DOUBLE e2 : DOUBLE e1 + e2 : INT e1 + e2 : DOUBLE e1 + e2 : INT e1 + e2 : DOUBLE 5

Algunas reglas mas complejas Mas complicado todavía e1 : INT e2 : INT e1 : DOUBLE e2 : DOUBLE e1 : T e2 : T e1 : T e2 : T e1 + e2 : INT e1 + e2 : DOUBLE e1 == e2 : e1!= e2 : Entonces podemos afirmar que e1+e2 también tiene tipo INT Por que especificar así? Provee una definición rigurosa de los tipos de datos, independiente de cualquier implementación de compilador Flexibiliza la implementación Podemos implementar como queramos, siempre que respetemos las reglas Permite verificación formal de propiedades Permite realizar pruebas inductivas en la estructura del programa Un problema x:??? Un problema x:??? Como sabemos el tipo de x, si no sabemos a que referencia? if (x == 1.5) 6

if (x == 1.5) if (x == 1.5) x : int if (x == 1.5) if (x == 1.5) d es una constante double d: double x : int x : int 1.5 : double if (x == 1.5) if (x == 1.5) 7

e1 : T e2 : T e1 == e2 : x : int 1.5 : double x : int 1.5 : double if (x == 1.5) if (x == 1.5) e1 : T e2 : T e1 == e2 : e1 : T e2 : T e1 == e2 : x : int 1.5 : double x : int 1.5 : double if (x == 1.5) x == 1.5 : bool if (x == 1.5) x == 1.5 : bool Problema En el ejemplo anterior, no podemos llegar a inferir que x == 1.5 tiene tipo booleano, ya que tenemos hechos contradictorios para x Los hechos no tienen contexto Debemos reforzar los hechos, para indicar bajo que circunstancias son correctos Escribimos: Agregamos el scope S e : T Si en el scope S, la expresión e tiene tipo T Los tipos ahora son verificados según el scope en el que se encuentran 8

S true : S false : La regla correcta seria i es una constante INT s es una constante STRING S i : INT d es una constante DOUBLE S d : DOUBLE S s : STRING x es una variable en scope S con tipo T S x : T S e1 : DOUBLE S e2 : DOUBLE S e1 + e2 : DOUBLE S e1 : INT S e2 : INT S e1 + e2 : INT La regla correcta seria Reglas para funciones x es una variable en scope S con tipo T S x : T S f(e1,e2,,en) :? Reglas para funciones Reglas para funciones f es un identificador f es un identificador f es una función en el scope S S f(e1,e2,,en) :? S f(e1,e2,,en) :? 9

Reglas para funciones Reglas para funciones f es un identificador f es una función en el scope S f tiene tipo (T1,T2,,Tn) U S f(e1,e2,,en) :? f es un identificador f es una función en el scope S f tiene tipo (T1,T2,,Tn) U S ei : Ti para 1 i n S f(e1,e2,,en) :? Reglas para funciones Reglas para arrays f es un identificador f es una función en el scope S f tiene tipo (T1,T2,,Tn) U S ei : Ti para 1 i n S f(e1,e2,,en) : U S e1 : T [ ] S e2 : int S e1[e2] : T Reglas para asignaciones Reglas para asignaciones S e1 : T S e2 : T S e1 = e2 : T S e1 : T S e2 : T S e1 = e2 : T Que pasa con una expresión de este estilo? 10 = x; 10

Reglas para asignaciones Tipos en Clases S e1 : T S e2 : T S e1 = e2 : T Si estamos en un lenguaje orientado a objetos, si tenemos dos clases, Base y Derivada (que extiende a Base), funciona la regla para este código? Como incorporamos la herencia en nuestras reglas de inferencia? Debemos considerar la forma de las jerarquias de clases Base mybase; Derivada myderived; mybase = myderived; Herencia simple A Herencia múltiple A B C D B C D E Propiedades de herencia Cualquier clase es convertible consigo misma (Reflexibilidad) Si A es convertible en B, y B es convertible en C, entonces A es convertible en C (Transitividad) Si A es convertible en B y B es convertible en A, entonces A y B son el mismo tipo (Antisimetría) Esto define un orden parcial sobre los tipos Orden parcial en tipos Decimos que A <= B, si A es convertible en B Tenemos entonces que: A <= A A <= B, B <= C entonces A <= C A <= B, B <= A entonces A = B Entonces, la regla de asignación queda como: 11

Reglas para asignaciones Regla para comparaciones S e1 : T1 S e2 : T2 T2 <= T1 S e1 = e2 : T1 S e1 : T S e2 : T S e1 == e2 : bool S e1 : T1 S e2 : T2 T1 y T2 son clases T1 <= T2 o T2 <= T1 S e1 == e2 : bool Regla para comparaciones Regla para comparaciones S e1 : T S e2 : T S e1 : T1 S e2 : T2 T1 y T2 son clases T1 <= T2 o T2 <= T1 S e1 : T S e2 : T S e1 : T1 S e2 : T2 T1 y T2 son clases T1 <= T2 o T2 <= T1 S e1 == e2 : bool S e1 == e2 : bool S e1 == e2 : bool S e1 == e2 : bool Implica que están en la misma jerarquía Son comparables entonces Seria interesante unificar las reglas Estructura de los tipos Extendemos la convertibilidad A B C D E bool string double int arrays Si A es un tipo primitivo o un array, entonces A es convertible solo con A Si A y B son tipos, si A es un tipo primitivo o un array, entonces: A <= B implica que A = B B <= A implica que A = B 12

Regla para comparaciones Regla para funciones S e1 : T1 S e2 : T2 T1 <= T2 o T2 <= T1 S e1 == e2 : bool f es un identificador f es una función en el scope S f tiene tipo (T1,T2,,Tn) U S ei : Ri para 1 i n Ri <= Ti para 1 i n S f(e1,e2,,en) : U Que pasa con esto? Estructura de los tipos A S null :??? B C D E bool string double int arrays null type Manejando el null Definimos un nuevo tipo de datos, correspondiente al literal null, lo llamamos null type Hacemos que null type <= A, para cualquier clase A El null type no es accesible al programador, solo puede ser usado internamente Muchos lenguajes orientados a objetos tienen esta contruccion Null Type S null : Null Type 13

Que pasa con los tipos y las sentencias? Podemos probar la correctitud del tipo de las expresiones Pero Como podemos probar que una sentencia IF tiene condiciones booleanas bien formadas? Como podemos probar que una sentencia RETURN devuelve el tipo correcto? Que pasa con los tipos y las sentencias? Extendemos el sistema de pruebas a las sentencias, para verificar que están bien formadas Escribimos: S WF(stmt) Si la sentencia stmt se encuentra bien formada en el scope S Si podemos asignar un tipo T en el scope S a la expresión expr Un ejemplo Reglas para secuencias S expr : T S WF(expr;) S WF(stmt1) S WF(stmt2) S WF(stmt1 stmt2) Entonces decimos que la sentencia expr; esta bien formada en el scope S Reglas para loops Reglas para bloques S expr : bool Sea S el scope dentro del loop S WF(stmt) S WF(while (expr) stmt) Sea S el scope formado al agregar decls a S S WF(stmt) S WF( decls stmt ) 14

Reglas para return Chequeando WF S esta dentro de una función que retorna T S expr : T T <= T S WF(return expr;) S esta dentro de una función que retorna void S WF(return;) Podemos hacerlo recursivamente, recorriendo el AST Para cada sentencia Controlamos los tipos de cualquier sobrexpresión Si no podemos asignar tipos, reportamos error Si asignamos el tipo errado, reportamos error Controlamos los tipos de las subsentencias Controlamos la correctitud de la sentencia 15