diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2014-02-28 00:56:33 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2014-02-28 00:56:33 -0800 |
commit | a9e06b4e815240f7f954d237f8625c30338be55f (patch) | |
tree | e8239869b0ea540e42b7083f95e3b60a61eff53b /eval.c | |
parent | 9caae19a42d87582a82c3d855b7dc59fe6427e7b (diff) | |
download | txr-a9e06b4e815240f7f954d237f8625c30338be55f.tar.gz txr-a9e06b4e815240f7f954d237f8625c30338be55f.tar.bz2 txr-a9e06b4e815240f7f954d237f8625c30338be55f.zip |
Bugfixing semantics of symbol macro hiding by variable bindings.
* eval.c (expand_vars): Expand vars needs to know whether it's
handling a sequential (let*-like) or parallel (let-like) binding.
The init form of a variable sees the previous macro environment,
but that variable must, for the remaining variables, shadow any
previous symbol macro.
(expand): In expand we must inform expand_vars whether we have
a sequential or parallel binding construct. Moreover, there was
a huge bug here: the new_menv (with the shadows) was passed to
expand_vars, so that all the variables were hiding same-named
symbol macros from all their initforms.
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 22 |
1 files changed, 16 insertions, 6 deletions
@@ -2070,7 +2070,8 @@ static val me_qquote(val form, val menv) return expand_qquote(second(form), menv); } -static val expand_vars(val vars, val menv, val form, val *spec_p) +static val expand_vars(val vars, val menv, val form, + val *spec_p, int seq_p) { val sym; @@ -2082,21 +2083,27 @@ static val expand_vars(val vars, val menv, val form, val *spec_p) return vars; } else if (special_p(sym = car(vars))) { val rest_vars = rest(vars); - val rest_vars_ex = rlcp(expand_vars(rest_vars, menv, form, spec_p), + val rest_vars_ex = rlcp(expand_vars(rest_vars, menv, form, spec_p, seq_p), rest_vars); val var_ex = cons(special_s, cons(nil, cons(sym, nil))); return rlcp(cons(var_ex, rest_vars_ex), vars); } else if (symbolp(sym)) { val rest_vars = rest(vars); - val rest_vars_ex = expand_vars(rest_vars, menv, form, spec_p); + val rest_vars_ex = expand_vars(rest_vars, menv, form, spec_p, seq_p); if (rest_vars == rest_vars_ex) return vars; return rlcp(cons(sym, rest_vars_ex), vars); } else { cons_bind (var, init, sym); val rest_vars = rest(vars); + /* This var's init form sees a previous symbol macro whose name is + the same as the variable, so menv is used. */ val init_ex = rlcp(expand_forms(init, menv), init); - val rest_vars_ex = rlcp(expand_vars(rest_vars, menv, form, spec_p), + /* The initforms of subsequent vars in a sequential binding + do not see a previous symbol macro; they see the var. */ + val menv_new = seq_p ? make_var_shadowing_env(menv, cons(var, nil)) : menv; + val rest_vars_ex = rlcp(expand_vars(rest_vars, menv_new, form, + spec_p, seq_p), rest_vars); if (special_p(var)) { @@ -2343,10 +2350,12 @@ tail: { val body = rest(rest(form)); val vars = second(form); + int seq_p = sym == let_star_s || sym == each_star_s || + sym == collect_each_star_s || sym == append_each_star_s; val new_menv = make_var_shadowing_env(menv, vars); val body_ex = expand_forms(body, new_menv); val specials_p = nil; - val vars_ex = expand_vars(vars, new_menv, form, &specials_p); + val vars_ex = expand_vars(vars, menv, form, &specials_p, seq_p); if (body == body_ex && vars == vars_ex && !specials_p) { return form; } else { @@ -2431,7 +2440,8 @@ tail: val incs = fourth(form); val forms = rest(rest(rest(rest(form)))); val specials_p = nil; - val vars_ex = expand_vars(vars, menv, form, &specials_p); + val vars_ex = expand_vars(vars, menv, form, &specials_p, + sym == for_star_s); val new_menv = make_var_shadowing_env(menv, vars); val cond_ex = expand_forms(cond, new_menv); val incs_ex = expand_forms(incs, new_menv); |