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

jlg at codespeak.net jlg at codespeak.net
Mon Jul 30 16:23:31 CEST 2007


Author: jlg
Date: Mon Jul 30 16:23:30 2007
New Revision: 45437

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:
let-syntax introduced

Modified: pypy/dist/pypy/lang/scheme/execution.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/execution.py	(original)
+++ pypy/dist/pypy/lang/scheme/execution.py	Mon Jul 30 16:23:30 2007
@@ -54,6 +54,7 @@
         'quasiquote': QuasiQuote,
         'syntax-rules': SyntaxRules,
         'define-syntax': DefineSyntax,
+        'let-syntax': LetSyntax,
     }
 
 OPERATION_MAP = {}

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 30 16:23:30 2007
@@ -592,7 +592,7 @@
         if isinstance(w_first, W_Symbol):
             w_val = w_second.car.eval(ctx)
             ctx.set(w_first.name, w_val)
-            return w_val #unspec
+            return w_val #undefined
         elif isinstance(w_first, W_Pair):
             #we have lambda definition here!
             w_name = w_first.car
@@ -603,7 +603,7 @@
             body = w_second
             w_lambda = W_Lambda(formals, body, ctx, pname=w_name.name)
             ctx.set(w_name.name, w_lambda)
-            return w_lambda #unspec
+            return w_lambda #undefined
         else:
             raise WrongArgType(w_first, "Identifier")
 
@@ -617,7 +617,7 @@
 
         w_val = lst.get_cdr_as_pair().car.eval(ctx)
         ctx.sete(w_identifier.name, w_val)
-        return w_val #unspec
+        return w_val #undefined
 
 class MacroIf(W_Macro):
     def call_tr(self, ctx, lst):
@@ -991,9 +991,9 @@
             
     def expand_eval(self, ctx, sexpr):
         #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, can introduce new bindings - expand_ctx 
+        # 1. macro was defined - self.closure
+        # 2. macro is called   - ctx
+        # 3. macro is expanded, can introduce new bindings - expand_ctx
         expanded = self.expand(ctx, sexpr)
         expand_ctx = self.closure.copy()
         return expanded.eval(expand_ctx)
@@ -1012,11 +1012,12 @@
 
         w_syntax_rules = lst.get_cdr_as_pair().car
         w_transformer = w_syntax_rules.eval(ctx)
-        assert isinstance(w_transformer, W_Transformer)
+        if not isinstance(w_transformer, W_Transformer):
+            raise SchemeSyntaxError
 
         w_macro = W_DerivedMacro(w_def.name, w_transformer)
         ctx.set(w_def.name, w_macro)
-        return w_macro
+        return w_macro #undefined
  
 class W_DerivedMacro(W_Macro):
     def __init__(self, name, transformer):
@@ -1027,8 +1028,34 @@
         return "#<derived-macro %s>" % (self.name,)
 
     def call(self, ctx, lst):
-        return self.transformer.expand_eval(ctx, W_Pair(W_Symbol(self.name), lst))
+        return self.transformer.expand_eval(ctx,
+                W_Pair(W_Symbol(self.name), lst))
 
     def expand(self, ctx, lst):
         return self.transformer.expand(ctx, lst)
 
+class LetSyntax(W_Macro):
+    def call_tr(self, ctx, lst):
+        #let uses eval_body, so it is tail-recursive aware
+        if not isinstance(lst, W_Pair):
+            raise SchemeSyntaxError
+        local_ctx = ctx.copy()
+        w_formal = lst.car
+        while isinstance(w_formal, W_Pair):
+            w_def = w_formal.get_car_as_pair()
+            #evaluate the values in caller ctx
+            w_transformer = w_def.get_cdr_as_pair().car.eval(ctx)
+            if not isinstance(w_transformer, W_Transformer):
+                raise SchemeSyntaxError
+
+            w_name = w_def.car
+            if not isinstance(w_name, W_Symbol):
+                raise SchemeSyntaxError
+
+            w_macro = W_DerivedMacro(w_name.name, w_transformer)
+
+            local_ctx.put(w_name.name, w_macro)
+            w_formal = w_formal.cdr
+
+        return self.eval_body(local_ctx, lst.cdr)
+

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 30 16:23:30 2007
@@ -226,3 +226,18 @@
     assert eval_(ctx, "(my-or #f 42)").to_number() == 42
     assert eval_(ctx, "(my-or #f #f 82)").to_number() == 82
 
+def test_let_syntax():
+    ctx = ExecutionContext()
+    w_result = \
+        eval_(ctx, """(let-syntax ((foo (syntax-rules ()
+                                          ((foo) #t)
+                                          ((foo arg) arg)))
+                                   (bar (syntax-rules ()
+                                          ((bar) #f)
+                                          ((bar arg) arg))))
+                        (foo (bar (foo))))""")
+
+    assert w_result.to_boolean() is True
+    py.test.raises(UnboundVariable, ctx.get, "foo")
+    py.test.raises(UnboundVariable, ctx.get, "bar")
+



More information about the Pypy-commit mailing list