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

jlg at codespeak.net jlg at codespeak.net
Mon Aug 13 15:34:33 CEST 2007


Author: jlg
Date: Mon Aug 13 15:34:32 2007
New Revision: 45625

Modified:
   pypy/dist/pypy/lang/scheme/TODO.txt
   pypy/dist/pypy/lang/scheme/object.py
   pypy/dist/pypy/lang/scheme/test/test_continuation.py
Log:
define continuation related bugfix; continuation pitfall tests added; LetStar is continuation friendly

Modified: pypy/dist/pypy/lang/scheme/TODO.txt
==============================================================================
--- pypy/dist/pypy/lang/scheme/TODO.txt	(original)
+++ pypy/dist/pypy/lang/scheme/TODO.txt	Mon Aug 13 15:34:32 2007
@@ -3,7 +3,7 @@
 
 - continuations
 
-continuation frame must be saved fot every non tail-call
+continuation frame must be saved for every non tail-call
 (for tail calls there is no cc)
 
 Do next
@@ -22,5 +22,7 @@
 - lambda called with wrong number of arguments issue
 - macros *are* not first-class objects
 
+- input/output operations
+- missing datatypes: chars, strings, vectors
 - switch to byte-code generation + eval instead of evaluating AST
 

Modified: pypy/dist/pypy/lang/scheme/object.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/object.py	(original)
+++ pypy/dist/pypy/lang/scheme/object.py	Mon Aug 13 15:34:32 2007
@@ -297,6 +297,12 @@
     def __init__(self, body):
         self.body = body
 
+    def __repr__(self):
+        return "<Body " + self.to_string() + ">"
+
+    def to_string(self):
+        return self.body.to_string()
+
     def eval_tr(self, ctx):
         return self.continue_tr(ctx, self.body, [], False)
 
@@ -743,14 +749,15 @@
     _symbol_name = "define"
 
     def continue_tr(self, ctx, lst, elst, cnt=True):
-        w_first = elst[0]
-        w_val = elst[1]
+        w_first = lst
+        w_val = elst[0]
         if isinstance(w_first, W_Symbol):
             ctx.set(w_first.name, w_val)
-            return (w_val, None)
-        elif isinstance(w_first, W_Pair):
-            #XXX no tests here
-            raise NotImplementedError
+            if len(ctx.cont_stack) == 0:
+                raise ContinuationReturn(w_val)
+
+            cont = ctx.cont_stack.pop()
+            return cont.run(ctx, w_val)
 
         raise SchemeSyntaxError
 
@@ -760,7 +767,7 @@
         w_first = lst.car
         w_second = lst.get_cdr_as_pair()
         if isinstance(w_first, W_Symbol):
-            w_val = w_second.car.eval_cf(ctx, self, w_first, [w_first], 1)
+            w_val = w_second.car.eval_cf(ctx, self, w_first)
             ctx.set(w_first.name, w_val)
             return w_val #undefined
         elif isinstance(w_first, W_Pair):
@@ -771,7 +778,10 @@
 
             formals = w_first.cdr #isinstance of W_List
             body = w_second
+            #remember this! ContinuationFrame creation
+            ctx.cont_stack.append(ContinuationFrame(self, w_first))
             w_lambda = W_Lambda(formals, body, ctx, pname=w_name.name)
+            ctx.cont_stack.pop()
             ctx.set(w_name.name, w_lambda)
             return w_lambda #undefined
 
@@ -848,20 +858,43 @@
 class LetStar(W_Macro):
     _symbol_name = "let*"
 
+    def continue_tr(self, ctx, lst, elst, cnt=True):
+        ctx = ctx.copy()
+        (body, w_def, w_val) = elst
+        ctx.sput(w_def, w_val)
+        w_formal = lst
+        while isinstance(w_formal, W_Pair):
+            w_def = w_formal.get_car_as_pair()
+            #evaluate the values in local ctx
+            w_val = w_def.get_cdr_as_pair().car.eval_cf(ctx, \
+                    self, lst.cdr, [elst[0], w_def.car], 2)
+            ctx.sput(w_def.car, w_val)
+            w_formal = w_formal.cdr
+
+        w_result = body.eval(ctx)
+
+        if len(ctx.cont_stack) == 0:
+            raise ContinuationReturn(w_result)
+
+        cont = ctx.cont_stack.pop()
+        return cont.run(ctx, w_result)
+
     def call_tr(self, ctx, lst):
         #let* uses eval_body, so it is tail-recursive aware
         if not isinstance(lst, W_Pair):
             raise SchemeSyntaxError
         local_ctx = ctx.copy()
+        body = Body(lst.cdr)
         w_formal = lst.car
         while isinstance(w_formal, W_Pair):
             w_def = w_formal.get_car_as_pair()
             #evaluate the values in local ctx
-            w_val = w_def.get_cdr_as_pair().car.eval(local_ctx)
+            w_val = w_def.get_cdr_as_pair().car.eval_cf(local_ctx, \
+                    self, w_formal.cdr, [body, w_def.car], 2)
             local_ctx.sput(w_def.car, w_val)
             w_formal = w_formal.cdr
 
-        return Body(lst.cdr).eval_tr(local_ctx)
+        return body.eval_tr(local_ctx)
 
 class Letrec(W_Macro):
     _symbol_name = "letrec"

Modified: pypy/dist/pypy/lang/scheme/test/test_continuation.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/test/test_continuation.py	(original)
+++ pypy/dist/pypy/lang/scheme/test/test_continuation.py	Mon Aug 13 15:34:32 2007
@@ -179,3 +179,101 @@
     eval_(ctx, "(oo +)")
     assert ctx.get("oo") is ctx.get("+")
 
+def test_lambda_call():
+    ctx = ExecutionContext()
+
+    eval_(ctx, "(define c1 'none)")
+    eval_(ctx, "(define c2 'none)")
+    eval_(ctx, """(define fun (lambda (x y z)
+                                (call/cc (lambda (k)
+                                           (set! c1 k)))
+                                (+ x y z)))""")
+
+    assert ctx.get("c1").to_string() == "none"
+    assert ctx.get("c2").to_string() == "none"
+
+    eval_(ctx, """(fun (call/cc (lambda (k)
+                                  (set! c2 k)
+                                  1))
+                       2 3)""")
+
+    w_result = eval_(ctx, "(c1)")
+    assert w_result.to_number() == 6
+
+    w_result = eval_(ctx, "(c2 0)")
+    assert w_result.to_number() == 5
+    w_result = eval_(ctx, "(c1)")
+    assert w_result.to_number() == 5
+
+    w_result = eval_(ctx, "(c2 5)")
+    assert w_result.to_number() == 10
+    w_result = eval_(ctx, "(c1)")
+    assert w_result.to_number() == 10
+
+def test_pitfall_1_1():
+    ctx = ExecutionContext()
+    w_result = eval_(ctx, """
+        (let ((cont #f))
+           (letrec ((x (call/cc (lambda (c) (set! cont c) 0)))
+                    (y (call/cc (lambda (c) (set! cont c) 0))))
+             (if cont
+                 (let ((c cont))
+                   (set! cont #f)
+                   (set! x 1)
+                   (set! y 1)
+                   (c 0))
+                 (+ x y))))""")
+
+    assert w_result.to_number() == 0
+
+def test_pitfall_1_2():
+    py.test.skip("(cond ...) and (procedure? ...) not implemented")
+    ctx = ExecutionContext()
+    w_result = eval_(ctx, """
+      (letrec ((x (call/cc list)) (y (call/cc list)))
+        (cond ((procedure? x) (x (pair? y)))
+          ((procedure? y) (y (pair? x))))
+        (let ((x (car x)) (y (car y)))
+          (and (call/cc x) (call/cc y) (call/cc x)))))""")
+
+    assert isinstance(w_result, W_Boolean)
+    assert w_result.to_boolean() is True
+
+def test_pitfall_1_3():
+    py.test.skip("(eq? ...) not implemented, letrec not cf")
+    ctx = ExecutionContext()
+    w_result = eval_(ctx, """
+      (letrec ((x (call/cc
+                    (lambda (c)
+                        (list #t c)))))
+          (if (car x)
+              ((car (cdr x)) (list #f (lambda () x)))
+              (eq? x ((car (cdr x))))))""")
+
+    assert isinstance(w_result, W_Boolean)
+    assert w_result.to_boolean() is True
+
+def test_pitfall_7_4():
+    ctx = ExecutionContext()
+    w_result = eval_(ctx, """
+        (let ((x '())
+              (y 0))
+            (call/cc 
+             (lambda (escape)
+               (let* ((yin ((lambda (foo) 
+                              (set! x (cons y x))
+                              (if (= y 10)
+                                  (escape x)
+                                  (begin
+                                    (set! y 0)
+                                    foo)))
+                            (call/cc (lambda (bar) bar))))
+                      (yang ((lambda (foo) 
+                               (set! y (+ y 1))
+                               foo)
+                             (call/cc (lambda (baz) baz)))))
+                 (yin yang)))))""")
+
+    assert isinstance(w_result, W_Pair)
+    assert w_result.to_string() == "(10 9 8 7 6 5 4 3 2 1 0)"
+



More information about the Pypy-commit mailing list