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

jlg at codespeak.net jlg at codespeak.net
Wed Jul 4 16:56:18 CEST 2007


Author: jlg
Date: Wed Jul  4 16:56:17 2007
New Revision: 44725

Modified:
   pypy/dist/pypy/lang/scheme/object.py
   pypy/dist/pypy/lang/scheme/test/test_eval.py
Log:
lambda in lambda cousure; Colusure(Location)

Modified: pypy/dist/pypy/lang/scheme/object.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/object.py	(original)
+++ pypy/dist/pypy/lang/scheme/object.py	Wed Jul  4 16:56:17 2007
@@ -33,11 +33,11 @@
 
         w_obj = ctx.get(self.name)
         if w_obj is not None:
-            return w_obj #.eval(ctx)
+            return w_obj
         else:
             #reference to undefined identifier
             #unbound
-            raise NotImplementedError
+            raise "Unbound variable: %s" % (self.name, )
 
 class W_Symbol(W_Root):
     def __init__(self, val):
@@ -160,7 +160,7 @@
         raise NotImplementedError
 
 class W_Lambda(W_Procedure):
-    def __init__(self, args, body, pname="#f"):
+    def __init__(self, args, body, clousure, pname="#f"):
         self.args = []
         arg = args
         while not isinstance(arg, W_Nil):
@@ -171,19 +171,23 @@
 
         self.body = body
         self.pname = pname
+        self.clousure = clousure
 
     def to_string(self):
         return "#<procedure %s>" % (self.pname,)
 
     def procedure(self, ctx, lst):
         if len(lst) != len(self.args):
-            #wrong argument count
-            raise
+            raise "Wrong argument count"
 
         local_ctx = ctx.copy()
+        #ugly hack
+        for (name, val) in self.clousure.scope.items():
+            local_ctx.lput(name, val.obj)
+
         vars = zip(self.args, lst)
         for (name, val) in vars:
-            local_ctx.put(name, val)
+            local_ctx.lput(name, val)
 
         return self.body.eval(local_ctx)
 
@@ -273,7 +277,7 @@
     def eval(self, ctx, lst):
         w_args = lst.car
         w_body = lst.cdr.car
-        return W_Lambda(w_args, w_body)
+        return W_Lambda(w_args, w_body, ctx.lcopy())
 
 ##
 # Location()
@@ -282,6 +286,10 @@
     def __init__(self, w_obj):
         self.obj = w_obj
 
+class Clousure(Location):
+    def __init__(self, w_obj):
+        self.obj = w_obj
+
 ##
 # dict mapping operations to W_Xxx objects
 # callables must have 2 arguments
@@ -313,7 +321,7 @@
 class ExecutionContext(object):
     """Execution context implemented as a dict.
 
-    { "IDENTIFIER": W_Root }
+    { "IDENTIFIER": Location(W_Root()) }
     """
     def __init__(self, scope=OPERATION_MAP):
         assert scope is not None
@@ -322,6 +330,14 @@
     def copy(self):
         return ExecutionContext(dict(self.scope))
 
+    def lcopy(self):
+        lscope = {}
+        for (name, loc) in self.scope.items():
+            if isinstance(loc, Clousure):
+                lscope[name] = loc
+
+        return ExecutionContext(lscope)
+
     def get(self, name):
         loc = self.scope.get(name, None)
 
@@ -331,6 +347,7 @@
             return None
 
     def set(self, name, obj):
+        """update existing location or create new location new"""
         loc = self.scope.get(name, None)
 
         if loc is not None:
@@ -338,9 +355,21 @@
         else:
             self.put(name, obj)
 
+    def seta(self, name, obj):
+        """update existing location"""
+        loc = self.scope.get(name, None)
+
+        if loc is not None:
+            loc.obj = obj
+        else:
+            #unbound var
+            raise "Unbound"
+
     def put(self, name, obj):
-        """Overwrites existing variable location
-        (new location is created)
-        """
+        """create new location"""
         self.scope[name] = Location(obj)
 
+    def lput(self, name, obj):
+        """create new location"""
+        self.scope[name] = Clousure(obj)
+

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	Wed Jul  4 16:56:17 2007
@@ -200,3 +200,18 @@
     w_result = eval_expr(ctx, "(fac 5)")
     assert w_result.to_number() == 120
 
+def test_lambda2():
+    ctx = ExecutionContext()
+    eval_expr(ctx, """(define adder (lambda (x) (lambda (y) (+ x y))))""")
+    w_lambda = eval_expr(ctx, "(adder 6)")
+    assert isinstance(w_lambda, W_Lambda)
+
+    eval_expr(ctx, """(define add6 (adder 6))""")
+    w_result = eval_expr(ctx, "(add6 5)")
+    assert isinstance(w_result, W_Fixnum)
+    assert w_result.to_number() == 11
+
+    w_result = eval_expr(ctx, "((adder 6) 5)")
+    assert isinstance(w_result, W_Fixnum)
+    assert w_result.to_number() == 11
+


More information about the pypy-svn mailing list