From eea05ff9248210210977cd5679b90437bc3733ff Mon Sep 17 00:00:00 2001 From: Stephen Dolan Date: Mon, 3 Sep 2012 16:50:38 +0100 Subject: [PATCH] Perl-style autovivification. .foo.bar = 1 will cause objects to be created if they don't exist. --- c/jv.c | 19 ++++++++++++++----- c/jv.h | 32 +++++++++++++++++++++++++++----- c/testdata | 18 ++++++++++++++++-- 3 files changed, 57 insertions(+), 12 deletions(-) diff --git a/c/jv.c b/c/jv.c index 4484dc9..9a3d308 100644 --- a/c/jv.c +++ b/c/jv.c @@ -125,10 +125,13 @@ static int jvp_array_length(jv_complex* a) { } static jv* jvp_array_read(jv_complex* a, int i) { - assert(i >= 0 && i < jvp_array_length(a)); - jvp_array* array = jvp_array_ptr(a); - assert(i + a->i[0] < array->length); - return &array->elements[i + a->i[0]]; + if (i >= 0 && i < jvp_array_length(a)) { + jvp_array* array = jvp_array_ptr(a); + assert(i + a->i[0] < array->length); + return &array->elements[i + a->i[0]]; + } else { + return 0; + } } static jv* jvp_array_write(jv_complex* a, int i) { @@ -223,7 +226,13 @@ int jv_array_length(jv j) { jv jv_array_get(jv j, int idx) { assert(jv_get_kind(j) == JV_KIND_ARRAY); - jv val = jv_copy(*jvp_array_read(&j.val.complex, idx)); + jv* slot = jvp_array_read(&j.val.complex, idx); + jv val; + if (slot) { + val = jv_copy(*slot); + } else { + val = jv_invalid(); + } jv_free(j); return val; } diff --git a/c/jv.h b/c/jv.h index b251329..8d9ebad 100644 --- a/c/jv.h +++ b/c/jv.h @@ -104,6 +104,14 @@ static jv jv_lookup(jv t, jv k) { } else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_NUMBER) { // FIXME: don't do lookup for noninteger index v = jv_array_get(t, (int)jv_number_value(k)); + if (!jv_is_valid(v)) { + v = jv_null(); + } + } else if (jv_get_kind(t) == JV_KIND_NULL && + (jv_get_kind(k) == JV_KIND_STRING || jv_get_kind(k) == JV_KIND_NUMBER)) { + jv_free(t); + jv_free(k); + v = jv_null(); } else { assert(0&&"bad lookup"); } @@ -118,12 +126,26 @@ static jv jv_lookup(jv t, jv k) { } static jv jv_modify(jv t, jv k, jv v) { - if (jv_get_kind(t) == JV_KIND_OBJECT && jv_get_kind(k) == JV_KIND_STRING) { - t = jv_object_set(t, k, v); - } else if (jv_get_kind(t) == JV_KIND_ARRAY && jv_get_kind(k) == JV_KIND_NUMBER) { - t = jv_array_set(t, (int)jv_number_value(k), 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"); + } } else { - assert(0 && "bad mod"); + assert(0 && "bad mod - seriously, wtf"); } return t; } diff --git a/c/testdata b/c/testdata index c6388d6..7007118 100644 --- a/c/testdata +++ b/c/testdata @@ -133,12 +133,18 @@ null # Builtin functions # -# FIXME: floats vs. integer - 1+1 null 2 +1+1 +"wtasdf" +2.0 + +1e+0+0.001e3 +"I wonder what this will be?" +20e-1 + .+4 15 19.0 @@ -212,3 +218,11 @@ def id(x):x; 2000 as $x | def f(x):1 as $x | id([$x, x, x]); def g(x): 100 as $x def inc(x): x |= .+1; inc(.[].a) [{"a":1,"b":2},{"a":2,"b":4},{"a":7,"b":8}] [{"a":2,"b":2},{"a":3,"b":4},{"a":8,"b":8}] + +.[2][3] = 1 +[4] +[4, null, [null, null, null, 1]] + +.foo[2].bar = 1 +{"foo":[11], "bar":42} +{"foo":[11,null,{"bar":1}], "bar":42} -- 2.40.0