summaryrefslogtreecommitdiffstats
path: root/eval.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-11-24 05:57:03 -0800
committerKaz Kylheku <kaz@kylheku.com>2016-11-24 05:57:03 -0800
commitf756436525725e477b85768926f4ecbc4d9798e9 (patch)
tree6e9a4b1f086a36d7cf5d17ed847e16e73463acf9 /eval.c
parent780e22e8b957f7070009811523b2c7567b27b7c0 (diff)
downloadtxr-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.c60
1 files changed, 31 insertions, 29 deletions
diff --git a/eval.c b/eval.c
index 8ed31f10..1f51f0c6 100644
--- a/eval.c
+++ b/eval.c
@@ -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(&macro);
- val params = expand_params(pop(&macro), menv);
- val macro_ex = expand_forms(macro, menv);
+ val params = pop(&macro);
+ 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);