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.
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 metodosnew permite instanciar una clase dadaget y set permiten acceder a, o cambiar, el campo de un objeto dadosend permite invocar un método de un objeto dado, con 0 o más argumentosthis permite acceder al objeto actual—solamente es válido usar this dentro del cuerpo de un métodoTanto 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:
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
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.
> (run-val '(local [(define c1 (class (method f (z) (< z 7)))) (define c (class <: c1)) (define o (new c))] (send o f 20))) #f
;; 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
> (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:
super solo pueden ocurrir desde los métodos.Object en el ambiente inicial de ejecuciónEn 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