summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Dolan <mu@netsoc.tcd.ie>2013-05-14 16:09:10 +0100
committerStephen Dolan <mu@netsoc.tcd.ie>2013-05-14 16:09:10 +0100
commit81be37b23601a948164f0eb4a4f0331fa83ccf15 (patch)
tree2b606e494caf6dff94405481a1e3a3557684d821
parent4d540b7102cb3a63ea5b966b1bbe42ad275fbf25 (diff)
Add the range function
-rw-r--r--builtin.c12
-rw-r--r--docs/content/3.manual/manual.yml16
-rw-r--r--execute.c27
-rw-r--r--opcode_list.h1
4 files changed, 56 insertions, 0 deletions
diff --git a/builtin.c b/builtin.c
index 2a48ba35..09ef9fcd 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 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: |
diff --git a/execute.c b/execute.c
index 48262df8..b9d1d31d 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 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)