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

jlg at codespeak.net jlg at codespeak.net
Fri Aug 3 15:54:37 CEST 2007


Author: jlg
Date: Fri Aug  3 15:54:36 2007
New Revision: 45476

Modified:
   pypy/dist/pypy/lang/scheme/object.py
   pypy/dist/pypy/lang/scheme/test/test_macro.py
Log:
nested macros; but no support for (obj ... ...)

Modified: pypy/dist/pypy/lang/scheme/object.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/object.py	(original)
+++ pypy/dist/pypy/lang/scheme/object.py	Fri Aug  3 15:54:36 2007
@@ -336,9 +336,8 @@
 
         return self.eval_body(local_ctx, self.body)
 
-def plst2lst(plst):
+def plst2lst(plst, w_cdr=w_nil):
     """coverts python list() of W_Root into W_Pair scheme list"""
-    w_cdr = w_nil
     plst.reverse()
     for w_obj in plst:
         w_cdr = W_Pair(w_obj, w_cdr)
@@ -865,10 +864,16 @@
     def __init__(self, mdict_lst):
         self.mdict_lst = mdict_lst
 
+    def __repr__(self):
+        return "#<e: " + str(self.mdict_lst) + ">"
+
 class EllipsisException(SchemeException):
     def __init__(self, length):
         self.length = length
 
+class EllipsisTemplate(SchemeException):
+    pass
+
 class EllipsisPattern(SchemeException):
     pass
 
@@ -895,7 +900,6 @@
             w_pattcar = w_patt.car
             if isinstance(w_expr, W_Pair):
                 mdict_car = self.matchr(ctx, w_pattcar, w_expr.car)
-
                 try:
                     #we catch EllipsisPattern here because in car
                     # we dont know how to deal with it
@@ -915,6 +919,8 @@
                     for name in mdict_lst[0].keys():
                         mdict_cdr[name] = ellipsis
 
+                    return mdict_cdr
+
                 mdict_car.update(mdict_cdr)
                 return mdict_car
 
@@ -1008,6 +1014,97 @@
         return self.substitute(ctx, template, match_dict)
 
     def substitute(self, ctx, sexpr, match_dict, ellipsis_cnt=-1):
+        #return self.substitute_(ctx, sexpr, match_dict, -1)
+        return self.substituter(ctx, sexpr, match_dict)
+
+    def find_elli(self, expr, mdict):
+        if isinstance(expr, W_Pair):
+            edict_car = self.find_elli(expr.car, mdict)
+            edict_cdr = self.find_elli(expr.cdr, mdict)
+            edict_car.update(edict_cdr)
+            return edict_car
+
+        if isinstance(expr, W_Symbol):
+            val = mdict.get(expr.name, None)
+            if val is None:
+                return {}
+
+            if isinstance(val, Ellipsis):
+                return {expr.name: val}
+
+        return {}
+
+    def substituter(self, ctx, sexpr, match_dict):
+        if isinstance(sexpr, W_Pair):
+            w_car = self.substituter(ctx, sexpr.car, match_dict)
+            try:
+                w_cdr = self.substituter(ctx, sexpr.cdr, match_dict)
+            except EllipsisTemplate:
+                print "ellipsis expand", sexpr
+                try:
+                    w_cdr = self.substituter(ctx, sexpr.cdr.cdr, match_dict)
+                except EllipsisTemplate:
+                    raise NotImplementedError
+
+                plst = []
+                mdict_elli = self.find_elli(sexpr.car, match_dict)
+                elli_len = 0
+                for (key, val) in mdict_elli.items():
+                    elli_len = len(val.mdict_lst)
+
+                for i in range(elli_len):
+                    new_mdict = match_dict.copy()
+                    for (key, val) in mdict_elli.items():
+                        yyy = val.mdict_lst[i][key]
+                        new_mdict[key] = yyy
+
+                    print new_mdict
+                    zzz = self.substituter(ctx, sexpr.car, new_mdict)
+                    plst.append(zzz)
+
+                w_lst = plst2lst(plst, w_cdr)
+                return w_lst
+
+            w_pair = W_Pair(w_car, w_cdr)
+            if isinstance(w_car, W_Symbol):
+                #XXX what if we have here SymbolClosure?
+                # can happen when recursive macro
+                try:
+                    w_macro = ctx.get(w_car.name)
+                    # recursive macro expansion
+                    if isinstance(w_macro, W_DerivedMacro):
+                        return w_macro.expand(ctx, w_pair)
+                except UnboundVariable:
+                    pass
+
+            return w_pair
+
+        if isinstance(sexpr, W_Symbol):
+            if sexpr is w_ellipsis:
+                raise EllipsisTemplate
+
+            w_sub = match_dict.get(sexpr.name, None)
+            if w_sub is not None:
+                # Hygenic macros close their input forms in the syntactic
+                # enviroment at the point of use
+
+                if isinstance(w_sub, Ellipsis):
+                    return w_sub
+
+                #not always needed, because w_sub can have no W_Symbol inside
+                if isinstance(w_sub, W_Symbol) and \
+                        not isinstance(w_sub, SymbolClosure):
+                    return SymbolClosure(ctx, w_sub)
+
+                if isinstance(w_sub, W_Pair) and \
+                        not isinstance(w_sub, PairClosure):
+                    return PairClosure(ctx, w_sub)
+
+                return w_sub
+
+        return sexpr
+
+    def substitute_(self, ctx, sexpr, match_dict, ellipsis_cnt=-1):
         if isinstance(sexpr, W_Symbol):
             w_sub = match_dict.get(sexpr.name, None)
             if w_sub is not None:
@@ -1039,14 +1136,14 @@
         elif isinstance(sexpr, W_Pair):
             try:
                 w_pair = W_Pair(
-                    self.substitute(ctx, sexpr.car, match_dict, ellipsis_cnt),
-                    self.substitute(ctx, sexpr.cdr, match_dict, ellipsis_cnt))
+                    self.substitute_(ctx, sexpr.car, match_dict, ellipsis_cnt),
+                    self.substitute_(ctx, sexpr.cdr, match_dict, ellipsis_cnt))
             except EllipsisException, e:
                 scdr = sexpr.cdr
                 if isinstance(scdr, W_Pair) and scdr.car is w_ellipsis:
                     plst = []
                     for i in range(e.length):
-                        zzz = self.substitute(ctx, sexpr.car, match_dict, i)
+                        zzz = self.substitute_(ctx, sexpr.car, match_dict, i)
                         plst.append(zzz)
 
                     ellipsis = plst2lst(plst)

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	Fri Aug  3 15:54:36 2007
@@ -325,12 +325,12 @@
                                  (syntax-rules ()
                                     ((_ sym ...)
                                      (begin
-                                       (if sym (set! sym 0)) ...))))""")
+                                       (if sym (set! sym 0)) ... #t))))""")
 
     eval_(ctx, "(define x #t)")
     eval_(ctx, "(define y #f)")
     eval_(ctx, "(define z #t)")
-    eval_(ctx, "(zero-if-true x y z)")
+    assert eval_(ctx, "(zero-if-true x y z)").to_boolean() == True
     assert eval_(ctx, "x").to_number() == 0
     assert eval_(ctx, "y").to_boolean() is False
     assert eval_(ctx, "z").to_number() == 0
@@ -388,6 +388,18 @@
     assert eval_(ctx, "(let2 (x y z) (1 2 3) (+ x y z))").to_number() == 6
 
 def test_nested_ellipsis():
+    ctx = ExecutionContext()
+    eval_(ctx, """(define-syntax quote-lists
+                                 (syntax-rules ()
+                                    ((_ (obj ...) ...)
+                                     (quote ((obj ...) ... end)))))""")
+
+    assert eval_(ctx, """(quote-lists (x y)
+                                       (1 2 3 4)
+                                       (+))""").to_string() == \
+            "((x y) (1 2 3 4) (+) end)"
+
+def test_nested_ellipsis2():
     py.test.skip("in progress")
     ctx = ExecutionContext()
     eval_(ctx, """(define-syntax quote-append



More information about the Pypy-commit mailing list