[pypy-svn] r45569 - in pypy/dist/pypy/lang/scheme: . test
jlg at codespeak.net
jlg at codespeak.net
Thu Aug 9 16:33:30 CEST 2007
Author: jlg
Date: Thu Aug 9 16:33:29 2007
New Revision: 45569
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:
W_Callable.eval_body is no more, Body(W_Root) now in charge; W_Pair operator is now call/cc frindly, funny (call/cc call/cc) tests
Modified: pypy/dist/pypy/lang/scheme/TODO.txt
==============================================================================
--- pypy/dist/pypy/lang/scheme/TODO.txt (original)
+++ pypy/dist/pypy/lang/scheme/TODO.txt Thu Aug 9 16:33:29 2007
@@ -10,7 +10,7 @@
-------
- implement key functions
- (apply, reduce, map and so on)
+ (apply, map and so on)
- comparison: < > eq? eqv?
Modified: pypy/dist/pypy/lang/scheme/object.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/object.py (original)
+++ pypy/dist/pypy/lang/scheme/object.py Thu Aug 9 16:33:29 2007
@@ -105,7 +105,7 @@
return self.boolval
def __repr__(self):
- return "<W_Boolean " + str(self.boolval) + " >"
+ return "<W_Boolean " + str(self.boolval) + ">"
class W_String(W_Root):
def __init__(self, val):
@@ -115,7 +115,7 @@
return self.strval
def __repr__(self):
- return "<W_String " + self.strval + " >"
+ return "<W_String \"" + self.strval + "\">"
class W_Real(W_Root):
def __init__(self, val):
@@ -210,8 +210,32 @@
def __repr__(self):
return "<W_Pair " + self.to_string() + ">"
+ def continue_tr(self, ctx, lst, elst, cnt=True):
+ oper = elst[0]
+ if not isinstance(oper, W_Callable):
+ raise NotCallable(oper)
+
+ cdr = lst
+ if isinstance(cdr, W_List):
+ result = oper.call_tr(ctx, cdr)
+ else:
+ raise SchemeSyntaxError
+
+ if result[1] is None:
+ result = result[0]
+ else:
+ result = result[0].eval(result[1])
+
+ if len(ctx.cont_stack) == 0:
+ raise ContinuationReturn(result)
+
+ cont = ctx.cont_stack.pop()
+ return cont.run(ctx, result)
+
def eval_tr(self, ctx):
+ ctx.cont_stack.append(ContinuationFrame(self, self.cdr))
oper = self.car.eval(ctx)
+ ctx.cont_stack.pop()
if not isinstance(oper, W_Callable):
raise NotCallable(oper)
@@ -244,7 +268,14 @@
def call(self, ctx, lst):
raise NotImplementedError
- def eval_body(self, ctx, body, cnt=False):
+class Body(W_Root):
+ def __init__(self, body):
+ self.body = body
+
+ def eval_tr(self, ctx):
+ return self.continue_tr(ctx, self.body, [], False)
+
+ def continue_tr(self, ctx, body, elst, cnt=True):
body_expression = body
while isinstance(body_expression, W_Pair):
if body_expression.cdr is w_nil:
@@ -335,10 +366,6 @@
def to_string(self):
return "#<primitive-macro %s>" % (self.pname,)
- def continue_tr(self, ctx, lst, elst, cnt=True):
- lst = W_Pair(elst[0], lst)
- return self.eval_body(ctx, lst, cnt=True)
-
class Formal(object):
def __init__(self, name, islist=False):
self.name = name
@@ -361,7 +388,7 @@
self.args.append(Formal(arg.car.to_string(), False))
arg = arg.cdr
- self.body = body
+ self.body = Body(body)
self.pname = pname
self.closure = closure
@@ -382,7 +409,7 @@
else:
local_ctx.put(formal.name, lst[idx])
- return self.eval_body(local_ctx, self.body)
+ return self.body.eval_tr(local_ctx)
def plst2lst(plst, w_cdr=w_nil):
"""coverts python list() of W_Root into W_Pair scheme list"""
@@ -673,6 +700,20 @@
return w_obj.round() % 2 == 0
+#XXX no tests for it
+class PairP(W_Procedure):
+ _symbol_name = "pair?"
+
+ def procedure(self, ctx, lst):
+ if len(lst) != 1:
+ raise WrongArgsNumber
+
+ w_obj = lst[0]
+ if isinstance(w_obj, W_Pair):
+ return W_Boolean(True)
+
+ return W_Boolean(False)
+
##
# Macro
##
@@ -750,7 +791,7 @@
def call_tr(self, ctx, lst):
#begin uses eval_body, so it is tail-recursive aware
- return self.eval_body(ctx, lst)
+ return Body(lst).eval_tr(ctx)
class Let(W_Macro):
_symbol_name = "let"
@@ -768,7 +809,7 @@
local_ctx.sput(w_def.car, w_val)
w_formal = w_formal.cdr
- return self.eval_body(local_ctx, lst.cdr)
+ return Body(lst.cdr).eval_tr(local_ctx)
class LetStar(W_Macro):
_symbol_name = "let*"
@@ -786,7 +827,7 @@
local_ctx.sput(w_def.car, w_val)
w_formal = w_formal.cdr
- return self.eval_body(local_ctx, lst.cdr)
+ return Body(lst.cdr).eval_tr(local_ctx)
class Letrec(W_Macro):
_symbol_name = "letrec"
@@ -814,7 +855,7 @@
for (name, w_val) in map_name_val.items():
local_ctx.ssete(map_name_symb[name], w_val)
- return self.eval_body(local_ctx, lst.cdr)
+ return Body(lst.cdr).eval_tr(local_ctx)
def quote(sexpr):
return W_Pair(W_Symbol('quote'), W_Pair(sexpr, w_nil))
@@ -1329,7 +1370,7 @@
local_ctx.put(w_name.name, w_macro)
w_formal = w_formal.cdr
- return self.eval_body(local_ctx, lst.cdr)
+ return Body(lst.cdr).eval_tr(local_ctx)
class ContinuationReturn(SchemeException):
def __init__(self, result):
@@ -1337,7 +1378,7 @@
class ContinuationFrame(object):
def __init__(self, callable, continuation, evaluated_args = []):
- assert isinstance(callable, W_Callable)
+ assert hasattr(callable, "continue_tr")
self.callable = callable
assert isinstance(continuation, W_Root)
self.continuation = continuation
@@ -1363,11 +1404,14 @@
#continuation captured on top-level
self.continuation = None
+ def to_string(self):
+ return "#<continuation -> %s>" % (self.continuation,)
+
def procedure_tr(self, ctx, lst):
if len(lst) == 0:
lst.append(w_undefined)
- print "Continuation called"
+ print "Continuation called", self.cont_stack
self.closure.cont_stack = self.cont_stack[:]
cont = self.continuation
if cont is None:
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 Thu Aug 9 16:33:29 2007
@@ -9,6 +9,21 @@
except ContinuationReturn, e:
return e.result
+def test_callcc_callcc():
+ ctx = ExecutionContext()
+ w_procedure = eval_(ctx, "(call/cc call/cc)")
+ assert isinstance(w_procedure, W_Procedure)
+ print w_procedure
+
+ eval_(ctx, "(define cont 'none)")
+ w_result = eval_(ctx, """((call/cc call/cc) (lambda (k)
+ (set! cont k)
+ 'done))""")
+ assert w_result.to_string() == "done"
+ assert isinstance(eval_(ctx, "cont"), W_Procedure)
+ eval_(ctx, "(cont +)")
+ assert eval_(ctx, "cont") is ctx.get("+")
+
def test_callcc():
ctx = ExecutionContext()
@@ -107,3 +122,17 @@
assert eval_(ctx, "(con2)").to_number() == 8
assert eval_(ctx, "(+ 1 (con2))").to_number() == 10
+def test_escape_continuation():
+ ctx = ExecutionContext()
+
+ eval_(ctx, "(define ret-failed #f)")
+ w_result = eval_(ctx, """
+ (let ((test 17))
+ (call/cc (lambda (return)
+ (if (odd? test) (return 'odd))
+ (set! ret-failed #t)
+ 'even)))""")
+
+ assert w_result.to_string() == "odd"
+ assert eval_(ctx, "ret-failed").to_boolean() == False
+
More information about the pypy-svn
mailing list