1
0
mirror of https://github.com/stedolan/jq.git synced 2024-05-11 05:55:39 +00:00

Fix foreach non-progation of errors

Errors were being re-propagated as "break".

Also add `error/0` builtin, which made this fix easier.
This commit is contained in:
Nicolas Williams
2014-12-26 03:31:01 -06:00
parent 46e3125e26
commit e51e916e31
2 changed files with 16 additions and 6 deletions

View File

@@ -959,6 +959,7 @@ static block bind_bytecoded_builtins(block b) {
#define LIBM_DD(name) "def " #name ": _" #name ";",
static const char* const jq_builtins[] = {
"def error: error(.);",
"def break: error(\"break\");",
"def map(f): [.[] | f];",
"def map_values(f): .[] |= f;",

View File

@@ -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);
}