[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