]> granicus.if.org Git - jq/commitdiff
Move from Jansson to JV - interpreter loop
authorStephen Dolan <mu@netsoc.tcd.ie>
Sun, 2 Sep 2012 16:20:13 +0000 (17:20 +0100)
committerStephen Dolan <mu@netsoc.tcd.ie>
Sun, 2 Sep 2012 16:20:13 +0000 (17:20 +0100)
Passes tests, but leaks some memory.

c/Makefile
c/execute.c
c/execute.h [deleted file]
c/forkable_stack.h
c/frame_layout.h
c/jv.c
c/main.c

index bf33acf35e864ca12fee6429b306b62838155662..2e5982046d768ba7241a35905eff6cd6352630a9 100644 (file)
@@ -17,8 +17,8 @@ parser.tab.c: parser.y lexer.yy.h
        bison -W -d parser.y -v --report-file=parser.info
 parser.tab.h: parser.tab.c
 
-parsertest: parser.tab.c lexer.yy.c main.c opcode.c bytecode.c compile.c execute.c builtin.c
-       $(CC) -o $@ $^ -ljansson
+parsertest: parser.tab.c lexer.yy.c main.c opcode.c bytecode.c compile.c execute.c builtin.c jv.c jv_parse.c jv_print.c jv_dtoa.c
+       $(CC) -o $@ $^
 
 jvtest: jvtest.c jv.c jv_print.c
        $(CC) -DNO_JANSSON -o $@ $^
index 9aa85b293647c6a0cd65eb72854252cb8db7a455..4677936384a778b2826e1a89e600726b7f37e842 100644 (file)
@@ -1,10 +1,8 @@
-#include <jansson.h>
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
 
-
 #include "opcode.h"
 #include "bytecode.h"
 #include "compile.h"
 
 
 typedef struct {
-  json_t* value;
+  jv value;
   int pathidx;
 } stackval;
 
 
-json_t** pathbuf;
+jv* pathbuf;
 int pathsize; // number of allocated elements
 
-
-int path_push(stackval sv, json_t* val) {
+// FIXME mem
+int path_push(stackval sv, jv val) {
   int pos = sv.pathidx;
   assert(pos <= pathsize);
   assert(pos >= 0);
@@ -37,14 +35,15 @@ int path_push(stackval sv, json_t* val) {
   return pos + 1;
 }
 
-stackval stackval_replace(stackval value, json_t* newjs) {
+stackval stackval_replace(stackval value, jv newjs) {
+  jv_free(value.value);
   stackval s = {newjs, value.pathidx};
   return s;
 }
 
 
 // Probably all uses of this function are bugs
-stackval stackval_root(json_t* v) {
+stackval stackval_root(jv v) {
   stackval s = {v, 0};
   return s;
 }
@@ -63,7 +62,9 @@ void stk_push(stackval val) {
 stackval stk_pop() {
   data_stk_elem* s = forkable_stack_peek(&data_stk);
   stackval sv = s->sv;
-  forkable_stack_pop(&data_stk);
+  if (!forkable_stack_pop(&data_stk)) {
+    sv.value = jv_copy(sv.value);
+  }
   return sv;
 }
 
@@ -118,9 +119,9 @@ static struct closure make_closure(struct forkable_stack* stk, frame_ptr fr, uin
 
 #define ON_BACKTRACK(op) ((op)+NUM_OPCODES)
 
-json_t* jq_next() {
-  json_t* cfunc_input[MAX_CFUNCTION_ARGS] = {0};
-  json_t* cfunc_output[MAX_CFUNCTION_ARGS] = {0};
+jv jq_next() {
+  jv cfunc_input[MAX_CFUNCTION_ARGS];
+  jv cfunc_output[MAX_CFUNCTION_ARGS];
 
   assert(!forkable_stack_empty(&frame_stk));
   uint16_t* pc = *frame_current_retaddr(&frame_stk);
@@ -143,7 +144,7 @@ json_t* jq_next() {
       } else {
         param = forkable_stack_peek_next(&data_stk, param);
       }
-      json_dumpf(param->sv.value, stdout, JSON_ENCODE_ANY);
+      jv_dump(jv_copy(param->sv.value));
       if (i < opdesc->stack_in-1) printf(" | ");
     }
 
@@ -159,16 +160,18 @@ json_t* jq_next() {
     default: assert(0 && "invalid instruction");
 
     case LOADK: {
-      json_t* v = json_array_get(frame_current_bytecode(&frame_stk)->constants, *pc++);
-      assert(v);
+      jv v = jv_array_get(jv_copy(frame_current_bytecode(&frame_stk)->constants), *pc++);
+      //FIXME assert(v);
       stack_push(stackval_replace(stack_pop(), v));
       break;
     }
 
     case DUP: {
       stackval v = stack_pop();
+      stackval v2 = v;
+      v2.value = jv_copy(v.value);
       stack_push(v);
-      stack_push(v);
+      stack_push(v2);
       break;
     }
 
@@ -181,44 +184,42 @@ json_t* jq_next() {
     }
       
     case POP: {
-      stack_pop();
+      jv_free(stack_pop().value);
       break;
     }
 
     case APPEND: {
       // FIXME paths
-      json_t* v = stack_pop().value;
-      json_t* array = stack_pop().value;
-      array = json_copy(array);
-      json_array_append(array, v);
+      jv v = stack_pop().value;
+      jv array = stack_pop().value;
+      array = jv_array_append(array, v);
       stack_push(stackval_root(array));
       break;
     }
 
     case INSERT: {
       stackval stktop = stack_pop();
-      json_t* v = stack_pop().value;
-      json_t* k = stack_pop().value;
+      jv v = stack_pop().value;
+      jv k = stack_pop().value;
       stackval objv = stack_pop();
-      assert(json_is_string(k));
-      assert(json_is_object(objv.value));
-      json_t* obj = json_copy(objv.value);
-      json_object_set(obj, json_string_value(k), v);
-      assert(json_is_object(obj));
-      stack_push(stackval_replace(objv, obj));
+      assert(jv_get_kind(k) == JV_KIND_STRING);
+      assert(jv_get_kind(objv.value) == JV_KIND_OBJECT);
+      objv.value = jv_object_set(objv.value, k, v);
+      stack_push(objv);
       stack_push(stktop);
       break;
     }
 
+      // FIXME: loadv/storev may do too much copying/freeing
     case LOADV: {
       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);
+      jv* var = frame_local_var(fp, v);
       printf("V%d = ", v);
-      json_dumpf(*var, stdout, JSON_ENCODE_ANY);
+      jv_dump(jv_copy(*var));
       printf("\n");
-      stack_push(stackval_replace(stack_pop(), *var));
+      stack_push(stackval_replace(stack_pop(), jv_copy(*var)));
       break;
     }
 
@@ -226,43 +227,31 @@ json_t* jq_next() {
       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);
+      jv* var = frame_local_var(fp, v);
       stackval val = stack_pop();
       printf("V%d = ", v);
-      json_dumpf(val.value, stdout, JSON_ENCODE_ANY);
+      jv_dump(jv_copy(val.value));
       printf("\n");
+      jv_free(*var);
       *var = val.value;
       break;
     }
 
-#if 0
-    case DISPLAY: {
-      stackval sv = stack_pop();
-      if (sv.value) {
-        json_dumpf(sv.value, stdout, JSON_ENCODE_ANY);
-      } else {
-        printf("#ERROR");
-      }
-      printf(" - ");
-      for (int i = 0; i < sv.pathidx; i++) {
-        printf("/");
-        json_dumpf(pathbuf[i], stdout, JSON_ENCODE_ANY);
-      }
-      printf("\n");
-      return;
-    }
-#endif
-
     case ASSIGN_DBG: {
+      assert(0);
+      /*
       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: {
+      assert(0);
+      /*
       stackval replacement = stack_pop();
       stackval path_end = stack_pop();
       stackval path_start = stack_pop();
@@ -272,17 +261,18 @@ json_t* jq_next() {
       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;
-      json_t* v = jv_lookup(t.value, k);
-      if (v) {
+      jv k = stack_pop().value;
+      jv v = jv_lookup(t.value, k);
+      if (1 /* fixme invalid lookups */) {
         stackval sv;
         sv.value = v;
-        sv.pathidx = path_push(t, k);
+        sv.pathidx = 0; //FIXME path_push(t, k);
         stack_push(sv);
       } else {
         assert(0 && "bad lookup");
@@ -298,23 +288,24 @@ json_t* jq_next() {
     }
 
     case EACH: 
-      stack_push(stackval_root(json_integer(0)));
+      stack_push(stackval_root(jv_number(0)));
       // fallthrough
     case ON_BACKTRACK(EACH): {
-      json_t* idxj = stack_pop().value;
-      int idx = json_integer_value(idxj);
+      int idx = jv_number_value(stack_pop().value);
       stackval array = stack_pop();
-      if (idx >= json_array_size(array.value)) {
+      if (idx >= jv_array_length(jv_copy(array.value))) {
         goto do_backtrack;
       } else {
         stack_save();
-        stack_push(array);
-        stack_push(stackval_root(json_integer(idx+1)));
+        stackval array2 = array;
+        array2.value = jv_copy(array2.value);
+        stack_push(array2);
+        stack_push(stackval_root(jv_number(idx+1)));
         frame_push_backtrack(&frame_stk, pc - 1);
         stack_switch();
         
-        stackval sv = {json_array_get(array.value, idx), 
-                       path_push(array, json_integer(idx))};
+        stackval sv = {jv_array_get(array.value, idx), 
+                       path_push(array, jv_number(idx))};
         stack_push(sv);
       }
       break;
@@ -323,7 +314,8 @@ json_t* jq_next() {
     do_backtrack:
     case BACKTRACK: {
       if (forkable_stack_empty(&fork_stk)) {
-        return 0;
+        // FIXME: invalid
+        return jv_null();
       }
       stack_restore();
       pc = *frame_current_retaddr(&frame_stk);
@@ -347,7 +339,7 @@ json_t* jq_next() {
     }
 
     case YIELD: {
-      json_t* value = stack_pop().value;
+      jv value = stack_pop().value;
       frame_push_backtrack(&frame_stk, pc);
       return value;
     }
@@ -361,7 +353,8 @@ json_t* jq_next() {
       struct cfunction* func = &frame_current_bytecode(&frame_stk)->globals->cfunctions[*pc++];
       printf(" call %s\n", func->name);
       func->fptr(cfunc_input, cfunc_output);
-      stack_push(stackval_replace(top, cfunc_output[0]));
+      top.value = cfunc_output[0];
+      stack_push(top);
       break;
     }
 
@@ -370,15 +363,16 @@ json_t* jq_next() {
       pc++; // skip nclosures
       pc++; // skip level
       stackval top = stack_pop();
-      json_t* a = stack_pop().value;
-      json_t* b = stack_pop().value;
+      jv a = stack_pop().value;
+      jv b = stack_pop().value;
       cfunc_input[0] = top.value;
       cfunc_input[1] = a;
       cfunc_input[2] = b;
       struct cfunction* func = &frame_current_bytecode(&frame_stk)->globals->cfunctions[*pc++];
       printf(" call %s\n", func->name);
       func->fptr(cfunc_input, cfunc_output);
-      stack_push(stackval_replace(top, cfunc_output[0]));
+      top.value = cfunc_output[0];
+      stack_push(top);
       break;
     }
 
@@ -409,7 +403,7 @@ json_t* jq_next() {
 }
 
 
-void jq_init(struct bytecode* bc, json_t* input) {
+void jq_init(struct bytecode* bc, jv input) {
   forkable_stack_init(&data_stk, sizeof(stackval) * 1000); // FIXME: lower this number, see if it breaks
   forkable_stack_init(&frame_stk, 10240); // FIXME: lower this number, see if it breaks
   forkable_stack_init(&fork_stk, 10240); // FIXME: lower this number, see if it breaks
@@ -421,10 +415,12 @@ void jq_init(struct bytecode* bc, json_t* input) {
 }
 
 void run_program(struct bytecode* bc) {
-  jq_init(bc, json_loadf(stdin, 0, 0));
-  json_t* result;
-  while ((result = jq_next())) {
-    json_dumpf(result, stdout, JSON_ENCODE_ANY);
+  char buf[4096];
+  fgets(buf, sizeof(buf), stdin);
+  jq_init(bc, jv_parse(buf));
+  jv result;
+  while (jv_get_kind(result = jq_next()) != JV_KIND_NULL) {
+    jv_dump(result);
     printf("\n");
   }
   printf("end of results\n");
diff --git a/c/execute.h b/c/execute.h
deleted file mode 100644 (file)
index b978a8e..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#include "opcode.h"
-#define MAX_CFUNCTION_PARAM 10
-typedef struct {
-  json_t* value;
-  int pathidx;
-} stackval;
-
-typedef void (*cfunction_ptr)(stackval* input, stackval* output);
-
-struct cfunction {
-  cfunction_ptr fptr;
-  const char* name;
-  opcode callop;
-};
index 971b4ec0e622e11cd5693aaf96ba46f90602aea2..9283198942953f8a2694dfae8fe2d2df46eb6810 100644 (file)
@@ -83,10 +83,14 @@ static void* forkable_stack_peek_next(struct forkable_stack* s, void* top) {
   }
 }
 
-static void forkable_stack_pop(struct forkable_stack* s) {
+// Returns 1 if the object being popped can not be accessed again
+// (i.e. was not saved with a fork)
+static int forkable_stack_pop(struct forkable_stack* s) {
   forkable_stack_check(s);
+  int finalpop = s->pos < s->savedlimit ? 1 : 0;
   struct forkable_stack_header* elem = forkable_stack_peek(s);
   s->pos = elem->next;
+  return finalpop;
 }
 
 
index fcbd1dc335d076b590b91c4a2a88fc16a8660555..141dbcd884bdb50bd3265db5f3f6dd6960ec1886 100644 (file)
@@ -1,7 +1,6 @@
 #ifndef FRAME_LAYOUT_H
 #include "forkable_stack.h"
 #include "bytecode.h"
-#include <jansson.h>
 
 struct closure {
   struct bytecode* bc;
@@ -18,7 +17,7 @@ typedef union frame_elem {
   FORKABLE_STACK_HEADER;
   struct continuation cont;
   struct closure closure;
-  json_t* jsonval;
+  jv jsonval;
 } *frame_ptr;
 
 /*
@@ -43,7 +42,7 @@ static struct closure* frame_closure_arg(frame_ptr fr, int closure) {
   return &fr[2+closure].closure;
 }
 
-static json_t** frame_local_var(frame_ptr fr, int var) {
+static jv* frame_local_var(frame_ptr fr, int var) {
   assert(var >= 0);
   assert(var < frame_self(fr)->bc->nlocals);
   return &fr[2 + frame_self(fr)->bc->nclosures + var].jsonval;
@@ -85,6 +84,9 @@ static frame_ptr frame_push(struct forkable_stack* stk, struct closure cl, uint1
   cc->bc = cl.bc;
   cc->env = cl.env;
   cc->retaddr = retaddr;
+  for (int i=0; i<cl.bc->nlocals; i++) {
+    *frame_local_var(fp, i) = jv_null();
+  }
   return fp;
 }
 
diff --git a/c/jv.c b/c/jv.c
index 7944d642f1b40108eaab7c426c712cda55665f45..03954314f4a1dedbb6f5bd726ecfe7396d924b6c 100644 (file)
--- a/c/jv.c
+++ b/c/jv.c
@@ -239,7 +239,7 @@ jv jv_array_concat(jv a, jv b) {
   assert(jv_get_kind(b) == JV_KIND_ARRAY);
 
   // FIXME: could be much faster
-  for (int i=0; i<jv_array_length(b); i++) {
+  for (int i=0; i<jv_array_length(jv_copy(b)); i++) {
     a = jv_array_append(a, jv_array_get(jv_copy(b), i));
   }
   jv_free(b);
index 56d8d1d260376164ffa25a8d658be8f99a7d37ca..077268b49f09c5c6cde79f9b840d8d6095c20bac 100644 (file)
--- a/c/main.c
+++ b/c/main.c
@@ -6,10 +6,10 @@
 
 block compile(const char* str);
 
-//void jq_init(struct bytecode* bc, jv value);
-//jv jq_next();
+void jq_init(struct bytecode* bc, jv value);
+jv jq_next();
 
-//void run_program(struct bytecode* bc);
+void run_program(struct bytecode* bc);
 
 int skipline(const char* buf) {
   int p = 0;
@@ -39,13 +39,12 @@ void run_tests() {
     printf("\n");
     fgets(buf, sizeof(buf), testdata);
     jv input = jv_parse(buf);
-    jv_free(input); //jq_init(bc, input);
+    jq_init(bc, input);
 
     while (fgets(buf, sizeof(buf), testdata)) {
       if (skipline(buf)) break;
       jv expected = jv_parse(buf);
-      //jv actual = jq_next(); FIXME
-      jv actual = jv_copy(expected);
+      jv actual = jq_next();
       if (!1) {
         printf("Insufficient results\n");
         pass = 0;
@@ -84,5 +83,5 @@ int main(int argc, char* argv[]) {
   block_free(blk);
   dump_disassembly(0, bc);
   printf("\n");
-  //run_program(bc);
+  run_program(bc);
 }