diff --git a/src/compile.c b/src/compile.c index 05478ab8e8..b7e18882e1 100644 --- a/src/compile.c +++ b/src/compile.c @@ -830,8 +830,9 @@ static block bind_alternation_matchers(block matchers, block body) { } block gen_reduce(block source, block matcher, block init, block body) { - block res_var = gen_op_var_fresh(STOREV, "reduce"); - block loop = BLOCK(gen_op_simple(DUPN), + block res_var = gen_op_var_fresh(STOREV, "*reduce"); + block dot_var = gen_op_var_fresh(STOREV, "*dot"); + block loop = BLOCK(gen_op_simple(DUP), source, bind_alternation_matchers(matcher, BLOCK(gen_op_bound(LOADVN, res_var), @@ -841,15 +842,23 @@ block gen_reduce(block source, block matcher, block init, block body) { return BLOCK(gen_op_simple(DUP), init, res_var, + BLOCK( + // dummy null + gen_op_pushk_under(jv_null()), + // stores the actual input + dot_var + ), gen_op_target(FORK, loop), + //consumes dummy null and null-restores the actual input + gen_op_bound(LOADVN, dot_var), loop, + //consumes dummy null and null-restores the result gen_op_bound(LOADVN, res_var)); } 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), + block loop = BLOCK(gen_op_simple(DUP), // get a value from the source expression: source, // destructure the value into variable(s) for all the code @@ -864,28 +873,11 @@ block gen_foreach(block source, block matcher, block init, block update, block e // 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))); + extract))); 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 + loop); return foreach; }