diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2023-05-31 19:36:06 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2023-05-31 19:36:06 -0700 |
commit | 661531cdc4529078c15c222fafe2da025c02591d (patch) | |
tree | 41443235b4dbf6714c128dd13aa51063f84d3c51 | |
parent | 6846740ce44659a1f31e01054b0f1bcc8dc04c7a (diff) | |
download | txr-661531cdc4529078c15c222fafe2da025c02591d.tar.gz txr-661531cdc4529078c15c222fafe2da025c02591d.tar.bz2 txr-661531cdc4529078c15c222fafe2da025c02591d.zip |
load: now establishes a block named load.
Files loaded from the command line or via the load function
or @(load) directive now have a block named load in scope.
Thus (return-from load <expr>) may be used to abort a
load when it is finished. The load function will then
return the value of <expr>.
* eval.c (load): Bind a load block around the whole thing
and use the captured return value as the function's
return value.
* match.c (v_load): Bind the load block here too. Ensure
that if the block return is taken, the ret variable
contains next_spec_k, so that processing continues with
whatever directive follows the @(load).
* txr.c (txr_main): Bind the block in severl cases that
load code.
* txr.1: Documented.
-rw-r--r-- | eval.c | 4 | ||||
-rw-r--r-- | match.c | 7 | ||||
-rw-r--r-- | txr.1 | 38 | ||||
-rw-r--r-- | txr.c | 34 |
4 files changed, 67 insertions, 16 deletions
@@ -4755,6 +4755,7 @@ val load(val target) val saved_dyn_env = dyn_env; val load_dyn_env = make_env(nil, nil, dyn_env); val rec = cdr(lookup_var(nil, load_recursive_s)); + uw_block_begin (load_s, ret); open_txr_file(path, &txr_lisp_p, &name, &stream, t, self); @@ -4822,8 +4823,9 @@ val load(val target) } uw_catch_end; + uw_block_end; - return nil; + return ret; } static val rt_load_for(struct args *args) @@ -4628,10 +4628,11 @@ static val v_load(match_files_ctx *c) path_cat(dir_name(parent), target)); val stream, name = target; val txr_lisp_p = nil; - val ret = nil; + val ret = next_spec_k; val saved_dyn_env = dyn_env; val load_dyn_env = make_env(nil, nil, dyn_env); val rec = cdr(lookup_var(nil, load_recursive_s)); + uw_block_begin (load_s, load_ret); open_txr_file(path, &txr_lisp_p, &name, &stream, t, self); @@ -4680,8 +4681,6 @@ static val v_load(match_files_ctx *c) nao); c->data = nil; } - - ret = next_spec_k; } } } else { @@ -4715,6 +4714,8 @@ static val v_load(match_files_ctx *c) uw_catch_end; + uw_block_end; + return ret; } } @@ -9357,7 +9357,18 @@ takes place prior to evaluation time, whereas .code load doesn't execute until evaluation time. +Note: +the +.code load +directive doesn't provide access to the value propagated by a +.code return +via the +.code load +block. + See also: the +.code load +function, and the .codn self-path , .code stdlib and @@ -79885,6 +79896,33 @@ loaded file has the effect of altering the value of that effect will be undone when the binding is removed after the load completes. +Over the evaluation of either a \*(TL, compiled file, or \*(TX file, +.code load +establishes a block named +.codn load , +which makes it possible for the loaded module to abort the loading +using the +.mono +.meti (return-from load << expr ) +.onom +expression. In this situation, the value of +.meta expr +will appear as the return value of the +.code load +function. A block named +.code load +is also established by the +.code @(load) +directive in the pattern language, that that directive provides +no access to the returned value. The block is also visible to the +file processed from the command line. When a such a file aborts +the load via +.codn return , +the returned value is discarded. If the interactive option +.code -i +was specified, the interactive listener will be entered, otherwise +the process will terminate successfully. + When the .code load function terminates normally after processing a file, @@ -1259,19 +1259,29 @@ int txr_main(int argc, char **argv) reg_varl(car(binding), cdr(binding)); } - if (txr_lisp_p == chr('o')) { - val result = read_compiled_file_noerr(self, parse_stream, spec_file_str, - std_error); - if (!enter_repl) + { + if (txr_lisp_p == chr('o')) { + val result = nil; + uw_block_begin (load_s, ret); + result = read_compiled_file_noerr(self, parse_stream, spec_file_str, + std_error); + uw_block_end; + if (!enter_repl) + return result ? 0 : EXIT_FAILURE; + } else if (enter_repl) { + uw_block_begin (load_s, ret); + read_eval_stream_noerr(self, parse_stream, spec_file_str, std_error); + uw_block_end; + close_stream(parse_stream, nil); + run_load_hooks(dyn_env); + uw_release_deferred_warnings(); + } else { + val result = nil; + uw_block_begin (load_s, ret); + result = read_eval_stream(self, parse_stream, std_error); + uw_block_end; return result ? 0 : EXIT_FAILURE; - } else if (enter_repl) { - read_eval_stream_noerr(self, parse_stream, spec_file_str, std_error); - close_stream(parse_stream, nil); - run_load_hooks(dyn_env); - uw_release_deferred_warnings(); - } else { - val result = read_eval_stream(self, parse_stream, std_error); - return result ? 0 : EXIT_FAILURE; + } } repl: |