[pypy-svn] r45328 - in pypy/dist/pypy/lang/scheme: . test
jlg at codespeak.net
jlg at codespeak.net
Wed Jul 25 16:22:45 CEST 2007
Author: jlg
Date: Wed Jul 25 16:22:45 2007
New Revision: 45328
Modified:
pypy/dist/pypy/lang/scheme/execution.py
pypy/dist/pypy/lang/scheme/object.py
pypy/dist/pypy/lang/scheme/test/test_macro.py
Log:
macro expansion more hygenic, expand_eval method added; ExecutionContext __init__ create new Location() for each operation
Modified: pypy/dist/pypy/lang/scheme/execution.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/execution.py (original)
+++ pypy/dist/pypy/lang/scheme/execution.py Wed Jul 25 16:22:45 2007
@@ -57,7 +57,7 @@
OPERATION_MAP = {}
for name, cls in OMAP.items():
- OPERATION_MAP[name] = Location(cls(name))
+ OPERATION_MAP[name] = cls(name)
class ExecutionContext(object):
"""Execution context implemented as a dict.
@@ -66,7 +66,10 @@
"""
def __init__(self, globalscope=None, scope=None, closure=False):
if globalscope is None:
- self.globalscope = OPERATION_MAP.copy()
+ self.globalscope = {}
+ for name, oper in OPERATION_MAP.items():
+ self.globalscope[name] = Location(oper)
+
else:
self.globalscope = globalscope
Modified: pypy/dist/pypy/lang/scheme/object.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/object.py (original)
+++ pypy/dist/pypy/lang/scheme/object.py Wed Jul 25 16:22:45 2007
@@ -904,6 +904,19 @@
return (False, {})
+class SyntacticClosure(W_Root):
+ def __init__(self, ctx, sexpr):
+ self.sexpr = sexpr
+ self.closure = ctx
+
+ def eval_tr(self, ctx):
+ #this symbol is in Syntactic Closure
+ return self.sexpr.eval_tr(self.closure)
+
+ def to_string(self):
+ #return "#<closure: " + self.sexpr.to_string() + ">"
+ return self.sexpr.to_string()
+
class W_Transformer(W_Procedure):
def __init__(self, syntax_lst, ctx, pname=""):
self.pname = pname
@@ -930,20 +943,29 @@
if template is None :
raise SchemeSyntaxError
- return self.substitute(template)
+ return self.substitute(template, ctx)
- def substitute(self, sexpr):
+ def substitute(self, sexpr, ctx):
if isinstance(sexpr, W_Symbol):
w_sub = self.match_dict.get(sexpr.to_string(), None)
if w_sub is not None:
- return w_sub
+ return SyntacticClosure(ctx, w_sub)
return sexpr
elif isinstance(sexpr, W_Pair):
- return W_Pair(self.substitute(sexpr.car),
- self.substitute(sexpr.cdr))
+ return W_Pair(self.substitute(sexpr.car, ctx),
+ self.substitute(sexpr.cdr, ctx))
- else:
- return sexpr
+ return sexpr
+ def expand_eval(self, sexpr, ctx):
+ #we have lexical scopes:
+ # 1. in which macro was defined - self.closure
+ # 2. in which macro is called - ctx
+ # 3. in which macro is expanded - expand_ctx
+
+ expand_ctx = self.closure.copy()
+ expanded = self.expand(sexpr, ctx)
+ return expanded.eval(expand_ctx)
+
Modified: pypy/dist/pypy/lang/scheme/test/test_macro.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/test/test_macro.py (original)
+++ pypy/dist/pypy/lang/scheme/test/test_macro.py Wed Jul 25 16:22:45 2007
@@ -91,7 +91,7 @@
w_expr = parse("(foo bar)")[0]
w_expanded = w_transformer.expand(w_expr, ctx)
- assert isinstance(w_expanded, W_Symbol)
+ #assert isinstance(w_expanded, W_Symbol)
assert w_expanded.to_string() == "bar"
w_transformer = eval_(ctx, """(syntax-rules ()
@@ -112,3 +112,67 @@
assert isinstance(w_expanded, W_Pair)
assert w_expanded.to_string() == "(let ((var 12)) (+ 1 var))"
+def test_syntax_rules_expand():
+ ctx = ExecutionContext()
+
+ w_transformer = eval_(ctx, """(syntax-rules ()
+ ((_ var)
+ (let ((temp 1)) (+ var temp))))""")
+
+ w_expr = parse("(_ 12)")[0]
+ w_expanded = w_transformer.expand(w_expr, ctx)
+ assert w_expanded.to_string() == "(let ((temp 1)) (+ 12 temp))"
+ assert w_transformer.expand_eval(w_expr, ctx).to_number() == 13
+
+ #transparency
+ eval_(ctx, "(define temp 12)")
+ w_expr = parse("(_ temp)")[0]
+ w_expanded = w_transformer.expand(w_expr, ctx)
+ assert w_expanded.to_string() == "(let ((temp 1)) (+ temp temp))"
+ assert w_transformer.expand_eval(w_expr, ctx).to_number() == 13
+
+ #define in closure, should not affect macro eval
+ closure = ctx.copy()
+ eval_(closure, "(define + -)")
+ assert w_transformer.expand_eval(w_expr, closure).to_number() == 13
+
+ #define in top level - should affect macro eval
+ eval_(ctx, "(define + -)")
+ assert w_transformer.expand_eval(w_expr, ctx).to_number() == 11
+
+def test_syntax_rules_hygenic_expansion():
+ ctx = ExecutionContext()
+
+ w_transformer = eval_(ctx, """(syntax-rules ()
+ ((dotimes count body)
+ (letrec ((loop
+ (lambda (counter)
+ (if (= counter 0)
+ ()
+ (begin
+ body
+ (loop (- counter 1)))))))
+ (loop count))))""")
+
+ w_expr = parse("(_ 5 (set! counter (+ counter 1)))")[0]
+ py.test.raises(UnboundVariable, w_transformer.expand_eval, w_expr, ctx)
+
+ eval_(ctx, "(define counter 0)")
+ w_expr = parse("(_ 5 (set! counter (+ counter 1)))")[0]
+ w_transformer.expand_eval(w_expr, ctx)
+ assert ctx.get("counter").to_number() == 5
+
+def test_shadow():
+ py.test.skip("in progress")
+ ctx = ExecutionContext()
+
+ w_transformer = eval_(ctx, """(syntax-rules ()
+ ((shadow used-arg body)
+ (let ((used-arg 5)) body)))""")
+
+ w_expr = parse("(shadow test test)")[0]
+ assert w_transformer.expand_eval(w_expr, ctx).to_number() == 5
+
+ eval_(ctx, "(define test 7)")
+ assert w_transformer.expand_eval(w_expr, ctx).to_number() == 5
+
More information about the Pypy-commit
mailing list