Next: , Previous: Program development, Up: Top


6 The Interpreter

Former versions of ECL, as well as many other lisps, used linked lists to represent code. As of version 0.3 a bytecodes compiler and a bytecodes interpreter were developed to circumvent the limitations of linked lists.

When you enter code at the lisp prompt, or when you load a source file, ECL begins a process known as minimal compilation. Barely this process consists on parsing each form, macroexpanding it and translating it into an intermediate language made of bytecodes.

The bytecodes compiler is implemented in src/c/compiler.d. The main entry point is the lisp function SI::MAKE-LAMBDA, which takes a name for the function and the body of the lambda lists, and produces a lisp object that can be invoked. For instance,

> (defvar fun (si::make-lambda 'f '((x) (1+ x))))
*FUN*
> (funcall fun 2)
3

ECL can only execute bytecodes. When a list is passed to EVAL it must be first compiled to bytecodes and, if the process succeeds, then the resulting bytecodes are passed to the interpreter. Similarly, every time a function object is created, such as in DEFUN or DEFMACRO, the bytecodes compiler processes the lambda form to produce a suitable bytecodes object.

The fact that ECL performs this eager compilation means that changes on a macro are not immediately seen in code which was already compiled. This has subtle implications. Take the following code:

> (defmacro f (a b) `(+ ,a ,b))
F
> (defun g (x y) (f x y))
G
> (g 1 2)
3
> (defmacro f (a b) `(- ,a ,b))
F
> (g 1 2)
3

The last statement always outputs 3 while in former implementations based on processing of lambda lists it would produce -1.