[pypy-svn] r45280 - in pypy/dist/pypy/lang/scheme: . test
jlg at codespeak.net
jlg at codespeak.net
Mon Jul 23 17:53:53 CEST 2007
Author: jlg
Date: Mon Jul 23 17:53:53 2007
New Revision: 45280
Modified:
pypy/dist/pypy/lang/scheme/TODO.txt
pypy/dist/pypy/lang/scheme/object.py
pypy/dist/pypy/lang/scheme/test/test_macro.py
Log:
syntax-rules now handles literals
Modified: pypy/dist/pypy/lang/scheme/TODO.txt
==============================================================================
--- pypy/dist/pypy/lang/scheme/TODO.txt (original)
+++ pypy/dist/pypy/lang/scheme/TODO.txt Mon Jul 23 17:53:53 2007
@@ -1,13 +1,13 @@
Do now
------
-- lambda called with wrong number of args issue
+- lambda called with wrong number of arguments issue
Do next
-------
- implement key functions
- (apply, reduce, mapcar and so on)
+ (apply, reduce, map and so on)
- comparison: < > eq? eqv?
@@ -17,6 +17,7 @@
Here starts the real fun!
- macros
+ * macros are not first-class objects
- continuations
- move syntax checking to parsing
- switch to byte-code generation + eval instead of evaluating AST
Modified: pypy/dist/pypy/lang/scheme/object.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/object.py (original)
+++ pypy/dist/pypy/lang/scheme/object.py Mon Jul 23 17:53:53 2007
@@ -822,6 +822,21 @@
if not isinstance(w_literals, W_List):
raise SchemeSyntaxError
+ literals_map = {}
+ while isinstance(w_literals, W_Pair):
+ if not isinstance(w_literals.car, W_Symbol):
+ raise SchemeSyntaxError
+
+ literal_name = w_literals.car.to_string()
+ try:
+ w_temp = ctx.get(literal_name)
+ except UnboundVariable:
+ w_temp = w_literals.car
+
+ literals_map[literal_name] = w_temp
+
+ w_literals = w_literals.cdr
+
w_syntax_lst = lst.cdr
syntax_lst = []
while isinstance(w_syntax_lst, W_Pair):
@@ -833,46 +848,64 @@
w_template = w_syntax.get_cdr_as_pair().car
#do stuff with w_syntax rules
- syntax_lst.append(SyntaxRule(w_pattern, w_template))
+ syntax_lst.append(SyntaxRule(w_pattern, w_template, literals_map))
w_syntax_lst = w_syntax_lst.cdr
- return W_Transformer(syntax_lst)
+ return W_Transformer(syntax_lst, ctx)
class SyntaxRule(object):
- def __init__(self, pattern, template):
+ def __init__(self, pattern, template, literals):
self.pattern = pattern
self.template = template
+ self.literals = literals
def __str__(self):
return self.pattern.to_string() + " -> " + self.template.to_string()
- def match(self, w_expr):
+ def match(self, w_expr, ctx):
w_patt = self.pattern
+ match_dict = {}
while isinstance(w_patt, W_Pair):
if w_expr is w_nil:
- return False
+ return (False, None)
+
+ w_literal = self.literals.get(w_patt.car.to_string(), None)
+ if w_literal is not None:
+ try:
+ w_form = ctx.get(w_expr.car.to_string())
+ except UnboundVariable:
+ w_form = w_expr.car
- if isinstance(w_patt, W_Symbol) and not isinstance(w_expr, W_Symbol):
- return False
+ if w_form is not w_literal:
+ return (False, None)
+ match_dict[w_patt.car.to_string()] = w_expr.car.to_string()
w_patt = w_patt.cdr
w_expr = w_expr.cdr
if w_expr is w_nil:
- return True
+ return (True, match_dict)
- return False
+ return (False, None)
class W_Transformer(W_Procedure):
- def __init__(self, syntax_lst, pname=""):
+ def __init__(self, syntax_lst, ctx, pname=""):
self.pname = pname
self.syntax_lst = syntax_lst
+ self.match_dict = {}
+ self.closure = ctx
+
+ def match(self, w_expr, ctx=None):
+ if ctx is None:
+ ctx = self.closure
- def match(self, w_expr):
for rule in self.syntax_lst:
- if rule.match(w_expr):
+ (matched, temp_dict) = rule.match(w_expr, ctx)
+ if matched:
+ self.match_dict = temp_dict
return rule.template
+ self.match_dict = {}
return False
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 Mon Jul 23 17:53:53 2007
@@ -29,4 +29,45 @@
assert w_transformer.match(w_expr).to_boolean()
w_expr = parse("(foo bar)")[0]
assert w_transformer.match(w_expr).to_string() == "foo"
+ assert w_transformer.match_dict["foo"] == "bar"
+
+ w_expr = parse("(foo bar boo)")[0]
+ assert not w_transformer.match(w_expr)
+ assert w_transformer.match_dict == {}
+
+def test_syntax_rules_literals():
+ ctx = ExecutionContext()
+
+ # => is literal, should be matched exactly
+ # w_transformer created in ctx
+ w_transformer = eval_expr(ctx, "(syntax-rules (=>) ((foo => bar) #t))")
+
+ w_expr = parse("(foo bar boo)")[0]
+ assert not w_transformer.match(w_expr, ctx)
+
+ # exact match
+ w_expr = parse("(foo => boo)")[0]
+
+ # within the same context
+ assert w_transformer.match(w_expr, ctx)
+
+ w_42 = W_Number(42)
+
+ # different lexical scope, not the same bindings for => in ctx and closure
+ closure = ctx.copy()
+ closure.put("=>", w_42)
+ w_transformer = eval_expr(ctx, "(syntax-rules (=>) ((foo => bar) #t))")
+ assert not w_transformer.match(w_expr, closure)
+
+ # 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_expr(ctx, "(syntax-rules (=>) ((foo => bar) #t))")
+ assert not w_transformer.match(w_expr, closure)
+
+ # the same binding for => in ctx and closure
+ ctx.put("=>", w_42)
+ assert ctx.get("=>") is closure.get("=>")
+ w_transformer = eval_expr(ctx, "(syntax-rules (=>) ((foo => bar) #t))")
+ assert w_transformer.match(w_expr, closure)
More information about the Pypy-commit
mailing list