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 | 6a9a84f20e925f76f58d935d9844215af4bf0363 (patch) | |
tree | d63553113db4a5c015cddecf25ee85eaf2f83a01 /match.c | |
parent | 5ca3693a7b5d65fd5aa67c737e7a60b457db2281 (diff) | |
download | txr-6a9a84f20e925f76f58d935d9844215af4bf0363.tar.gz txr-6a9a84f20e925f76f58d935d9844215af4bf0363.tar.bz2 txr-6a9a84f20e925f76f58d935d9844215af4bf0363.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.
Diffstat (limited to 'match.c')
-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) |