]> granicus.if.org Git - jq/commitdiff
Add the range function
authorStephen Dolan <mu@netsoc.tcd.ie>
Tue, 14 May 2013 15:09:10 +0000 (16:09 +0100)
committerStephen Dolan <mu@netsoc.tcd.ie>
Tue, 14 May 2013 15:09:10 +0000 (16:09 +0100)
builtin.c
docs/content/3.manual/manual.yml
execute.c
opcode_list.h

index 2a48ba35dec69001cac646f2e2a0bb6ad3349418..09ef9fcdc076143ca55c29d095e30eece7d62d3b 100644 (file)
--- 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);
 }
index 94348ea7cc5069585905f2ca7df22625ef128ce5..e5fff391c0cd3dbfe828662fb1620371c98c00ab 100644 (file)
@@ -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: |
index 48262df81835f2ef6304006c44b2de09fc5c1efb..b9d1d31d897c4401568aa7994aad5695033eb9e4 100644 (file)
--- 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++;
index 91a6aba1fe176c6b8f21ed1a86fd82bed691b273..38206871d8f9d4a213385a3a6ef23854cb509c33 100644 (file)
@@ -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)