diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2018-03-13 20:23:18 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2018-03-13 20:23:18 -0700 |
commit | d32527312c4467817eef8527907fccb3cc5ed42a (patch) | |
tree | 81a176256dbb27e6e58ea3038631029dd6b3676f /eval.c | |
parent | f3fddb31b01d7f015d9f35b6c6312fad28177ae4 (diff) | |
download | txr-d32527312c4467817eef8527907fccb3cc5ed42a.tar.gz txr-d32527312c4467817eef8527907fccb3cc5ed42a.tar.bz2 txr-d32527312c4467817eef8527907fccb3cc5ed42a.zip |
expander bug: sequential vars with no init forms.
The test case for this is (let* (a (b a))) which raises
suspicion by diagnosing an "unbound variable a" error against
the (b a) var-init pair. The error goes away if we make it
(let* ((a nil) (b a))), a perfectly equivalent form. The
diagnostic is just a symptom; the problem is that in the case
when a doesn't have an initform, the (b a) var-init pair is
being incorrectly expanded in an environment that hasn't been
extended with the a variable.
* eval.c (expand_vars): In the sequential binding situation
(let*), we must extend the environment for each variable in
the no-init-form case exactly as we do in the with-init-form
case.
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 3 |
1 files changed, 2 insertions, 1 deletions
@@ -3355,7 +3355,8 @@ static val expand_vars(val vars, val menv, val form, int seq_p) return vars; } else if (symbolp(sym = car(vars))) { val rest_vars = rest(vars); - val rest_vars_ex = expand_vars(rest_vars, menv, form, seq_p); + val menv_new = seq_p ? make_var_shadowing_env(menv, cons(sym, nil)) : menv; + val rest_vars_ex = expand_vars(rest_vars, menv_new, form, seq_p); if (!bindable(sym)) not_bindable_error(form, sym); |