Sussman and Steele | December 22, 1975 | 34 | Implementation of the Interpreter |
(DEFUN AEVAL () (COND ((ATOM **EXP**) (COND ((NUMBERP **EXP**) (SETQ **VAL** **EXP**) (RESTORE)) ((PRIMOP **EXP**) (SETQ **VAL** **EXP**) (RESTORE)) ((SETQ **TEM** (ASSQ **EXP** **ENV**)) (SETQ **VAL** (CADR **TEM**)) (RESTORE)) (T (SETQ **VAL** (SYMEVAL **EXP**)) (RESTORE)))) ((ATOM (CAR **EXP**)) (COND ((SETQ **TEM** (GET (CAR **EXP**) 'AINT)) (SETQ **PC** **TEM**)) ((EQ (CAR **EXP**) 'LAMBDA) (SETQ **VAL** (LIST 'BETA **EXP** **ENV**)) (RESTORE)) ((SETQ **TEM** (GET (CAR **EXP**) 'AMACRO)) (SETQ **EXP** (FUNCALL **TEM** **EXP**))) (T (SETQ **EVLIS** NIL **UNEVLIS** **EXP** **PC** 'EVLIS)))) ((EQ (CAAR **EXP**) 'LAMBDA) (SETQ **EVLIS** (LIST (CAR **EXP**)) **UNEVLIS** (CDR **EXP**) **PC** 'EVLIS)) (T (SETQ **EVLIS** NIL **UNEVLIS** **EXP** **PC** 'EVLIS))))
We come to EVLIS
when a combination is encountered. The intention is to evaluate each component of the combination and then apply the resulting function to the resulting arguments. We use the register **UNEVLIS**
to hold the list of components yet to be evaluated, and the register **EVLIS**
to hold the list of evaluated components. We assume that these have been set up by AEVAL
. Note that in the case of an explicit LAMBDA
expression in the CAR
of a combination **UNEVLIS**
is initialized to be the list of unevaluated arguments and **EVLIS**
is initialized to be the list containing the lambda expression.
EVLIS
checks to see if there remain any more components yet to be evaluated. If not, it applies the function. Note that the primitive operators are applied using the LISP function APPLY
. Note also how a BETA
expression controls the environment in which its body is to be evaluated. DELTA
expressions are CATCH
tags (see CATCH
). It is interesting that the evaluated components are collected in the reverse order from that which we need them in, and so we must reverse the list before applying the function. Do you see why we must not use side effects (e.g. the NREVERSE
function) to reverse the list? Think about CATCH
!
If there remain components yet to be evaluated, EVLIS
saves up a frame,