SimpleLisp (1) Compilando Lisp a JavaScript

Published on Author lopez

Siguiente Post

Ya varias veces implementé un intérprete Lisp, en C#, en Java, en JavaScript. Ver proyectos

https://github.com/ajlopez/AjLisp
https://github.com/ajlopez/AjLispJava
https://github.com/ajlopez/AjLispJs

Siempre es bueno implementar Lisp. Es un lenguaje simple, sencillo, poderoso, con funciones como ciudadanos de primera clase, y con el “twist” de implementar: algunas funciones que no evalúan de antemano sus argumentos, y macros.

Pero esta vez quiero implementar un compiladr Lisp. Es decir, algo que traslade al lenguaje anfitrión el programa Lisp. He elegido JavaScript como lenguaje anfitrión, y también como lenguaje de compilación: JavaScript mismo es el encargado de leer y traducir código Lisp a JavaScript. Pueden ver mi avance en

https://github.com/ajlopez/SimpleLisp

Como es costumbre, todo armado siguiendo el flujo de trabajo de TDD (Test-Driven Development), y sin tener todo el diseño de antemano, simplemente va surgiendo con los pequeños casos de uso que voy incorporando. Como es mi primer compilador Lisp, estoy aprendiendo nuevas formas de implementar el lenguaje. Algo vi en los últimos años al toparme con Clojure, que compila a Java, a CLR y a JavaScript. Lo que veo que tengo que implementar es:

Símbolos: identificadores por nombre, con valor asociado. Los estoy compilando a variables de JavaScript. En SimpleLisp, un símbolo puede quedar definido para el tope del programa, para un bloque let, o como argumento de una función. Entonces, depende del caso, lo paso a una variable tope de JavaScript (o al menos, tope en el módulo que estoy armando en compilación), a una variable local, o a un argumento con nombre.

Funciones: traducir una función normal de Lisp a una función normal de JavaScript. Lo único diferente es que las funciones de Lisp siempre devuelven en un valor, los “comandos” son siempre expresiones, como en Ruby. Una lista a evaluar en SimpleLisp la compilo a una llamada a función simple en JavaScript.

Special Forms: Su implementación es novedosa para mí. Ahora que tengo que compilar, no interpretar, cada vez que me topo con un una lista cuya cabeza es un if, un do, un let, etc…  voy y la compilo de forma especial a JavaScript. Un (if … ) de SimpleLisp queda transformado en un if de JavaScript (es un poco más complicado, porque el if de SimpleLisp tiene que devolver un valor, es una expresión, mientras que un if de JavaScript es un comando; ya veremos en futuro post la implementación que adopté).

Macros: De nuevo, al tener que compilar, puedo adoptar una implementación nueva: expandir la macro AL MOMENTO DE COMPILAR. Veremos hasta donde puedo llegar con este camino. Una consecuencia que veo: no puedo pasar una macro como valor funcional como argumento de otra función. Justamente, lo que pasa en Clojure: las macros no son valores funcionales, son “trucos” que se expande en tiempo de compilación.

Y como en otras implementaciones, agrego acceso a invocar JavaScript nativo desde SimpleLisp. Mi idea es poder escribir un sitio Node.js/Express con SimpleLisp.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez