Análisis Semántico y Chequeo de Tipos

Slides:



Advertisements
Presentaciones similares
SIES – SISTEMA INTEGRADO DE EDUCACIÓN SUPERIOR
Advertisements

ANALIZADOR SEMANTICO DIANA CAROLINA CASTAÑO YANCI VIVIANA CASTRO PEDRO LUIS FLÓREZ SANTIAGO GUTIÉRREZ A.
Curso de java básico (scjp)
DATSI, FI, UPM José M. Peña Programación en C DATSI, FI, UPM José M. Peña Programación en C.
Los números del 0 al cero uno dos tres cuatro cinco 6 7 8
INTELIGENCIA ARTIFICIAL
Universidad San Martín de Porres
1 LA UTILIZACION DE LAS TIC EN LAS MICROEMPRESAS GALLEGAS. AÑO mayo 2005.
1 LA UTILIZACION DE LAS TIC EN LAS PYMES GALLEGAS AÑO de Junio de 2005.
1 INFORME RESUMEN SOBRE EL NIVEL DE UTILIZACION DE LAS TIC EN LAS EMPRESAS GALLEGAS ( Resumen PYMES ) Noviembre de 2004.
AYUDA A LA FUNCIÓN DOCENTE Internet
TEMA 5.- 1ª PARTE. EL A.O. Y SUS APLICACIONES
TEMA 2 MÚLTIPLOS Y DIVISORES
02- Plan Organización Docente v.2 Noviembre 2009 SIES – SISTEMA INTEGRADO DE EDUCACIÓN SUPERIOR.
02- PLAN DOCENTE Febrero 2009 SIES – SISTEMA INTEGRADO DE EDUCACIÓN SUPERIOR.
01- OFERTA FORMATIVA v.2 Noviembre 2009 SIES – SISTEMA INTEGRADO DE EDUCACIÓN SUPERIOR.
Aladdín-respuestas 1.Vivía 2.Era 3.Amaba 4.Quería 5.Gustaban 6.Se sentía 7.Salía 8.Tenía 9.Decidió 10.escapó 11. Se vistió 12. Conoció 13. Vio 14. Pensó
Respuestas Buscando a Nemo.
ABECEDARIO FIGURAS GEOMÉTRICAS NÚMERO
Curso de java básico (scjp)
Objetivo: Los estudiantes van a usar vocabulario del desayuno para comprender un cuento. Práctica: 1. ¿Te gusta comer? 2. ¿Te gusta beber Mt. Dew.
Mulán /75 puntos. 1.Querían 2.Gustaban 3.Escuchó 4.Dijo 5.Tenía 6.Ayudaron 7.Maquillaron 8.Arreglaron 9.Dio 10.Estaba 11.Iba 12.Quería 13.Salió 14.Gritó
Lenguaje de programación Java
60 razones para seguir vivo
Clases Extendidas La clase extendida hereda los campos y métodos de la clase de la cual extiende. La clase original se conoce como superclase y la clase.
TELEFONÍA IP.
Parte 3. Descripción del código de una función 1.
Vocabulario querer comerlo -paja por supuesto - madera
FUNCIONES DE UNA VARIABLE REAL
Arquitectura CLARO-TECNOTREE
EL OSO APRENDIZ Y SUS AMIGOS
Interpretando objetos
1 PROYECTO DE PRESUPUESTO DE EGRESOS DE LA FEDERACION 2002 COORDINACIÓN DE POLITICA ECONOMICA GP-PRD.
Ecuaciones Cuadráticas
¡Primero mira fijo a la bruja!
Informática II Prof. Dr. Gustavo Patiño MJ
Informática II Prof. Dr. Gustavo Patiño MJ
¿Qué es un conjunto? Un conjunto es una colección de objetos considerada como un todo. Los objetos de un conjunto son llamados elementos o miembros del.
Aplicación del paradigma orientado a objetos
Traducción dirigida por la Sintaxis
Quetzalpapalotl Quetzalpapalotl – Gevederde Slang, vlindergod.
Módulo 2: Condiciones Generales de Trabajo

Realimentacion de la salida
Tema 7: Polimorfismo Antonio J. Sierra. Índice Introducción. Sobrecarga de métodos. Objetos como parámetros. Paso de argumentos. Devolución de objetos.
Programación Orientada a Objetos usando C++
Medio de tele-comunicación
Modificadores.
Lic. Rosemary Torrico Bascopé
Abstracción de los datos y Orientación a Objeto Clase 13.
Clases y objetos La unidad fundamental de programación OO son las clases. Conjunto de métodos y semántica Qué se va a hacer POO Clase: que define la implementación.
Estructuras de control
1 Herencia en Java Agustín J. González Diseño y Programación Orientados a Objetos.
Variables polimórficas (plantillas): definición, uso y aplicación
Herramienta FRAX Expositor: Boris Inturias.
 2003 Prentice Hall, Inc. All rights reserved. 1 Capítulo 6: Clases y Abstracción de Datos Índice del capítulo 6.1 Introducción 6.2 Estructuras 6.3 Clases.
M.C. Juan Carlos Olivares Rojas
INGENIERIA EN SISTEMAS COMPUTACIONALES
Clasificación de Gramáticas y Manejo de Errores
Tipos de Datos (Data Types)
Introducción al Análisis Sintáctico
Programación de Sistemas
Herencia. Introducción La idea básica es poder crear clases basadas en clases ya existentes. Cuando heredamos de una clase existente, estamos re-usando.
UNIVERSIDAD LATINA (UNILA)
Programación orientada a objetos
Programación de Sistemas
Programación orientada a objetos La programación orientada a objetos o POO (OOP según sus siglas en inglés) es un paradigma de programación que usa objetos.
Programación en Java Introducción a Java. Reseña histórica Surge en 1991 por Sun Microsystems Desarrollado para electrodomésticos Se buscaba un código.
Programación en Java Introducción a Java. Reseña histórica Surge en 1991 por Sun Microsystems Desarrollado para electrodomésticos Se buscaba un código.
Análisis Semántico y Chequeo de Tipos. Resumen Introducción Tablas de Símbolos Chequeo Semántico Chequeo de Tipos Semántica de un Programa Orientado a.
Transcripción de la presentación:

Análisis Semántico y Chequeo de Tipos

Oscar Bonilla 2 Universidad Galileo Resumen Introducción Tablas de Símbolos Chequeo Semántico Chequeo de Tipos Semántica de un Programa Orientado a Objetos Tipos Polimórficos Oscar Bonilla 2 Universidad Galileo

¿Dónde estamos? Programa (character stream) Analizador Léxico (Scanner) Token Stream Analizador Sintáctico (Parser) Arbol de Parseo Oscar Bonilla 3 Universidad Galileo

¿Dónde estamos? Programa (character stream) Analizador Léxico (Scanner) Token Stream Analizador Sintáctico (Parser) Arbol de Parseo Analizador Semántico Generador de Código Intermedio Representación Intermedia + Tabla de Símbolos Oscar Bonilla 4 Universidad Galileo

¿Qué es la semántica de un programa? Sintáxis Cómo se ve un programa Representación textual o estructura Es posible dar una definición matemática precisa Semántica Cuál es el significado del programa Es más difícil dar una definición matemática precisa Oscar Bonilla 5 Universidad Galileo

Por qué hacer análisis semántico Asegurarnos que el programa cumple con la definición del lenguaje de programación Proveer mensajes de error útiles al usuario Oscar Bonilla 6 Universidad Galileo

Oscar Bonilla 7 Universidad Galileo Resumen Introducción Tablas de Símbolos Chequeo Semántico Chequeo de Tipos Semántica de un Programa Orientado a Objetos Tipos Polimórficos Oscar Bonilla 7 Universidad Galileo

Oscar Bonilla 8 Universidad Galileo Tabla de Símbolos Un lugar para guardar toda la información adicional acerca del programa Representaciones intermedias: expresiones, statements, control de flujo, etc. Tabla de Símbolos: Tipos, variables, scope, etc. Oscar Bonilla 8 Universidad Galileo

Oscar Bonilla 9 Universidad Galileo Scope Un nombre puede tener significados distintos en lugares distintos Tipos, variables, etc tiene scope (ámbito) Tenemos que mantener una tabla de símbolos para cada scope Oscar Bonilla 9 Universidad Galileo

Operaciones en la tabla de símbolos make_table(parent_table)  symbol_table scope(id)  symbol_table lookup_variable(id, symbol_table)  variable lookup_type(id, symbol_table)  type get_type(variable)  type add_type(id, symbol_table, type)  type add_variable(id, symbol_table, type)  variable Oscar Bonilla 10 Universidad Galileo

Oscar Bonilla 11 Universidad Galileo Siguiente Clase Todo acerca de tablas de símbolos Scopes y visibilidad Información que se mantiene en la tabla de símbolos Implementación de tablas de símbolos Oscar Bonilla 11 Universidad Galileo

Oscar Bonilla 12 Universidad Galileo Resumen Introducción Tablas de Símbolos Chequeo Semántico Chequeo de Tipos Semántica de un Programa Orientado a Objetos Tipos Polimórficos Oscar Bonilla 12 Universidad Galileo

Oscar Bonilla 13 Universidad Galileo Chequeo Semántico Chequeos estáticos vs. Chequeos dinámicos Chequeos estáticos Chequeos de control de flujo Chequeos de unicidad Chequeos de Tipo Oscar Bonilla 13 Universidad Galileo

Chequeos de Control de Flujo El control de flujo del programa es sensitivo al contexto Ejemplos: Declaración de una variable debe ser visible al usarla (en scope) Declaración de una variable debe estar ántes de usarla Cada camino de salida (exit path) retorna un valor del tipo correcto ¿Qué más? Oscar Bonilla 14 Universidad Galileo

Oscar Bonilla 15 Universidad Galileo Chequeos de Unicidad Uso (y mal uso) de identificadores No se puede representar en una CFG (mismo token) Ejemplos: Ningún identificador puede ser usado para dos definiciones diferentes en el mismo scope Oscar Bonilla 15 Universidad Galileo

Oscar Bonilla 16 Universidad Galileo Chequeos de Tipo Los chequeos semánticos más extensos Ejemplos: Que el número de argumentos haga match con el número de parámetros formales y que los tipos correspondientes sean equivalentes Si se llama como expresión, debe retornar un tipo Cada acceso a una variable debe hacer match con la declaración (arreglo, estructura, etc.) Los identificadores en una expresión deben ser “evaluables” LHS de una asignación debe ser “asignable” En una expresión los tipos de las variables, tipos de retorno de métodos y de operadores deben ser “compatibles” Oscar Bonilla 16 Universidad Galileo

Oscar Bonilla 17 Universidad Galileo Chequeos Dinámicos Chequeos de límites de arreglos Chequeo de dereferencia del Null Pointer Oscar Bonilla 17 Universidad Galileo

Oscar Bonilla 18 Universidad Galileo Resumen Introducción Tablas de Símbolos Chequeo Semántico Chequeo de Tipos Semántica de un Programa Orientado a Objetos Tipos Polimórficos Oscar Bonilla 18 Universidad Galileo

Oscar Bonilla 19 Universidad Galileo Sistemas de Tipos Un sistema de tipos es usado para el chequeo de tipos Un sistema de tipos incorpora Construcciones estáticas del lenguaje Noción de tipos Reglas para asignar tipos a construcciones del lenguaje Oscar Bonilla 19 Universidad Galileo

Oscar Bonilla 20 Universidad Galileo Expresiones de Tipos Un tipo compuesto es denotado por una expresión de tipo Una expresión de tipo es Un tipo básico La aplicación de un constructor de tipo a otras expresiones de tipo Oscar Bonilla 20 Universidad Galileo

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” Oscar Bonilla 21 Universidad Galileo

Expresiones de Tipo: Nombres Ya que las expresiones de tipos pueden ser nombradas, un nombre de tipo es una expresión de tipo Oscar Bonilla 22 Universidad Galileo

Expresiones de Tipo: Productos Si T1 y T2 son expresiones de tipo, T1  T2 es también una expresión de tipo Oscar Bonilla 23 Universidad Galileo

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) Oscar Bonilla 24 Universidad Galileo

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 Oscar Bonilla 25 Universidad Galileo

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 (integer  integer)  integer  (integer  integer) Oscar Bonilla 26 Universidad Galileo

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 Oscar Bonilla 27 Universidad Galileo

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? Oscar Bonilla 28 Universidad Galileo

Oscar Bonilla 29 Universidad Galileo 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); } Oscar Bonilla 29 Universidad Galileo

Oscar Bonilla 30 Universidad Galileo Acciones del Parser E  literal { E.type = char; } E  num { E.type = integer; } E  id { E.type = lookup_type(id.name); } Oscar Bonilla 30 Universidad Galileo

Oscar Bonilla 31 Universidad Galileo 24 Acciones del Parser E  E1 + E2 { if E1.type == integer and E2 .type == integer then E.type = integer else E.type = type_error } Oscar Bonilla 31 Universidad Galileo

Oscar Bonilla 32 Universidad Galileo 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 } Oscar Bonilla 32 Universidad Galileo

Oscar Bonilla 33 Universidad Galileo 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 Oscar Bonilla 33 Universidad Galileo

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) Oscar Bonilla 34 Universidad Galileo

Oscar Bonilla 35 Universidad Galileo 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 Oscar Bonilla 35 Universidad Galileo

Oscar Bonilla 36 Universidad Galileo Widening conversions Conversiones sin pérdida de información Ejemplos: integers a floats shorts a longs Oscar Bonilla 36 Universidad Galileo

Narrowing conversions Conversiones que pueden perder información Ejemplos: integers a chars longs a shorts Raro en lenguajes Oscar Bonilla 37 Universidad Galileo

Oscar Bonilla 38 Universidad Galileo 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 Oscar Bonilla 38 Universidad Galileo

Oscar Bonilla 39 Universidad Galileo Pregunta: ¿Podemos asignarle un solo tipo a todas las variables, funciones y operadores? ¿Qué hay de +, cuál es su tipo? Oscar Bonilla 39 Universidad Galileo

Oscar Bonilla 40 Universidad Galileo 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 A = A + X ¿Cuál es el tipo de + ? Oscar Bonilla 40 Universidad Galileo

Oscar Bonilla 41 Universidad Galileo Resumen Introducción Tablas de Símbolos Chequeo Semántico Chequeo de Tipos Semántica de un Programa Orientado a Objetos Tipos Polimórficos Oscar Bonilla 41 Universidad Galileo

Oscar Bonilla 42 Universidad Galileo 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) Oscar Bonilla 42 Universidad Galileo

Oscar Bonilla 43 Universidad Galileo Clase Ejemplo campo class vehicle { int num_wheels; void print_num_wheels( ) { … } } método vehicle A; A.print_num_wheels( ) El Objeto es un parámetro implícito de la llamada del método Oscar Bonilla 43 Universidad Galileo

Oscar Bonilla 44 Universidad Galileo 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 Oscar Bonilla 44 Universidad Galileo

Oscar Bonilla 45 Universidad Galileo 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 Oscar Bonilla 45 Universidad Galileo

Oscar Bonilla 46 Universidad Galileo Herencia Herencia Sencilla Cuando cada clase está restringida a tener una sola superclase inmediata (máximo) Herencia Múltiple Cuando cada clase puede tener más de una superclase inmediata Oscar Bonilla 46 Universidad Galileo

Oscar Bonilla 47 Universidad Galileo Jerarquía de Herencia La relación subclase/superclase Definida por los “extends” Puede ser modelada mediante un grafo acíclico dirigido (DAG) Oscar Bonilla 47 Universidad Galileo

Oscar Bonilla 48 Universidad Galileo Jerarquía de Herencia vehicle SUV car motorbike 4wd 2wd 2-door 4-door 5-door Car es un hijo de vehicle (subclase inmediata) Vehicle es un padre de SUV (superclase inmediata) 4wd es un descendiente de vehicle (subclase) Vehicle es un ancestro de 2-door (superclase) Oscar Bonilla 48 Universidad Galileo

Reglas de Control de Acceso Conjunto de tipos de control de acceso usados por un lenguaje OO genérico (e.d. Espresso) Visibilidad en scope Acceso a datos Acceso a métodos públicos Acceso a métodos privados Muchos lenguajes OO tienen controles de acceso más complicados Oscar Bonilla 49 Universidad Galileo

Oscar Bonilla 50 Universidad Galileo Visibilidad en Scope Las variables y los campos de una clase pueden ser declarados en cualquier parte en el programa en la que se permita una declaración y la definición de la clase esté visible Si un campo en una subclase y superclase usa el mismo nombre La resolución de nombres se hace usando reglas de scope Se trata el scope de la subclase dentro del scope de la superclase Oscar Bonilla 50 Universidad Galileo

Oscar Bonilla 51 Universidad Galileo Acceso a Datos Los campos de datos de una clase sólo pueden ser accesados por los métodos definidos en esa clase Una variación más permisiva: Todos los métodos de las subclases pueden accesar los campos en la superclase Oscar Bonilla 51 Universidad Galileo

Acceso a métodos públicos Todos los métodos públicos de una clase pueden ser invocados por cualquier método que pueda declarar una variable o un campo del tipo de la clase Oscar Bonilla 52 Universidad Galileo

Acceso a métodos privados Los métodos privados de una clase sólo pueden ser invocados por: Los métodos de esa clase Los métodos de cualquier clase que sea descendiente de la clase Oscar Bonilla 53 Universidad Galileo

Ejemplo: control de acceso de C++ Una clase puede ser friend de otra clase Los métodos y campos pueden ser private: visibles a funciones miembro y friends protected: visibles a funciones miembro, friends, y clases derivadas (y sus friends) public: pueden ser usados por cualquier función Oscar Bonilla 54 Universidad Galileo

Conversión automática de tipos Una expresión de una clase es coercionada a una clase ancestro cuando se requiera Pero no al revés Llamado “up-casting” Siempre legal porque la subclase contiene todos los campos de la superclase Down-casting Esto es más permisivo Conversión explícita de una clase ancestro a una clase descendiente Sólo tiene sentido si el objeto fue creado inicialmente como en la subclase, pero después convertido a la superclase No puede chequearse en tiempo de compilación Oscar Bonilla 55 Universidad Galileo

Métodos Estáticos vs. Dinámicos Consecuencia de up-casting Implementación del método declarado en una superclase puede ser desconocida al momento de compilar El método es sobreescrito en una subclase Variaciones de Lenguajes Todos los métodos no declarados estáticos pueden ser up-casted Sólo los métodos declarados virtuales pueden ser up-casted Análisis e implementación de métodos dinámicos No se puede efectuar ningún chequeo semántico Necesitamos soporte en tiempo de corrida (runtime) al generar el código Oscar Bonilla 56 Universidad Galileo

Herencia vs. Agregación Una clase T2 es una agregación de una clase T1 si T2 contiene uno o más campos de tipo T1 A diferencia de la herencia, T2 no puede accesar campos o métodos privados en T1 ¿Cuándo heredear y cuándo agregar? heredar: T2 es un T1 agregar: T2 tiene un T1 Oscar Bonilla 57 Universidad Galileo

Ejemplo: Herencia vs. Agregación SUV es un vehículo SUV tiene un motor class vehiculo { … } class SUV extends vehiculo { motor power_plant; Oscar Bonilla 58 Universidad Galileo

Oscar Bonilla 59 Universidad Galileo Herencia múltiple Permite que una clase sea una extensión de múltiples clases Lleva a semánticas más complicadas para subtipos Oscar Bonilla 59 Universidad Galileo

Ejemplo de Herencia Múltiple class vehicle { … } class yuppie_toys { class SUV extends vehicle, yuppie_toys { Oscar Bonilla 60 Universidad Galileo

Jerarquía de Herencia Múltiple toys yuppie_toy teen_toy vehicle SUV car motorbike 4wd 2wd 2-door 4-door 5-door Jerarquía de Herencia Múltiple es un DAG Pregunta: ¿Sí tanto yuppie_toys como vehicle tienen un método price() cuándo SUV invoque a price, qué método se invoca? Oscar Bonilla 61 Universidad Galileo

Jerarquía de Herencia Múltiple big_ticket_items toys yuppie_toy teen_toy vehicle SUV car motorbike 4wd 2wd 2-door 4-door 5-door Es todavía más complicado cuándo hay un ancestro común Pregunta: ¿Cuántas instancias de bti van a ser incluidas en la clase SUV? Oscar Bonilla 62 Universidad Galileo

Oscar Bonilla 63 Universidad Galileo Resumen Introducción Tablas de Símbolos Chequeo Semántico Chequeo de Tipos Semántica de un Programa Orientado a Objetos Tipos Polimórficos Oscar Bonilla 63 Universidad Galileo

¿Qué es un tipo polimórfico? Procedimientos ordinarios permiten que el cuerpo sea ejecutado con argumentos de tipo fijo Cada llamada a un procedimiento polimórfico ejecuta el cuerpo con el tipo de los argumentos Beneficios del polimorfismo Reuso de Código Ejemplo El mismo procedimiento puede aplicarse a una lista de enteros o a una lista de strings Oscar Bonilla 64 Universidad Galileo

Polimorfismo Paramétrico Los procedimientos tienen tipos paramétrizados Instanciamos el procedimiento con un tipo determinado de datos Templates en C++ Ejemplo: template<class T> class linked_list_elem { T elem; linked_list_elem * next; ... } lined_list_elem<int> integer_list; lined_list_elem<foo> foo_list; Oscar Bonilla 65 Universidad Galileo

Oscar Bonilla 66 Universidad Galileo Lecturas Tigre 6.1, Capítulos 7 y 8 Ballena 4.1, 4.2, 4.3, 4.4, 4.5 Dragón Capítulo 8 Oscar Bonilla 66 Universidad Galileo