support for letrec
authorRamakrishnan Muthukrishnan <vu3rdd@gmail.com>
Sun, 1 Jan 2012 05:54:37 +0000 (11:24 +0530)
committerRamakrishnan Muthukrishnan <vu3rdd@gmail.com>
Sun, 1 Jan 2012 05:54:37 +0000 (11:24 +0530)
src/sicp/metacircular2.rkt

index a2dd8d4728f4610fa510dd95be1e1efa1c88be75..1e8e0e3c9b01f89e7c7581fdf23ddac45d64e665 100644 (file)
   (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)
         ,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)]
     [`(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)]))