summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eval.c32
-rw-r--r--txr.139
2 files changed, 67 insertions, 4 deletions
diff --git a/eval.c b/eval.c
index 1aa56866..9977883d 100644
--- a/eval.c
+++ b/eval.c
@@ -4501,7 +4501,7 @@ val macro_form_p(val form, val menv)
return nil;
}
-static val macroexpand_1(val form, val menv)
+static val do_macroexpand_1(val form, val menv, val (*lookup)(val, val))
{
val macro;
@@ -4514,7 +4514,7 @@ static val macroexpand_1(val form, val menv)
return rlcp_tree(rlcp_tree(mac_expand, form), macro);
}
- if (bindable(form) && (macro = lookup_symac(menv, form))) {
+ if (bindable(form) && (macro = lookup(menv, form))) {
val mac_expand = cdr(macro);
if (mac_expand == form)
return form;
@@ -4524,16 +4524,36 @@ static val macroexpand_1(val form, val menv)
return form;
}
-static val macroexpand(val form, val menv)
+static val macroexpand_1(val form, val menv)
+{
+ return do_macroexpand_1(form, menv, lookup_symac);
+}
+
+static val macroexpand_1_lisp1(val form, val menv)
+{
+ return do_macroexpand_1(form, menv, lookup_symac_lisp1);
+}
+
+static val do_macroexpand(val form, val menv, val (*lookup_sm)(val, val))
{
for (;;) {
- val mac_expand = macroexpand_1(form, menv);
+ val mac_expand = do_macroexpand_1(form, menv, lookup_sm);
if (mac_expand == form)
return form;
form = mac_expand;
}
}
+static val macroexpand(val form, val menv)
+{
+ return do_macroexpand(form, menv, lookup_symac);
+}
+
+static val macroexpand_lisp1(val form, val menv)
+{
+ return do_macroexpand(form, menv, lookup_symac_lisp1);
+}
+
static val constantp_noex(val form)
{
if (consp(form)) {
@@ -5976,8 +5996,12 @@ void eval_init(void)
reg_fun(intern(lit("macro-form-p"), user_package), func_n2o(macro_form_p, 1));
reg_fun(intern(lit("macroexpand-1"), user_package),
func_n2o(macroexpand_1, 1));
+ reg_fun(intern(lit("macroexpand-1-lisp1"), user_package),
+ func_n2o(macroexpand_1_lisp1, 1));
reg_fun(intern(lit("macroexpand"), user_package),
func_n2o(macroexpand, 1));
+ reg_fun(intern(lit("macroexpand-lisp1"), user_package),
+ func_n2o(macroexpand_lisp1, 1));
reg_fun(intern(lit("expand-params"), system_package), func_n5(expand_params));
reg_fun(intern(lit("constantp"), user_package), func_n2o(constantp, 1));
reg_fun(intern(lit("make-env"), user_package), func_n3o(make_env_intrinsic, 0));
diff --git a/txr.1 b/txr.1
index 72ad9949..ed998606 100644
--- a/txr.1
+++ b/txr.1
@@ -30172,6 +30172,45 @@ and
.code a
respectively.
+.coNP Functions @ macroexpand-1-lisp1 and @ macroexpand-lisp1
+.synb
+.mets (macroexpand-1-lisp1 < obj <> [ env ])
+.mets (macroexpand-lisp1 < obj <> [ env ])
+.syne
+.desc
+The
+.code macroexpand-1-lisp1
+and
+.code macroexpand-lisp1
+functions closely resemble, respectively,
+.code macroexpand-1
+and
+.codn macroexpand .
+
+The argument and return value syntax and semantics is almost
+identical, except for one difference. These functions consider argument
+.meta obj
+to be syntax in a Lisp-1 evaluation context, such as any argument
+position of the
+.code dwim
+operator, or the equivalent DWIM Brackets notation.
+
+This makes a difference because in a Lisp-1 evaluation context, an
+inner function binding is able to shadow an outer symbol macro binding
+of the same name.
+
+The requirements about this language area are given in more
+detail in the description of the
+.code dwim
+operator.
+
+Note: the
+.code macroexpand-lisp1
+function is useful to the implementor of a macro whose semantics requires
+one or more argument forms to be treated in a Lisp-1 context, in situations
+when such a macro needs to itself expand the material, rather than merely
+insert it as-is into the output code template.
+
.coNP Functions @ lexical-var-p and @ lexical-fun-p
.synb
.mets (lexical-var-p < env << form )