Skip to main content

Lisra

rascal-0.40.17

Synopsis

A Lisp interpreter in Rascal.

Description

Writing a Lisp interpreter is a classical challenge. Popular word has that all large applications evolve until they include a Lisp interpreter. (A variant says the same about including an email client in every large application).

We will closely follow and reuse parts of Peter Norvig's excellent page on Lispy, a Lisp interpreter written in Python. The Lisp variant to be implemented is the following subset of the Scheme language:

FormSyntaxSemantics and Example
variable referencevarA symbol is interpreted as a variable name; its value is the variable's value. Example: x
constant literalnumberA number evaluates to itself. Example: 12
quotation(quote exp)Return the exp literally; do not evaluate it. Example: (quote (a b c)) =>; (a b c)
conditional(if _test conseq alt_)Evaluate test; if true, evaluate and return conseq; otherwise evaluate and return alt. Example: (if (< 10 20) (+ 1 1) (+ 3 3)) => 2
assignment(set! _var exp_)Evaluate exp and assign that value to var, which must have been previously defined (with a define or as a parameter to an enclosing procedure).
definition(define var exp)Define a new variable in the innermost environment and give it the value of evaluating the expression exp. Examples: (define r 3) or (define square (lambda (x) (* x x)))
procedure(lambda (_var..._) exp)Create a procedure with parameter(s) named var... and the expression as the body. Example: (lambda (r) (* r r))
sequencing(begin _exp..._)Evaluate each of the expressions in left-to-right order, and return the final value. Example: `(begin (set! x 1) (set! x (+ x 1)) (* x 2)) => 4
procedure call(_proc exp..._)If proc is anything other than one of the symbols if, set!, define, lambda, begin, or quote then it is treated as a procedure. It is evaluated using the same rules defined here. All the expressions are evaluated as well, and then the procedure is called with the list of expressions as arguments. Example: <`(square 12) => 144

In this table, var must be a symbol--an identifier such as x or square--and number must be an integer number, while the other italicized words can be any expression. The notation exp... means zero or more repetitions of exp.

A Lisp interpreter consists of the following parts:

  • A parser that reads a Lisp program in text form and converts it to a runtime representation that is suitable for the interpreter.
  • The interpreter itself that executes the program in runtime representation and computes its outcome.
  • A pretty printer that converts the outcome in internal representation back to text.
  • Finally, an interactive console is needed that interact with the user.

We discuss all these aspects: