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 /lisplib.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 'lisplib.c')
-rw-r--r-- | lisplib.c | 21 |
1 files changed, 21 insertions, 0 deletions
@@ -560,6 +560,23 @@ static val doloop_instantiate(val set_fun) return nil; } +static val op_set_entries(val dlt, val fun) +{ + val name[] = { + lit("op"), lit("do"), + nil + }; + set_dlt_entries(dlt, name, fun); + return nil; +} + +static val op_instantiate(val set_fun) +{ + funcall1(set_fun, nil); + load(format(nil, lit("~aop.tl"), stdlib_path, nao)); + return nil; +} + val dlt_register(val dlt, val (*instantiate)(val), val (*set_entries)(val, val)) @@ -601,6 +618,10 @@ void lisplib_init(void) dlt_register(dl_table, keyparams_instantiate, keyparams_set_entries); dlt_register(dl_table, ffi_instantiate, ffi_set_entries); dlt_register(dl_table, doloop_instantiate, doloop_set_entries); + + if (!opt_compat || opt_compat >= 185) + dlt_register(dl_table, op_instantiate, op_set_entries); + reg_fun(intern(lit("try-load"), system_package), func_n1(lisplib_try_load)); } |