]> granicus.if.org Git - jq/commitdiff
first pass at assignment
authorStephen Dolan <mu@netsoc.tcd.ie>
Mon, 27 Aug 2012 09:11:55 +0000 (10:11 +0100)
committerStephen Dolan <mu@netsoc.tcd.ie>
Mon, 27 Aug 2012 09:12:02 +0000 (10:12 +0100)
c/compile.c
c/compile.h
c/execute.c
c/jv.h [new file with mode: 0644]
c/lexer.l
c/opcode_list.h
c/parser.y
c/testdata

index d2b9cee7ca44b8a9adc6bc5ad98ea770f815653a..93f7188809d272da3652ef322050386949502bde 100644 (file)
@@ -288,6 +288,25 @@ block gen_collect(block expr) {
   return c;
 }
 
+block gen_assign(block expr) {
+  block c = gen_noop();
+  block_append(&c, gen_op_simple(DUP));
+  block result_var = block_bind(gen_op_var_unbound(STOREV, "result"),
+                                gen_noop(), OP_HAS_VARIABLE);
+  block_append(&c, result_var);
+
+  block loop = gen_noop();
+  block_append(&loop, gen_op_simple(DUP));
+  block_append(&loop, expr);
+  block_append(&loop, gen_op_var_bound(ASSIGN, result_var));
+  block_append(&loop, gen_op_simple(BACKTRACK));
+
+  block_append(&c, gen_op_target(FORK, loop));
+  block_append(&c, loop);
+  block_append(&c, gen_op_var_bound(LOADV, result_var));
+  return c;
+}
+
 block gen_else(block a, block b) {
   assert(0);
 }
index d72ddcefde0407642f7179d360f58b93a4b03230..2ce02c0ea11a67373332264296338b816ecf5ac9 100644 (file)
@@ -25,6 +25,7 @@ block gen_op_symbol(opcode op, const char* name);
 block gen_subexp(block a);
 block gen_both(block a, block b);
 block gen_collect(block expr);
+block gen_assign(block expr);
 block gen_else(block a, block b);
 
 
index 9d952d6b8198ed396d52a4b33641751102189b38..f9e2570c24a9f2f246ee3c0735ab6b5f5cf8e9cc 100644 (file)
@@ -12,6 +12,8 @@
 #include "forkable_stack.h"
 #include "frame_layout.h"
 
+#include "jv.h"
+
 
 typedef struct {
   json_t* value;
@@ -108,6 +110,8 @@ static struct closure make_closure(struct forkable_stack* stk, frame_ptr fr, uin
     return *frame_closure_arg(fr, idx);
   }
 }
+
+
 #define stack_push stk_push
 #define stack_pop stk_pop
 
@@ -245,20 +249,37 @@ json_t* jq_next() {
     }
 #endif
 
+    case ASSIGN_DBG: {
+      stackval replacement = stack_pop();
+      stackval path_end = stack_pop();
+      stackval path_start = stack_pop();
+      json_t* obj = jv_insert(path_start.value, replacement.value, pathbuf + path_start.pathidx, path_end.pathidx - path_start.pathidx);
+      stack_push(stackval_replace(path_start, obj));
+      break;
+    }
+
+    case ASSIGN: {
+      stackval replacement = stack_pop();
+      stackval path_end = stack_pop();
+      stackval path_start = stack_pop();
+
+      uint16_t level = *pc++;
+      uint16_t v = *pc++;
+      frame_ptr fp = frame_get_level(&frame_stk, frame_current(&frame_stk), level);
+      json_t** var = frame_local_var(fp, v);
+      *var = jv_insert(*var, replacement.value, pathbuf + path_start.pathidx, path_end.pathidx - path_start.pathidx);
+      break;
+    }
+
     case INDEX: {
       stackval t = stack_pop();
       json_t* k = stack_pop().value;
-      stackval v;
-      if (json_is_string(k)) {
-        v.value = json_object_get(t.value, json_string_value(k));
-      } else if (json_is_integer(k)) {
-        v.value = json_array_get(t.value, json_integer_value(k));
-      } else {
-        assert(0 && "key neither string nor int");
-      }
-      if (v.value) {
-        v.pathidx = path_push(t, k);
-        stack_push(v);
+      json_t* v = jv_lookup(t.value, k);
+      if (v) {
+        stackval sv;
+        sv.value = v;
+        sv.pathidx = path_push(t, k);
+        stack_push(sv);
       } else {
         assert(0 && "bad lookup");
       }
@@ -314,6 +335,7 @@ json_t* jq_next() {
       pc++; // skip offset this time
       break;
     }
+
     case ON_BACKTRACK(FORK): {
       uint16_t offset = *pc++;
       pc += offset;
diff --git a/c/jv.h b/c/jv.h
new file mode 100644 (file)
index 0000000..fc964fa
--- /dev/null
+++ b/c/jv.h
@@ -0,0 +1,41 @@
+#ifndef JV_H
+#define JV_H
+
+#include <jansson.h>
+
+static json_t* jv_lookup(json_t* t, json_t* k) {
+  json_t* v;
+  if (json_is_object(t) && json_is_string(k)) {
+    v = json_object_get(t, json_string_value(k));
+  } else if (json_is_array(t) && json_is_number(k)) {
+    v = json_array_get(t, json_integer_value(k));
+  } else {
+    assert(0&&"bad lookup");
+  }
+  if (v) 
+    return v;
+  else
+    return json_null();
+}
+
+static json_t* jv_modify(json_t* t, json_t* k, json_t* v) {
+  t = json_copy(t);
+  if (json_is_object(t) && json_is_string(k)) {
+    json_object_set(t, json_string_value(k), v);
+  } else if (json_is_array(t) && json_is_number(k)) {
+    json_array_set(t, json_integer_value(k), v);
+  } else {
+    assert(0 && "bad mod");
+  }
+  return t;
+}
+
+static json_t* jv_insert(json_t* root, json_t* value, json_t** path, int pathlen) {
+  if (pathlen == 0) {
+    return value;
+  }
+  return jv_modify(root, *path, jv_insert(jv_lookup(root, *path), value, path+1, pathlen-1));
+}
+
+
+#endif
index abf33263e0824c10239bf4ac996d05dd609625e8..e4ffafcef5c3dff2a1efad6ab620ade619448542 100644 (file)
--- a/c/lexer.l
+++ b/c/lexer.l
@@ -12,6 +12,7 @@
 "==" { return EQ; }
 "as" { return AS; }
 "def" { return DEF; }
+"|=" { return SETPIPE; }
 "."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"\$" { return yytext[0];}
 
 [[:digit:]]+  { yylval->num = atoi(yytext);   return NUMBER;}
index 1d6d277366b530389ec9a1b242733e300448f824..dde072262dd2958800fbc7838b80348343bd1d58 100644 (file)
@@ -14,6 +14,9 @@ OP(BACKTRACK, NONE, 0, 0)
 OP(APPEND, NONE,    2, 1)
 OP(INSERT, NONE,    4, 2)
 
+OP(ASSIGN_DBG, NONE, 3, 1)
+OP(ASSIGN, VARIABLE, 3, 0)
+
 OP(CALL_BUILTIN_1_1, CFUNC, 1, 1)
 OP(CALL_BUILTIN_3_1, CFUNC, 3, 1)
 
index ebc90a32176f6be242b5e0db1b5542981ea07bf2..31c708653d672ca88cbf82ee9b9431b6872b5634 100644 (file)
@@ -28,6 +28,8 @@
 %token EQ "=="
 %token AS "as"
 %token DEF "def"
+%token SETPIPE "|="
+%nonassoc '=' SETPIPE
 %nonassoc EQ
 %left '+'
 
@@ -76,6 +78,22 @@ Term "as" '$' IDENT '|' Exp {
   block_append(&$$, block_bind(gen_op_var_unbound(STOREV, $4), $6, OP_HAS_VARIABLE));
 } |
 
+Exp '=' Exp {
+  block assign = gen_op_simple(DUP);
+  block_append(&assign, $3);
+  block_append(&assign, gen_op_simple(SWAP));
+  block_append(&assign, $1);
+  block_append(&assign, gen_op_simple(SWAP));
+  $$ = gen_assign(assign);
+} |
+
+Exp "|=" Exp {
+  block assign = $1;
+  block_append(&assign, gen_op_simple(DUP));
+  block_append(&assign, $3);
+  $$ = gen_assign(assign);
+} |
+
 Exp '|' Exp { 
   $$ = block_join($1, $3); 
 } |
index f2bd4ee31336766280b0551db8762bb0da8bcb8a..1d8420d6c9adc54d5a6f3eeb9087eaad38ff7796 100644 (file)
@@ -153,3 +153,4 @@ def f(x): $$x | $$x; $$f([.], . + [42])
 [[1,2,3],42]
 [[1,2,3,42]]
 [1,2,3,42,42]
+