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