Angel \”Java\” Lopez on Blog

December 10, 2014

SimpleLisp (2) Compiling Lisp Values and Variables to JavaScript

Previos Post

Let’s review the project’s implementation

https://github.com/ajlopez/SimpleLisp

the Lisp compiler to JavaScript, written in JavaScript, following the workflow of TDD (Test-Driven Development). All is “work in progress”, so today I will explain part of the implementation but it could be change in the future, when new use cases were added, and new ways of doing things were implemented.

I took the decision that each Lisp symbol is a JavaScript variable. So, the compilation of a symbol is:

exports['compile symbol'] = function (test) {
    test.equal(sl.compile('a'), 'a');
}

The sl is the SimpleLisp module, loaded in this test file (test/compile.js)

An integer and an string are compiled to natural values in JavaScript:

exports['compile integer'] = function (test) {
    test.equal(sl.compile('42'), '42');
}

exports['compile string'] = function (test) {
    test.equal(sl.compile('"foo"'), '"foo"');
}

It’s quoted values, too:

exports['compile quoted integer'] = function (test) {
    test.equal(sl.compile("'42"), '42');
}

exports['compile quoted string'] = function (test) {
    test.equal(sl.compile("'\"foo\""), '"foo"');
}

I decided to compile Lisp nil to JavaScript null. The boolean values are the same:

exports['compile nil'] = function (test) {
    test.equal(sl.compile('nil'), 'null');
}

exports['compile booleans'] = function (test) {
    test.strictEqual(sl.compile('false'), 'false');
    test.strictEqual(sl.compile('true'), 'true');
}

But, what happens if an expression serie is compiled? I build an anonymous function, invoked without arguments, and the last expression value is returned:

exports['compile two symbols'] = function (test) {
    test.equal(sl.compile('a b'), '(function () { a; return b; })()');
}

Next topics: compilation of a Lisp lisp, and more quoted values, macros, ect.

Stay tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

November 25, 2014

SimpleLisp (1) Compiling Lisp to JavaScript

Next Post

I implemented Lisp as interpreter, using C#, Java, and JavaScript. See:

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

The implementation of a Lisp is a good programming exercise. Lisp is a simple and powerful language, with functions as first class citizens. And with the “twist” of implementing functions that don’t evaluate their arguments, and macros.

This time, I want to implement a Lisp, but as a compiler. I started to write a Lisp compiler in JavaScript, that generates JavaScript. The project:

https://github.com/ajlopez/SimpleLisp

As usual, I worked using the Test-Driven Development workflow. With simple use cases, I implemented the needed features. This is my first Lisp compiler, so I’m trying new implementation approaches. I know Clojure, as a basis for a Lisp compiler. I should implement:

Symbols: identifiers witn name and associated value. Now, I’m compiling them to JavaScript variables. In SimpleLisp, a symbol can be defined at top, in a let block, or as a function argument. Then, I produce a top variable (or a least, a module variable), or a local variable in let, or an argument in function.

Functions: I’m translating a normal function in Lisp to a normal function in JavaScript. The main difference is that Lisp functions returns a value, there are no commands, all are expression, as in Ruby. A list in SimpleLisp is then compiled to a function call in JavaScript.

Special Forms: Their implementation is a novelty to me. In a compiler, I could generate directly the final code for each list with a head that is an special form. So, I’m compiling directly to JavaScript any list with head if, do, let, etc… . A list (if ….) is compiled to a JavaScript if, but returning a value.

Macros: In a compiler, I could adopt a new implementation: to expand the macro at COMPILING TIME. I’m not sure yet if I can take this approach in every case. Notably, in Clojure a macro is not a functional value: a macro cannot be passed as an argument. A macro make sense only at compiling time.

A final use case: write a web site using Node.js/Express in SimpleLisp.

Stay tuned!

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

Blog at WordPress.com.