diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-09-03 07:28:46 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-09-03 07:28:46 -0700 |
commit | c5985ee382ef9e11322346b25504216fa8a87510 (patch) | |
tree | 60f9cc1c6f97f3ec0a305244fbc847f4d25f18f6 | |
parent | ee19313e53e3a98321e1a405e41c8a0489fc68ca (diff) | |
download | txr-c5985ee382ef9e11322346b25504216fa8a87510.tar.gz txr-c5985ee382ef9e11322346b25504216fa8a87510.tar.bz2 txr-c5985ee382ef9e11322346b25504216fa8a87510.zip |
load: scope change for load hooks.
* eval.c (run_load_hooks): Install the given environment as dyn_env
temporarily, and don't restore it until after calling the hooks.
Thus the specified environment is now in effect when running the
hooks. Also, pass nil to lookup_var, in the spirit of the previous
commit. The fact that load_dyn_env had to be passed to lookup_var
previously, which is an anti-pattern, tells us that this scoping rule
was a code smell. If the *load-hooks* value comes from a given
dynamic environment, then those functions should be executed in
exactly that environment.
* txr.1: Documentation updated.
-rw-r--r-- | eval.c | 5 | ||||
-rw-r--r-- | txr.1 | 31 |
2 files changed, 16 insertions, 20 deletions
@@ -4600,7 +4600,8 @@ static val me_pop_after_load(val form, val menv) void run_load_hooks(val load_dyn_env) { - val hooks_binding = lookup_var(load_dyn_env, load_hooks_s); + val saved_de = set_dyn_env(load_dyn_env); + val hooks_binding = lookup_var(nil, load_hooks_s); val hooks = cdr(hooks_binding); if (hooks) { @@ -4608,6 +4609,8 @@ void run_load_hooks(val load_dyn_env) funcall(car(hooks)); rplacd(hooks_binding, nil); } + + set_dyn_env(saved_de); } static void run_load_hooks_atexit(void) @@ -74594,19 +74594,14 @@ situation, the variable which is accessed is that binding which was established by that invocation of .codn load . -However, the functions are invoked in a dynamic environment in which that -binding of the variable has already been removed. When the processing of +The execution of the functions from the .code *load-hooks* -takes place due to the termination of -.codn load , -all of the dynamic bindings established by that invocation of -.code load -have already been removed. Therefore, the -.code *load-hooks* -binding which is visible to these functions is whichever binding had been -shadowed by the +list takes place in the dynamic environment of the +.codn load : +all of the dynamic variable bindings established by that .code load -function. +are still visible, including that of +.codn *load-hooks* . The .code *load-hooks* @@ -74614,20 +74609,18 @@ list is also processed after processing a \*(TX or \*(TL file that is specified on the command line. If the interactive listener is also being entered, this processing of .code *load-hooks* -occurs prior to entering the listener. In this situation, the top-level -binding of +occurs prior to entering the listener. This situation occurs in the +context of the top-level dynamic environment, and so the global value of .code *load-hooks* -is used, and therefore that same binding is visible to the invoked -functions. +is referenced. Lastly, .code *load-hooks* is also processed if the \*(TX process terminates normally, regardless -of its exit status. In this situation, the current dynamic value of the +of its exit status. This processing executes in whatever dynamic +environment is current at the point of exit, using its value of the .code *load-hooks* -variable is used, from the dynamic environment as it exists at the -time of exit, and that same environment is in effect over the execution -of the functions. It is unspecified whether, at exit time, the +variable is used. It is unspecified whether, at exit time, the .code *load-hooks* functions are executed first, or whether the functions registered by .code at-exit-call |