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

jlg at codespeak.net jlg at codespeak.net
Wed Aug 15 16:10:29 CEST 2007


Author: jlg
Date: Wed Aug 15 16:10:28 2007
New Revision: 45681

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:
macros handles now zero length match for ellipsis

Modified: pypy/dist/pypy/lang/scheme/TODO.txt
==============================================================================
--- pypy/dist/pypy/lang/scheme/TODO.txt	(original)
+++ pypy/dist/pypy/lang/scheme/TODO.txt	Wed Aug 15 16:10:28 2007
@@ -25,4 +25,5 @@
 - input/output operations
 - missing datatypes: chars, strings, vectors
 - switch to byte-code generation + eval instead of evaluating AST
+- random code stress test
 

Modified: pypy/dist/pypy/lang/scheme/object.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/object.py	(original)
+++ pypy/dist/pypy/lang/scheme/object.py	Wed Aug 15 16:10:28 2007
@@ -1218,18 +1218,15 @@
                 return mdict_car
 
             if w_expr is w_nil:
-                #one matched to ellipsis
+                #one matched to ellipsis, previous (up) w_expr.car
                 if w_pattcar is w_ellipsis:
                     raise EllipsisPattern
 
                 #zero matched to ellipsis
                 if isinstance(w_pattcdr, W_Pair) and \
                         w_pattcdr.car is w_ellipsis:
-                    if not isinstance(w_pattcar, W_Symbol):
-                        #XXX this must be added (with tests)
-                        #print w_patt, "matched to ()"
-                        raise NotImplementedError
-                    return {w_pattcar.name: Ellipsis([])}
+                    #all symbols from w_pattcar match zero length Ellipsis
+                    return self.dict_traverse_expr(w_pattcar, Ellipsis([]))
 
         if w_patt is w_ellipsis:
             raise EllipsisPattern
@@ -1260,6 +1257,18 @@
         # or w_patt is W_Pair but w_expr is not
         raise MatchError
 
+    def dict_traverse_expr(self, expr, val=None):
+        if isinstance(expr, W_Pair):
+            dict_car = self.dict_traverse_expr(expr.car, val)
+            dict_cdr = self.dict_traverse_expr(expr.cdr, val)
+            dict_car.update(dict_cdr)
+            return dict_car
+
+        if isinstance(expr, W_Symbol) and not expr is w_ellipsis:
+            return {expr.name: val}
+
+        return {}
+
 class SymbolClosure(W_Symbol):
     def __init__(self, ctx, symbol):
         assert isinstance(symbol, W_Symbol)
@@ -1344,6 +1353,8 @@
         return {}
 
     def plst_append(self, plst, w_cdr=None):
+        if len(plst) == 0:
+            return w_cdr
         first_cons = plst[0]
 
         last_cons = None

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	Wed Aug 15 16:10:28 2007
@@ -332,6 +332,7 @@
     assert eval_(ctx, "(or 12)").to_number() == 12
     assert eval_(ctx, "(or 12 42)").to_number() == 12
     
+    assert eval_(ctx, "(or #f 42)").to_number() == 42
     assert eval_(ctx, "(or #f #f 82)").to_number() == 82
     assert eval_(ctx, "(or #f #f #f 162)").to_number() == 162
 
@@ -455,6 +456,49 @@
     # pattern should be ignored during matching and not be a pattern
     # variable.  But MIT-Scheme disagrees with me...
 
+def test_ellipsis_nil():
+    ctx = ExecutionContext()
+    eval_(ctx, """(define-syntax or (syntax-rules ()
+                                      ((or) #f)
+                                      ((or e1 e2 ...)
+                                       (let ((temp e1))
+                                         (if temp
+                                             temp
+                                             (or e2 ...))))))""")
+
+    #here <e2 ...> should match zero elements
+    assert eval_(ctx, "(or 12)").to_number() == 12
+    assert eval_(ctx, "(or #f)").to_boolean() is False
+    assert eval_(ctx, "(or #f 42)").to_number() == 42
+    assert eval_(ctx, "(or #f #f 82)").to_number() == 82
+    assert eval_(ctx, "(or #f #f #f 162)").to_number() == 162
+
+def test_ellipsis_nested_nil():
+    ctx = ExecutionContext()
+    eval_(ctx, """(define-syntax or (syntax-rules ()
+                                      ((or) #f)
+                                      ((or (e1) (e2 ...) ...)
+                                       (let ((temp e1))
+                                         (if temp
+                                             temp
+                                             (or (e2) ... ...))))))""")
+
+    assert eval_(ctx, "(or (12))").to_number() == 12
+    assert eval_(ctx, "(or (#f))").to_boolean() is False
+    assert eval_(ctx, "(or (#f) (42))").to_number() == 42
+    assert eval_(ctx, "(or (#f) (#f) (82))").to_number() == 82
+    assert eval_(ctx, "(or (#f) (#f) (#f) (162))").to_number() == 162
+
+    #here scheme48 does not agree with me, it expands to:
+    # (let ((temp #f))
+    #   (if temp
+    #       temp
+    #       (or (#f #f 162))))
+    #       ^ this should be (my and mzscheme opinion)
+    #       (or (#f) (#f) (162))))
+    assert eval_(ctx, "(or (#f) (#f #f 162))").to_number() == 162
+    assert eval_(ctx, "(or (#f) (#f #f) (#f #f 322))").to_number() == 322
+
 # some tests from http://sisc-scheme.org/r5rs_pitfall.scm
 def test_pitfall_3_1():
     w_result = eval_noctx("""(let-syntax ((foo (syntax-rules ()
@@ -490,4 +534,3 @@
 def test_pitfall_3_4():
     w_result = eval_noctx("(let-syntax ((x (syntax-rules ()))) 1)")
     assert w_result.to_number() == 1
-



More information about the Pypy-commit mailing list