From df9f85b3b720a9ebf7381b2cad7a9680ad0e31bf Mon Sep 17 00:00:00 2001 From: Kaz Kylheku <kaz@kylheku.com> Date: Sat, 26 Nov 2016 08:40:22 -0800 Subject: bugfix: quasilit read/print consistency, part 1. The bug is that `@@@a` prints as `@@a` which reads as a different object. In this patch we simplify how quasiliterals are represented. Embedded expressions are no longer (sys:expr E), just E. Meta-numbers N and variables V are still (sys:var N). However `@@a` and `@a` remain equivalent. * eval.c (subst_vars): No need to look for expr_s; just evaluate a compound form. The recursive nested case is unnecessary and is removed. (expand_quasi): Do nothandle expr_s; it is not part of the quasi syntax any more. * lib.c (out_quasi_str): Do not look for expr_s in the quasi syntax; just print any expression with a @ the fallback case. * match.c (tx_subst_vars): Analogous changes to those done in subst_vars in eval.c. * parser.y (quasi_meta_helper): Static function removed. This was responsible for the issue due to stripping a level of meta from expressions already having a meta on them. (quasi_item): In the `@` n_expr syntax case, no longer call quasi_meta_helper. The remaining logic is simple enough to put in line. Symbols and integers get wrapped with (sys:var ...); other expressions are integrated into the syntax as-is. --- eval.c | 15 +++------------ lib.c | 4 ++-- match.c | 11 +++-------- parser.y | 25 +++++-------------------- 4 files changed, 13 insertions(+), 42 deletions(-) diff --git a/eval.c b/eval.c index a5f74b5a..6fe12132 100644 --- a/eval.c +++ b/eval.c @@ -2365,19 +2365,14 @@ val subst_vars(val forms, val env, val filter) iter = list_collect_append(iter, nested); forms = cdr(forms); continue; - } else if (sym == expr_s) { - val str = eval(rest(form), env, form); + } else { + val str = eval(form, env, form); if (listp(str)) str = cat_str(mapcar(func_n1(tostringp), str), lit(" ")); else if (!stringp(str)) str = tostringp(str); forms = cons(filter_string_tree(filter, tostringp(str)), rest(forms)); continue; - } else { - val nested = subst_vars(form, env, filter); - iter = list_collect_append(iter, nested); - forms = cdr(forms); - continue; } } else if (bindable(form)) { forms = cons(cons(var_s, cons(form, nil)), cdr(forms)); @@ -2983,12 +2978,8 @@ static val expand_quasi(val quasi_forms, val menv) if (consp(form)) { val sym = car(form); - if (sym == expr_s) { - val expr_ex = expand(rest(form), menv); - if (expr_ex != rest(form)) - form_ex = rlcp(cons(sym, expr_ex), form); - } else if (sym == var_s) { + if (sym == var_s) { val param = second(form); val mods = third(form); val param_ex = expand(param, menv); diff --git a/lib.c b/lib.c index 641b7337..c510ba73 100644 --- a/lib.c +++ b/lib.c @@ -9481,9 +9481,9 @@ static void out_quasi_str(val args, val out, struct strm_ctx *ctx) } if (need_brace) put_char(chr('}'), out); - } else if (sym == expr_s) { + } else { put_char(chr('@'), out); - obj_print_impl(rest(elem), out, nil, ctx); + obj_print_impl(elem, out, nil, ctx); } } else { obj_print_impl(elem, out, nil, ctx); diff --git a/match.c b/match.c index d9df8764..93b84a07 100644 --- a/match.c +++ b/match.c @@ -1493,13 +1493,13 @@ static val tx_subst_vars(val spec, val bindings, val filter) iter = list_collect_append(iter, nested); spec = cdr(spec); continue; - } else if (sym == expr_s) { + } else { if (opt_compat && opt_compat < 100) { - val result = tleval(spec, rest(elem), bindings); + val result = tleval(spec, elem, bindings); spec = cons(filter_string_tree(filter, tostringp(result)), rest(spec)); continue; } else { - val str = tleval(spec, rest(elem), bindings); + val str = tleval(spec, elem, bindings); if (listp(str)) str = cat_str(mapcar(func_n1(tostringp), str), lit(" ")); else if (!stringp(str)) @@ -1507,11 +1507,6 @@ static val tx_subst_vars(val spec, val bindings, val filter) spec = cons(filter_string_tree(filter, tostringp(str)), rest(spec)); continue; } - } else { - val nested = tx_subst_vars(elem, bindings, filter); - iter = list_collect_append(iter, nested); - spec = cdr(spec); - continue; } } diff --git a/parser.y b/parser.y index 8d3e5a89..b54c7bf8 100644 --- a/parser.y +++ b/parser.y @@ -68,7 +68,6 @@ static val rlrec(parser_t *, val form, val line); static wchar_t char_from_name(const wchar_t *name); static val make_expr(parser_t *, val sym, val rest, val lineno); static val check_for_include(val spec_rev); -static val quasi_meta_helper(val obj); static void misplaced_consing_dot_check(scanner_t *scanner, val term_atom_cons); #if YYBISON @@ -1165,7 +1164,11 @@ quasi_item : litchars { $$ = lit_char_helper($1); } | q_var { $$ = $1; } | METANUM { $$ = cons(var_s, cons($1, nil)); rl($$, num(parser->lineno)); } - | '@' n_expr { $$ = quasi_meta_helper($2); } + | '@' n_expr { if (integerp($2) || symbolp($2)) + $$ = rlcp_tree(cons(var_s, cons($2, nil)), + $2); + else + $$ = $2; } ; litchars : LITCHAR { $$ = rl(cons(chr($1), nil), num(parser->lineno)); } @@ -1644,24 +1647,6 @@ static val check_for_include(val spec_rev) return spec_rev; } -static val quasi_meta_helper(val obj) -{ - if (integerp(obj) || symbolp(obj)) - goto var; - - if (atom(obj)) - goto expr; - - if (first(obj) == var_s || first(obj) == expr_s) - return obj; - -expr: - return rlcp(cons(expr_s, obj), obj); - -var: - return rlcp_tree(cons(var_s, cons(obj, nil)), obj); -} - static void misplaced_consing_dot_check(scanner_t *scanner, val term_atom_cons) { if (car(term_atom_cons) != unique_s) { -- cgit v1.2.3