diff --git a/c/execute.c b/c/execute.c index 9f7b63b5..cbde413a 100644 --- a/c/execute.c +++ b/c/execute.c @@ -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 f8b79ce6..214354ce 100644 --- 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 ""; } diff --git a/c/jv.h b/c/jv.h index ef64816c..3c557c45 100644 --- 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; }