A Lisp Interpreter in JavaScript

Inspired by Peter Norvig ‘s Lisp interpreter in Python Lisp.py, I took a night to reimplement a Lisp interpreter in JavaScript. The structure of interpreter is basically as same as the Lisp.py, but implementation is different, for examples, in JavaScript I use underscore as functional utilities library and also I add more primitives and some improvements to it.

For the arithmetic operation, in Lisp.py which is implemented by Python’s operator.add. Consequently, it can only have two operands, but actually in Lisp or Scheme we may write:

(+ 1 2 3 4)

My interpreter, by using the reduce function, can directly deal with arbitrary number of arguments. This is the implementation for it:

var r_template = function(g) {
    return function() {
        return _.reduce(Array.prototype.slice.apply(arguments), g); 
    };
};
env.update({
    "+": r_template(function(x, y) { return x + y; }),
});

In the above code, env is an enviornment which maps variable name to value. Before interpreting any actual code, the enviornment already contrains some built-in functions. This piece of code adds + operator and corresponding function into global enviornment. The r_template function is used for creating a function that supports unlimited arguments for +, -, *, /, and and or operators.

Also, the interpreter has supports of let, let*, cond and else. The let expression is just a syntax sugar of lambda, for instance, a let expression:

(let ((a 1)(b 2)) (+ b a))

can be transformed to

((lambda (a b) (+ b a)) 1 2)

To implement let* expression, the interpreter creates a local enviornment to store the evaluated result, then the local bindings have ability to access each others or itself recursively.

This interpreter, though, is very simple and crude, but can run some interesting code, for example, a Y combinator!

The Lisp.js on Github