]> granicus.if.org Git - jq/commitdiff
Refactor assignment.
authorStephen Dolan <mu@netsoc.tcd.ie>
Sat, 29 Dec 2012 16:43:36 +0000 (16:43 +0000)
committerStephen Dolan <mu@netsoc.tcd.ie>
Sat, 29 Dec 2012 16:43:36 +0000 (16:43 +0000)
New version is much more elegant and probably slower. Uses
library functions implemented in jq rather than dedicated opcodes.

builtin.c
compile.c
compile.h
execute.c
opcode_list.h
parser.y
testdata

index dca3d6ff06310172faf532407aea3459dce238c8..f5917cbe73af16c0bed81d056c51b8673b05404b 100644 (file)
--- a/builtin.c
+++ b/builtin.c
@@ -552,6 +552,9 @@ static const char* jq_builtins[] = {
   "def max_by(f): _max_by_impl(map([f]));",
   "def min_by(f): _min_by_impl(map([f]));",
   "def del(f): delpaths([path(f)]);",
+  "def _assign(paths; value): value as $v | fold . as $obj (path(paths) as $p | $obj | setpath($p; $v));",
+  "def _modify(paths; update): fold . as $obj (path(paths) as $p | $obj | setpath($p; getpath($p) | update));",
+  
 };
 
 
index 178b046344370195d6a06db41c9fe20e05141b9d..081878364a79cb0df75cfc198fffb572b4d4de5f 100644 (file)
--- a/compile.c
+++ b/compile.c
@@ -317,22 +317,6 @@ block gen_fold(const char* varname, block init, block fold) {
                           OP_HAS_VARIABLE));
 }
 
-block gen_assign(block expr) {
-  block result_var = block_bind(gen_op_var_unbound(STOREV, "result"),
-                                gen_noop(), OP_HAS_VARIABLE);
-
-  block loop = BLOCK(gen_op_simple(DUP),
-                     expr,
-                     gen_op_var_bound(ASSIGN, result_var),
-                     gen_op_simple(BACKTRACK));
-
-  return BLOCK(gen_op_simple(DUP),
-               result_var,
-               gen_op_target(FORK, loop),
-               loop,
-               gen_op_var_bound(LOADV, result_var));
-}
-
 block gen_definedor(block a, block b) {
   // var found := false
   block found_var = block_bind(gen_op_var_unbound(STOREV, "found"),
index ce1b308968d2a9a85887536e305d8f9edfbe6078..150eef2828f6e825bb0673f54f2b636b68960832 100644 (file)
--- a/compile.h
+++ b/compile.h
@@ -34,7 +34,6 @@ block gen_subexp(block a);
 block gen_both(block a, block b);
 block gen_collect(block expr);
 block gen_fold(const char* varname, block init, block body);
-block gen_assign(block expr);
 block gen_definedor(block a, block b);
 block gen_condbranch(block iftrue, block iffalse);
 block gen_and(block a, block b);
index ed251d18f4939589f6446cd22681365b0e0c77de..94f6cd43c9faf59bac430e324a2f85e65f65b694 100644 (file)
--- a/execute.c
+++ b/execute.c
@@ -298,34 +298,6 @@ jv jq_next() {
       break;
     }
 
-    case ASSIGN: {
-      stackval replacement = stack_pop();
-      stackval path_end = stack_pop();
-      stackval path_start = stack_pop();
-      jv_free(path_end.value);
-      jv_free(path_start.value);
-
-      jv path = jv_array();
-      for (int i=path_start.pathidx; i<path_end.pathidx; i++) {
-        path = jv_array_set(path, i, jv_copy(pathbuf[i]));
-      }
-
-
-
-      uint16_t level = *pc++;
-      uint16_t v = *pc++;
-      frame_ptr fp = frame_get_level(&frame_stk, frame_current(&frame_stk), level);
-      jv* var = frame_local_var(fp, v);
-      jv result = jv_setpath(*var, path, replacement.value);
-      if (jv_is_valid(result)) {
-        *var = result;
-      } else {
-        print_error(result);
-        *var = jv_null();
-      }
-      break;
-    }
-
     case INDEX: {
       stackval t = stack_pop();
       jv k = stack_pop().value;
index e460ffe9d5b9818744c04722a3cfd2a542dd6dac..0185b5a6d603e03b1736ae0d5edf4aadd4650102 100644 (file)
@@ -16,7 +16,6 @@ OP(APPEND, NONE,    2, 1)
 OP(INSERT, NONE,    4, 2)
 
 OP(GETPATH, NONE,   2, 1)
-OP(ASSIGN, VARIABLE, 3, 0)
 
 OP(CALL_BUILTIN, CFUNC, -1, 1)
 
index 2b9732c09ffec53217f74273803cd5cedfbc8d24..a1be0b7fd3617e3f28bc6f32e5e0e4bfbf7bdb41 100644 (file)
--- a/parser.y
+++ b/parser.y
@@ -164,11 +164,16 @@ static block gen_format(block a, jv fmt) {
   return BLOCK(a, gen_call("format", BLOCK(gen_lambda(gen_const(fmt)))));
 }
  
-static block gen_update(block a, block op, int optype) {
-  if (optype) {
-    op = gen_binop(gen_noop(), op, optype);
-  }
-  return gen_assign(BLOCK(a, gen_op_simple(DUP), op));
+static block gen_update(block object, block val, int optype) {
+  block tmp = block_bind(gen_op_var_unbound(STOREV, "tmp"),
+                         gen_noop(), OP_HAS_VARIABLE);
+  return BLOCK(gen_op_simple(DUP),
+               val,
+               tmp,
+               gen_call("_modify", BLOCK(gen_lambda(object), 
+                                         gen_lambda(gen_binop(gen_noop(),
+                                                              gen_op_var_bound(LOADV, tmp),
+                                                              optype)))));
 }
 
 %}
@@ -216,7 +221,7 @@ Term "as" '$' IDENT '|' Exp {
 } |
 
 Exp '=' Exp {
-  $$ = gen_assign(BLOCK(gen_op_simple(DUP), $3, gen_op_simple(SWAP), $1, gen_op_simple(SWAP)));
+  $$ = gen_call("_assign", BLOCK(gen_lambda($1), gen_lambda($3)));
 } |
 
 Exp "or" Exp {
@@ -236,7 +241,7 @@ Exp "//=" Exp {
 } |
 
 Exp "|=" Exp {
-  $$ = gen_update($1, $3, 0);
+  $$ = gen_call("_modify", BLOCK(gen_lambda($1), gen_lambda($3)));
 } |
 
 Exp '|' Exp { 
index 576c02d66f0d3832330ffb318a4dedd4e5db5388..224f06516a954209cbd41f48c5f10cd084f0655f 100644 (file)
--- a/testdata
+++ b/testdata
@@ -411,6 +411,10 @@ null
 [-1,1,3]
 [0.5, 1.5, 2.5]
 
+.foo += .foo
+{"foo":2}
+{"foo":4}
+
 .[0].a |= {"old":., "new":(.+1)}
 [{"a":1,"b":2}]
 [{"a":{"old":1, "new":2},"b":2}]