summaryrefslogtreecommitdiffstats
path: root/eval.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-03-29 06:17:17 -0700
committerKaz Kylheku <kaz@kylheku.com>2018-03-29 06:17:17 -0700
commitca6199a0a48cba367ebc81e6d463c4e0a170f9c5 (patch)
tree9fa27a593d96121c6cc26eda15a39d87a92d44be /eval.c
parentff3da7279363941f489e210983141f55bf2c9079 (diff)
downloadtxr-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.
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c20
1 files 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(&param);