From ca6199a0a48cba367ebc81e6d463c4e0a170f9c5 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 29 Mar 2018 06:17:17 -0700 Subject: eval: bugs/regressions in handling nil in param expansion. Due to a number of changes since December 2016, we have two problems in the evaluator: (lambda (nil)) is accepted rather than complaining that nil is not bindable; and (tree-bind (()) '(3)) silently proceeds rather than diagnosing that the atom 3 doesn't match the empty pattern (). * eval.c (expand_opt_params_rec, expand_params_rec): When not expandin macro-style params, check for a parameter not being bindable, and also avoid recursion entirely when not doing macro style. (bind_macro_params): Don't assume that an atom parameter is a variable, but rather tha a non-list parameter is a variable. Otherwise we bind nil rather than treating it as an empty sub-pattern. Before the December 2016 change (744340ab), we were checking bindablep here; the idea was to hoist the detailed checking to expansion time. But then the pattern versus variable distinction was bungled here. --- eval.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/eval.c b/eval.c index cbbcaeb7..77c8c4f3 100644 --- a/eval.c +++ b/eval.c @@ -914,14 +914,14 @@ static val expand_opt_params_rec(val params, val menv, return params; return rlcp(cons(pair, params_ex), cdr(params)); } - } else if (!macro_style_p && consp(car(pair))) { + } else if (!macro_style_p && !bindable(car(pair))) { eval_error(form, lit("~s: parameter symbol expected, not ~s"), car(form), car(pair), nao); } else { val param = car(pair); - val param_ex = expand_params_rec(param, menv, - macro_style_p, - form, pspecials); + val param_ex = if3(macro_style_p && consp(param), + expand_params_rec(param, menv, t, form, pspecials), + param); val initform = cadr(pair); val initform_ex = rlcp(expand(initform, menv), initform); val opt_sym = caddr(pair); @@ -987,9 +987,13 @@ static val expand_params_rec(val params, val menv, eval_error(form, lit("~s: ~s parameter requires bindable symbol"), car(form), param, nao); param_ex = param; - } else { - param_ex = expand_params_rec(param, menv, macro_style_p, form, pspecials); + } else if (macro_style_p && (nilp(param) || consp(param))) { + param_ex = expand_params_rec(param, menv, t, form, pspecials); new_menv = make_var_shadowing_env(menv, get_param_syms(param_ex)); + } else if (!bindable(param)) { + not_bindable_error(form, param); + } else { + param_ex = param; } { @@ -1232,7 +1236,7 @@ static val bind_macro_params(val env, val menv, val params, val form, goto noarg; } - if (atom(param)) { + if (!listp(param)) { env_vbind(new_env, param, car(form)); } else { if (optargs) { @@ -1276,7 +1280,7 @@ static val bind_macro_params(val env, val menv, val params, val form, } noarg: - if (atom(param)) { + if (!listp(param)) { env_vbind(new_env, param, nil); } else { val nparam = pop(¶m); -- cgit v1.2.3