summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--parser.y10
-rw-r--r--txr.126
3 files changed, 45 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index c4b12c7b..6c7dc43b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2011-12-02 Kaz Kylheku <kaz@kylheku.com>
+ * parser.y (list): unquote and splice actions look inside the
+ argument form. If an unquote or splice are applied to a quoted
+ form, its quote becomes a regular quote.
+ This behavior is necessary to make ,',form work in nested
+ quotes, otherwise the ' is a quasiquote which captures
+ the comma in ,form, reducing ,',form to ,form.
+
+ * txr.1: Documented this special behavior.
+
+2011-12-02 Kaz Kylheku <kaz@kylheku.com>
+
* eval.c (expand_qquote): Bugfix: removed bogus recognition
and processing of regular quote form. This broke nested
backquote processing, and quasiquote forms containing
diff --git a/parser.y b/parser.y
index affcd636..82fd9101 100644
--- a/parser.y
+++ b/parser.y
@@ -607,10 +607,16 @@ var_op : '*' { $$ = list(t, nao); }
list : '(' exprs ')' { $$ = rl($2, num($1)); }
| '(' ')' { $$ = nil; }
- | ',' expr { $$ = rlcp(list(unquote_s, $2, nao), $2); }
+ | ',' expr { val expr = $2;
+ if (consp(expr) && first(expr) == qquote_s)
+ expr = cons(quote_s, rest(expr));
+ $$ = rlcp(list(unquote_s, expr, nao), $2); }
| '\'' expr { $$ = rlcp(list(choose_quote($2),
$2, nao), $2); }
- | SPLICE expr { $$ = rlcp(list(splice_s, $2, nao), $2); }
+ | SPLICE expr { val expr = $2;
+ if (consp(expr) && first(expr) == qquote_s)
+ expr = cons(quote_s, rest(expr));
+ $$ = rlcp(list(splice_s, expr, nao), $2); }
| '(' error { $$ = nil;
yybadtoken(yychar, lit("list expression")); }
;
diff --git a/txr.1 b/txr.1
index 86877df4..808c7c9d 100644
--- a/txr.1
+++ b/txr.1
@@ -4225,6 +4225,10 @@ of the variable a.
Note that TXR Lisp does not have a distinct quote and backquote syntax.
There is only one quote, which supports unquoting.
+A quoted form which contains no unquotes codifies an ordinary quote.
+
+A quoted form which contains unquotes expresses a quasiquote.
+
.IP ,form
Thes comma character is used within a quoted list to denote an unquote. Wheras
@@ -4241,6 +4245,28 @@ the form which follows ,* must evaluate to a list. That list is spliced into
the quoted list. For example: '(a b c ,*(list (+ 3 3) (+ 4 4) d) evaluates
to (a b c 6 8 d). The expression (list (+ 3 3) (+ 4 4)) is evaluated
to produce the list (6 8), and this list is spliced into the quoted template.
+
+.IP ,'form
+
+The comma-quote combination has a special meaning: the quote always
+behaves as a regular quote and not a quasiquote, even if form contains
+unquotes. Therefore, it does not "capture" these unquotes: they cannot
+"belong" to this quote. The comma and quote "cancel out", so the only effect
+of comma-quote is to add one level of unquoting. So for instance, whereas in
+'(a b c '(,d)), the subsitution of d belongs to the inner quote (it is unquoted
+by the leftmost comma which belongs to the innermost quote) by contrast,
+in '(a b c '(,',d)) the d is now one comma removed from the leftmost comma and
+thus the substitution of d belongs to the outer quote.
+In other dialects of Lisp, this would be written `(a b c `(,',d)), making it
+explicit which kind of quote is being specified. TXR Lisp works out which
+kind of quote to use internally.
+
+.IP ,*'form
+
+The comma-splice form is analogous to comma-quote (see above). Like in the
+,' combination, in the ,*' combination, the quote behaves as a regular quote
+and not a quasiquote.
+
.PP
.SS Nested Quotes