[pypy-svn] r45160 - in pypy/dist/pypy/lang/scheme: . test
jlg at codespeak.net
jlg at codespeak.net
Tue Jul 17 16:37:18 CEST 2007
Author: jlg
Date: Tue Jul 17 16:37:17 2007
New Revision: 45160
Modified:
pypy/dist/pypy/lang/scheme/object.py
pypy/dist/pypy/lang/scheme/test/test_eval.py
Log:
letrec is cool now
Modified: pypy/dist/pypy/lang/scheme/object.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/object.py (original)
+++ pypy/dist/pypy/lang/scheme/object.py Tue Jul 17 16:37:17 2007
@@ -628,7 +628,29 @@
return self.eval_body(local_ctx, lst.cdr)
-Letrec = Let
+class Letrec(W_Macro):
+ 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()
+ map_name_expr = {}
+ w_formal = lst.car
+ while isinstance(w_formal, W_Pair):
+ w_def = w_formal.get_car_as_pair()
+ name = w_def.car.to_string()
+ map_name_expr[name] = w_def.get_cdr_as_pair().car
+ local_ctx.bound(name)
+ w_formal = w_formal.cdr
+
+ map_name_val = {}
+ for (name, expr) in map_name_expr.items():
+ map_name_val[name] = expr.eval(local_ctx)
+
+ for (name, w_val) in map_name_val.items():
+ local_ctx.sete(name, w_val)
+
+ return self.eval_body(local_ctx, lst.cdr)
def literal(sexpr):
return W_Pair(W_Identifier('quote'), W_Pair(sexpr, W_Nil()))
@@ -728,10 +750,14 @@
def get(self, name):
loc = self.scope.get(name, None)
if loc is not None:
+ if loc.obj is None:
+ raise UnboundVariable(name)
return loc.obj
loc = self.globalscope.get(name, None)
if loc is not None:
+ if loc.obj is None:
+ raise UnboundVariable(name)
return loc.obj
raise UnboundVariable(name)
@@ -774,6 +800,13 @@
else:
self.globalscope[name] = Location(obj)
+ def bound(self, name):
+ """create new location"""
+ if self.closure:
+ self.scope[name] = Location(None)
+ else:
+ self.globalscope[name] = Location(None)
+
def get_location(self, name):
"""internal/test use only
returns location bound to variable
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 Tue Jul 17 16:37:17 2007
@@ -394,6 +394,12 @@
assert w_result.to_number() == 44
assert ctx.get("var") is w_global
+ w_result = eval_expr(ctx, """
+ (let ((x (lambda () 1)))
+ (let ((y (lambda () (x)))
+ (x (lambda () 2))) (y)))""")
+ assert w_result.to_number() == 1
+
py.test.raises(UnboundVariable, eval_noctx, "(let ((y 0) (x y)) x)")
def test_letrec():
@@ -412,6 +418,12 @@
(even? 2000))""")
assert w_result.to_boolean() is True
+ w_result = eval_expr(ctx, """
+ (let ((x (lambda () 1)))
+ (letrec ((y (lambda () (x)))
+ (x (lambda () 2))) (y)))""")
+ assert w_result.to_number() == 2
+
py.test.raises(UnboundVariable, eval_noctx, "(letrec ((y 0) (x y)) x)")
def test_letstar():
More information about the Pypy-commit
mailing list