diff options
author | Stephen Dolan <mu@netsoc.tcd.ie> | 2013-05-14 16:09:10 +0100 |
---|---|---|
committer | Stephen Dolan <mu@netsoc.tcd.ie> | 2013-05-14 16:09:10 +0100 |
commit | 81be37b23601a948164f0eb4a4f0331fa83ccf15 (patch) | |
tree | 2b606e494caf6dff94405481a1e3a3557684d821 | |
parent | 4d540b7102cb3a63ea5b966b1bbe42ad275fbf25 (diff) |
Add the range function
-rw-r--r-- | builtin.c | 12 | ||||
-rw-r--r-- | docs/content/3.manual/manual.yml | 16 | ||||
-rw-r--r-- | execute.c | 27 | ||||
-rw-r--r-- | opcode_list.h | 1 |
4 files changed, 56 insertions, 0 deletions
@@ -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 94348ea7..e5fff391 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: | @@ -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 91a6aba1..38206871 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) |