[pypy-svn] r45159 - in pypy/dist/pypy/lang/scheme: . test

jlg at codespeak.net jlg at codespeak.net
Tue Jul 17 15:31:02 CEST 2007


Author: jlg
Date: Tue Jul 17 15:31:01 2007
New Revision: 45159

Modified:
   pypy/dist/pypy/lang/scheme/TODO.txt
   pypy/dist/pypy/lang/scheme/object.py
   pypy/dist/pypy/lang/scheme/test/test_eval.py
   pypy/dist/pypy/lang/scheme/test/test_object.py
Log:
(let* ...) added; Letrec = Let in our case; ExecutionContex.get() raises UnboundVariable instead of returning None

Modified: pypy/dist/pypy/lang/scheme/TODO.txt
==============================================================================
--- pypy/dist/pypy/lang/scheme/TODO.txt	(original)
+++ pypy/dist/pypy/lang/scheme/TODO.txt	Tue Jul 17 15:31:01 2007
@@ -6,8 +6,6 @@
 Do next
 -------
 
-- definitions: let*
-
 - symbols vs identifier, which name is better
   - global dict for symbols _obarray_
 

Modified: pypy/dist/pypy/lang/scheme/object.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/object.py	(original)
+++ pypy/dist/pypy/lang/scheme/object.py	Tue Jul 17 15:31:01 2007
@@ -74,12 +74,7 @@
 
     def eval_tr(self, ctx):
         w_obj = ctx.get(self.name)
-        if w_obj is not None:
-            return (w_obj, None)
-        else:
-            #reference to undefined identifier
-            #unbound
-            raise UnboundVariable(self.name)
+        return (w_obj, None)
 
 class W_Boolean(W_Root):
     def __init__(self, val):
@@ -606,39 +601,35 @@
             raise SchemeSyntaxError
         local_ctx = ctx.copy()
         w_formal = lst.car
-        while not isinstance(w_formal, W_Nil) and isinstance(w_formal, W_Pair):
-            name = w_formal.get_car_as_pair().car.to_string()
+        while isinstance(w_formal, W_Pair):
+            w_def = w_formal.get_car_as_pair()
+            name = w_def.car.to_string()
             #evaluate the values in caller ctx
-            val = w_formal.get_car_as_pair().get_cdr_as_pair().car.eval(ctx)
-            local_ctx.put(name, val)
+            w_val = w_def.get_cdr_as_pair().car.eval(ctx)
+            local_ctx.put(name, w_val)
             w_formal = w_formal.cdr
 
         return self.eval_body(local_ctx, lst.cdr)
 
-class Letrec(W_Macro):
+class LetStar(W_Macro):
     def call_tr(self, ctx, lst):
-        """letrec uses eval_body, so it is tail-recursive aware"""
+        """let* uses eval_body, so it is tail-recursive aware"""
         if not isinstance(lst, W_Pair):
             raise SchemeSyntaxError
         local_ctx = ctx.copy()
-
-        #bound variables
-        w_formal = lst.car
-        while isinstance(w_formal, W_Pair):
-            name = w_formal.get_car_as_pair().car.to_string()
-            local_ctx.put(name, W_Nil())
-            w_formal = w_formal.cdr
-
-        #eval in local_ctx and assign values 
         w_formal = lst.car
         while isinstance(w_formal, W_Pair):
-            name = w_formal.get_car_as_pair().car.to_string()
-            val = w_formal.get_car_as_pair().get_cdr_as_pair().car.eval(local_ctx)
-            local_ctx.set(name, val)
+            w_def = w_formal.get_car_as_pair()
+            name = w_def.car.to_string()
+            #evaluate the values in local ctx
+            w_val = w_def.get_cdr_as_pair().car.eval(local_ctx)
+            local_ctx.put(name, w_val)
             w_formal = w_formal.cdr
 
         return self.eval_body(local_ctx, lst.cdr)
 
+Letrec = Let
+
 def literal(sexpr):
     return W_Pair(W_Identifier('quote'), W_Pair(sexpr, W_Nil()))
 
@@ -660,7 +651,7 @@
 # Location()
 ##
 class Location(object):
-    def __init__(self, w_obj):
+    def __init__(self, w_obj=None):
         self.obj = w_obj
 
 ##
@@ -704,6 +695,7 @@
         'if': MacroIf,
         'lambda': Lambda,
         'let': Let,
+        'let*': LetStar,
         'letrec': Letrec,
         'quote': Quote,
     }
@@ -742,7 +734,7 @@
         if loc is not None:
             return loc.obj
 
-        return None
+        raise UnboundVariable(name)
 
     def sete(self, name, obj):
         """update existing location or raise

Modified: pypy/dist/pypy/lang/scheme/test/test_eval.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/test/test_eval.py	(original)
+++ pypy/dist/pypy/lang/scheme/test/test_eval.py	Tue Jul 17 15:31:01 2007
@@ -274,7 +274,7 @@
     eval_expr(ctx, """(define long_body (lambda () (define x 42) (+ x 1)))""")
     w_result = eval_expr(ctx, "(long_body)")
     assert w_result.to_number() == 43
-    assert ctx.get("x") is None
+    py.test.raises(UnboundVariable, ctx.get, "x")
 
 def test_lambda_lstarg():
     ctx = ExecutionContext()
@@ -394,6 +394,8 @@
     assert w_result.to_number() == 44
     assert ctx.get("var") is w_global
 
+    py.test.raises(UnboundVariable, eval_noctx, "(let ((y 0) (x y)) x)")
+
 def test_letrec():
     ctx = ExecutionContext()
     w_result = eval_expr(ctx, """
@@ -410,6 +412,19 @@
                 (even? 2000))""")
     assert w_result.to_boolean() is True
 
+    py.test.raises(UnboundVariable, eval_noctx, "(letrec ((y 0) (x y)) x)")
+
+def test_letstar():
+    #test for (let* ...)
+    w_result = eval_noctx("""
+        (let* ((x 42)
+                (y (- x 42))
+                (z (+ x y)))
+                z)""")
+    assert w_result.to_number() == 42
+
+    py.test.raises(UnboundVariable, eval_noctx, "(let* ((x (+ 1 y)) (y 0)) x)")
+
 def test_quit():
     py.test.raises(SchemeQuit, eval_noctx, "(quit)")
 

Modified: pypy/dist/pypy/lang/scheme/test/test_object.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/test/test_object.py	(original)
+++ pypy/dist/pypy/lang/scheme/test/test_object.py	Tue Jul 17 15:31:01 2007
@@ -64,7 +64,7 @@
 
     assert w_symb is ctx.get("symb")
     assert w_fnum is ctx.get("v1")
-    assert ctx.get("no_such_key") is None
+    py.test.raises(UnboundVariable, ctx.get, "no_such_key")
 
 def test_location():
     w_fnum = W_Integer(42)



More information about the Pypy-commit mailing list