;;; Basic metacircular evaluator from section 4.1 (define (m-eval exp env) (cond ((self-evaluating? exp) exp) ((quoted? exp) (text-of-quotation exp)) ((variable? exp) (lookup-variable-value exp env)) ((assignment? exp) (eval-assignment exp env)) ((definition? exp) (eval-definition exp env)) ((if? exp) (eval-if exp env)) ((lambda? exp) (make-procedure (lambda-parameters exp) (lambda-body exp) env)) ((begin? exp) (eval-sequence (begin-actions exp) env)) ((cond? exp) (m-eval (cond->if exp) env)) ((let? exp) (m-eval (let->combination exp) env)) ((application? exp) (m-apply (m-eval (operator exp) env) (list-of-values (operands exp) env))) (else (error "Unknown expression type -- M-EVAL")))) (define (m-apply procedure arguments) (cond ((primitive-procedure? procedure) (apply-primitive-procedure procedure arguments)) ((compound-procedure? procedure) (eval-sequence (procedure-body procedure) (extend-environment (procedure-parameters procedure) arguments (procedure-environment procedure)))) (else (error "Unknown procedure type -- M-APPLY")))) (define (list-of-values exps env) (cond ((no-operands? exps) '()) (else (cons (m-eval (first-operand exps) env) (list-of-values (rest-operands exps) env))))) (define (eval-if exp env) (if (true? (m-eval (if-predicate exp) env)) (m-eval (if-consequent exp) env) (m-eval (if-alternative exp) env))) (define (eval-sequence exps env) (cond ((last-exp? exps) (m-eval (first-exp exps) env)) (else (m-eval (first-exp exps) env) (eval-sequence (rest-exps exps) env)))) (define (eval-assignment exp env) (set-variable-value! (assignment-variable exp) (m-eval (assignment-value exp) env) env)) (define (eval-definition exp env) (define-variable! (definition-variable exp) (m-eval (definition-value exp) env) env)) ;;; 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 "M-EVAL=> ") the-global-environment))) (newline) (display ";;M-value: ") (write result) (driver-loop))) (define (mini-eval exp env) (m-eval exp env)) (define the-global-environment) ;;; The environment is set up here to hook into Scheme along the lines ;;; of exercise ???. 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))