[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-svn
mailing list