From 3bcad308dba9cbe1ee6e66fc405e479c29992567 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Tue, 18 Jan 2022 07:50:17 -0800 Subject: quasiquote: make new @,expr work in dot position. Bugfix: the newly introduced @.expr fails in the dotted position because ^(a . @,expr) turns into (list 'a 'let ...). * eval.c (is_meta_unquote): New static function. (expand_qquote_rec): Replace existing shape test with is_meta_unquote. We must also use this test in one more place: whenever the cdr of a list has the meta unquote shape, we must treat the result similarly to a dotted atom, by converting to append format. * tests/010/qquote.tl: Test cases to cover this. --- eval.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'eval.c') diff --git a/eval.c b/eval.c index 41777807..a1c6b8b4 100644 --- a/eval.c +++ b/eval.c @@ -3642,6 +3642,14 @@ static val optimize_qquote(val form) return optimize_qquote_args(optimize_qquote_form(form)); } +static val is_meta_unquote(val args, val unq) +{ + val uqform; + return tnil(consp(args) && !cdr(args) && + consp((uqform = car(args))) && + car(uqform) == unq && consp(cdr(uqform)) && !cddr(uqform)); +} + static val expand_qquote(val qquoted_form, val qq, val unq, val spl); static val expand_qquote_rec(val qquoted_form, val qq, val unq, val spl) @@ -3661,7 +3669,6 @@ static val expand_qquote_rec(val qquoted_form, val qq, val unq, val spl) return cons(quote_s, cons(qquoted_form, nil)); } else { val sym = car(qquoted_form); - val args, uqform; if (sym == spl) { val error_msg = if3(spl == sys_splice_s, @@ -3692,12 +3699,9 @@ static val expand_qquote_rec(val qquoted_form, val qq, val unq, val spl) val opts = expand_qquote(second(qquoted_form), qq, unq, spl); val keys = expand_qquote(rest(rest(qquoted_form)), qq, unq, spl); return rlcp(list(tree_construct_s, opts, keys, nao), qquoted_form); - } else if (sym == expr_s && consp((args = cdr(qquoted_form))) - && !cdr(args) && consp((uqform = car(args))) && - car(uqform) == unq && consp(cdr(uqform)) && !cddr(uqform)) - { + } else if (sym == expr_s && is_meta_unquote(cdr(qquoted_form), unq)) { val gs = gensym(nil); - val ret = list(let_s, cons(list(gs, cadr(uqform), nao), nil), + val ret = list(let_s, cons(list(gs, cadadr(qquoted_form), nao), nil), list(if_s, list(atom_s, gs, nao), list(list_s, list(quote_s, var_s, nao), gs, nao), @@ -3730,7 +3734,10 @@ static val expand_qquote_rec(val qquoted_form, val qq, val unq, val spl) if (nilp(r_ex)) { return rlcp_tree(cons(append_s, cons(f_ex, nil)), qquoted_form); - } else if (atom(r_ex)) { + } else if (atom(r_ex) || + (consp(r) && car(r) == expr_s && + is_meta_unquote(cdr(r), unq))) + { return rlcp_tree(cons(append_s, cons(f_ex, cons(r_ex, nil))), qquoted_form); } else { if (consp(r) && car(r) == unq) -- cgit v1.2.3