diff --git a/src/core/inttypes.c b/src/core/inttypes.c index ac00854e..0df24454 100644 --- a/src/core/inttypes.c +++ b/src/core/inttypes.c @@ -36,8 +36,8 @@ #define MAX_INT_IN_DBL 9007199254740992ULL /* 2^53 */ -static Janet it_s64_get(void *p, Janet key); -static Janet it_u64_get(void *p, Janet key); +static int it_s64_get(void *p, Janet key, Janet *out); +static int it_u64_get(void *p, Janet key, Janet *out); static void int64_marshal(void *p, JanetMarshalContext *ctx) { janet_marshal_abstract(ctx, p); @@ -351,18 +351,20 @@ static JanetMethod it_u64_methods[] = { {NULL, NULL} }; -static Janet it_s64_get(void *p, Janet key) { +static int it_s64_get(void *p, Janet key, Janet *out) { (void) p; if (!janet_checktype(key, JANET_KEYWORD)) - janet_panicf("expected keyword, got %v", key); - return janet_getmethod(janet_unwrap_keyword(key), it_s64_methods); + return 0; + *out = janet_getmethod(janet_unwrap_keyword(key), it_s64_methods); + return !janet_checktype(*out, JANET_NIL); } -static Janet it_u64_get(void *p, Janet key) { +static int it_u64_get(void *p, Janet key, Janet *out) { (void) p; if (!janet_checktype(key, JANET_KEYWORD)) - janet_panicf("expected keyword, got %v", key); - return janet_getmethod(janet_unwrap_keyword(key), it_u64_methods); + return 0; + *out = janet_getmethod(janet_unwrap_keyword(key), it_u64_methods); + return !janet_checktype(*out, JANET_NIL); } static const JanetReg it_cfuns[] = { diff --git a/src/core/io.c b/src/core/io.c index 004125c1..cc4ae06b 100644 --- a/src/core/io.c +++ b/src/core/io.c @@ -53,7 +53,7 @@ struct IOFile { }; static int cfun_io_gc(void *p, size_t len); -static Janet io_file_get(void *p, Janet); +static int io_file_get(void *p, Janet key, Janet *out); JanetAbstractType cfun_io_filetype = { "core/file", @@ -353,11 +353,12 @@ static JanetMethod io_file_methods[] = { {NULL, NULL} }; -static Janet io_file_get(void *p, Janet key) { +static int io_file_get(void *p, Janet key, Janet *out) { (void) p; if (!janet_checktype(key, JANET_KEYWORD)) - janet_panicf("expected keyword, got %v", key); - return janet_getmethod(janet_unwrap_keyword(key), io_file_methods); + return 0; + *out = janet_getmethod(janet_unwrap_keyword(key), io_file_methods); + return !janet_checktype(*out, JANET_NIL); } FILE *janet_dynfile(const char *name, FILE *def) { diff --git a/src/core/math.c b/src/core/math.c index 62bcb8ed..d794ec86 100644 --- a/src/core/math.c +++ b/src/core/math.c @@ -29,7 +29,7 @@ static JANET_THREAD_LOCAL JanetRNG janet_vm_rng = {0, 0, 0, 0, 0}; -static Janet janet_rng_get(void *p, Janet key); +static int janet_rng_get(void *p, Janet key, Janet *out); static void janet_rng_marshal(void *p, JanetMarshalContext *ctx) { JanetRNG *rng = (JanetRNG *)p; @@ -196,10 +196,11 @@ static const JanetMethod rng_methods[] = { {NULL, NULL} }; -static Janet janet_rng_get(void *p, Janet key) { +static int janet_rng_get(void *p, Janet key, Janet *out) { (void) p; - if (!janet_checktype(key, JANET_KEYWORD)) janet_panicf("expected keyword method"); - return janet_getmethod(janet_unwrap_keyword(key), rng_methods); + if (!janet_checktype(key, JANET_KEYWORD)) return 0; + *out = janet_getmethod(janet_unwrap_keyword(key), rng_methods); + return !janet_checktype(*out, JANET_NIL); } /* Get a random number */ diff --git a/src/core/parse.c b/src/core/parse.c index 92486500..16430f55 100644 --- a/src/core/parse.c +++ b/src/core/parse.c @@ -730,7 +730,7 @@ static int parsergc(void *p, size_t size) { return 0; } -static Janet parserget(void *p, Janet key); +static int parserget(void *p, Janet key, Janet *out); static JanetAbstractType janet_parse_parsertype = { "core/parser", @@ -1055,10 +1055,11 @@ static const JanetMethod parser_methods[] = { {NULL, NULL} }; -static Janet parserget(void *p, Janet key) { +static int parserget(void *p, Janet key, Janet *out) { (void) p; - if (!janet_checktype(key, JANET_KEYWORD)) janet_panicf("expected keyword method"); - return janet_getmethod(janet_unwrap_keyword(key), parser_methods); + if (!janet_checktype(key, JANET_KEYWORD)) return 0; + *out = janet_getmethod(janet_unwrap_keyword(key), parser_methods); + return !janet_checktype(*out, JANET_NIL); } static const JanetReg parse_cfuns[] = { diff --git a/src/core/typedarray.c b/src/core/typedarray.c index e34fc69b..1b17dfea 100644 --- a/src/core/typedarray.c +++ b/src/core/typedarray.c @@ -166,50 +166,51 @@ static void *ta_view_unmarshal(JanetMarshalContext *ctx) { static JanetMethod tarray_view_methods[6]; -static Janet ta_getter(void *p, Janet key) { - Janet value; +static int ta_getter(void *p, Janet key, Janet *out) { size_t index, i; JanetTArrayView *array = p; - if (janet_checktype(key, JANET_KEYWORD)) - return janet_getmethod(janet_unwrap_keyword(key), tarray_view_methods); + if (janet_checktype(key, JANET_KEYWORD)) { + *out = janet_getmethod(janet_unwrap_keyword(key), tarray_view_methods); + return !janet_checktype(*out, JANET_NIL); + } if (!janet_checksize(key)) janet_panic("expected size as key"); index = (size_t) janet_unwrap_number(key); i = index * array->stride; if (index >= array->size) { - value = janet_wrap_nil(); + return 0; } else { switch (array->type) { case JANET_TARRAY_TYPE_U8: - value = janet_wrap_number(array->as.u8[i]); + *out = janet_wrap_number(array->as.u8[i]); break; case JANET_TARRAY_TYPE_S8: - value = janet_wrap_number(array->as.s8[i]); + *out = janet_wrap_number(array->as.s8[i]); break; case JANET_TARRAY_TYPE_U16: - value = janet_wrap_number(array->as.u16[i]); + *out = janet_wrap_number(array->as.u16[i]); break; case JANET_TARRAY_TYPE_S16: - value = janet_wrap_number(array->as.s16[i]); + *out = janet_wrap_number(array->as.s16[i]); break; case JANET_TARRAY_TYPE_U32: - value = janet_wrap_number(array->as.u32[i]); + *out = janet_wrap_number(array->as.u32[i]); break; case JANET_TARRAY_TYPE_S32: - value = janet_wrap_number(array->as.s32[i]); + *out = janet_wrap_number(array->as.s32[i]); break; #ifdef JANET_INT_TYPES case JANET_TARRAY_TYPE_U64: - value = janet_wrap_u64(array->as.u64[i]); + *out = janet_wrap_u64(array->as.u64[i]); break; case JANET_TARRAY_TYPE_S64: - value = janet_wrap_s64(array->as.s64[i]); + *out = janet_wrap_s64(array->as.s64[i]); break; #endif case JANET_TARRAY_TYPE_F32: - value = janet_wrap_number_safe(array->as.f32[i]); + *out = janet_wrap_number_safe(array->as.f32[i]); break; case JANET_TARRAY_TYPE_F64: - value = janet_wrap_number_safe(array->as.f64[i]); + *out = janet_wrap_number_safe(array->as.f64[i]); break; default: janet_panicf("cannot get from typed array of type %s", @@ -217,7 +218,7 @@ static Janet ta_getter(void *p, Janet key) { break; } } - return value; + return 1; } static void ta_setter(void *p, Janet key, Janet value) { @@ -450,7 +451,8 @@ static Janet cfun_typed_array_slice(int32_t argc, Janet *argv) { JanetArray *array = janet_array(range.end - range.start); if (array->data) { for (int32_t i = range.start; i < range.end; i++) { - array->data[i - range.start] = ta_getter(src, janet_wrap_number(i)); + if (!ta_getter(src, janet_wrap_number(i), &array->data[i - range.start])) + array->data[i - range.start] = janet_wrap_nil(); } } array->count = range.end - range.start; diff --git a/src/core/value.c b/src/core/value.c index 1189e3fb..7f436773 100644 --- a/src/core/value.c +++ b/src/core/value.c @@ -197,7 +197,8 @@ Janet janet_in(Janet ds, Janet key) { case JANET_ABSTRACT: { JanetAbstractType *type = (JanetAbstractType *)janet_abstract_type(janet_unwrap_abstract(ds)); if (type->get) { - value = (type->get)(janet_unwrap_abstract(ds), key); + if (!(type->get)(janet_unwrap_abstract(ds), key, &value)) + janet_panicf("key %v not found in %v ", key, ds); } else { janet_panicf("no getter for %v ", ds); } @@ -223,10 +224,13 @@ Janet janet_get(Janet ds, Janet key) { return janet_wrap_integer(str[index]); } case JANET_ABSTRACT: { + Janet value; void *abst = janet_unwrap_abstract(ds); JanetAbstractType *type = (JanetAbstractType *)janet_abstract_type(abst); if (!type->get) return janet_wrap_nil(); - return (type->get)(abst, key); + if ((type->get)(abst, key, &value)) + return value; + return janet_wrap_nil(); } case JANET_ARRAY: case JANET_TUPLE: @@ -304,7 +308,8 @@ Janet janet_getindex(Janet ds, int32_t index) { case JANET_ABSTRACT: { JanetAbstractType *type = (JanetAbstractType *)janet_abstract_type(janet_unwrap_abstract(ds)); if (type->get) { - value = (type->get)(janet_unwrap_abstract(ds), janet_wrap_integer(index)); + if (!(type->get)(janet_unwrap_abstract(ds), janet_wrap_integer(index), &value)) + value = janet_wrap_nil(); } else { janet_panicf("no getter for %v ", ds); } diff --git a/src/core/vm.c b/src/core/vm.c index 984ab3cf..fec41235 100644 --- a/src/core/vm.c +++ b/src/core/vm.c @@ -1200,9 +1200,8 @@ Janet janet_mcall(const char *name, int32_t argc, Janet *argv) { if (janet_checktype(argv[0], JANET_ABSTRACT)) { void *abst = janet_unwrap_abstract(argv[0]); JanetAbstractType *type = (JanetAbstractType *)janet_abstract_type(abst); - if (!type->get) + if (!type->get || !(type->get)(abst, janet_ckeywordv(name), &method)) janet_panicf("abstract value %v does not implement :%s", argv[0], name); - method = (type->get)(abst, janet_ckeywordv(name)); } else if (janet_checktype(argv[0], JANET_TABLE)) { JanetTable *table = janet_unwrap_table(argv[0]); method = janet_table_get(table, janet_ckeywordv(name)); diff --git a/src/include/janet.h b/src/include/janet.h index 753b6a32..9473d190 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -894,7 +894,7 @@ struct JanetAbstractType { const char *name; int (*gc)(void *data, size_t len); int (*gcmark)(void *data, size_t len); - Janet(*get)(void *data, Janet key); + int (*get)(void *data, Janet key, Janet *out); void (*put)(void *data, Janet key, Janet value); void (*marshal)(void *p, JanetMarshalContext *ctx); void *(*unmarshal)(JanetMarshalContext *ctx);