]> granicus.if.org Git - jq/commitdiff
Better error handling and messages for invalid index/assign operations.
authorStephen Dolan <mu@netsoc.tcd.ie>
Tue, 11 Sep 2012 09:37:44 +0000 (10:37 +0100)
committerStephen Dolan <mu@netsoc.tcd.ie>
Tue, 11 Sep 2012 09:37:44 +0000 (10:37 +0100)
c/execute.c
c/jv.c
c/jv.h

index 9f7b63b5704ce467ff330815f69e10ea7e18ff1b..cbde413a419baddc37e3a10177213e6dfa29ed7b 100644 (file)
@@ -133,7 +133,14 @@ static struct closure make_closure(struct forkable_stack* stk, frame_ptr fr, uin
   }
 }
 
-
+void print_error(jv value) {
+  assert(!jv_is_valid(value));
+  jv msg = jv_invalid_get_msg(value);
+  if (jv_get_kind(msg) == JV_KIND_STRING) {
+    fprintf(stderr, "jq: error: %s\n", jv_string_value(msg));
+  }
+  jv_free(msg);
+}
 #define ON_BACKTRACK(op) ((op)+NUM_OPCODES)
 
 jv jq_next() {
@@ -273,7 +280,13 @@ jv jq_next() {
       uint16_t v = *pc++;
       frame_ptr fp = frame_get_level(&frame_stk, frame_current(&frame_stk), level);
       jv* var = frame_local_var(fp, v);
-      *var = jv_insert(*var, replacement.value, pathbuf + path_start.pathidx, path_end.pathidx - path_start.pathidx);
+      jv result = jv_insert(*var, replacement.value, pathbuf + path_start.pathidx, path_end.pathidx - path_start.pathidx);
+      if (jv_is_valid(result)) {
+        *var = result;
+      } else {
+        print_error(result);
+        *var = jv_null();
+      }
       break;
     }
 
@@ -282,13 +295,14 @@ jv jq_next() {
       jv k = stack_pop().value;
       int pathidx = path_push(t, jv_copy(k));
       jv v = jv_lookup(t.value, k);
-      if (1 /* fixme invalid lookups */) {
+      if (jv_is_valid(v)) {
         stackval sv;
         sv.value = v;
         sv.pathidx = pathidx;
         stack_push(sv);
       } else {
-        assert(0 && "bad lookup");
+        print_error(v);
+        goto do_backtrack;
       }
       break;
     }
@@ -379,11 +393,7 @@ jv jq_next() {
       if (jv_is_valid(top.value)) {
         stack_push(top);
       } else {
-        jv msg = jv_invalid_get_msg(top.value);
-        if (jv_get_kind(msg) == JV_KIND_STRING) {
-          fprintf(stderr, "jq: error: %s\n", jv_string_value(msg));
-        }
-        jv_free(msg);
+        print_error(top.value);
         goto do_backtrack;
       }
       break;
@@ -405,11 +415,7 @@ jv jq_next() {
       if (jv_is_valid(top.value)) {
         stack_push(top);
       } else {
-        jv msg = jv_invalid_get_msg(top.value);
-        if (jv_get_kind(msg) == JV_KIND_STRING) {
-          fprintf(stderr, "jq: error: %s\n", jv_string_value(msg));
-        }
-        jv_free(msg);
+        print_error(top.value);
         goto do_backtrack;
       }
       break;
diff --git a/c/jv.c b/c/jv.c
index f8b79ce6e827fa17eb9d063e10e1be3ec8b38256..214354ce20f57a8aab663fdfaa66306c17a8a312 100644 (file)
--- a/c/jv.c
+++ b/c/jv.c
@@ -49,7 +49,7 @@ const char* jv_kind_name(jv_kind k) {
   case JV_KIND_ARRAY:   return "array";
   case JV_KIND_OBJECT:  return "object";
   }
-  assert(0);
+  assert(0 && "invalid kind");
   return "<unknown>";
 }
 
diff --git a/c/jv.h b/c/jv.h
index ef64816c6b9d41e5f4e62173b2b67663980ad1c4..3c557c45eebe493bc879a22355e2ce48a63c347c 100644 (file)
--- a/c/jv.h
+++ b/c/jv.h
@@ -126,39 +126,33 @@ static jv jv_lookup(jv t, jv k) {
     jv_free(k);
     v = jv_null();
   } else {
-    assert(0&&"bad lookup");
+    v = jv_invalid_with_msg(jv_string_fmt("Cannot index %s with %s",
+                                          jv_kind_name(jv_get_kind(t)),
+                                          jv_kind_name(jv_get_kind(k))));
+    jv_free(t);
+    jv_free(k);
   }
   return v;
-  // FIXME: invalid indexes, JV_KIND_INVALID
-  /*
-  if (v) 
-    return v;
-  else
-    return jv_null();
-  */
 }
 
 static jv jv_modify(jv t, jv k, jv v) {
-  if (jv_get_kind(k) == JV_KIND_STRING) {
-    if (jv_get_kind(t) == JV_KIND_NULL) {
-      t = jv_object();
-    }
-    if (jv_get_kind(t) == JV_KIND_OBJECT) {
-      t = jv_object_set(t, k, v);
-    } else {
-      assert(0 && "bad mod - not an object");
-    }
-  } else if (jv_get_kind(k) == JV_KIND_NUMBER) {
-    if (jv_get_kind(t) == JV_KIND_NULL) {
-      t = jv_array();
-    }
-    if (jv_get_kind(t) == JV_KIND_ARRAY) {
-      t = jv_array_set(t, (int)jv_number_value(k), v);
-    } else {
-      assert(0 && "bad mod - not an array");
-    }
+  int isnull = jv_get_kind(t) == JV_KIND_NULL;
+  if (jv_get_kind(k) == JV_KIND_STRING && 
+      (jv_get_kind(t) == JV_KIND_OBJECT || isnull)) {
+    if (isnull) t = jv_object();
+    t = jv_object_set(t, k, v);
+  } else if (jv_get_kind(k) == JV_KIND_NUMBER &&
+             (jv_get_kind(t) == JV_KIND_ARRAY || isnull)) {
+    if (isnull) t = jv_array();
+    t = jv_array_set(t, (int)jv_number_value(k), v);
   } else {
-    assert(0 && "bad mod - seriously, wtf");
+    jv err = jv_invalid_with_msg(jv_string_fmt("Cannot update field at %s index of %s",
+                                               jv_kind_name(jv_get_kind(t)),
+                                               jv_kind_name(jv_get_kind(v))));
+    jv_free(t);
+    jv_free(k);
+    jv_free(v);
+    t = err;
   }
   return t;
 }