summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--eval.c14
-rw-r--r--parser.y26
3 files changed, 52 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 52cad4b0..597c1950 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,20 @@
2014-06-20 Kaz Kylheku <kaz@kylheku.com>
+ Bugfix: macros not being expanded in expansions embedded in
+ quasilierals: i.e. the forms X and Y in `@{X}`
+ and `@{X Y}`, where X and Y can be Lisp symbol macros or compound
+ forms that is a macro call.
+
+ * eval.c (expand_quasi): Handle the var forms in a quasi.
+
+ * parser.y (n_exprs_opt, q_var): New grammar nonterminals.
+ q_var is a clone of o_var, but with different construction behavior.
+ It fixes the bug that o_var applies expand_meta to embedded
+ Lisp forms, which is not appropriate for TXR Lisp quasiliterals.
+ (quasi_item): Derive q_var rather than o_var.
+
+2014-06-20 Kaz Kylheku <kaz@kylheku.com>
+
Optimization: add missing tail updates to some list
collecting loops.
diff --git a/eval.c b/eval.c
index c5e024ee..ec10d1e1 100644
--- a/eval.c
+++ b/eval.c
@@ -2219,6 +2219,20 @@ static val expand_quasi(val quasi_forms, val menv)
if (expr_ex != rest(form))
form_ex = rlcp(cons(sym, expr_ex), form);
+ } else if (sym == var_s) {
+ val param = second(form);
+ val next = third(form);
+ val mods = fourth(form);
+ val param_ex = expand(param, menv);
+ val mods_ex = expand_forms(mods, menv);
+
+ /* next should be nil because this structure should have
+ been passed through o_elemes_transform in the parser
+ which unravels the nesting. */
+ assert (next == nil);
+
+ if (param_ex != param || mods_ex != mods)
+ form_ex = rlcp(list(sym, param_ex, nil, mods_ex, nao), form);
}
}
diff --git a/parser.y b/parser.y
index 1266157d..be8e6063 100644
--- a/parser.y
+++ b/parser.y
@@ -95,10 +95,10 @@ static val parsed_spec;
%type <val> if_clause elif_clauses_opt else_clause_opt
%type <val> line elems_opt elems clause_parts_h additional_parts_h
%type <val> text texts elem var var_op modifiers vector hash
-%type <val> list exprs exprs_opt expr n_exprs n_expr
+%type <val> list exprs exprs_opt expr n_exprs n_expr n_exprs_opt
%type <val> out_clauses out_clauses_opt out_clause
%type <val> repeat_clause repeat_parts_opt o_line
-%type <val> o_elems_opt o_elems o_elem o_var rep_elem rep_parts_opt
+%type <val> o_elems_opt o_elems o_elem o_var q_var rep_elem rep_parts_opt
%type <val> regex lisp_regex regexpr regbranch
%type <val> regterm regtoken regclass regclassterm regrange
%type <val> strlit chrlit quasilit quasi_items quasi_item litchars wordslit
@@ -701,6 +701,22 @@ o_var : SYMTOK { $$ = list(var_s, sym_helper($1, nil), nao);
yybadtoken(yychar, lit("variable spec")); }
;
+q_var : SYMTOK { $$ = list(var_s, sym_helper($1, nil), nao);
+ rl($$, num(lineno)); }
+ | SYMTOK quasi_item { $$ = list(var_s, sym_helper($1, nil),
+ $2, nao);
+ rl($$, num(lineno)); }
+ | '{' n_expr n_exprs_opt '}'
+ { $$ = list(var_s, $2, nil, $3, nao);
+ rl($$, num(lineno)); }
+ | '{' n_expr n_exprs_opt '}' quasi_item
+ { $$ = list(var_s, $2, $5, $3, nao);
+ rl($$, num(lineno)); }
+ | SYMTOK error { $$ = nil;
+ yybadtoken(yychar, lit("variable spec")); }
+ ;
+
+
vector : '#' list { if (unquotes_occur($2, 0))
$$ = rlcp(cons(vector_lit_s,
cons($2, nil)), $2);
@@ -783,6 +799,10 @@ n_expr : SYMTOK { $$ = sym_helper($1, t); }
| SPLICE n_expr { $$ = rlcp(list(sys_splice_s, $2, nao), $2); }
;
+n_exprs_opt : n_exprs { $$ = $1; }
+ | /* empty */ { $$ = nil; }
+ ;
+
regex : '/' regexpr '/' { $$ = cons(regex_s, $2); end_of_regex();
rl($$, num(lineno)); }
| '/' error { $$ = nil;
@@ -926,7 +946,7 @@ quasi_items : quasi_item { $$ = cons($1, nil);
quasi_item : litchars { $$ = lit_char_helper($1); }
| TEXT { $$ = string_own($1); }
- | o_var { $$ = $1; }
+ | q_var { $$ = $1; }
| METANUM { $$ = cons(var_s, cons($1, nil));
rl($$, num(lineno)); }
| list { $$ = rlcp(cons(expr_s, $1), $1); }