From: Stephen Dolan Date: Tue, 14 May 2013 15:09:10 +0000 (+0100) Subject: Add the range function X-Git-Tag: jq-1.3~11 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=81be37b23601a948164f0eb4a4f0331fa83ccf15;p=jq Add the range function --- diff --git a/builtin.c b/builtin.c index 2a48ba3..09ef9fc 100644 --- a/builtin.c +++ b/builtin.c @@ -530,6 +530,18 @@ static block bind_bytecoded_builtins(block b) { builtin_def_1arg[i].code)); } } + { + block rangevar = block_bind(gen_op_var_unbound(STOREV, "rangevar"), + gen_noop(), OP_HAS_VARIABLE); + block init = BLOCK(gen_op_simple(DUP), gen_call("start", gen_noop()), rangevar); + block range = BLOCK(init, + gen_call("end", gen_noop()), + gen_op_var_bound(RANGE, rangevar)); + builtins = BLOCK(builtins, gen_function("range", + BLOCK(gen_op_block_unbound(CLOSURE_PARAM, "start"), + gen_op_block_unbound(CLOSURE_PARAM, "end")), + range)); + } return block_bind(builtins, b, OP_IS_CALL_PSEUDO); } diff --git a/docs/content/3.manual/manual.yml b/docs/content/3.manual/manual.yml index 94348ea..e5fff39 100644 --- a/docs/content/3.manual/manual.yml +++ b/docs/content/3.manual/manual.yml @@ -588,6 +588,22 @@ sections: - program: add input: '[]' output: ["null"] + + - title: `range` + body: | + + The `range` function produces a range of numbers. `range(4;10)` + produces 6 numbers, from 4 (inclusive) to 10 (exclusive). The numbers + are produced as separate outputs. Use `[range(4;10)]` to get a range as + an array. + + examples: + - program: 'range(2;4)' + input: 'null' + output: ['2', '3'] + - program: '[range(2;4)]' + input: 'null' + output: ['[2,3]'] - title: `tonumber` body: | diff --git a/execute.c b/execute.c index 48262df..b9d1d31 100644 --- a/execute.c +++ b/execute.c @@ -266,6 +266,33 @@ jv jq_next(jq_state *jq) { break; } + case ON_BACKTRACK(RANGE): + case RANGE: { + uint16_t level = *pc++; + uint16_t v = *pc++; + frame_ptr fp = frame_get_level(&jq->frame_stk, frame_current(&jq->frame_stk), level); + jv* var = frame_local_var(fp, v); + jv max = stack_pop(jq); + if (jv_get_kind(*var) != JV_KIND_NUMBER || + jv_get_kind(max) != JV_KIND_NUMBER) { + print_error(jv_invalid_with_msg(jv_string_fmt("Range bounds must be numeric"))); + jv_free(max); + goto do_backtrack; + } else if (jv_number_value(jv_copy(*var)) >= jv_number_value(jv_copy(max))) { + /* finished iterating */ + goto do_backtrack; + } else { + jv curr = jv_copy(*var); + *var = jv_number(jv_number_value(*var) + 1); + + stack_save(jq, pc - 3); + stack_push(jq, jv_copy(max)); + stack_switch(jq); + stack_push(jq, curr); + } + break; + } + // FIXME: loadv/storev may do too much copying/freeing case LOADV: { uint16_t level = *pc++; diff --git a/opcode_list.h b/opcode_list.h index 91a6aba..3820687 100644 --- a/opcode_list.h +++ b/opcode_list.h @@ -13,6 +13,7 @@ OP(JUMP_F,BRANCH, 1, 0) OP(BACKTRACK, NONE, 0, 0) OP(APPEND, VARIABLE,1, 0) OP(INSERT, NONE, 4, 2) +OP(RANGE, VARIABLE, 1, 1) OP(SUBEXP_BEGIN, NONE, 1, 2) OP(SUBEXP_END, NONE, 2, 2)