Skip to content

Commit 25b03bf

Browse files
committedFeb 17, 2025
fix: foreach should not break init backtracking with DUPN
Fixes compilation of `foreach` to avoid the problem in jqlang#3227. Does not address `reduce`, which is less trivial.
1 parent 6d8e9f9 commit 25b03bf

File tree

1 file changed

+19
-39
lines changed

1 file changed

+19
-39
lines changed
 

‎src/compile.c

+19-39
Original file line numberDiff line numberDiff line change
@@ -845,46 +845,26 @@ block gen_reduce(block source, block matcher, block init, block body) {
845845
}
846846

847847
block gen_foreach(block source, block matcher, block init, block update, block extract) {
848-
block output = gen_op_targetlater(JUMP);
849848
block state_var = gen_op_var_fresh(STOREV, "foreach");
850-
block loop = BLOCK(gen_op_simple(DUPN),
851-
// get a value from the source expression:
852-
source,
853-
// destructure the value into variable(s) for all the code
854-
// in the body to see
855-
bind_alternation_matchers(matcher,
856-
// load the loop state variable
857-
BLOCK(gen_op_bound(LOADV, state_var),
858-
// generate updated state
859-
update,
860-
// save the updated state for value extraction
861-
gen_op_simple(DUP),
862-
// save new state
863-
gen_op_bound(STOREV, state_var),
864-
// extract an output...
865-
extract,
866-
// ...and output it by jumping
867-
// past the BACKTRACK that comes
868-
// right after the loop body,
869-
// which in turn is there
870-
// because...
871-
//
872-
// (Incidentally, extract can also
873-
// backtrack, e.g., if it calls
874-
// empty, in which case we don't
875-
// get here.)
876-
output)));
877-
block foreach = BLOCK(gen_op_simple(DUP),
878-
init,
879-
state_var,
880-
gen_op_target(FORK, loop),
881-
loop,
882-
// ...at this point `foreach`'s original input
883-
// will be on top of the stack, and we don't
884-
// want to output it, so we backtrack.
885-
gen_op_simple(BACKTRACK));
886-
inst_set_target(output, foreach); // make that JUMP go bast the BACKTRACK at the end of the loop
887-
return foreach;
849+
return BLOCK(gen_op_simple(DUP),
850+
init,
851+
state_var,
852+
gen_op_simple(DUP),
853+
// get a value from the source expression:
854+
source,
855+
// destructure the value into variable(s) for all the code
856+
// in the body to see
857+
bind_alternation_matchers(matcher,
858+
// load the loop state variable
859+
BLOCK(gen_op_bound(LOADV, state_var),
860+
// generate updated state
861+
update,
862+
// save the updated state for value extraction
863+
gen_op_simple(DUP),
864+
// save new state
865+
gen_op_bound(STOREV, state_var),
866+
// extract an output...
867+
extract)));
888868
}
889869

890870
block gen_definedor(block a, block b) {

0 commit comments

Comments
 (0)