Los lenguajes SL y CL
Muchos lenguajes de programación se implementan mediante transformación (o compilación) a lenguajes intermedios de más bajo nivel. Así mismo, en esta tarea, hay dos lenguajes: SL (Surface Language) y CL (Core Language).
- SL es un lenguaje tipado con funciones de primera clase, números y expresiones sobre éstos (suma e
if0
), impresión de caracteres ywith
.
- CL es un lenguaje no tipado, como los vistos en clase, que cuenta con lo mismo que SL, excepto por
with
.
Un programa SL se ejecuta mediante una transformación a CL. En el código entregado, esta transformación es bastante trivial: convierte los nodos del AST del programa SL en nodos del AST de un programa CL. Su único rol es borrar la información de tipado, y convertir el with
en una aplicación de lambda (CL no incluye with
).
Los archivos que les entregamos en tarea-2-init.zip incluyen: core-base.rkt, surface-base.rkt y env.rkt.
- para CL: definición de la sintaxis, AST, parser, e intérprete
- para SL: definición de la sintaxis, AST, parser, typechecker y transformación a CL
Note que el typechecker de SL opera de manera distinta a lo que vimos en la tarea anterior: la información de tipo se hace persistente en cada nodo del AST. Es decir, cada expresión (nodo del AST) lleva consigo información de su tipo, la cual se inicializa al valor #f
tras realizar el parseo, y se rellena con el tipo correcto tras llamar a la función type-ast
. A continuación les ilustramos el resultado de cada paso, desde el parseo hasta la ejecución final.
> (parse-sl '{+ 1 2}) (sadd #f (snum 1) (snum 2)) > (type-ast (parse-sl '{+ 1 2})) (sadd (TNum) (snum 1) (snum 2)) > (transform (type-ast (parse-sl '{+ 1 2}))) (add (num 1) (num 2)) > (interp-top (transform (type-ast (parse-sl '{+ 1 2})))) 3
Antes de empezar la tarea, prueben ambos lenguajes y las distintas funciones provistas para parsear, typecheckear, tranformar, ejecutar, etc. En particular, miren el tipado y la transformación de programas con with
y funciones. Por último, noten que la impresión de caracteres retorna el mismo valor que está siendo impreso, de manera que puede ser utilizada dentro de otras expresiones sin problema.
> (run-cl '{+ 10 {printn {+ 2 3}}}) 5 ; valor impreso -- ¿cómo testear esto? vea la parte 1! 15 ; valor final del programa