summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-08-07 00:25:46 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-08-07 00:25:46 -0700
commit25eb966ccb8b61dbe4ff2b2e1970e1e9caa0282f (patch)
tree427b31848c6040b83e69003c95f5f7c2d06bfd0d /lib.c
parent586d5d840219a76bd8d36e3b04951e3377709fbd (diff)
downloadtxr-25eb966ccb8b61dbe4ff2b2e1970e1e9caa0282f.tar.gz
txr-25eb966ccb8b61dbe4ff2b2e1970e1e9caa0282f.tar.bz2
txr-25eb966ccb8b61dbe4ff2b2e1970e1e9caa0282f.zip
lazy-stream-cons: control close throwing behavior.
* eval.c (eval_init): Update registrations of lazy-stream-cons and get-lines with one more optional argument. * lib.c (simple_lazy_stream_func_nt, lazy_stream_func_nt): New static functions. (lazy_stream_cons): Take a new argument, no_throw_close, defaulting it to nil. When calling close_stream directly, pass the inverted value of no_throw_close. Choose the new _nt functions for the lazy list if no_throw_close is true; those functions pass nil as the second argument of close_stream. * lib.h (lazy_stream_cons): Declaration updated. * match.c (v_next_impl, open_data_source, match_fun): Pass down the nothrow value to lazy_stream_cons, or else nil in situations when that is not applicable or there is no such value. Thus the :nothrow feature of v_next will now not only ensure that there is no exception when opening the stream but also when closing it. Unusual situations encountered when the lazy list reads from the stream still throw. * txr.1: Documented.
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c44
1 files changed, 37 insertions, 7 deletions
diff --git a/lib.c b/lib.c
index 5de9f170..79b3c1e4 100644
--- a/lib.c
+++ b/lib.c
@@ -8995,12 +8995,24 @@ static val simple_lazy_stream_func(val stream, val lcons)
return nil;
}
-static val lazy_stream_cont(val stream, val func, val env)
+static val simple_lazy_stream_func_nt(val stream, val lcons)
+{
+ if (set(mkloc(lcons->lc.car, lcons), get_line(stream)) != nil) {
+ set(mkloc(lcons->lc.cdr, lcons), make_lazy_cons(us_lcons_fun(lcons)));
+ } else {
+ close_stream(stream, nil);
+ lcons->lc.cdr = nil;
+ }
+
+ return nil;
+}
+
+static val lazy_stream_cont(val stream, val func, val env, val throw_p)
{
val next = get_line(stream);
if (!next) {
- close_stream(stream, t);
+ close_stream(stream, throw_p);
return nil;
}
@@ -9015,27 +9027,45 @@ static val lazy_stream_func(val env, val lcons)
set(mkloc(lcons->lc.car, lcons), prefetched_line);
set(mkloc(lcons->lc.cdr, lcons), lazy_stream_cont(stream,
- us_lcons_fun(lcons), env));
+ us_lcons_fun(lcons), env, t));
return prefetched_line;
}
-val lazy_stream_cons(val stream)
+static val lazy_stream_func_nt(val env, val lcons)
+{
+ val stream = car(env);
+ val prefetched_line = cdr(env);
+
+ set(mkloc(lcons->lc.car, lcons), prefetched_line);
+ set(mkloc(lcons->lc.cdr, lcons), lazy_stream_cont(stream,
+ us_lcons_fun(lcons), env, nil));
+
+ return prefetched_line;
+}
+
+
+val lazy_stream_cons(val stream, val no_throw_close)
{
stream = default_arg_strict(stream, std_input);
+ no_throw_close = default_null_arg(no_throw_close);
if (real_time_stream_p(stream)) {
- return make_lazy_cons(func_f1(stream, simple_lazy_stream_func));
+ return make_lazy_cons(func_f1(stream, if3(no_throw_close,
+ simple_lazy_stream_func_nt,
+ simple_lazy_stream_func)));
} else {
val first = get_line(stream);
if (!first) {
- close_stream(stream, t);
+ close_stream(stream, null(no_throw_close));
return nil;
}
return make_lazy_cons(func_f1(cons(stream, first),
- lazy_stream_func));
+ if3(no_throw_close,
+ lazy_stream_func_nt,
+ lazy_stream_func)));
}
}