X-Git-Url: https://git.rkrishnan.org/?a=blobdiff_plain;f=src%2Fsicp%2Fmetacircular2.rkt;fp=src%2Fsicp%2Fmetacircular2.rkt;h=1e8e0e3c9b01f89e7c7581fdf23ddac45d64e665;hb=3e66d12e055a0aca2ed8556f4a1a3dcb966264f6;hp=a2dd8d4728f4610fa510dd95be1e1efa1c88be75;hpb=a7bf1376fa635c6868752c6458442aef5da63327;p=sicp.git diff --git a/src/sicp/metacircular2.rkt b/src/sicp/metacircular2.rkt index a2dd8d4..1e8e0e3 100644 --- a/src/sicp/metacircular2.rkt +++ b/src/sicp/metacircular2.rkt @@ -61,7 +61,10 @@ (if (eq? env the-empty-environment) (error "unbound variable:" var) (let ([frame (first-frame env)]) - (hash-ref frame var (lambda () (lookup-variable-value var (enclosing-environment env))))))) + (let ([value (hash-ref frame var (lambda () (lookup-variable-value var (enclosing-environment env))))]) + (if (eq? value '*unassigned*) + (error "evaluating a variable that is not assigned a value -- " var) + value))))) (define (set-variable-value! var val env) (if (eq? env the-empty-environment) @@ -189,9 +192,22 @@ ,rest))] [_ body])) +;; letrec +(define (letrec->combination lexpr) + (match lexpr + [`(letrec (,bindings ...) ,body ..1) + `(let ,(map (lambda (v) (list (car v) ''*unassigned*)) bindings) + ,@(map (lambda (binding) + (let ([name (car binding)] + [value (cadr binding)]) + `(set! ,name ,value))) + bindings) + ,@body)])) + ;; eval (define (eval exp env) - (display (format "~s~%" exp)) + ;; use this display statement to visualize the recursive evaluation process + ;;(display (format "~s~%" exp)) (match exp [(? self-evaluating? exp) exp] [(? variable? exp) (lookup-variable-value exp env)] @@ -205,6 +221,7 @@ [`(cond ,clauses ...) (eval (cond->if clauses) env)] [`(let ,bindings ,body ..1) (eval (let->combination exp) env)] [`(let* ,bindings ,body ..1) (eval (let*->nested-lets exp) env)] + [`(letrec ,bindings ,body ..1) (eval (letrec->combination exp) env)] [(list f x ...) (apply (eval f env) (list-of-values x env))] [_ (error "unable to evaluate expression -- EVAL " exp)]))