diff options
-rw-r--r-- | builtin.c | 3 | ||||
-rw-r--r-- | compile.c | 16 | ||||
-rw-r--r-- | compile.h | 1 | ||||
-rw-r--r-- | execute.c | 28 | ||||
-rw-r--r-- | opcode_list.h | 1 | ||||
-rw-r--r-- | parser.y | 19 | ||||
-rw-r--r-- | testdata | 4 |
7 files changed, 19 insertions, 53 deletions
@@ -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));", + }; @@ -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"), @@ -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); @@ -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; diff --git a/opcode_list.h b/opcode_list.h index e460ffe9..0185b5a6 100644 --- a/opcode_list.h +++ b/opcode_list.h @@ -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) @@ -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 { @@ -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}] |