summaryrefslogtreecommitdiffstats
path: root/compile.c
diff options
context:
space:
mode:
authorNicolas Williams <nico@cryptonector.com>2014-12-26 03:31:01 -0600
committerNicolas Williams <nico@cryptonector.com>2014-12-26 23:05:20 -0600
commite51e916e3191176f2d2f64ada60f6f4304ed0f54 (patch)
treeabd838721b8a26801ae94cb51b009e14898146c3 /compile.c
parent46e3125e26037cca5c9e9ecc257527c640797784 (diff)
Fix `foreach` non-progation of errors
Errors were being re-propagated as "break". Also add `error/0` builtin, which made this fix easier.
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/compile.c b/compile.c
index 50a3d49a..042161db 100644
--- a/compile.c
+++ b/compile.c
@@ -685,7 +685,16 @@ block gen_foreach(const char* varname, block source, block init, block update, b
gen_op_bound(STOREV, state_var),
// extract an output...
extract,
- // ...and output it
+ // ...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),
OP_HAS_VARIABLE));
block foreach = BLOCK(gen_op_simple(DUP),
@@ -693,14 +702,14 @@ block gen_foreach(const char* varname, block source, block init, block update, b
state_var,
gen_op_target(FORK, loop),
loop,
- // At this point `foreach`'s input will be on
- // top of the stack, and we don't want to output
- // it, so we backtrack.
+ // ...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);
+ inst_set_target(output, foreach); // make that JUMP go bast the BACKTRACK at the end of the loop
block handler = gen_cond(gen_call("_equal", BLOCK(gen_lambda(gen_const(jv_string("break"))), gen_lambda(gen_noop()))),
gen_op_simple(BACKTRACK),
- gen_call("break", gen_noop()));
+ gen_call("error", gen_noop()));
return gen_try(foreach, handler);
}