From 5b0ee1a4dcdad30c4554a9aaa17600ae3e8073d7 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Fri, 20 Jun 2014 07:49:04 -0700 Subject: 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. --- ChangeLog | 15 +++++++++++++++ eval.c | 14 ++++++++++++++ parser.y | 26 +++++++++++++++++++++++--- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 52cad4b0..597c1950 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2014-06-20 Kaz Kylheku + + 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 Optimization: add missing tail updates to some list 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 if_clause elif_clauses_opt else_clause_opt %type line elems_opt elems clause_parts_h additional_parts_h %type text texts elem var var_op modifiers vector hash -%type list exprs exprs_opt expr n_exprs n_expr +%type list exprs exprs_opt expr n_exprs n_expr n_exprs_opt %type out_clauses out_clauses_opt out_clause %type repeat_clause repeat_parts_opt o_line -%type o_elems_opt o_elems o_elem o_var rep_elem rep_parts_opt +%type o_elems_opt o_elems o_elem o_var q_var rep_elem rep_parts_opt %type regex lisp_regex regexpr regbranch %type regterm regtoken regclass regclassterm regrange %type 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); } -- cgit v1.2.3