;;; environment structure for letrec, using AST with circular links (let ((time-stamp "Time-stamp: <2000-12-12 19:04:49 wand>")) (eopl:printf "letrec3.scm -- AST rep of environments with circular links ~a~%" (substring time-stamp 13 29))) (define-datatype environment environment? (empty-env-record) (extended-env-record (syms (list-of symbol?)) (vals vector?) (env environment?))) (define apply-env (lambda (env sym) (cases environment env (empty-env-record () (eopl:error 'empty-env "No binding for ~s" sym)) (extended-env-record (syms vals old-env) (let ((pos (rib-find-position sym syms))) (if (number? pos) (vector-ref vals pos) (apply-env old-env sym))))))) (define empty-env (lambda () (empty-env-record))) (define extend-env (lambda (syms vals env) (extended-env-record syms (list->vector vals) env))) (define extend-env-recursively (lambda (proc-names idss bodies old-env) (let ((len (length proc-names))) (let ((vec (make-vector len))) (let ((env (extended-env-record proc-names vec old-env))) (for-each (lambda (pos ids body) (vector-set! vec pos (closure ids body env))) (iota len) idss bodies) env))))) (define rib-find-position (lambda (sym los) (list-find-position sym los))) (define list-find-position (lambda (sym los) (list-index (lambda (sym1) (eqv? sym1 sym)) los))) (define list-index (lambda (pred ls) (cond ((null? ls) #f) ((pred (car ls)) 0) (else (let ((list-index-r (list-index pred (cdr ls)))) (if (number? list-index-r) (+ list-index-r 1) #f)))))) (define iota (lambda (end) (let loop ((next 0)) (if (>= next end) '() (cons next (loop (+ 1 next)))))))