summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2025-04-08 22:22:57 -0700
committerKaz Kylheku <kaz@kylheku.com>2025-04-08 22:22:57 -0700
commit156d1bfac12f59a6b60f3afbfae1f01e60f63dbf (patch)
tree206cd002edec3b7491cd67ac2c3f04cc7e03c22d
parentc1306d943aa9c19d6bbccc1a5c72cddb5af7e564 (diff)
downloadtxr-156d1bfac12f59a6b60f3afbfae1f01e60f63dbf.tar.gz
txr-156d1bfac12f59a6b60f3afbfae1f01e60f63dbf.tar.bz2
txr-156d1bfac12f59a6b60f3afbfae1f01e60f63dbf.zip
expand-hook: implement in macroexpand-1.
When expanding a form with macroexpand-1 or macroexpand, and an expand hook is in effect, we must call the hook. Otherwise macrology that relies on macroexpand or macroexpand-1 might not work with expander-driven syntax. I'm running into not being able to, for instance, use the swap macro on a pair of infix expressions because of this. macroexpand-1 must behave like the real macro expander. eval.c (do_macroexpand_1): After looking up whether the form is a macro, pass it through the hook if it is defined. If the hook transforms the code, then iterate on this. We pass the form through the expand hook even if it is not a macro call, and classify it based on whether is a function call, dwim brackets form or other, careful not to pass down special operators.
-rw-r--r--eval.c43
1 files changed, 35 insertions, 8 deletions
diff --git a/eval.c b/eval.c
index 24e4dd92..4c44d10b 100644
--- a/eval.c
+++ b/eval.c
@@ -5693,6 +5693,7 @@ val macro_form_p(val form, val menv)
static val do_macroexpand_1(val form, val menv, val (*lookup)(val, val))
{
val macro;
+ val eh = expand_hook;
#if CONFIG_DEBUG_SUPPORT
uw_frame_t expand_fr;
uw_push_expand(&expand_fr, form, menv);
@@ -5700,14 +5701,40 @@ static val do_macroexpand_1(val form, val menv, val (*lookup)(val, val))
menv = default_null_arg(menv);
- if (consp(form) && (macro = lookup_mac(menv, car(form)))) {
- val mac_expand = expand_macro(form, macro, menv);
- if (mac_expand != form)
- form = rlcp_tree(rlcp_tree(mac_expand, form), macro);
- } else if (bindable(form) && (macro = lookup(menv, form))) {
- val mac_expand = cdr(macro);
- if (mac_expand != form)
- form = rlcp_tree(mac_expand, macro);
+ for (;;) {
+ if (consp(form) && (macro = lookup_mac(menv, car(form)))) {
+ if (eh) {
+ val eh_form = funcall3(eh, form, menv, macro_k);
+ if (eh_form != form) {
+ form = rlcp_tree(eh_form, form);
+ continue;
+ }
+ }
+ {
+ val mac_expand = expand_macro(form, macro, menv);
+ if (mac_expand != form)
+ form = rlcp_tree(rlcp_tree(mac_expand, form), macro);
+ }
+ break;
+ } else if (bindable(form) && (macro = lookup(menv, form))) {
+ val mac_expand = cdr(macro);
+ if (mac_expand != form)
+ form = rlcp_tree(mac_expand, macro);
+ break;
+ } else if (eh && consp(form)) {
+ val op = car(form);
+ if (op == dwim_s || !special_operator_p(op)) {
+ val eh_type = if3(lookup_fun(menv, op),
+ fun_k,
+ if2(op == dwim_s, dwim_s));
+ val eh_form = funcall3(eh, form, menv, eh_type);
+ if (eh_form != form) {
+ form = rlcp_tree(eh_form, form);
+ continue;
+ }
+ }
+ }
+ break;
}
#if CONFIG_DEBUG_SUPPORT