[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