From 539dccae904cebb575de46e7640739e90ab49404 Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Mon, 7 Jul 2014 18:48:13 -0500 Subject: [PATCH] Add `break` builtin for `foreach` --- builtin.c | 1 + compile.c | 5 ++++- docs/content/3.manual/manual.yml | 3 +-- tests/all.test | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/builtin.c b/builtin.c index e742c0e2..38ad1cfc 100644 --- a/builtin.c +++ b/builtin.c @@ -902,6 +902,7 @@ static block bind_bytecoded_builtins(block b) { #define LIBM_DD(name) "def " #name ": _" #name ";", static const char* const jq_builtins[] = { + "def break: error(\"break\");", "def map(f): [.[] | f];", "def select(f): if f then . else empty end;", "def sort(f): _sort_by_impl(map([f]));", diff --git a/compile.c b/compile.c index b3e58041..64ff41d0 100644 --- a/compile.c +++ b/compile.c @@ -406,7 +406,10 @@ block gen_foreach(const char* varname, block source, block init, block update, b // it, so we backtrack. gen_op_simple(BACKTRACK)); inst_set_target(output, foreach); - return foreach; + 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())); + return gen_try(foreach, handler); } block gen_definedor(block a, block b) { diff --git a/docs/content/3.manual/manual.yml b/docs/content/3.manual/manual.yml index 12fcffb7..e8e80115 100644 --- a/docs/content/3.manual/manual.yml +++ b/docs/content/3.manual/manual.yml @@ -1844,8 +1844,7 @@ sections: This is mostly useful only for constructing `reduce`- and `limit`-like functions. But it is much more general, as it allows for partial reductions (see the example below), as well - as breaking out of the "loop" with `empty`, or even `error(x)` - if there's a try/catch around the foreach. + as breaking out of the "loop" with `break`. examples: - program: '[foreach .[] as $item diff --git a/tests/all.test b/tests/all.test index e68998b7..1c8a3d3f 100644 --- a/tests/all.test +++ b/tests/all.test @@ -226,7 +226,7 @@ null 1 [1,2,4,8,16,32,64] -[foreach .[] as $item ([3, null]; if .[0] < 1 then empty else [.[0] -1, $item] end; .[1])] +[foreach .[] as $item ([3, null]; if .[0] < 1 then break else [.[0] -1, $item] end; .[1])] [11,22,33,44,55,66,77,88,99] [11,22,33]