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

jlg at codespeak.net jlg at codespeak.net
Thu Jul 26 17:27:54 CEST 2007


Author: jlg
Date: Thu Jul 26 17:27:54 2007
New Revision: 45351

Modified:
   pypy/dist/pypy/lang/scheme/execution.py
   pypy/dist/pypy/lang/scheme/object.py
   pypy/dist/pypy/lang/scheme/test/test_macro.py
Log:
DefineSyntax and W_DerivedMacro (should not be first class object); now we can define simple macros; W_Transformer can be evaluated

Modified: pypy/dist/pypy/lang/scheme/execution.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/execution.py	(original)
+++ pypy/dist/pypy/lang/scheme/execution.py	Thu Jul 26 17:27:54 2007
@@ -53,6 +53,7 @@
         'quote': Quote,
         'quasiquote': QuasiQuote,
         'syntax-rules': SyntaxRules,
+        'define-syntax': DefineSyntax,
     }
 
 OPERATION_MAP = {}
@@ -83,9 +84,11 @@
     def _dispatch(self, symb):
         if isinstance(symb, W_Symbol):
             return (self, symb.name)
-        elif isinstance(symb, SyntacticClosure) and \
-                isinstance(symb.sexpr, W_Symbol):
-            return (symb.closure, symb.sexpr.name)
+
+        elif isinstance(symb, SyntacticClosure):
+            symbol = symb.sexpr
+            if isinstance(symbol, W_Symbol):
+                return (symb.closure, symbol.name)
 
         raise SchemeSyntaxError
 

Modified: pypy/dist/pypy/lang/scheme/object.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/object.py	(original)
+++ pypy/dist/pypy/lang/scheme/object.py	Thu Jul 26 17:27:54 2007
@@ -811,6 +811,9 @@
 
         return W_Promise(lst.car, ctx)
 
+##
+# DerivedMacros
+##
 class SyntaxRules(W_Macro):
     def call(self, ctx, lst):
         if not isinstance(lst, W_Pair):
@@ -869,36 +872,35 @@
             w_patt = pattern
 
         match_dict = {}
-        while isinstance(w_patt, W_Pair):
-            if w_expr is w_nil:
-                return (False, {})
+        while isinstance(w_patt, W_Pair) and isinstance(w_expr, W_Pair):
             w_pattcar = w_patt.car
+            w_exprcar = 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_expr.car.to_string())
+                    w_form = ctx.get(w_exprcar.to_string())
                 except UnboundVariable:
-                    w_form = w_expr.car
+                    w_form = w_exprcar
 
                 if w_form is not w_literal:
                     return (False, {})
 
             if isinstance(w_pattcar, W_Pair):
-                if not isinstance(w_expr.car, W_Pair):
+                if not isinstance(w_exprcar, W_Pair):
                     return (False, {})
 
-                (matched, match_nested) = self.match(w_expr.car, ctx, w_pattcar)
+                (matched, match_nested) = self.match(w_exprcar, ctx, w_pattcar)
                 if not matched:
                     return (False, {})
 
                 match_dict.update(match_nested)
 
-            match_dict[w_pattcar.to_string()] = w_expr.car
+            match_dict[w_pattcar.to_string()] = w_exprcar
             w_patt = w_patt.cdr
             w_expr = w_expr.cdr
 
-        if w_expr is w_nil:
+        if w_expr is w_nil and w_patt is w_nil:
             return (True, match_dict)
 
         return (False, {})
@@ -964,8 +966,35 @@
         #we have lexical scopes:
         # 1. in which macro was defined - self.closure
         # 2. in which macro is called   - ctx
-        # 3. in which macro is expanded, and can introduce new bindings - expand_ctx 
+        # 3. in which macro is expanded, can introduce new bindings - expand_ctx 
         expanded = self.expand(sexpr, ctx)
         expand_ctx = self.closure.copy()
         return expanded.eval(expand_ctx)
 
+    def procedure(self, ctx, lst):
+        return self.expand_eval(lst[0], ctx)
+
+class DefineSyntax(W_Macro):
+    def call(self, ctx, lst):
+        if not isinstance(lst, W_Pair):
+            raise SchemeSyntaxError
+
+        w_def = lst.car
+        if not isinstance(w_def, W_Symbol):
+            raise SchemeSyntaxError
+
+        w_syntax_rules = lst.get_cdr_as_pair().car
+        w_transformer = w_syntax_rules.eval(ctx)
+        assert isinstance(w_transformer, W_Transformer)
+
+        w_macro = W_DerivedMacro(w_def.name, w_transformer)
+        ctx.set(w_def.name, w_macro)
+        return w_macro
+ 
+class W_DerivedMacro(W_Macro):
+    def __init__(self, name, transformer):
+        self.name = name
+        self.transformer = transformer
+
+    def call(self, ctx, lst):
+        return self.transformer.expand_eval(W_Pair(W_Symbol(self.name), lst), ctx)

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 Jul 26 17:27:54 2007
@@ -147,7 +147,7 @@
                                       (letrec ((loop
                                        (lambda (counter)
                                          (if (= counter 0)
-                                             ()
+                                             #f
                                              (begin
                                                 body
                                                 (loop (- counter 1)))))))
@@ -174,3 +174,26 @@
     eval_(ctx, "(define test 7)")
     assert w_transformer.expand_eval(w_expr, ctx).to_number() == 5
 
+def test_transformer_eval():
+    ctx = ExecutionContext()
+    eval_(ctx, """(define foo (syntax-rules ()
+                                     ((_) #t)
+                                     ((_ bar) bar)))""")
+
+    w_foo = eval_(ctx, "(foo '(_))")
+    assert w_foo.to_boolean()
+
+    w_foobar = eval_(ctx, """(foo '(_ 42))""")
+    assert w_foobar.to_number() == 42
+
+def test_define_syntax():
+    ctx = ExecutionContext()
+    eval_(ctx, """(define-syntax foo (syntax-rules ()
+                                     ((_) #t)
+                                     ((_ bar) bar)))""")
+    w_foo = eval_(ctx, """(foo)""")
+    assert w_foo.to_boolean()
+
+    w_foobar = eval_(ctx, """(foo 42)""")
+    assert w_foobar.to_number() == 42
+



More information about the Pypy-commit mailing list