[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