diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-08-29 18:57:56 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-08-29 18:57:56 -0700 |
commit | 7bc478a5c838c72c07097c8473c410dedecaa3d8 (patch) | |
tree | 58ed3cb4a340a401c3d1b6f4afa44b36638403c9 /eval.c | |
parent | 46bea2a664da70d4326206295fa4f3d54e66ab87 (diff) | |
download | txr-7bc478a5c838c72c07097c8473c410dedecaa3d8.tar.gz txr-7bc478a5c838c72c07097c8473c410dedecaa3d8.tar.bz2 txr-7bc478a5c838c72c07097c8473c410dedecaa3d8.zip |
Rewriting op/do macros in Lisp.
The new implementation treats the @1, @2 ... @rest
op arguments as local macros, leveraging the power of the
macro expander to perform the substitution which renames these
to gensyms.
As a result, the implementation is correct.
The old implementation blindly walks the tree
structure doing the substitution, so that @1 is substituted
even though it is in a quoted literal:
[(op list '(@1)) 42] -> ((#:arg-01-0166))
under the new implementation, '(@1) is left alone:
[(op list '(@1)) 42] -> ((@1) 42)
* eval.c (expand_quasi): Because the new op macro doesn't
rudely reach into quasi forms to substitute sys:var
elements, relying on macro expansion, we must now macro-expand
sys:var elements. The sys:var macro created by op is
smart enough to skip the compound ones that have modifiers;
they are handled via the inner expansion of the symbol.
That is to say, `@@1` contains the structure
(sys:var (sys:var 1)). The sys:var macro ignores the outer
sys:var. But existing behavior in expand_quasi expands the
inner (sys:var 1), so the substitution takes place.
(eval_init): Do not register the hacky old op and do macros,
except in compatibility mode with 184 or older.
* lisplib.c (op_set_entries, op_instantiate): New functions.
(dlt_register): Register auto-loads for op and do macros via
new functions, except when in compatibility mode with 184
or older, in which case we want the old build-in hacky op
to be used.
* share/txr/stdlib/op.tl: New file.
* txr.1: Fixed or removed no-longer-true text which hints at
special hacks implemented in the op expander. Added
compatibility notes for all new compat-switched op behaviors.
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 13 |
1 files changed, 10 insertions, 3 deletions
@@ -3400,6 +3400,10 @@ val expand_quasi(val quasi_forms, val menv) if (consp(form)) { val sym = car(form); + int comp_184 = opt_compat && opt_compat <= 184; + + if (!comp_184) + form_ex = expand(form, menv); if (sym == var_s) { val param = second(form); @@ -3410,7 +3414,8 @@ val expand_quasi(val quasi_forms, val menv) if (param_ex != param || mods_ex != mods) form_ex = rlcp(list(sym, param_ex, mods_ex, nao), form); } else { - form_ex = expand(form, menv); + if (comp_184) + form_ex = expand(form, menv); } } @@ -5677,8 +5682,10 @@ void eval_init(void) reg_mac(gen_s, func_n2(me_gen)); reg_mac(gun_s, func_n2(me_gun)); reg_mac(intern(lit("delay"), user_package), func_n2(me_delay)); - reg_mac(op_s, func_n2(me_op)); - reg_mac(do_s, func_n2(me_op)); + if (opt_compat && opt_compat <= 184) { + reg_mac(op_s, func_n2(me_op)); + reg_mac(do_s, func_n2(me_op)); + } reg_mac(ap_s, func_n2(me_ap)); reg_mac(intern(lit("ip"), user_package), func_n2(me_ip)); reg_mac(intern(lit("ado"), user_package), func_n2(me_ado)); |