summaryrefslogtreecommitdiffstats
path: root/lisplib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-08-29 18:57:56 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-08-29 18:57:56 -0700
commit7bc478a5c838c72c07097c8473c410dedecaa3d8 (patch)
tree58ed3cb4a340a401c3d1b6f4afa44b36638403c9 /lisplib.c
parent46bea2a664da70d4326206295fa4f3d54e66ab87 (diff)
downloadtxr-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.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/lisplib.c b/lisplib.c
index 588384df..8379abf9 100644
--- a/lisplib.c
+++ b/lisplib.c
@@ -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));
}