summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Dolan <mu@netsoc.tcd.ie>2012-12-29 16:43:36 +0000
committerStephen Dolan <mu@netsoc.tcd.ie>2012-12-29 16:43:36 +0000
commitd5fdf70434a243e6f3bd6967dbc2d28c9144cb29 (patch)
tree17901a90c2a2ff0a2219fa9bab9a340af95e36c7
parent465a4ec565a106e0e4cc1d64214fb2d6d791c8dc (diff)
Refactor assignment.
New version is much more elegant and probably slower. Uses library functions implemented in jq rather than dedicated opcodes.
-rw-r--r--builtin.c3
-rw-r--r--compile.c16
-rw-r--r--compile.h1
-rw-r--r--execute.c28
-rw-r--r--opcode_list.h1
-rw-r--r--parser.y19
-rw-r--r--testdata4
7 files changed, 19 insertions, 53 deletions
diff --git a/builtin.c b/builtin.c
index dca3d6ff..f5917cbe 100644
--- 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));",
+
};
diff --git a/compile.c b/compile.c
index 178b0463..08187836 100644
--- 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"),
diff --git a/compile.h b/compile.h
index ce1b3089..150eef28 100644
--- 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);
diff --git a/execute.c b/execute.c
index ed251d18..94f6cd43 100644
--- 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;
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)
diff --git a/parser.y b/parser.y
index 2b9732c0..a1be0b7f 100644
--- 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 {
diff --git a/testdata b/testdata
index 576c02d6..224f0651 100644
--- 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}]