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

jlg at codespeak.net jlg at codespeak.net
Fri Aug 10 15:06:44 CEST 2007


Author: jlg
Date: Fri Aug 10 15:06:43 2007
New Revision: 45582

Modified:
   pypy/dist/pypy/lang/scheme/object.py
   pypy/dist/pypy/lang/scheme/test/test_continuation.py
Log:
creation of ContinuationFrame is no longer copying elst; define is continuation friendly now

Modified: pypy/dist/pypy/lang/scheme/object.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/object.py	(original)
+++ pypy/dist/pypy/lang/scheme/object.py	Fri Aug 10 15:06:43 2007
@@ -40,7 +40,7 @@
     def __repr__(self):
         return "<W_Root " + self.to_string() + ">"
 
-    def eval_cf(self, ctx, caller, cont, elst=[]):
+    def eval_cf(self, ctx, caller, cont, elst=[], enum=0):
         return self.eval(ctx)
 
     def eval(self, ctx):
@@ -177,9 +177,9 @@
 class W_Eval(W_Root):
     #this class is for objects which does more than
     # evaluate to themselves
-    def eval_cf(self, ctx, caller, cont, elst=[]):
+    def eval_cf(self, ctx, caller, cont, elst=[], enum=0):
         #eval with continuation frame!
-        ctx.cont_stack.append(ContinuationFrame(caller, cont, elst))
+        ctx.cont_stack.append(ContinuationFrame(caller, cont, elst, enum))
         result = self.eval(ctx)
         ctx.cont_stack.pop()
         return result
@@ -197,7 +197,7 @@
     def to_string(self):
         return "()"
 
-    def eval_cf(self, ctx, caller, cont, elst=[]):
+    def eval_cf(self, ctx, caller, cont, elst=[], enum=0):
         #XXX not tests here
         raise SchemeSyntaxError
 
@@ -338,6 +338,7 @@
     def continue_tr(self, ctx, lst, elst, cnt=True):
         #evaluate all arguments into list
         arg_lst = elst
+        arg_num = 0
         arg = lst
         while isinstance(arg, W_Pair):
             #this is non tail-call, it should create continuation frame
@@ -346,8 +347,9 @@
             #  - arg (W_Pair) = arg.cdr as a pointer to not evaluated
             #    arguments
             #  - actual context
-            w_obj = arg.car.eval_cf(ctx, self, arg.cdr, arg_lst)
+            w_obj = arg.car.eval_cf(ctx, self, arg.cdr, arg_lst, arg_num)
 
+            arg_num += 1
             arg_lst.append(w_obj)
             arg = arg.cdr
 
@@ -740,13 +742,25 @@
 class Define(W_Macro):
     _symbol_name = "define"
 
+    def continue_tr(self, ctx, lst, elst, cnt=True):
+        w_first = elst[0]
+        w_val = elst[1]
+        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
+
+        raise SchemeSyntaxError
+
     def call(self, ctx, lst):
         if not isinstance(lst, W_Pair):
             raise SchemeSyntaxError
         w_first = lst.car
         w_second = lst.get_cdr_as_pair()
         if isinstance(w_first, W_Symbol):
-            w_val = w_second.car.eval(ctx)
+            w_val = w_second.car.eval_cf(ctx, self, w_first, [w_first], 1)
             ctx.set(w_first.name, w_val)
             return w_val #undefined
         elif isinstance(w_first, W_Pair):
@@ -760,8 +774,8 @@
             w_lambda = W_Lambda(formals, body, ctx, pname=w_name.name)
             ctx.set(w_name.name, w_lambda)
             return w_lambda #undefined
-        else:
-            raise SchemeSyntaxError
+
+        raise SchemeSyntaxError
 
 class Sete(W_Macro):
     _symbol_name = "set!"
@@ -1397,25 +1411,24 @@
         self.result = result
 
 class ContinuationFrame(object):
-    def __init__(self, callable, continuation, evaluated_args = []):
+    def __init__(self, callable, continuation, evaluated_args = [], enum=0):
         assert hasattr(callable, "continue_tr")
         self.callable = callable
         assert isinstance(continuation, W_Root)
         self.continuation = continuation
         assert isinstance(evaluated_args, list)
-        #XXX copying of evaluated_args here is SLOW,
-        # it should ocur only on continuation capture
-        self.evaluated_args = evaluated_args[:]
+        self.evaluated_args = evaluated_args
+        self.evaluated_args_num = enum
 
     def run(self, ctx, arg):
-        elst = self.evaluated_args[:]
+        elst = self.evaluated_args[:self.evaluated_args_num]
         elst.append(arg)
         print self.callable.to_string(), elst, self.continuation
         return self.callable.continue_tr(ctx, self.continuation, elst, True)
 
 class Continuation(W_Procedure):
     def __init__(self, ctx, continuation):
-        self.closure = ctx #XXX to .copy() ot not to .copy()
+        self.closure = ctx #to .copy() ot not to .copy()
         #copy of continuation stack
         self.cont_stack = continuation[:]
         try:

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	Fri Aug 10 15:06:43 2007
@@ -88,7 +88,7 @@
         (define (test)
           (let ((i 0))
             (call/cc (lambda (k) (set! con k)))
-            ; The next time tc is called, we start here.
+            ; The next time con is called, we start here.
             (set! i (+ i 1))
             i))""")
 
@@ -136,3 +136,46 @@
     assert w_result.to_string() == "odd"
     assert eval_(ctx, "ret-failed").to_boolean() == False
 
+def test_loop():
+    ctx = ExecutionContext()
+
+    eval_(ctx, "(define k 'none)")
+    eval_(ctx, "(define num 'none)")
+    w_result = eval_(ctx, """
+        (call/cc
+            (lambda (return)
+                (letrec ((loop
+                          (lambda (n)
+                            (if (zero? n)
+                                0
+                                (begin
+                                  (call/cc (lambda (cc)
+                                             (set! k cc)
+                                             (return n)))
+                                  (set! num n)
+                                  (loop (- n 1)))))))
+                      (loop 10))))""")
+
+    assert w_result.to_number() == 10
+    assert isinstance(ctx.get("k"), Continuation)
+    assert ctx.get("num").to_string() == "none"
+
+    for i in range(9, -1, -1):
+        w_result = eval_(ctx, "(k)")
+        assert w_result.to_number() == i
+        assert ctx.get("num").to_number() == i+1
+
+    w_result = eval_(ctx, "(k)")
+    assert w_result.to_number() == 0
+    assert ctx.get("num").to_number() == 1
+
+def test_let_define():
+    ctx = ExecutionContext()
+    
+    eval_(ctx, """(define oo
+                          (let ((cont (call/cc (lambda (k) k))))
+                               cont))""")
+    assert isinstance(ctx.get("oo"), Continuation)
+    eval_(ctx, "(oo +)")
+    assert ctx.get("oo") is ctx.get("+")
+



More information about the Pypy-commit mailing list