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

jlg at codespeak.net jlg at codespeak.net
Thu Aug 2 16:07:00 CEST 2007


Author: jlg
Date: Thu Aug  2 16:06:58 2007
New Revision: 45455

Modified:
   pypy/dist/pypy/lang/scheme/object.py
   pypy/dist/pypy/lang/scheme/test/test_macro.py
Log:
SyntaxRule match refactoring; test_macro.py changed; more ellipsis working

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  2 16:06:58 2007
@@ -862,13 +862,18 @@
         return W_Transformer(syntax_lst, ctx)
 
 class Ellipsis(W_Root):
-    def __init__(self, expr):
-        self.expr = expr
+    def __init__(self, mdict_lst):
+        self.mdict_lst = mdict_lst
 
 class EllipsisException(SchemeException):
-    def __init__(self, ellipsis, name):
-        self.expr = ellipsis.expr
-        self.name = name
+    def __init__(self, ellipsis):
+        self.mdict_lst = ellipsis.mdict_lst
+
+class EllipsisPattern(SchemeException):
+    pass
+
+class MatchError(SchemeException):
+    pass
 
 class SyntaxRule(object):
     def __init__(self, pattern, template, literals):
@@ -881,58 +886,63 @@
 
     def match(self, ctx, w_expr, pattern=None):
         if pattern is None:
-            w_patt = self.pattern
-        else:
-            w_patt = pattern
+            return self.matchr(ctx, self.pattern, w_expr)
 
-        match_dict = {}
-        while isinstance(w_patt, W_Pair) and isinstance(w_expr, W_Pair):
+        return self.matchr(ctx, pattern, w_expr)
+
+    def matchr(self, ctx, w_patt, w_expr):
+        if isinstance(w_patt, W_Pair):
             w_pattcar = w_patt.car
-            w_exprcar = w_expr.car
+            if isinstance(w_expr, W_Pair):
+                mdict_car = self.matchr(ctx, w_pattcar, w_expr.car)
 
-            w_literal = self.literals.get(w_pattcar.to_string(), None)
-            if w_literal is not None:
                 try:
-                    w_form = ctx.get(w_exprcar.to_string())
-                except UnboundVariable:
-                    w_form = w_exprcar
-
-                if w_form is not w_literal:
-                    return (False, {})
+                #we catch EllipsisPattern here because in car
+                # we dont know how to deal with it
+                    mdict_cdr = self.matchr(ctx, w_patt.cdr, w_expr.cdr)
+                except EllipsisPattern:
+                    print "ellipsis matched", w_patt, w_expr
 
-            w_pattcdr = w_patt.cdr
-            if isinstance(w_pattcdr, W_Pair) and w_pattcdr.car is w_ellipsis:
-                #w_pattcar should be matched 0-inf times in ellipsis
-                print w_patt, w_expr
-                match_dict[w_pattcar.to_string()] = Ellipsis(w_expr)
-                return (True, match_dict)
-
-            if isinstance(w_pattcar, W_Pair):
-                if not isinstance(w_exprcar, W_Pair):
-                    return (False, {})
+                    mdict_lst = []
+                    w_pair = w_expr
+                    while isinstance(w_pair, W_Pair):
+                        mdict = self.matchr(ctx, w_pattcar, w_pair.car)
+                        mdict_lst.append(mdict)
+                        w_pair = w_pair.cdr
 
-                (matched, match_nested) = self.match(ctx, w_exprcar, w_pattcar)
-                if not matched:
-                    return (False, {})
+                    mdict_cdr = {}
+                    ellipsis = Ellipsis(mdict_lst)
+                    for name in mdict_lst[0].keys():
+                        mdict_cdr[name] = ellipsis
+
+                mdict_car.update(mdict_cdr)
+                return mdict_car
 
-                match_dict.update(match_nested)
+            if w_pattcar is w_ellipsis and w_expr is w_nil:
+                raise EllipsisPattern
 
-            match_dict[w_pattcar.to_string()] = w_exprcar
+        if w_patt is w_ellipsis:
+            raise EllipsisPattern
 
-            w_patt = w_patt.cdr
-            w_expr = w_expr.cdr
+        if isinstance(w_patt, W_Symbol):
+            w_literal = self.literals.get(w_patt.name, None)
+            if w_literal is not None:
+                try:
+                    w_form = ctx.get(w_expr.to_string())
+                except UnboundVariable:
+                    w_form = w_expr
 
-        if (w_expr is w_nil) and (w_patt is w_nil):
-                return (True, match_dict)
+                if w_form is not w_literal:
+                    raise MatchError
 
-        if w_patt is w_nil:
-            return (False, {})
+            return {w_patt.name: w_expr}
 
-        #w_patt is symbol or primitive //as cdr of dotted list
-        match_dict[w_patt.to_string()] = w_expr
-        return (True, match_dict)
+        if w_patt is w_nil and w_expr is w_nil:
+            return {}
 
-        return (False, {})
+        #w_patt is w_nil, but w_expr is not
+        # or w_patt is W_Pair but w_expr is not
+        raise MatchError
 
 class SymbolClosure(W_Symbol):
     def __init__(self, ctx, symbol):
@@ -981,16 +991,18 @@
 
     def match(self, ctx, w_expr):
         for rule in self.syntax_lst:
-            (matched, match_dict) = rule.match(ctx, w_expr)
-            if matched:
+            try:
+                match_dict = rule.match(ctx, w_expr)
                 return (rule.template, match_dict)
+            except MatchError:
+                pass
 
-        return (None, {})
+        raise MatchError
 
     def expand(self, ctx, w_expr):
-        (template, match_dict) = self.match(ctx, w_expr)
-
-        if template is None :
+        try:
+            (template, match_dict) = self.match(ctx, w_expr)
+        except MatchError:
             raise SchemeSyntaxError
 
         return self.substitute(ctx, template, match_dict)
@@ -1012,7 +1024,7 @@
                     return PairClosure(ctx, w_sub)
 
                 if isinstance(w_sub, Ellipsis):
-                    raise EllipsisException(w_sub, sexpr.name)
+                    raise EllipsisException(w_sub)
 
                 return w_sub
 
@@ -1024,23 +1036,20 @@
                         self.substitute(ctx, sexpr.cdr, match_dict))
             except EllipsisException, e:
                 scdr = sexpr.cdr
-                print ">", sexpr, e.name, e.expr
+                print ">", sexpr, e.mdict_lst
                 if isinstance(scdr, W_Pair) and scdr.car is w_ellipsis:
-                    print ">>", sexpr, e.name, e.expr
+                    print ">>", sexpr, e.mdict_lst
+
                     plst = []
-                    w_pair = e.expr
-                    while isinstance(w_pair, W_Pair):
-                        #plst.append(W_Pair(w_pair.car, scdr))
-                        zzz = self.substitute(ctx, sexpr.car,
-                                {e.name: w_pair.car})
+                    for mdict in e.mdict_lst:
+                        zzz = self.substitute(ctx, sexpr.car, mdict)
                         plst.append(zzz)
-                        w_pair = w_pair.cdr
 
                     ellipsis = plst2lst(plst)
                     print ellipsis
                     return ellipsis
                 else:
-                    raise e #EllipsisException(ellipsis, e.name)
+                    raise e
 
             w_paircar = w_pair.car
             if isinstance(w_paircar, W_Symbol):

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	Thu Aug  2 16:06:58 2007
@@ -9,41 +9,42 @@
 def eval_noctx(expr):
     return parse(expr)[0].eval(ExecutionContext())
 
+def parse_(expr):
+    return parse(expr)[0]
+
 def test_syntax_rules_match():
     ctx = ExecutionContext()
     py.test.raises(SchemeSyntaxError, eval_noctx, "(syntax-rules 1)")
     py.test.raises(SchemeSyntaxError, eval_noctx, "(syntax-rules () 1)")
 
     w_transformer = eval_noctx("(syntax-rules ())")
-    w_expr = parse("(foo)")[0]
-    assert not w_transformer.match(ctx, w_expr)[0]
+    w_expr = parse_("(foo)")
+    py.test.raises(MatchError, w_transformer.match, ctx, w_expr)
 
     w_transformer = eval_noctx("(syntax-rules () ((foo) #t))")
-    w_expr = parse("(bar)")[0]
-    assert w_transformer.match(ctx, w_expr)[0]
-    w_expr = parse("(foo bar)")[0]
-    assert not w_transformer.match(ctx, w_expr)[0]
+    w_expr = parse_("(bar)")
+    assert w_transformer.match(ctx, w_expr)[0].to_boolean()
+    w_expr = parse_("(foo bar)")
+    py.test.raises(MatchError, w_transformer.match, ctx, w_expr)
 
     w_transformer = eval_noctx("""(syntax-rules () ((_) #t)
                                                    ((_ foo) foo))""")
-    w_expr = parse("(foo)")[0]
+    w_expr = parse_("(foo)")
     assert w_transformer.match(ctx, w_expr)[0].to_boolean()
-    w_expr = parse("(foo bar)")[0]
+    w_expr = parse_("(foo 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]
-    (template, match_dict) = w_transformer.match(ctx, w_expr)
-    assert not template
-    assert match_dict == {}
+    w_expr = parse_("(foo bar boo)")
+    py.test.raises(MatchError, w_transformer.match, ctx, w_expr)
 
     w_transformer = eval_noctx("(syntax-rules () ((foo (bar)) bar))")
-    w_expr = parse("(_ fuzz)")[0]
-    assert not w_transformer.match(ctx, w_expr)[0]
-    w_expr = parse("(_ (fuzz))")[0]
+    w_expr = parse_("(_ fuzz)")
+    py.test.raises(MatchError, w_transformer.match, ctx, w_expr)
+    w_expr = parse_("(_ (fuzz))")
     (template, match_dict) = w_transformer.match(ctx, w_expr)
-    assert template
+    assert template.to_string() == "bar"
     assert match_dict["bar"].to_string() == "fuzz"
 
 def test_syntax_rules_literals():
@@ -53,14 +54,14 @@
     # w_transformer created in ctx
     w_transformer = eval_(ctx, "(syntax-rules (=>) ((foo => bar) #t))")
 
-    w_expr = parse("(foo bar boo)")[0]
-    assert not w_transformer.match(ctx, w_expr)[0]
+    w_expr = parse_("(foo bar boo)")
+    py.test.raises(MatchError, w_transformer.match, ctx, w_expr)
 
     # exact match
-    w_expr = parse("(foo => boo)")[0]
+    w_expr = parse_("(foo => boo)")
 
     # within the same context
-    assert w_transformer.match(ctx, w_expr)[0]
+    assert w_transformer.match(ctx, w_expr)[0].to_boolean()
 
     w_42 = W_Number(42)
 
@@ -68,19 +69,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)[0]
+    py.test.raises(MatchError, w_transformer.match, closure, w_expr)
 
     # 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)[0]
+    py.test.raises(MatchError, w_transformer.match, closure, w_expr)
 
     # 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)[0]
+    assert w_transformer.match(closure, w_expr)[0].to_boolean()
 
 def test_syntax_rules_expand_simple():
     ctx = ExecutionContext()
@@ -88,12 +89,12 @@
     w_transformer = eval_(ctx, """(syntax-rules () ((_) #t)
                                                    ((_ foo) foo))""")
 
-    w_expr = parse("(foo)")[0]
+    w_expr = parse_("(foo)")
     w_expanded = w_transformer.expand(ctx, w_expr)
     assert isinstance(w_expanded, W_Boolean)
     assert w_expanded.to_boolean() == True
 
-    w_expr = parse("(foo bar)")[0]
+    w_expr = parse_("(foo bar)")
     w_expanded = w_transformer.expand(ctx, w_expr)
     assert w_expanded.to_string() == "bar"
 
@@ -101,7 +102,7 @@
                                         ((let1 var val body)
                                          (let ((var val)) body)))""")
 
-    w_expr = parse("(let1 var 12 (+ 1 var))")[0]
+    w_expr = parse_("(let1 var 12 (+ 1 var))")
     w_expanded = w_transformer.expand(ctx, w_expr)
     assert isinstance(w_expanded, W_Pair)
     assert w_expanded.to_string() == "(let ((var 12)) (+ 1 var))"
@@ -110,7 +111,7 @@
                                         ((let1 (var val) body)
                                          (let ((var val)) body)))""")
 
-    w_expr = parse("(let1 (var 12) (+ 1 var))")[0]
+    w_expr = parse_("(let1 (var 12) (+ 1 var))")
     w_expanded = w_transformer.expand(ctx, w_expr)
     assert isinstance(w_expanded, W_Pair)
     assert w_expanded.to_string() == "(let ((var 12)) (+ 1 var))"
@@ -122,14 +123,14 @@
                                        ((_ var)
                                         (let ((temp 1)) (+ var temp))))""")
 
-    w_expr = parse("(_ 12)")[0]
+    w_expr = parse_("(_ 12)")
     w_expanded = w_transformer.expand(ctx, w_expr)
     assert w_expanded.to_string() == "(let ((temp 1)) (+ 12 temp))"
     assert w_transformer.expand_eval(ctx, w_expr).to_number() == 13
 
     #transparency
     eval_(ctx, "(define temp 12)")
-    w_expr = parse("(_ temp)")[0]
+    w_expr = parse_("(_ temp)")
     w_expanded = w_transformer.expand(ctx, w_expr)
     assert w_expanded.to_string() == "(let ((temp 1)) (+ temp temp))"
     assert w_transformer.expand_eval(ctx, w_expr).to_number() == 13
@@ -157,11 +158,11 @@
                                                 (loop (- counter 1)))))))
                                         (loop count))))""")
 
-    w_expr = parse("(dotimes 5 (set! counter (+ counter 1)))")[0]
+    w_expr = parse_("(dotimes 5 (set! counter (+ counter 1)))")
     py.test.raises(UnboundVariable, w_transformer.expand_eval, ctx, w_expr)
 
     eval_(ctx, "(define counter 0)")
-    w_expr = parse("(dotimes 5 (set! counter (+ counter 1)))")[0]
+    w_expr = parse_("(dotimes 5 (set! counter (+ counter 1)))")
     w_transformer.expand_eval(ctx, w_expr)
     assert ctx.get("counter").to_number() == 5
 
@@ -172,7 +173,7 @@
                                      ((shadow used-arg body)
                                       (let ((used-arg 5)) body)))""")
 
-    w_expr = parse("(shadow test test)")[0]
+    w_expr = parse_("(shadow test test)")
     assert w_transformer.expand_eval(ctx, w_expr).to_number() == 5
 
     eval_(ctx, "(define test 7)")
@@ -182,7 +183,7 @@
                                      ((shadow used-arg body)
                                       (letrec ((used-arg 5)) body)))""")
 
-    w_expr = parse("(shadow test test)")[0]
+    w_expr = parse_("(shadow test test)")
     assert w_transformer.expand_eval(ctx, w_expr).to_number() == 5
 
     eval_(ctx, "(define test 7)")
@@ -226,10 +227,10 @@
     assert eval_(ctx, "(my-or 12)").to_number() == 12
 
     #should expand recursively and after that eval
-    w_expr = parse("(my-or 12 42)")[0]
+    w_expr = parse_("(my-or 12 42)")
     assert ctx.get("my-or").expand(ctx, w_expr).to_string() == \
             "(if 12 12 42)"
-    w_expr = parse("(my-or 12 42 82)")[0]
+    w_expr = parse_("(my-or 12 42 82)")
     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
@@ -245,7 +246,7 @@
                                           ((bar) (foo))
                                           ((bar arg) (foo arg))))""")
 
-    w_expr = parse("(bar 42)")[0]
+    w_expr = parse_("(bar 42)")
     #should expand directly (recursively) to 42
     assert ctx.get("bar").expand(ctx, w_expr).to_string() == "42"
 
@@ -298,7 +299,7 @@
 
     assert eval_(ctx, "(or 12)").to_number() == 12
     assert eval_(ctx, "(or 12 42)").to_number() == 12
-    assert eval_(ctx, "(or #f 42)").to_number() == 42
+    
     assert eval_(ctx, "(or #f #f 82)").to_number() == 82
     assert eval_(ctx, "(or #f #f #f 162)").to_number() == 162
 
@@ -335,7 +336,6 @@
     assert eval_(ctx, "z").to_number() == 0
 
 def test_ellipsis_list_pattern():
-    py.test.skip("in progress")
     ctx = ExecutionContext()
     eval_(ctx, """(define-syntax rlet
                                  (syntax-rules ()
@@ -353,5 +353,3 @@
                                (set! z 1)
                                (+ x y z))""").to_number() == 3
 
-    assert False
-



More information about the Pypy-commit mailing list