diff options
-rw-r--r-- | eval.c | 4 | ||||
-rw-r--r-- | lib.c | 44 | ||||
-rw-r--r-- | lib.h | 2 | ||||
-rw-r--r-- | match.c | 11 | ||||
-rw-r--r-- | txr.1 | 39 | ||||
-rw-r--r-- | txr.c | 2 |
6 files changed, 82 insertions, 20 deletions
@@ -7123,8 +7123,8 @@ void eval_init(void) reg_fun(intern(lit("compl-span-str"), user_package), func_n2(compl_span_str)); reg_fun(intern(lit("break-str"), user_package), func_n2(break_str)); - reg_fun(intern(lit("lazy-stream-cons"), user_package), func_n1(lazy_stream_cons)); - reg_fun(intern(lit("get-lines"), user_package), func_n1o(lazy_stream_cons, 0)); + reg_fun(intern(lit("lazy-stream-cons"), user_package), func_n2o(lazy_stream_cons, 1)); + reg_fun(intern(lit("get-lines"), user_package), func_n2o(lazy_stream_cons, 0)); reg_fun(intern(lit("lazy-str"), user_package), func_n3o(lazy_str, 1)); reg_fun(intern(lit("lazy-stringp"), user_package), func_n1(lazy_stringp)); reg_fun(intern(lit("lazy-str-force-upto"), user_package), func_n2(lazy_str_force_upto)); @@ -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))); } } @@ -1089,7 +1089,7 @@ val replace_vec(val vec_in, val items, val from, val to); val replace_obj(val obj, val items, val from, val to); val fill_vec(val vec, val item, val from_in, val to_in); val cat_vec(val list); -val lazy_stream_cons(val stream); +val lazy_stream_cons(val stream, val no_throw_close); val lazy_str(val list, val term, val limit); val lazy_str_force_upto(val lstr, val index); val lazy_str_force(val lstr); @@ -2843,7 +2843,8 @@ static val v_next_impl(match_files_ctx *c) if (stream) { cons_bind (new_bindings, success, match_files(mf_file_data(*c, str, stream, - lazy_stream_cons(stream), one))); + lazy_stream_cons(stream, nothrow), + one))); if (success) return cons(new_bindings, @@ -4604,7 +4605,7 @@ static void open_data_source(match_files_ctx *c) } else { debuglf(first_spec, lit("opening standard input as data source"), nao); c->curfile = lit("-"); - c->data = lazy_stream_cons(std_input); + c->data = lazy_stream_cons(std_input, nil); c->data_lineno = one; } } else if (non_matching_dir) { @@ -4628,10 +4629,10 @@ static void open_data_source(match_files_ctx *c) c->curfile = source_spec; c->stream = stream; - if ((c->data = lazy_stream_cons(stream)) != nil) + if ((c->data = lazy_stream_cons(stream, nothrow)) != nil) c->data_lineno = one; } else if (streamp(name)) { - if ((c->data = lazy_stream_cons(name))) + if ((c->data = lazy_stream_cons(name, nil))) c->data_lineno = one; } else { sem_error(specline, lit("~s doesn't denote a valid data source"), name, nao); @@ -4773,7 +4774,7 @@ val match_fun(val name, val args, val input_in, val files_in) val files = cons(curfile, default_null_arg(files_in)); val in_bindings = cdr(uw_get_match_context()); val data = if3(streamp(input), - lazy_stream_cons(input), + lazy_stream_cons(input, nil), input); /* TODO: pass through source location context */ match_files_ctx c = mf_all(spec, files, in_bindings, data, @@ -4045,7 +4045,21 @@ is invoked with the .code :nothrow keyword, then if the input source cannot be opened, the situation is treated as a simple -match failure. +match failure. The +.code :nothrow +keyword also ensures that when the stream is later closed, +which occurs when the lazy list reads all of the available data, +the implicit call to the +.code close-stream +function specifies +.code nil +as the argument value to that function's +.meta throw-on-error-p +parameter. This +.code :nothrow +mechanism does not suppress all exceptions related to the processing +of that stream; unusual conditions encountered during the reading of +data from the stream may throw exceptions. The variant .code "@(next :args)" @@ -22855,8 +22869,8 @@ function: .coNP Functions @ lazy-stream-cons and @ get-lines .synb -.mets (lazy-stream-cons << stream ) -.mets (get-lines <> [ stream ]) +.mets (lazy-stream-cons << stream <> [ no-throw-close-p ]) +.mets (get-lines >> [ stream <> [ no-throw-close-p ]]) .syne .desc The @@ -22903,7 +22917,8 @@ by making another call to .codn lazy-stream-cons , installing the result into the .code cdr -field. +field. When this lazy list obtains an end-of-file indication from the stream, +it closes the stream. .code lazy-stream-cons inspects the real-time property of a stream @@ -22928,6 +22943,22 @@ a one-line stream translates to .onom and so forth. +If and when +.meta stream +is closed by the function directly, or else by the returned lazy list, the +.meta no-throw-close-p +Boolean argument, defaulting to +.codn nil , +controls the +.meta throw-on-error-p +argument of the call to the +.code close-stream +function. These arguments have opposite polarity: if +.meta no-throw-close-p +is true, then +.meta throw-on-error-p +shall be false, and vice versa. + .coNP Macro @ delay .synb .mets (delay << expression ) @@ -381,7 +381,7 @@ static int license(void) for (iter = path_list; iter; iter = cdr(iter)) { val lic = open_file(car(iter), lit("r")); - put_lines(lazy_stream_cons(lic), std_output); + put_lines(lazy_stream_cons(lic, nil), std_output); put_char(chr('\n'), std_output); } } |