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

jlg at codespeak.net jlg at codespeak.net
Wed Jul 18 19:22:40 CEST 2007


Author: jlg
Date: Wed Jul 18 19:22:39 2007
New Revision: 45192

Modified:
   pypy/dist/pypy/lang/scheme/object.py
   pypy/dist/pypy/lang/scheme/test/test_eval.py
Log:
unquote-splicing added

Modified: pypy/dist/pypy/lang/scheme/object.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/object.py	(original)
+++ pypy/dist/pypy/lang/scheme/object.py	Wed Jul 18 19:22:39 2007
@@ -720,9 +720,9 @@
             raise SchemeSyntaxError
 
         if isinstance(w_lst, W_Pair):
-            w_car = w_lst.car
-            if isinstance(w_car, W_Identifier):
-                if w_car.to_string() == "unquote":
+            w_oper = w_lst.car
+            if isinstance(w_oper, W_Identifier):
+                if w_oper.to_string() == "unquote":
                     if deep == 1:
                         return w_lst.get_cdr_as_pair().car.eval(ctx)
 
@@ -731,17 +731,54 @@
                                 w_lst.get_cdr_as_pair().car,
                                 deep-1)
 
-                        return W_Pair(w_car, W_Pair(w_unq, W_Nil()))
+                        return W_Pair(w_oper, W_Pair(w_unq, W_Nil()))
 
-                if w_car.to_string() == "quasiquote":
+                if w_oper.to_string() == "quasiquote":
                     w_unq = self.unquote(ctx,
                             w_lst.get_cdr_as_pair().car,
                             deep+1)
-                    return W_Pair(w_car, W_Pair(w_unq, W_Nil()))
+                    return W_Pair(w_oper, W_Pair(w_unq, W_Nil()))
 
-            return W_Pair(self.unquote(ctx, w_car, deep),
+                if w_oper.to_string() == "unquote-splicing":
+                    if deep > 1:
+                        w_unq = self.unquote(ctx,
+                                w_lst.get_cdr_as_pair().car,
+                                deep-1)
+
+                        return W_Pair(w_oper, W_Pair(w_unq, W_Nil()))
+
+            #for unquote-splice we need to check one level earlier
+            #cond = if we have w_oper = (unquote-splice <sexpr>)
+            if deep == 1 and isinstance(w_oper, W_Pair) and \
+                    isinstance(w_oper.car, W_Identifier) and \
+                    w_oper.car.to_string() == "unquote-splicing":
+
+                #rest of list, needed for "stripping away" closing parens
+                w_unq_cdr = self.unquote(ctx, w_lst.cdr, deep)
+
+                #unquote into list
+                w_unq = w_oper.get_cdr_as_pair().car.eval(ctx)
+                #w_unq must be proper list
+                if isinstance(w_unq, W_Nil):
+                    #if nil: reeturn only rest of list
+                    return w_unq_cdr
+
+                #traverse w_unq to find last cdr and set it to w_cdr
+                w_pair = w_unq
+                while isinstance(w_pair, W_Pair):
+                    if isinstance(w_pair.cdr, W_Nil):
+                        w_pair.cdr = w_unq_cdr
+                        break
+
+                    w_pair = w_pair.cdr
+
+                return w_unq
+
+            #no special cases, traverse tree
+            return W_Pair(self.unquote(ctx, w_oper, deep),
                     self.unquote(ctx, w_lst.cdr, deep))
 
+        #trivial case, just return
         return w_lst
 
 class Delay(W_Macro):

Modified: pypy/dist/pypy/lang/scheme/test/test_eval.py
==============================================================================
--- pypy/dist/pypy/lang/scheme/test/test_eval.py	(original)
+++ pypy/dist/pypy/lang/scheme/test/test_eval.py	Wed Jul 18 19:22:39 2007
@@ -606,3 +606,16 @@
     assert w_res.to_string() == \
         "(a (quasiquote (b (unquote x) (unquote (quote y)) d)) e)"
 
+def test_quasiquote_splicing():
+    w_res = eval_noctx("""`(1 2 ,@(list 3 4) 5 6)""")
+    assert w_res.to_string() == "(1 2 3 4 5 6)"
+
+    w_res = eval_noctx("""`(1 2 ,@(list 3 4) . ,(+ 2 3))""")
+    assert w_res.to_string() == "(1 2 3 4 . 5)"
+
+    w_res = eval_noctx("""`(( foo  7) ,@(cdr '(c)) . ,(car '(cons)))""")
+    assert w_res.to_string() == "((foo 7) . cons)"
+
+def test_quasiquote_splicing2():
+    w_res = eval_noctx("""`(1 `(2 ,@(list ,@(list 3 4) 5 6 ,(+ 0 7))))""")
+    assert w_res.to_string() == "(1 (quasiquote (2 (unquote-splicing (list 3 4 5 6 7)))))"



More information about the Pypy-commit mailing list