summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-02-16 16:03:38 -0800
committerKaz Kylheku <kaz@kylheku.com>2018-02-16 16:03:38 -0800
commit4c8dfaaf842db7c8e34d34b83d9cf38627f120da (patch)
tree8f80502cd7a821fa7c0fe9ba45cb4ad7043f78f1
parent9a78780d28d1e74f66338376f9604b4773161d8a (diff)
downloadtxr-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.c34
-rw-r--r--match.c4
-rw-r--r--txr.1101
3 files changed, 108 insertions, 31 deletions
diff --git a/eval.c b/eval.c
index 64cfc1ad..324722d2 100644
--- a/eval.c
+++ b/eval.c
@@ -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;
diff --git a/match.c b/match.c
index 5ce37849..10fd1770 100644
--- a/match.c
+++ b/match.c
@@ -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;
}
diff --git a/txr.1 b/txr.1
index d375beaf..e560a764 100644
--- a/txr.1
+++ b/txr.1
@@ -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