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

jlg at codespeak.net jlg at codespeak.net
Fri Jul 27 14:49:49 CEST 2007


Author: jlg
Date: Fri Jul 27 14:49:48 2007
New Revision: 45401

Modified:
   pypy/dist/pypy/lang/scheme/object.py
   pypy/dist/pypy/lang/scheme/test/test_macro.py
Log:
W_Transformer.match_dict is no more, now it is returned by match function and passed to substitute; removed bug with Closuring already Closured symbol

Modified: pypy/dist/pypy/lang/scheme/object.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/object.py	(original)
+++ pypy/dist/pypy/lang/scheme/object.py	Fri Jul 27 14:49:48 2007
@@ -922,47 +922,52 @@
     def __init__(self, syntax_lst, ctx, pname=""):
         self.pname = pname
         self.syntax_lst = syntax_lst
-        self.match_dict = {}
         self.closure = ctx
 
     def match(self, ctx, w_expr):
         for rule in self.syntax_lst:
-            (matched, temp_dict) = rule.match(ctx, w_expr)
+            (matched, match_dict) = rule.match(ctx, w_expr)
             if matched:
-                self.match_dict = temp_dict
-                return rule.template
+                return (rule.template, match_dict)
 
-        self.match_dict = {}
-        return None
+        return (None, {})
 
     def expand(self, ctx, w_expr):
-        template = self.match(ctx, w_expr)
+        (template, match_dict) = self.match(ctx, w_expr)
 
         if template is None :
             raise SchemeSyntaxError
 
-        return self.substitute(ctx, template)
+        return self.substitute(ctx, template, match_dict)
 
-    def substitute(self, ctx, sexpr):
+    def substitute(self, ctx, sexpr, match_dict):
         if isinstance(sexpr, W_Symbol):
-            w_sub = self.match_dict.get(sexpr.name, None)
+            w_sub = match_dict.get(sexpr.name, None)
             if w_sub is not None:
                 # Hygenic macros close their input forms in the syntactic
                 # enviroment at the point of use
 
                 #not always needed, because w_sub can have no W_Symbols inside
+                
+                #already is a SyntacticClosure
+                if isinstance(w_sub, SyntacticClosure):
+                    assert w_sub.closure is ctx
+
+                    return w_sub
+
                 return SyntacticClosure(ctx, w_sub)
 
             return sexpr
 
         elif isinstance(sexpr, W_Pair):
-            w_pair = W_Pair(self.substitute(ctx, sexpr.car),
-                    self.substitute(ctx, sexpr.cdr))
+            w_pair = W_Pair(self.substitute(ctx, sexpr.car, match_dict),
+                    self.substitute(ctx, sexpr.cdr, match_dict))
 
             w_paircar = w_pair.car
             if isinstance(w_paircar, W_Symbol):
                 try:
                     w_macro = ctx.get(w_paircar.name)
+
                     # recursive macro expansion
                     if isinstance(w_macro, W_DerivedMacro):
                         return w_macro.expand(ctx, w_pair)
@@ -978,6 +983,7 @@
                     # recursive macro expansion
                     if isinstance(w_macro, W_DerivedMacro):
                         return w_macro.expand(ctx, w_pair)
+
                 except UnboundVariable:
                     pass
 

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	Fri Jul 27 14:49:48 2007
@@ -16,32 +16,35 @@
 
     w_transformer = eval_noctx("(syntax-rules ())")
     w_expr = parse("(foo)")[0]
-    assert not w_transformer.match(ctx, w_expr)
+    assert not w_transformer.match(ctx, w_expr)[0]
 
     w_transformer = eval_noctx("(syntax-rules () ((foo) #t))")
     w_expr = parse("(bar)")[0]
-    assert w_transformer.match(ctx, w_expr)
+    assert w_transformer.match(ctx, w_expr)[0]
     w_expr = parse("(foo bar)")[0]
-    assert not w_transformer.match(ctx, w_expr)
+    assert not w_transformer.match(ctx, w_expr)[0]
 
     w_transformer = eval_noctx("""(syntax-rules () ((_) #t)
                                                    ((_ foo) foo))""")
     w_expr = parse("(foo)")[0]
-    assert w_transformer.match(ctx, w_expr).to_boolean()
+    assert w_transformer.match(ctx, w_expr)[0].to_boolean()
     w_expr = parse("(foo bar)")[0]
-    assert w_transformer.match(ctx, w_expr).to_string() == "foo"
-    assert w_transformer.match_dict["foo"].to_string() == "bar"
+    (template, match_dict) = w_transformer.match(ctx, w_expr)
+    assert template.to_string() == "foo"
+    assert match_dict["foo"].to_string() == "bar"
 
     w_expr = parse("(foo bar boo)")[0]
-    assert not w_transformer.match(ctx, w_expr)
-    assert w_transformer.match_dict == {}
+    (template, match_dict) = w_transformer.match(ctx, w_expr)
+    assert not template
+    assert match_dict == {}
 
     w_transformer = eval_noctx("(syntax-rules () ((foo (bar)) bar))")
     w_expr = parse("(_ fuzz)")[0]
-    assert not w_transformer.match(ctx, w_expr)
+    assert not w_transformer.match(ctx, w_expr)[0]
     w_expr = parse("(_ (fuzz))")[0]
-    assert w_transformer.match(ctx, w_expr)
-    assert w_transformer.match_dict["bar"].to_string() == "fuzz"
+    (template, match_dict) = w_transformer.match(ctx, w_expr)
+    assert template
+    assert match_dict["bar"].to_string() == "fuzz"
 
 def test_syntax_rules_literals():
     ctx = ExecutionContext()
@@ -51,13 +54,13 @@
     w_transformer = eval_(ctx, "(syntax-rules (=>) ((foo => bar) #t))")
 
     w_expr = parse("(foo bar boo)")[0]
-    assert not w_transformer.match(ctx, w_expr)
+    assert not w_transformer.match(ctx, w_expr)[0]
 
     # exact match
     w_expr = parse("(foo => boo)")[0]
 
     # within the same context
-    assert w_transformer.match(ctx, w_expr)
+    assert w_transformer.match(ctx, w_expr)[0]
 
     w_42 = W_Number(42)
 
@@ -65,19 +68,19 @@
     closure = ctx.copy()
     closure.put("=>", w_42)
     w_transformer = eval_(ctx, "(syntax-rules (=>) ((foo => bar) #t))")
-    assert not w_transformer.match(closure, w_expr)
+    assert not w_transformer.match(closure, w_expr)[0]
 
     # different lexical scope, not the same bindings for => in ctx and closure
     ctx.put("=>", W_Number(12))
     assert ctx.get("=>") is not closure.get("=>")
     w_transformer = eval_(ctx, "(syntax-rules (=>) ((foo => bar) #t))")
-    assert not w_transformer.match(closure, w_expr)
+    assert not w_transformer.match(closure, w_expr)[0]
 
     # the same binding for => in ctx and closure
     ctx.put("=>", w_42)
     assert ctx.get("=>") is closure.get("=>")
     w_transformer = eval_(ctx, "(syntax-rules (=>) ((foo => bar) #t))")
-    assert w_transformer.match(closure, w_expr)
+    assert w_transformer.match(closure, w_expr)[0]
 
 def test_syntax_rules_expand_simple():
     ctx = ExecutionContext()
@@ -203,15 +206,23 @@
                                     ((my-or arg1 arg2)
                                      (if arg1
                                          arg1
-                                         (my-or arg2)))))""")
+                                         (my-or arg2)))
+                                    ((my-or arg1 arg2 arg3)
+                                     (if arg1
+                                         arg1
+                                         (my-or arg2 arg3)))))""")
 
     assert eval_(ctx, "(my-or)").to_boolean() is False
     assert eval_(ctx, "(my-or 12)").to_number() == 12
 
-    #should expand recursively and after that eval, how to check it?
+    #should expand recursively and after that eval
     w_expr = parse("(my-or 12 42)")[0]
     assert ctx.get("my-or").expand(ctx, w_expr).to_string() == \
             "(if 12 12 42)"
+    w_expr = parse("(my-or 12 42 82)")[0]
+    assert ctx.get("my-or").expand(ctx, w_expr).to_string() == \
+            "(if 12 12 (if 42 42 82))"
     assert eval_(ctx, "(my-or 12 42)").to_number() == 12
     assert eval_(ctx, "(my-or #f 42)").to_number() == 42
+    assert eval_(ctx, "(my-or #f #f 82)").to_number() == 82
 



More information about the Pypy-commit mailing list