The Metacircular Evaluator
Exercises (SICP 4.1): add and/or, let*, named let, internal definitions scanned out, separating syntactic analysis from execution (analyze), and data-directed dispatch on special forms.
;; A Scheme interpreter in Scheme (SICP 4.1, condensed)
(define (m-eval exp env)
(cond ((self-evaluating? exp) exp)
((symbol? exp) (lookup-variable exp env))
((tagged? exp 'quote) (cadr exp))
((tagged? exp 'set!) (set-variable! (cadr exp) (m-eval (caddr exp) env) env) 'ok)
((tagged? exp 'define) (eval-definition exp env))
((tagged? exp 'if) (if (true? (m-eval (cadr exp) env))
(m-eval (caddr exp) env)
(if (null? (cdddr exp)) #f (m-eval (cadddr exp) env))))
((tagged? exp 'lambda) (make-procedure (cadr exp) (cddr exp) env))
((tagged? exp 'begin) (eval-sequence (cdr exp) env))
((tagged? exp 'cond) (m-eval (cond->if (cdr exp)) env))
((tagged? exp 'let) (m-eval (let->combination exp) env))
((pair? exp) (m-apply (m-eval (car exp) env)
(map (lambda (e) (m-eval e env)) (cdr exp))))
(else (error "Unknown expression type" exp))))
(define (m-apply proc args)
(cond ((primitive? proc) (apply (cadr proc) args))
((compound? proc)
(eval-sequence (procedure-body proc)
(extend-e
…