(define the-empty-env (list 'empty-env)) (define extend-env (lambda (sym-list val-list env) (list 'extended-env sym-list (list->vector val-list) env))) (define apply-env (lambda (env symbol) (record-case env (empty-env () (error 'empty-env "no association for symbol: ~s" symbol)) (extended-env (sym-list val-vector env) (let ((x (memq symbol sym-list))) (if x (vector-ref val-vector (- (length sym-list) (length x))) (apply-env env symbol)))) (else (error 'apply-env "Invalid finite function: ~s" env))))) (define variable? symbol?) (define literal? number?) (define app->rator car) (define app->rands cdr) (define *prim-op-names* '(+ - * add1 sub1)) (define apply-prim-op (lambda (prim-op args) (case prim-op ((+) (+ (car args) (cadr args))) ((-) (- (car args) (cadr args))) ((*) (* (car args) (cadr args))) ((add1) (+ (car args) 1)) ((sub1) (- (car args) 1)) (else (error 'apply-prim-op "Invalid prim-op name: ~s" prim-op))))) (define make-prim-proc (lambda (prim-op-name) (list 'prim-proc prim-op-name))) (define init-env (extend-env *prim-op-names* (map make-prim-proc *prim-op-names*) the-empty-env)) (define apply-proc (lambda (proc args) (if (pair? proc) (record-case proc (prim-proc (prim-op) (apply-prim-op prim-op args)) (else (error 'apply-proc "Invalid procedure: ~s" proc))) (error 'apply-proc "Invalid procedure: ~s" proc)))) (define eval-exp (lambda (exp) (cond ((literal? exp) exp) ((variable? exp) (apply-env init-env exp)) (else (let ((proc (eval-exp (app->rator exp))) (args (eval-rands (app->rands exp)))) (apply-proc proc args)))))) (define eval-rands (lambda (rands) (map eval-exp rands))) (define run eval-exp) (define repl ; read-eval-print loop (lambda () (display "--> ") (write (run (read))) (newline) (repl)))