;;; Evaluator from section 4.1.6 ;;; Analyze produces (lambda (env) ...) (define (analyze exp) (cond ((self-evaluating? exp) (analyze-self-evaluating exp)) ((quoted? exp) (analyze-quoted exp)) ((variable? exp) (analyze-variable exp)) ((assignment? exp) (analyze-assignment exp)) ((definition? exp) (analyze-definition exp)) ((if? exp) (analyze-if exp)) ((lambda? exp) (analyze-lambda exp)) ((begin? exp) (analyze-sequence (begin-actions exp))) ((cond? exp) (analyze (COND->IF exp))) ((let? exp) (analyze (LET->combination exp))) ((application? exp) (analyze-application exp)) (else (error "Unknown expression type -- ANALYZE" exp)))) (define (analyze-self-evaluating exp) (lambda (env) exp)) (define (analyze-quoted exp) (let ((qval (text-of-quotation exp))) (lambda (env) qval))) (define (analyze-variable exp) (lambda (env) (lookup-variable-value exp env))) (define (analyze-assignment exp) (let ((var (assignment-variable exp)) (vproc (analyze (assignment-value exp)))) (lambda (env) (set-variable-value! var (vproc env) env)))) (define (analyze-definition exp) (let ((var (definition-variable exp)) (vproc (analyze (definition-value exp)))) (lambda (env) (define-variable! var (vproc env) env)))) (define (analyze-lambda exp) (let ((vars (lambda-parameters exp)) (bproc (analyze-sequence (lambda-body exp)))) (lambda (env) (make-procedure vars bproc env)))) (define (analyze-if exp) (let ((pproc (analyze (if-predicate exp))) (cproc (analyze (if-consequent exp))) (aproc (analyze (if-alternative exp)))) (lambda (env) (if (pproc env) (cproc env) (aproc env))))) (define (analyze-sequence exps) (define (sequentially a b) (lambda (env) (a env) (b env))) (define (loop first rest) (if (null? rest) first (loop (sequentially first (car rest)) (cdr rest)))) (let ((procs (map analyze exps))) (if (null? procs) (error "Sequence requires subexpressions -- ANALYZE" exps)) (loop (car procs) (cdr procs)))) (define (analyze-application exp) (let ((fproc (analyze (operator exp))) (aprocs (map analyze (operands exp)))) (lambda (env) (exapply (fproc env) (map (lambda (aproc) (aproc env)) aprocs))))) (define (exapply proc args) (cond ((primitive-procedure? proc) (apply-primitive-procedure proc args)) ((compound-procedure? proc) ((procedure-body proc) (extend-environment (procedure-parameters proc) args (procedure-environment proc)))) (else (error "Unknown procedure type -- EXAPPLY" proc)))) ;;; Initialization and driver loop ;;; The prompt is handled a bit differently than in the notes (define (driver-loop) (newline) (let ((result (mini-eval (prompt-for-command-expression "A-EVAL=> ") the-global-environment))) (newline) (display ";;A-value: ") (write result) (driver-loop))) (define (mini-eval exp env) ((analyze exp) env)) (define the-global-environment) ;;; The environment is set up here to hook into Scheme along the lines ;;; of exercise 4.11. The Scheme variable cache is an optimization ;;; (look at the implementation of lookup-variable-value in EVDATA.SCM) (define (init) (set! the-global-environment (extend-environment '() '() the-empty-environment)) (set! scheme-variable-cache '()) (driver-loop))