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
…