The Small Lisp Interpreter in Small Lisp!
Eval and Apply
The core of of a Lisp interpreter is a pair of functions
called eval
and apply
. The eval
function
evaluates a Small Lisp in the context of environments of
function and value environments.
Eval in Small Lisp
Below is the eval
function for Small Lisp, written in Small Lisp!
;;; ;;; "sl-eval": The heart of the Small Lisp interpreter. ;;; sl-eval[expr; fn-env; value-env] = [identifier-p[expr] --> apply-env[value-env; id-name[expr]]; numeric-atom-expr-p[expr] --> numeric-val[expr]; symbolic-atom-expr-p[expr] --> symbolic-val[expr]; list-expr-p[expr] --> list-val[expr]; fn-call-p[expr] --> sl-apply [callee[expr]; sl-evlis[arguments[expr]; fn-env; value-env]; fn-env; reset-to-global-frame[value-env]]; cond-expr-p[expr] --> sl-evcond[clauses[expr]; fn-env; value-env]; let-expr-p[expr] --> sl-eval [final-expr[expr]; fn-env; extend-local-env[fn-env; value-env; local-defs[expr]]]; otherwise --> error2[(Bad S-Lisp expression --); expr]] ;;; ;;; Evaluate a list of expressions in the context of function ;;; and value environments. ;;; sl-evlis[explist; fn-env; val-env] = {val1 = sl-eval[first[explist]; fn-env; val-env] : [single-p[explist] --> list1[val1]; otherwise --> cons[val1; sl-evlis[rest[explist]; fn-env; val-env]]]} ;;; ;;; Process conditional clauses by evaluating the clause ;;; predicates until one evaluates to T. When this happens ;;; evaluate and return the corresponding result expression. ;;; sl-evcond[condclauses; fn-env; env] = [sl-eval[predicate[first[condclauses]]; fn-env; env] --> sl-eval[result[first[condclauses]]; fn-env; env]; single-p[condclauses] --> error[(Error in conditional expression -- no true predicate)]; otherwise --> sl-evcond[rest[condclauses]; fn-env; env]] ;;; ;;; Update the local frame of the value environment with the ;;; bindings (local definitions) of a let expression. ;;; extend-local-env[fn-env; value-env; local-defs] = {var-name = id-name[local-var[first[local-defs]]]; val = sl-eval[local-val[first[local-defs]]; fn-env; value-env] : [single-p[local-defs] --> extend-env[value-env; var-name; val]; otherwise --> extend-env [extend-local-env[fn-env; value-env; rest[local-defs]]; var-name; val]]}
Apply in Small Lisp
;;; ;;; "sl-apply": the core routine for evaluation of ;;; function applications. ;;; sl-apply[callee; args; fn-env; val-env] = {fn = id-name[callee] : [eq[fn; "first"] --> first[first[args]]; eq[fn; "rest"] --> rest[first[args]]; eq[fn; "endp"] --> endp[first[args]]; eq[fn; "numberp"] --> numberp[first[args]]; eq[fn; "symbolp"] --> symbolp[first[args]]; eq[fn; "listp"] --> listp[first[args]]; eq[fn; "eq"] --> eq[first[args]; second[args]]; eq[fn; "cons"] --> cons[first[args]; second[args]]; eq[fn; "plus"] --> plus[first[args]; second[args]]; eq[fn; "minus"] --> minus[first[args]; second[args]]; eq[fn; "times"] --> times[first[args]; second[args]]; eq[fn; "divide"] --> divide[first[args]; second[args]]; eq[fn; "rem"] --> rem[first[args]; second[args]]; eq[fn; "eqp"] --> eqp[first[args]; second[args]]; eq[fn; "lessp"] --> lessp[first[args]; second[args]]; eq[fn; "greaterp"] --> greaterp[first[args]; second[args]]; eq[fn; "sym-lessp"] --> sym-lessp[first[args]; second[args]]; eq[fn; "explode"] --> explode[first[args]]; eq[fn; "implode"] --> implode[first[args]]; eq[fn; "error"] --> error[first[args]]; otherwise --> {defn = apply-fn-env[fn-env; fn] : sl-eval [body[defn]; fn-env; add-associations[val-env; parameters[defn]; args]]}]} add-associations[env; parms; args] = {new-env = extend-env[env; first[parms]; first[args]] : [single-p[parms] --> new-env; otherwise --> add-associations[new-env; rest[parms]; rest[args]]]}
The Main Program Driver
;;; ;;; This function contains the main driver functions for the ;;; Lisp-in-Lisp interpreter. ;;; ;;; The "interpret" function evaluates an expression (expr) in the ;;; context of a set of function and constant definitions (defs). ;;; It calls the "setup-envs-then-eval" auxiliary function to ;;; do the work of setting up the appropriate function and ;;; value environments before evaluating "expr". ;;; interpret[defs; expr] = setup-envs-then-eval [null-fn-env; extend-env [extend-env [extend-env[null-env; "F"; "F"]; "T"; "T"]; "otherwise"; "T"]; defs; expr] setup-envs-then-eval[fn-env; val-env; defs; expr] = [endp[defs] --> sl-eval[expr; fn-env; mark-global-frame[val-env]]; fn-def-p[first[defs]] --> setup-envs-then-eval [extend-fn-env[fn-env; fn-name[first[defs]]; first[defs]]; val-env; rest[defs]; expr]; const-def-p[first[defs]] --> setup-envs-then-eval [fn-env; extend-env [val-env; const-name[first[defs]]; sl-eval[const-val[first[defs]]; fn-env; val-env]]; rest[defs]; expr]]
Updated Sat Sept. 01 2018, 18:24 by cameron.