]> granicus.if.org Git - jq/commitdiff
Fix a bug in lexical scoping, add tests
authorStephen Dolan <mu@netsoc.tcd.ie>
Tue, 28 Aug 2012 17:38:30 +0000 (18:38 +0100)
committerStephen Dolan <mu@netsoc.tcd.ie>
Tue, 28 Aug 2012 17:38:30 +0000 (18:38 +0100)
c/compile.c
c/execute.c
c/frame_layout.h
c/testdata

index f9f738d8f7832139eac4bc3e66c51cfecca3695b..dc90aed343406f881e4a948e591af753d755d6f0 100644 (file)
@@ -418,7 +418,10 @@ static void compile(struct bytecode* bc, block b) {
         default: assert(0 && "Unknown type of argument");
         case CLOSURE_CREATE:
           code[pos++] = curr->bound_by->imm.intval | ARG_NEWCLOSURE;
-          if (i == 0) desired_params = bc->subfunctions[curr->bound_by->imm.intval]->nclosures;
+          if (i == 0) {
+            inst* i = curr->bound_by;
+            desired_params = i->compiled->subfunctions[i->imm.intval]->nclosures;
+          }
           break;
         case CLOSURE_PARAM:
           code[pos++] = curr->bound_by->imm.intval;
index 75aaec09c6dafd387bfb1cdf950e0705e6a0d6f7..9aa85b293647c6a0cd65eb72854252cb8db7a455 100644 (file)
@@ -104,9 +104,10 @@ static struct closure make_closure(struct forkable_stack* stk, frame_ptr fr, uin
   if (idx & ARG_NEWCLOSURE) {
     int subfn_idx = idx & ~ARG_NEWCLOSURE;
     assert(subfn_idx < frame_self(fr)->bc->nsubfunctions);
-    return closure_new(stk, frame_self(fr)->bc->subfunctions[subfn_idx]);
+    struct closure cl = {frame_self(fr)->bc->subfunctions[subfn_idx],
+                         forkable_stack_to_idx(stk, fr)};
+    return cl;
   } else {
-    // FIXME: set pc
     return *frame_closure_arg(fr, idx);
   }
 }
@@ -214,6 +215,9 @@ json_t* jq_next() {
       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);
+      printf("V%d = ", v);
+      json_dumpf(*var, stdout, JSON_ENCODE_ANY);
+      printf("\n");
       stack_push(stackval_replace(stack_pop(), *var));
       break;
     }
@@ -411,7 +415,8 @@ void jq_init(struct bytecode* bc, json_t* input) {
   forkable_stack_init(&fork_stk, 10240); // FIXME: lower this number, see if it breaks
   
   stack_push(stackval_root(input));
-  frame_push(&frame_stk, closure_new_toplevel(bc), 0);
+  struct closure top = {bc, -1};
+  frame_push(&frame_stk, top, 0);
   frame_push_backtrack(&frame_stk, bc->code);
 }
 
index b2e590ebf46dfbca44fb6c4be0d5a290a4408db2..fcbd1dc335d076b590b91c4a2a88fc16a8660555 100644 (file)
@@ -79,17 +79,6 @@ static frame_ptr frame_get_level(struct forkable_stack* stk, frame_ptr fr, int l
   return fr;
 }
 
-static struct closure closure_new_toplevel(struct bytecode* bc) {
-  struct closure cl = {bc, -1};
-  return cl;
-}
-
-static struct closure closure_new(struct forkable_stack* stk, struct bytecode* bc) {
-  struct closure cl = {bc, 
-                       forkable_stack_to_idx(stk, frame_current(stk))};
-  return cl;
-}
-
 static frame_ptr frame_push(struct forkable_stack* stk, struct closure cl, uint16_t* retaddr) {
   frame_ptr fp = forkable_stack_push(stk, frame_size(cl.bc));
   struct continuation* cc = frame_self(fp);
index 6e40b9ae1fa00c6f51d9b2b8b1bb43d983eea193..95e40781e423147e891c3514e8bdb05cba289e11 100644 (file)
@@ -143,6 +143,8 @@ def f: (1000,2000); f
 1000
 2000
 
+# test backtracking through function calls and returns
+# this test is *evil*
 [[20,10][1,0] as $x | def f: (100,200) as $y | def g: [$x + $y, .]; . + $x | g; f[0] | [f][0][1] | f]
 "woo, testing!"
 [[110.0, 130.0], [210.0, 130.0], [110.0, 230.0], [210.0, 230.0], [120.0, 160.0], [220.0, 160.0], [120.0, 260.0], [220.0, 260.0]]
@@ -154,3 +156,7 @@ def f(x): x | x; f([.], . + [42])
 [[1,2,3,42]]
 [1,2,3,42,42]
 
+# test closures and lexical scoping
+def id(x):x; 2000 as $x | def f(x):1 as $x | id([$x, x, x]); def g(x): 100 as $x | f($x,$x+x); g($x)
+"more testing"
+[1,100,2100.0,100,2100.0]