From 156d1bfac12f59a6b60f3afbfae1f01e60f63dbf Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Tue, 8 Apr 2025 22:22:57 -0700 Subject: 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. --- eval.c | 43 +++++++++++++++++++++++++++++++++++-------- 1 file 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 -- cgit v1.2.3