diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2025-04-08 22:22:57 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2025-04-08 22:22:57 -0700 |
commit | 156d1bfac12f59a6b60f3afbfae1f01e60f63dbf (patch) | |
tree | 206cd002edec3b7491cd67ac2c3f04cc7e03c22d | |
parent | c1306d943aa9c19d6bbccc1a5c72cddb5af7e564 (diff) | |
download | txr-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.c | 43 |
1 files changed, 35 insertions, 8 deletions
@@ -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 |