;;; Environment management for Scheme meta-circular evaluators ; Environments: (frame ... ) ; (define make-env cons) (define first-frame car) (define rest-frames cdr) (define set-first-frame! set-car!) ; Get value of variable in environment ; (define (get-var-value var env) (let ((b (binding-in-env var env))) (if (pair? b) (binding-value b) (error "unbound variable:" var)))) (define (binding-in-env var env) (if (null? env) '() (let ((b (binding-in-frame var (first-frame env)))) (if (pair? b) b (binding-in-env var (rest-frames env)))))) ; Extend env by binding values to corresponding variables ; (define (extend-env vars values env) (cons (make-frame vars values) env)) ; Update environment by changing value bound to variable ; (define (set-var-value! var value env) (let ((b (binding-in-env var env))) (if (pair? b) (set-binding-value! b value) (error "unbound variable:" var)))) ; Frames: ((var . value) ...) ; Make new frame by binding values to corresponding variables ; (define (make-frame vars values) (if (not (= (length vars) (length values))) (error "incorrect number of values supplied:" values) (map make-binding vars values))) (define extend-frame cons) (define binding-in-frame assq) ; Bindings: (var . value) ; (define make-binding cons) (define binding-var car) ; only used implicitly in binding-in-frame (define binding-value cdr) (define set-binding-value! set-cdr!) ; Errors: (error string val) displays string and val, then halts. ; (define error (lambda args (display "Error: ") (for-each (lambda (arg) (display arg) (display " ")) args) (newline) *undefined*)) ;;; eof