Tarea 5

Esta tarea se distribuye con dos ficheros start.rkt y tests.rkt (mediante U-Cursos). Considere las definiciones del archivo start.rkt y escriba sus funciones en él. Escriba sus tests en el archivo tests.rkt adjunto. Ambos ficheros deben ser entregados vía U-Cursos. Los tests forman parte de su evaluación! Consulte las normas de entrega de tareas en http://pleiad.cl/teaching/cc4101.

En esta tarea extenderemos un lenguaje base para soportar clases y objetos. El lenguaje base tiene números, booleanos y operaciones sobre ellos. Además contiene expressiones if, seqn, local y define, pero no tiene soporte para funciones. Tome un tiempo de experimentar con el lenguaje base antes de comenzar a implementar las siguientes extensiones.

(3.0) Clases y objetos como valores

A continuación se presenta la sintáxis del lenguaje extendido:

<expr> ::= ... (expresiones del lenguage entregado) ...
        | (class <def>*)
        | (new <expr>)
        | (get <expr> <id>)
        | (set <expr> <id> <expr>)
        | (send <expr> <id> <expr>*)
        | this
 
<def>  ::= (field <id> <expr>)
         | (method <id> (<id>*) <expr>)

Donde:

  • class se usa para crear una nueva clase (anónima), con definiciones de campos y metodos
  • new permite instanciar una clase dada
  • get y set permiten acceder a, o cambiar, el campo de un objeto dado
  • send permite invocar un método de un objeto dado, con 0 o más argumentos
  • this permite acceder al objeto actual—solamente es válido usar this dentro del cuerpo de un método
  • una definición de campo incluye una expresión de inicialización, la cual se tiene que ejecutar nuevamente para cada instancia creada
  • una definición de método especifica 0 a más parámetros, y su cuerpo

Tanto clases como objetos son valores. Usted deber decidir los attributos que tendrán sus respectivos nodos en el AST. Modifique el parser y el interprete para soportar el lenguaje extendido. Nota:

  • El acceso a un campo inexistente de un objeto debe arrojar el error “field not found”.
  • La invocación de un método inexistente debe lanzar el error “method not found”.

Veamos algunos ejemplos de clases y objetos en accción:

> (run-val (local
             [(define c (class
                            (field x 1)
                          (field y 2)
                          (method sum (z) (+ (get this x) (+ (get this y) z)))
                          (method set-x (val) (set this x val))))
              (define o (new c))]
             (seqn
              (send o set-x (+ 1 3))
              (+ (send o sum 3) (get o y)))))
11
;clases son valores
> (run-val '(local
              [(define A
                 (class
                     (method apply (c)
                             (send (new c) m))))
               (define ins (new A))]
              (send ins apply (class
                                (field x 2) 
                                (method m () (get this x))))))
2

(3.0) Herencia Simple

Extienda su lenguaje con herencia simple, incluyendo field shadowing y llamados con super. Estudie la sección de herencia del OOPLAI1) para aclarar la semántica deseada.

La extensión de la sintáxis es:

<expr> ::= ... (todo lo anterior) ...
         | ( class <: <expr> <def>* )
         | ( super <id> <expr>* )

Se agrega una forma para crear clases, especificando su superclase. Sigue válido crear una clase sin especificar su superclase. En este caso extenderá de la clase raíz Object, que tendrá que definir.

  1. (1.0) Implemente la búsqueda de métodos 2) correspondiente a la herencia
    > (run-val '(local
                  [(define c1 (class
                                  (method f (z) (< z 7))))
                   (define c (class <: c1))
                   (define o (new c))]
                  (send o f 20)))
    #f
  2. (1.0) Implemente el soporte para llamados con super 3).
    ;; llamada a super de metodo no definido en el padre directo
    (run-val '(local
              [(define c2 (class
                              (method h (x) (+ x 1))))
               (define c1 (class <: c2
                            (method f () #f)))
               (define c (class <: c1                       
                           (method g () (super h 10))))
               (define o (new c))]
              (send o g)))
    11
  3. (1.0) Implemente la semántica de field shadowing 4)para sobreescritura de campos.
    > (run-val '(local
                  [(define A (class 
                               [field x 1]
                               [field y 0]
                               [method ax () (get this x)]))
                   (define B (class <: A
                               [field x 2]
                               [method bx () (get this x)]))
                   (define b (new B))]
                  (send b ax)))
    1

Nota:

  • Los llamados con super solo pueden ocurrir desde los métodos.
  • No se olvide incluir a la clase Object en el ambiente inicial de ejecución

(0.5)[Opcional] Codificando lambdas con objetos

En esta extensión incorporamos lambdas a nuestro lenguaje. A diferencia de lo visto durante el curso, en esta ocasión no daremos una interpretaremos directamente las funciones. Usted deber ingeniar una manera de codificar una lambda como un objeto. Esto significa que no puede modificar el interprete para soportar funciones, ni aplicaciones de funciones. Las modificaciones que debe hacer son en el parser.

<expr> ::= ...
         | (fun (<id>*) <expr>)
         | (<expr> <expr>*)

Ejemplo de uso:

> (run-val '(local
              [(define f (fun (x)
                              (+ x x)))]
              (f 5)))
10