diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2018-02-16 16:03:38 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2018-02-16 16:03:38 -0800 |
commit | 4c8dfaaf842db7c8e34d34b83d9cf38627f120da (patch) | |
tree | 8f80502cd7a821fa7c0fe9ba45cb4ad7043f78f1 | |
parent | 9a78780d28d1e74f66338376f9604b4773161d8a (diff) | |
download | txr-4c8dfaaf842db7c8e34d34b83d9cf38627f120da.tar.gz txr-4c8dfaaf842db7c8e34d34b83d9cf38627f120da.tar.bz2 txr-4c8dfaaf842db7c8e34d34b83d9cf38627f120da.zip |
Lisp load function supports .txr files.
* eval.c (load): Instead of throwing error when a .txr file
is opened, process it according to sensible requirements.
* match.c (v_load): Store bindings in the current environment
frame before evaluating Lisp, and then update afterward.
This allows .txr files loaded from Lisp to continue matching
with the current bindings and extend those bindings.
* txr.1: Update documentation of load.
-rw-r--r-- | eval.c | 34 | ||||
-rw-r--r-- | match.c | 4 | ||||
-rw-r--r-- | txr.1 | 101 |
3 files changed, 108 insertions, 31 deletions
@@ -44,6 +44,7 @@ #include "unwind.h" #include "regex.h" #include "stream.h" +#include "y.tab.h" #include "parser.h" #include "hash.h" #include "debug.h" @@ -3976,12 +3977,6 @@ val load(val target) open_txr_file(path, &txr_lisp_p, &name, &stream); - if (!txr_lisp_p) { - close_stream(stream, nil); - uw_throwf(error_s, lit("load: cannot process .txr file ~a"), - path, nao); - } - uw_simple_catch_begin; dyn_env = make_env(nil, nil, dyn_env); @@ -3989,9 +3984,32 @@ val load(val target) env_vbind(dyn_env, load_recursive_s, t); env_vbind(dyn_env, package_s, cur_package); - if (!read_eval_stream(stream, std_error)) { + if (txr_lisp_p) { + if (!read_eval_stream(stream, std_error)) { + close_stream(stream, nil); + uw_throwf(error_s, lit("load: ~a contains errors"), path, nao); + } + } else { + int gc = gc_state(0); + parser_t parser; + parse_once(stream, name, &parser); + gc_state(gc); + close_stream(stream, nil); - uw_throwf(error_s, lit("load: ~a contains errors"), path, nao); + + uw_release_deferred_warnings(); + + if (parser.errors) + uw_throwf(query_error_s, lit("load: parser errors in ~a"), + path, nao); + { + val match_ctx = uw_get_match_context(); + val bindings = cdr(match_ctx); + val result = extract(parser.syntax_tree, nil, bindings); + cons_bind (new_bindings, success, result); + if (success) + uw_set_match_context(cons(car(match_ctx), new_bindings)); + } } dyn_env = saved_dyn_env; @@ -4308,11 +4308,15 @@ static val v_load(match_files_ctx *c) } } } else { + uw_set_match_context(cons(c->spec, c->bindings)); + if (!read_eval_stream(stream, std_error)){ close_stream(stream, nil); sem_error(specline, lit("load: ~a contains errors"), path, nao); } + c->bindings = cdr(uw_get_match_context()); + ret = (sym == include_s) ? nil : next_spec_k; } @@ -55314,11 +55314,17 @@ can immediately use to expand the given form that is being traversed. .desc The .code load -function causes a file of \*(TL code to be read and evaluated. +function causes a file containing \*(TL or \*(TX code to be read and processed. The .meta target argument is a string. +Firstly, the value in +.meta target +is converted to an +.I "effective pathname" +as follows. + If .meta target specifies a pure relative pathname, as defined by the @@ -55339,42 +55345,91 @@ then a pure relative pathname is used as-is, and thus resolved relative to the current working directory. -If -.meta target -has no suffix, then +Once the effective path name is determined, .code load -first tries to load the un-suffixed name. If that cannot be opened, the -.str .tl -suffix is added to the path and another attempt is made. If that fails, -an exception is thrown. - -If +first tries to open that exact path name. +If this succeeds, then the file will be treated as containing \*(TL, +unless .meta target -has a -.str .txr -suffix, it is assumed to be a \*(TX pattern language file, and -an exception of type -.code eval-error -is thrown, since this is not supported. +ends ends with the +.code .txr +suffix, in which case the file will be treated as containing +\*(TX pattern language syntax. -If -.meta target -is successfully resolved and opened, \*(TL forms are read from the file -in succession. Each form is evaluated as if by the +If loading the original effective path name fails, and that name is unsuffixed, +then the +.code .tl +suffix is added and another attempt is made. If that succeeds, +the file will be treated as \*(TL. + +If a file is successfully resolved and opened for \*(TL processing, +then \*(TL forms are read from it in succession. Each form is evaluated as if +by the .code eval function, before the next form is read. If a syntax error is encountered, an exception of type .code eval-error is thrown. -Over the evaluation of the forms, the special variable -.code *load-path* -to the path name of that file. +If a file is successfully resolved and opened for \*(TX processing, +then its contents are parsed in their entirety as a \*(TX +query. If the parse is successful, the query is executed. +Previous \*(TX pattern variable and function bindings are in +effect. If the query binds new variables and functions, +these emerge from the +.code load +and take effect. If the parse is unsuccessful, an exception of type +.code query-error +is thrown. Parser error messages are directed to the .code *stderr* stream. +Over the evaluation of either a \*(TL or \*(TX file, +.code load +establishes a new dynamic binding for several special +variables. The variable +.code *load-path* +is given a new binding containing the effective path name. This excludes any +.code .tl +suffix that was added by +.codn load . +The +.code *package* +variable is also given a new dynamic binding, whose value is the +same as the existing binding. Thus if the processing of the +loaded file has the effect of altering the value of +.codn *package* , +that effect will be undone when the binding is removed +after the load completes. + +When the +.code load +function terminates normally after processing a file, +it returns +.codn nil . +If the file contains a \*(TX pattern query which is +processed to completion, the matching success or failure +of that query has no bearing on the return value of +.codn load . +Note that this behavior is different from the +.code @(load) +directive which itself fails if the loaded query +fails, causing subsequent directives not to be processed. + +A \*(TX pattern language file loaded with the Lisp +.code load +function does not have the usual implicit access to the +command line arguments, unlike a top-level \*(TX query. +If the directives in the file try to match input, they +work against the +.code *stdin* +stream. The +.code @(next) +directive behaves as it does when no more arguments +are available. + .coNP Special variable @ *load-path* .desc The |