Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
teaching:cc4101:tareas:xyz:tarea1b [2024/04/03 17:57] – [Checkeo Estático de Tipos] fdiaz | teaching:cc4101:tareas:xyz:tarea1b [2024/04/30 18:08] (current) – gricci | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Tarea 1b (Entrega: | + | ====== Tarea 1b (Entrega: |
==== Lenguaje con tipos estáticos ==== | ==== Lenguaje con tipos estáticos ==== | ||
Line 5: | Line 5: | ||
Ya se habrán dado cuenta que ciertos lenguajes tienen tipos estáticos (C/C++, Java, C#, Scala, etc.) y otros tienen tipos dinámicos (Python, Racket, JavaScript, etc.). | Ya se habrán dado cuenta que ciertos lenguajes tienen tipos estáticos (C/C++, Java, C#, Scala, etc.) y otros tienen tipos dinámicos (Python, Racket, JavaScript, etc.). | ||
- | En esta tarea van a implementar un lenguaje simple con funciones de primer orden, tipos de datos básicos y pares. Para implementar este lenguaje necesitaremos un parser (lo implementamos en la tarea 1a), y un interprete, dividiremos el desarrollo de esta tarea en dos partes (más una opcional). Primero, el lenguaje contará sólo con chequeo dinámico de tipos (parte 1), para luego agregar verificación de tipos estáticos (parte 2). Opcionalmente (como bonus), puede agregar contratos dinámicos para funciones (parte 3). | + | En esta tarea van a implementar un lenguaje simple con funciones de primer orden, tipos de datos básicos y pares. Para implementar este lenguaje necesitaremos un parser (lo implementamos en la tarea 1a), y un intérprete, dividiremos el desarrollo de esta tarea en dos partes (más una opcional). Primero, el lenguaje contará sólo con chequeo dinámico de tipos (parte 1), para luego agregar verificación de tipos estáticos (parte 2). Opcionalmente (como bonus), puede agregar contratos dinámicos para funciones (parte 3). |
---- | ---- | ||
Line 14: | Line 14: | ||
</ | </ | ||
+ | **Distribución de Puntaje** | ||
- | Deben entregar via U-cursos | + | Esta tarea tiene **4 pts** en total, |
+ | * 3 pts por implementación (subdividido como especifica el enunciado). | ||
+ | * 0.5 pts para testing. | ||
+ | * 0.5 pts para calidad de código. | ||
- | Si lo desea, puede obtener un bonus resolviendo la tercera parte, que es opcional: '' | + | Deben entregar via U-cursos **un archivo .zip** que contenga los siguientes archivos: '' |
+ | |||
+ | Si lo desea, puede obtener un bonus resolviendo la tercera parte, que es opcional: '' | ||
+ | |||
+ | **Nota:** Es libre de implementar el intérprete usando sustitución inmediata o diferida (con ambientes), en cuyo caso podría serle útil el archivo {{ : | ||
Deben entregar vía U-Cursos **un único archivo .zip** que contenga todos los archivos de su entrega. | Deben entregar vía U-Cursos **un único archivo .zip** que contenga todos los archivos de su entrega. | ||
<note important> | <note important> | ||
- | * Recuerde incluir tests con cobertura de todos los casos relevantes para todas las funciones que implemente, pues esto se considerará en la evaluación. | + | * Recuerde incluir tests con cobertura de todos los casos relevantes para todas las funciones que implemente |
</ | </ | ||
- | ===== Parte 1. Lenguaje con funciones de primer orden (1.5 ptos.) ===== | + | |
+ | ===== Parte 1. Lenguaje con funciones de primer orden (1.1 ptos.) ===== | ||
En esta parte, vamos a implementar un lenguaje que incluye primitivas útiles (números, booleanos, pares, y operadores simples), identificadores locales ('' | En esta parte, vamos a implementar un lenguaje que incluye primitivas útiles (números, booleanos, pares, y operadores simples), identificadores locales ('' | ||
Line 52: | Line 61: | ||
| {<id> < | | {<id> < | ||
- | < | + | < |
</ | </ | ||
Line 58: | Line 67: | ||
Esta gramática es similar a la presentada en la tarea 1a, con las siguientes diferencias. | Esta gramática es similar a la presentada en la tarea 1a, con las siguientes diferencias. | ||
* Se agregan dos operadores booleanos extra, estos son ''&&'' | * Se agregan dos operadores booleanos extra, estos son ''&&'' | ||
- | * Se agregan pares, | + | * Se agregan pares, |
- | Los programas que terminan reducen a valores. Estos pueden ser números, booleanos o pares de valores. Siguiendo buenas prácticas, | + | Los programas que terminan reducen a valores. Estos pueden ser números, booleanos o pares de valores. Siguiendo |
- | Algunos ejemplos de programas válidos para este lenguaje pueden ser: | + | Algunos ejemplos de programas válidos para el lenguaje |
<code scheme> | <code scheme> | ||
{ | { | ||
Line 84: | Line 93: | ||
} | } | ||
+ | { | ||
+ | | ||
+ | | ||
+ | } | ||
</ | </ | ||
Line 89: | Line 102: | ||
**Observaciones importantes**: | **Observaciones importantes**: | ||
* Recuerde que la estructura del BNF dicta la estructura de las funciones que procesan los programas, definiciones, | * Recuerde que la estructura del BNF dicta la estructura de las funciones que procesan los programas, definiciones, | ||
- | * Al implementar el lenguaje, asegúrese de hacerlo | + | * La semántica del '' |
- | | + | |
- | * Verifique | + | { |
+ | {with {{x 2} | ||
+ | {y {add1 x}}} | ||
+ | {add1 y}} | ||
+ | } | ||
+ | |||
+ | >> Free identifier: x | ||
+ | </ | ||
+ | En cambio, el siguiente programa si funciona, pues '' | ||
+ | <code scheme> | ||
+ | { | ||
+ | {with {{x 2}} | ||
+ | {with {{y {add1 x}}} | ||
+ | {add1 y}} | ||
+ | } | ||
+ | </ | ||
+ | Además de lo anterior, asumiremos por simplicidad que en los bindings de un mismo '' | ||
+ | <code scheme> | ||
+ | { | ||
+ | {with {{x 2} | ||
+ | {x 4}} | ||
+ | x} | ||
+ | } | ||
+ | </ | ||
+ | * Debe verificar | ||
* Considere que la igualdad solo es válida sobre números. | * Considere que la igualdad solo es válida sobre números. | ||
* La condición de una expresión '' | * La condición de una expresión '' | ||
- | | + | * En caso de programas con errores dinámicos |
- | | + | < |
+ | donde ''< | ||
+ | **Nota:** En el código base se provee la función '' | ||
- | <code scheme> | + | A continuación se muestran algunos programas que fallan dinámicamente por errores de tipo: |
- | debe fallar en tiempo de ejecución con un error (se levantan con '' | + | |
- | <code scheme>"Runtime type error: expected | + | <code scheme> |
+ | { | ||
+ | | ||
+ | } | ||
+ | |||
+ | >> Runtime type error: expected Number found {cons 3 4} | ||
+ | </ | ||
+ | <code scheme> | ||
+ | { | ||
+ | {&& {+ 1 2} #f} | ||
+ | } | ||
+ | |||
+ | >> Runtime type error: expected Boolean found 3 | ||
+ | </ | ||
+ | <code scheme> | ||
+ | { | ||
+ | {snd {! #t}} | ||
+ | } | ||
+ | |||
+ | >> Runtime type error: expected Pair found #f | ||
+ | </ | ||
+ | <code scheme> | ||
+ | { | ||
+ | {if {cons 2 3} | ||
+ | 1 | ||
+ | 0} | ||
+ | } | ||
+ | |||
+ | >> | ||
+ | </ | ||
Recuerde que puede verificar si un test lanza una excepción con '' | Recuerde que puede verificar si un test lanza una excepción con '' | ||
+ | * Al aplicar una función, debe verificar en tiempo de ejecución que la función esté definida y que sea aplicada al número correcto de argumentos, de lo contrario debe lanzar un error. Por ejemplo, los siguientes programas lanzan errores: | ||
+ | <code scheme> | ||
+ | { | ||
+ | {foo 2 3} | ||
+ | } | ||
- | Mediante una función '' | + | >> Undefined function: foo |
- | * Obtenemos el programa a partir de la entrega con '' | ||
- | * Ejecutamos el programa resultante con '' | ||
- | Para desarrollar el intérprete, dividiremos su implementación | + | { |
+ | {define {bar p} {! p}} | ||
+ | {bar #t #f} | ||
+ | } | ||
+ | |||
+ | >> Arity mismatch: function bar expected 1 arguments, received 2 | ||
+ | </ | ||
+ | |||
+ | |||
+ | Teniendo | ||
+ | |||
+ | - **[0.9 pts]** '' | ||
+ | - **[0.2 pts]** '' | ||
----- | ----- | ||
- | ===== Parte 2. Verificación estática de tipos (2.5 ptos.) ===== | + | |
+ | ===== Parte 2. Verificación estática de tipos (1.9 ptos.) ===== | ||
En esta parte vamos a extender el lenguaje con anotaciones de tipos y verificación estática de ellos. Las diferencias en la sintaxis del lenguaje respecto de la parte anterior son: | En esta parte vamos a extender el lenguaje con anotaciones de tipos y verificación estática de ellos. Las diferencias en la sintaxis del lenguaje respecto de la parte anterior son: | ||
Line 120: | Line 204: | ||
;; < | ;; < | ||
- | < | + | < |
< | < | ||
Line 139: | Line 223: | ||
{+ x y}} | {+ x y}} | ||
} | } | ||
+ | </ | ||
+ | <code scheme> | ||
{ | { | ||
{with {{x 5}} | {with {{x 5}} | ||
Line 145: | Line 230: | ||
{+ x y}} | {+ x y}} | ||
} | } | ||
+ | </ | ||
+ | <code scheme> | ||
{ | { | ||
{define {add-pair {p : {Pair Num Num}} {x : Num}} : {Pair Num Num} | {define {add-pair {p : {Pair Num Num}} {x : Num}} : {Pair Num Num} | ||
Line 151: | Line 237: | ||
{add-pair {cons 1 1} 1} | {add-pair {cons 1 1} 1} | ||
} | } | ||
+ | </ | ||
+ | <code scheme> | ||
{ | { | ||
{define {id {x : Num}} : Num x} | {define {id {x : Num}} : Num x} | ||
{id 5} | {id 5} | ||
} | } | ||
+ | </ | ||
+ | <code scheme> | ||
{ | { | ||
{define {sum {x : Num} {y : Num} {z : Num}} : Num | {define {sum {x : Num} {y : Num} {z : Num}} : Num | ||
Line 166: | Line 254: | ||
{sum x {fst y} {cadr y}} } | {sum x {fst y} {cadr y}} } | ||
} | } | ||
- | |||
</ | </ | ||
Line 172: | Line 259: | ||
Note que se agregó el nodo ''< | Note que se agregó el nodo ''< | ||
- | - **[0.0 pts]** Defina el tipo de datos '' | + | - **[0.1 pts]** Defina el tipo de datos '' |
- | - **[0.0 pts]** Implemente la función '' | + | - **[0.2 pts]** Implemente la función '' |
- | - **[0.0 pts]** Modifique la función '' | + | - **[0.1 pts]** Modifique la función '' |
Además de lo anterior, observe que el nodo ''< | Además de lo anterior, observe que el nodo ''< | ||
- | - **[0.0 pts]** Modifique el tipo de datos '' | + | - **[0.1 pts]** Modifique el tipo de datos '' |
- | - **[0.0 pts]** Modifique la función '' | + | - **[0.1 pts]** Modifique la función '' |
Line 185: | Line 272: | ||
Para poder realizar un checkeo de tipos estático, necesitaremos: | Para poder realizar un checkeo de tipos estático, necesitaremos: | ||
- | - **[0.0 pts]** Implementar la función '' | + | - **[0.6 pts]** Implementar la función '' |
- | - **[0.0 pts]** Implementar '' | + | - **[0.4 pts]** Implementar '' |
- | - **[0.0 pts]** Implementar '' | + | - **[0.2 pts]** Implementar '' |
- | - **[0.0 pts]** Extender la función '' | + | - **[0.1 pts]** Extender la función '' |
Line 200: | Line 287: | ||
* Para '' | * Para '' | ||
* En la aplicación de función se valida que el número de argumentos coincide, y que el tipo de los argumentos coincide con los tipos esperados de la función aplicada. El tipo resultante de una aplicación es el tipo de retorno de la función aplicada. | * En la aplicación de función se valida que el número de argumentos coincide, y que el tipo de los argumentos coincide con los tipos esperados de la función aplicada. El tipo resultante de una aplicación es el tipo de retorno de la función aplicada. | ||
- | |||
- | **Comportamiento del typecheck**: | ||
- | * Necesitará almacenar en un ambiente el tipo de las variables introducidas por algún bind para poder completar el typecheck. | ||
- | * El typecheck de un operador unario o binario verifica que el tipo de los datos que recibe correspondan con los tipos de los datos que se esperan para ese operador. | ||
- | * El typecheck de un with verifica para cada binding que la expresión cumpla con el tipo declarado para esa variable. | ||
- | * El typecheck de la aplicación de una función de primer orden verifica cumple con la aridad de la función, y que el tipo de los parámetros que recibe correspondan con los tipos de los datos declarados en su firma. | ||
**Para los errores**: | **Para los errores**: | ||
- | * Los errores de identificadores libres | + | * Los errores de identificadores libres, funciones no definidas |
* Los mensajes de error de tipo detectados estáticamente tienen que seguir el siguiente patrón: | * Los mensajes de error de tipo detectados estáticamente tienen que seguir el siguiente patrón: | ||
<code scheme>" | <code scheme>" | ||
Line 214: | Line 295: | ||
Algunos ejemplos (no representan todos los casos, es de su responsabilidad entregar //test suites// completos): | Algunos ejemplos (no representan todos los casos, es de su responsabilidad entregar //test suites// completos): | ||
< | < | ||
- | > (typecheck '{3}) | + | > (typecheck |
(numT) | (numT) | ||
- | > (typecheck ' | + | > (typecheck |
- | {f {< 3 4}}}) | + | |
(numT) </ | (numT) </ | ||
- | > (typecheck ' | + | > (typecheck |
- | {one #t}}) | + | |
" | " | ||
- | > (typecheck ' | + | > (typecheck |
" | " | ||
- | > (typecheck '{{if 73 #t #t}}) | + | > (typecheck |
" | " | ||
- | > (typecheck ' | + | > (typecheck |
- | z}}) | + | |
+ | | ||
+ | | ||
" | " | ||
Line 234: | Line 317: | ||
---- | ---- | ||
- | ===== Parte 3. Contratos en funciones de primer orden (por definir) ===== | + | ===== Parte 3. Contratos en funciones de primer orden (1 pt. de bonus) ===== |
<note important> | <note important> | ||
- | Esta parte es de realización opcional. Si la desarrolla correctamente obtendrá | + | Esta parte es de realización |
</ | </ | ||
- | Ahora vamos a añadir verificación dinámica mediante contratos a las funciones de nuestro lenguaje. El único cambio en la sintaxis del lenguaje se ve reflejado en la definición de funciones, donde ahora se puede definir además un contrato para cada argumento: | + | El propósito de esta parte es añadir verificación dinámica mediante contratos a las funciones de nuestro lenguaje. El único cambio en la sintaxis del lenguaje se ve reflejado en la definición de funciones, donde ahora se puede definir además un contrato para cada argumento: |
<code scheme> | <code scheme> | ||
Line 250: | Line 333: | ||
Un contrato corresponde a un predicado, una función que recibe exactamente un argumento y retorna un booleano. Un ejemplo de programa válido puede ser: | Un contrato corresponde a un predicado, una función que recibe exactamente un argumento y retorna un booleano. Un ejemplo de programa válido puede ser: | ||
<code scheme> | <code scheme> | ||
- | {{define {positive {x : Num}} {< 0 x}} | + | {{define {positive {x : Num}} : Bool {< 0 x}} |
| | ||
{- y x}} | {- y x}} | ||
Line 264: | Line 347: | ||
" | " | ||
</ | </ | ||
- | * Una función usada como contrato **debe** aceptar un solo argumento de cualquier tipo válido y **debe** retornar un valor de tipo '' | + | * Una función usada como contrato **debe** aceptar un solo argumento de cualquier tipo válido y **debe** retornar un valor de tipo '' |
" | " | ||
</ | </ | ||
Line 280: | Line 363: | ||
{+ {pair-div {cons 30 5}} {pair-div {cons 60 0}}} | {+ {pair-div {cons 30 5}} {pair-div {cons 60 0}}} | ||
} | } | ||
- | " | + | " |
</ | </ | ||
Line 290: | Line 373: | ||
" | " | ||
</ | </ | ||
+ |