diff --git a/src/compile.c b/src/compile.c index da4c2f75..da8f8516 100644 --- a/src/compile.c +++ b/src/compile.c @@ -843,46 +843,26 @@ block gen_reduce(block source, block matcher, block init, block body) { } block gen_foreach(block source, block matcher, block init, block update, block extract) { - block output = gen_op_targetlater(JUMP); block state_var = gen_op_var_fresh(STOREV, "foreach"); - block loop = BLOCK(gen_op_simple(DUPN), - // get a value from the source expression: - source, - // destructure the value into variable(s) for all the code - // in the body to see - bind_alternation_matchers(matcher, - // load the loop state variable - BLOCK(gen_op_bound(LOADV, state_var), - // generate updated state - update, - // save the updated state for value extraction - gen_op_simple(DUP), - // save new state - gen_op_bound(STOREV, state_var), - // extract an output... - extract, - // ...and output it by jumping - // past the BACKTRACK that comes - // right after the loop body, - // which in turn is there - // because... - // - // (Incidentally, extract can also - // backtrack, e.g., if it calls - // empty, in which case we don't - // get here.) - output))); - block foreach = BLOCK(gen_op_simple(DUP), - init, - state_var, - gen_op_target(FORK, loop), - loop, - // ...at this point `foreach`'s original input - // will be on top of the stack, and we don't - // want to output it, so we backtrack. - gen_op_simple(BACKTRACK)); - inst_set_target(output, foreach); // make that JUMP go bast the BACKTRACK at the end of the loop - return foreach; + return BLOCK(gen_op_simple(DUP), + init, + state_var, + gen_op_simple(DUP), + // get a value from the source expression: + source, + // destructure the value into variable(s) for all the code + // in the body to see + bind_alternation_matchers(matcher, + // load the loop state variable + BLOCK(gen_op_bound(LOADV, state_var), + // generate updated state + update, + // save the updated state for value extraction + gen_op_simple(DUP), + // save new state + gen_op_bound(STOREV, state_var), + // extract an output... + extract))); } block gen_definedor(block a, block b) { diff --git a/tests/jq.test b/tests/jq.test index f5a57b18..245652bb 100644 --- a/tests/jq.test +++ b/tests/jq.test @@ -2319,3 +2319,11 @@ try ltrimstr("x") catch "x", try rtrimstr("x") catch "x" | "ok" try ["OK", setpath([[1]]; 1)] catch ["KO", .] [] ["KO","Cannot update field at array index of array"] + +# regression test for #3227 +foreach .[] as $x (0, 1; . + $x) +[1, 2] +1 +3 +2 +4