From a9e06b4e815240f7f954d237f8625c30338be55f Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Fri, 28 Feb 2014 00:56:33 -0800 Subject: 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. --- eval.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'eval.c') diff --git a/eval.c b/eval.c index bc01cdf3..a5b5aba5 100644 --- a/eval.c +++ b/eval.c @@ -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); -- cgit v1.2.3