Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
teaching:cc4101:tareas:2024-1:tarea1b [2024/04/08 17:32] – created gricciteaching:cc4101:tareas:2024-1:tarea1b [2025/04/08 22:09] (current) – [Tarea 1b (Entrega: Domingo 21 de Abril de 2024)] dibanez
Line 1: Line 1:
-====== Tarea 1b (Entrega: Jueves 18 de Abril de 2024) ======+====== Tarea 1b (Entrega: Domingo 20 de Abril de 2024) ======
  
 ==== Lenguaje con tipos estáticos ==== ==== Lenguaje con tipos estáticos ====
Line 17: Line 17:
  
 Si lo desea, puede obtener un bonus resolviendo la tercera parte, que es opcional: ''{{ :teaching:cc4101:tareas:2024-1:tarea1b:p3.rkt |p3.rkt}}'' y ''{{ :teaching:cc4101:tareas:2024-1:tarea1b:p3-test.rkt |p3-test.rkt}}''. Más detalles al final del documento. Si lo desea, puede obtener un bonus resolviendo la tercera parte, que es opcional: ''{{ :teaching:cc4101:tareas:2024-1:tarea1b:p3.rkt |p3.rkt}}'' y ''{{ :teaching:cc4101:tareas:2024-1:tarea1b:p3-test.rkt |p3-test.rkt}}''. Más detalles al final del documento.
 +
 +**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 {{ :teaching:cc4101:tareas:2023-1:env.rkt |env.rkt}}
  
 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.
Line 52: Line 54:
            | {<id> <expr>*}            | {<id> <expr>*}
  
-<binding> ::= (<id> <expr>)+<binding> ::= {<id> <expr>}
                        
 </code> </code>
Line 111: Line 113:
   }   }
   </code>   </code>
 +Además de lo anterior, asumiremos por simplicidad que en los bindings de un mismo ''with'' no pueden haber repeticiones/reintroducciones de identificadores. **No es necesario que verifique este punto**, puede simplemente asumir que es parte del contrato. Por ejemplo, el comportamiento del siguiente programa estaría indefinido:
 +<code scheme>
 +  {
 +     {with {{x 2}
 +            {x 4}}
 +        x}
 +  }
 +</code>
   * Debe verificar en tiempo de ejecución que los argumentos de los operadores numéricos sean numéricos, que los argumentos de los operadores booleanos sean booleanos, y que los argumentos de los operadores de pares sean pares (En la parte 2 se alineará la verificación dinámica con la verificación estática).   * Debe verificar en tiempo de ejecución que los argumentos de los operadores numéricos sean numéricos, que los argumentos de los operadores booleanos sean booleanos, y que los argumentos de los operadores de pares sean pares (En la parte 2 se alineará la verificación dinámica con la verificación estática).
   * Considere que la igualdad solo es válida sobre números.   * Considere que la igualdad solo es válida sobre números.
Line 172: Line 182:
 Teniendo en cuenta todo lo descrito anteriormente, implemente las siguientes funciones: Teniendo en cuenta todo lo descrito anteriormente, implemente las siguientes funciones:
  
-  - **[1.0 pts]** ''interp :: Expr List[Fundef] -> Val or error'', que interpreta una expresión considerando una lista de funciones definidas al top-level.+  - **[1.0 pts]** ''interp :: Expr List[Fundef] -> Val or error'', que interpreta una expresión considerando una lista de funciones definidas al top-level. Si lo desea, puede implementar ''interp'' usando ambientes (sustitución diferida). Recuerde actualizar la firma de la función si elige dicha opción.
   - **[0.2 pts]** ''run :: s-expr -> Val or error'', que toma un programa escrito en sintaxis concreta, lo parsea e interpreta.   - **[0.2 pts]** ''run :: s-expr -> Val or error'', que toma un programa escrito en sintaxis concreta, lo parsea e interpreta.
  
-El testing recibe **0.3 pts**+El testing recibe **0.3 pts**
 ----- -----
  
Line 254: Line 263:
  
  
 +===== Checkeo Estático de Tipos =====
 +
 +Para poder realizar un checkeo de tipos estático, necesitaremos:
 +  - **[0.7 pts]** Implementar la función ''typecheck-expr :: Exp Env List[Fundef] -> Type or error'' que toma una expresión, un ambiente y una lista de definiciones de funciones, y retorna el tipo de la expresión o lanza un error.
 +  - **[0.4 pts]** Implementar ''typecheck-fundef :: Fundef List[Fundef] -> Type or error'' que recibe una definición de función y una lista de definiciones de funciones, y retorna el tipo de retorno de la función, o lanza un error.
 +  - **[0.2 pts]** Implementar ''typecheck :: Prog -> Type or error'' que toma un programa y nos retorna su tipo, o lanza un error.
 +  - **[0.1 pts]** Extender la función ''run'' para que verifique el tipo del programa (este paso puede fallar) antes de interpretarlo. Note que tendrá que hacer pequeñas modificaciones a la función ''interp'' para que pueda procesar el nuevo AST con anotaciones de tipo. Unicamente los casos para el ''with'' y aplicaciones de función se verán afectados.
 +
 +
 +**Observaciones importantes**:
 +  * Recuerden que la gramática BNF dicta la estructura de sus definiciones.
 +  * La verificación de tipos de un programa consiste en verificar que todas las definiciones de función estén bien tipadas, y que la última expresión tiene un tipo (no importa cuál).
 +  * Para una definición de función, se valida que la expresión del cuerpo tenga el mismo tipo que el tipo de retorno declarado, suponiendo que cada argumento tiene el tipo declarado.
 +  * Debe definir los tipos de los operadores primitivos de manera exacta, p.ej. ''%%<%%'' es una operación que toma dos ''Num'' y retorna ''Bool''
 +  * Considere que la igualdad (''='') solo puede comparar números.
 +  * Para una expresión ''%%if%%'' la condición debe tener tipo ''%%Bool%%'' y ambas ramas deben tener el mismo tipo ''%%t%%''. El tipo resultante de la expresión ''%%if%%'' es ''%%t%%''.
 +  * Para ''%%with%%'' se verifica que todos los argumentos cumplan con el tipo declarado y el tipo resultante será el del cuerpo de la expresión. Si los identificadores no tienen tipo explícito, entonces se les asigna el de la expresión asociada.
 +  * 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.
 +
 +**Para los errores**:
 +  * Los errores de identificadores libres, funciones no definidas y errores de aridad deben ahora detectarse estáticamente. El formato de los mensajes de error es el mismo que se especificó en la parte 1.
 +  * Los mensajes de error de tipo detectados estáticamente tienen que seguir el siguiente patrón: 
 +<code scheme>"Static type error: expected T1 found T2"</code> donde ''T1'' es el tipo esperado y ''T2'' el tipo encontrado.
 +
 +Algunos ejemplos (no representan todos los casos, es de su responsabilidad entregar //test suites// completos):
 + <code scheme>
 +  >  (typecheck (parse-prog '{3}))
 +  (numT)  </code> <code scheme>
 +  > (typecheck (parse-prog '{{define {f {p : Bool}} {if p 23 42}}
 +                             {f {< 3 4}}}))
 +  (numT) </code> <code scheme>   
 +  > (typecheck (parse-prog '{{define {one {x : Num}} 1}
 +                             {one #t}}))
 +  "Static type error: expected Num found Bool" </code> <code scheme>
 +  > (typecheck (parse-prog  '{{< 10 #t}}))
 +  "Static type error: operator < expected Num found Bool"</code> <code scheme>
 +   > (typecheck (parse-prog '{{if 73 #t #t}}))
 +  "Static type error: expected Bool found Num"</code> <code scheme>
 +  > (typecheck (parse-prog '{{with {{x : Num 5}
 +                                    {y : Num #t}
 +                                    {z : Num 42}}
 +                                 z}}))
 +  "Static type error: expected Num found Bool"</code>
 +
 +¿Puede efectivamente convencerse de que todo programa que pasa la verificación de tipo no se cae con un error de tipo durante la ejecución?
 +
 +El testing de esta parte recibe **0.5 pts**
 +----
 +
 +===== Parte 3. Contratos en funciones de primer orden (1 pt. de bonus) =====
 +
 +<note important>
 +Esta parte es de realización **opcional**. Si la desarrolla correctamente obtendrá un bono de **1 pt** que podrán agregar a la nota de cualquiera de las tareas. 
 +</note>
 +
 +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>
 +<fundef> ::= {define {<id> <arg>*} : <type> <expr>} ; como antes
 +<arg>    ::= {<id> : <type>       ; como antes
 +           | {<id> : <type> @ <contract> ; lo único nuevo
 +</code>
 +
 +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>
 +{{define {positive {x : Num}} : Bool {< 0 x}}
 + {define {sub {x : Num @ positive} {y : Num}} : Num
 +           {- y x}}
 + {sub 5 3}}
 +</code>
 +Donde el argumento ''x'' posee como contrato la función ''positive'', que comprueba en tiempo de ejecución que ''x'' sea mayor que 0.
 +
 +  * Extienda nuevamente su función ''run'' para que verifique los contratos en tiempo de ejecución. 
 +
 +**Observaciones importantes**:
 +  * En el intérprete, cuando se efectúa una aplicación de función, se debe que verificar que los argumentos cumplan con los contratos declarados (en caso de que existan). 
 +  * Cuando el contrato no se cumpla, se debe lanzar un error con el siguiente patrón: <code scheme>
 +"Runtime contract error: <v> does not satisfy <contract>"
 +</code> donde ''<v>'' es el valor al que se le aplicó el contrato <contract> el nombre de este.
 +  * Una función usada como contrato **debe** aceptar un solo argumento de cualquier tipo válido y **debe** retornar un valor de tipo ''Bool''. Esta verificación debe realizarse estáticamente y, en caso de no cumplir dicha condición, se debe lanzar un error con el siguiente patrón: <code scheme>
 +"Static contract error: invalid type for <c>"
 +</code>  donde ''<c>'' es el nombre del contrato que no tipa.
 +
 +Más ejemplos:
 +<code scheme>
 +{{define {positive {x : Num}} : Bool {< 0 x}}
 + {define {negate {x : Num @ positive}} : Num {- 0 x}}
 + {negate 23}}
 +</code>
 +
 +<code scheme>
 +{{define {pair-non-zero? {p : {Pair Num Num}}} : Bool {&& {= 0 {fst p}} {= 0 {snd p}}}}
 + {define {pair-div {p : {Pair Num Num} @ pair-non-zero?}} : Num {/ {fst x} {snd x}}}
 + {+ {pair-div {cons 30 5}} {pair-div {cons 60 0}}}
 +}
 +"Runtime contract error: {cons 60 0} does not satisfy pair-non-zero?"
 +</code>
 +
 +
 +<code scheme>
 +> (run '{{define {add {x : Num} {y : Num}} : Num {+ x y}}
 +         {define {oh-no {x : Num @ add}} : Bool x}
 +         {oh-no 21 21}})
 +"Static contract error: invalid type for add"
 +</code>