diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2019-04-05 19:40:15 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2019-04-05 19:40:15 -0700 |
commit | 9363c10007a001af53b82fb703476e747c4c6524 (patch) | |
tree | d63553113db4a5c015cddecf25ee85eaf2f83a01 | |
parent | f8469c34f5b934c69de6520f734aa5fd1d14224e (diff) | |
download | txr-9363c10007a001af53b82fb703476e747c4c6524.tar.gz txr-9363c10007a001af53b82fb703476e747c4c6524.tar.bz2 txr-9363c10007a001af53b82fb703476e747c4c6524.zip |
@(output): bugfix: lazy evaluation doesn't work.
In an @(output), if we reference a variable bound to a lazy
list, and the generation of that logic references TXR pattern
variables, things break: the lazy list's code doesn't see
the binding. This is because the lazy list is forced by some
logic that doesn't establish the proper environment for
that evaluation. Inside a @(repeat), the do_output function
measures the lengths of lists emanating from variables,
and that has the effect of forcing the lazy lists.
* match.c (v_output): Just set up the dynamic environment
around the entire function, so that any Lisp evaluation that
occurs is happening as if it were via tleval.
-rw-r--r-- | match.c | 19 |
1 files changed, 15 insertions, 4 deletions
@@ -3734,6 +3734,13 @@ static val v_output(match_files_ctx *c) val named_var = nil, continue_expr = nil, finish_expr = nil; val alist; val stream = nil; + val ret = next_spec_k; + + uw_env_begin; + + val saved_de = set_dyn_env(make_env(c->bindings, nil, nil)); + + uw_set_match_context(cons(c->spec, c->spec)); if (first(dest_spec) == nothrow_k) { if (rest(dest_spec)) @@ -3812,7 +3819,7 @@ static val v_output(match_files_ctx *c) c->bindings = acons(into_var, list_out, c->bindings); } } - return next_spec_k; + goto out; } } @@ -3831,7 +3838,7 @@ static val v_output(match_files_ctx *c) if (finish_expr) close_stream(stream, t); - return next_spec_k; + goto out; } stream = complex_open(dest, t, append, nothrow, nil); @@ -3841,7 +3848,8 @@ static val v_output(match_files_ctx *c) if (!stream) { debuglf(specline, lit("could not open ~a: " "treating as failed match due to nothrow"), dest, nao); - return nil; + ret = nil; + goto out; } else { do_output(c->bindings, specs, filter, stream); flush_stream(stream); @@ -3852,7 +3860,10 @@ static val v_output(match_files_ctx *c) close_stream(stream, t); } - return next_spec_k; +out: + set_dyn_env(saved_de); + uw_env_end; + return ret; } static val v_try(match_files_ctx *c) |