diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-11-24 05:57:03 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2016-11-24 05:57:03 -0800 |
commit | f756436525725e477b85768926f4ecbc4d9798e9 (patch) | |
tree | 6e9a4b1f086a36d7cf5d17ed847e16e73463acf9 /eval.c | |
parent | 780e22e8b957f7070009811523b2c7567b27b7c0 (diff) | |
download | txr-f756436525725e477b85768926f4ecbc4d9798e9.tar.gz txr-f756436525725e477b85768926f4ecbc4d9798e9.tar.bz2 txr-f756436525725e477b85768926f4ecbc4d9798e9.zip |
bugfix: macrolet args not included in macro env.
When the function bodies of macrolets are themselves
being macro-expanded, this is incorrectly being done in
the original macro environment without taking into account
the macrolet parameters which those bodies have in scope.
Hence the parameters are not able to shadow symbol macros.
* eval.c (make_var_shadowing_env): Moved above expand_macrolet
so we can avoid adding a forward declaration. Otherwise
unchanged.
(expand_macrolet): For each macrolet function, create
a shadowing environment which contains its parameters,
and use that for expanding the body.
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 60 |
1 files changed, 31 insertions, 29 deletions
@@ -1772,6 +1772,32 @@ static void builtin_reject_test(val op, val sym, val form) } } +/* + * Generate a symbol macro environment in which every + * variable in the binding list vars is listed + * as a binding, with the value sys:special. + * This is a shadow entry, which allows ordinary + * bindings to shadow symbol macro bindings. + */ +static val make_var_shadowing_env(val menv, val vars) +{ + if (nilp(vars)) { + return menv; + } else { + list_collect_decl (shadows, ptail); + + for (; vars; vars = cdr(vars)) { + val var = car(vars); + + ptail = list_collect(ptail, cons(if3(consp(var), + car(var), + var), special_s)); + } + + return make_env(shadows, nil, menv); + } +} + static val expand_macrolet(val form, val menv) { val op = car(form); @@ -1782,8 +1808,10 @@ static val expand_macrolet(val form, val menv) for (; macs; macs = cdr(macs)) { val macro = car(macs); val name = pop(¯o); - val params = expand_params(pop(¯o), menv); - val macro_ex = expand_forms(macro, menv); + val params = pop(¯o); + val new_menv = make_var_shadowing_env(menv, get_param_syms(params)); + val params_ex = expand_params(params, menv); + val macro_ex = expand_forms(macro, new_menv); val block = rlcp_tree(cons(block_s, cons(name, macro_ex)), macro_ex); builtin_reject_test(op, name, form); @@ -1794,7 +1822,7 @@ static val expand_macrolet(val form, val menv) * doesn't capture that. */ rlcp_tree(env_fbind(new_env, name, - func_f2(cons(nil, cons(params, cons(block, nil))), + func_f2(cons(nil, cons(params_ex, cons(block, nil))), me_interp_macro)), block); } @@ -1819,32 +1847,6 @@ static val expand_symacrolet(val form, val menv) return maybe_progn(expand_forms(body, new_env)); } -/* - * Generate a symbol macro environment in which every - * variable in the binding list vars is listed - * as a binding, with the value sys:special. - * This is a shadow entry, which allows ordinary - * bindings to shadow symbol macro bindings. - */ -static val make_var_shadowing_env(val menv, val vars) -{ - if (nilp(vars)) { - return menv; - } else { - list_collect_decl (shadows, ptail); - - for (; vars; vars = cdr(vars)) { - val var = car(vars); - - ptail = list_collect(ptail, cons(if3(consp(var), - car(var), - var), special_s)); - } - - return make_env(shadows, nil, menv); - } -} - static val make_fun_shadowing_env(val menv, val funcs) { val env = make_var_shadowing_env(menv, funcs); |