diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2018-03-29 06:17:17 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2018-03-29 06:17:17 -0700 |
commit | ca6199a0a48cba367ebc81e6d463c4e0a170f9c5 (patch) | |
tree | 9fa27a593d96121c6cc26eda15a39d87a92d44be | |
parent | ff3da7279363941f489e210983141f55bf2c9079 (diff) | |
download | txr-ca6199a0a48cba367ebc81e6d463c4e0a170f9c5.tar.gz txr-ca6199a0a48cba367ebc81e6d463c4e0a170f9c5.tar.bz2 txr-ca6199a0a48cba367ebc81e6d463c4e0a170f9c5.zip |
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.
-rw-r--r-- | eval.c | 20 |
1 files changed, 12 insertions, 8 deletions
@@ -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); |