diff --git a/src/core/corelib.c b/src/core/corelib.c index 8abcb2a0..a2f68df4 100644 --- a/src/core/corelib.c +++ b/src/core/corelib.c @@ -262,59 +262,15 @@ static Janet janet_core_setdyn(int32_t argc, Janet *argv) { return argv[1]; } +// XXX inline asm function with a new op - OP_GET_PERMISSIVE? +// This would match up with OP_GET which is used for 'in'. static Janet janet_core_get(int32_t argc, Janet *argv) { janet_arity(argc, 2, 3); - Janet ds = argv[0]; - Janet key = argv[1]; - Janet dflt = argc == 3 ? argv[2] : janet_wrap_nil(); - JanetType t = janet_type(argv[0]); - switch (t) { - default: - return dflt; - case JANET_STRING: - case JANET_SYMBOL: - case JANET_KEYWORD: { - if (!janet_checkint(key)) return dflt; - int32_t index = janet_unwrap_integer(key); - if (index < 0) return dflt; - const uint8_t *str = janet_unwrap_string(ds); - if (index >= janet_string_length(str)) return dflt; - return janet_wrap_integer(str[index]); - } - case JANET_ABSTRACT: { - void *abst = janet_unwrap_abstract(ds); - JanetAbstractType *type = (JanetAbstractType *)janet_abstract_type(abst); - if (!type->get) return dflt; - return (type->get)(abst, key); - } - case JANET_ARRAY: - case JANET_TUPLE: { - if (!janet_checkint(key)) return dflt; - int32_t index = janet_unwrap_integer(key); - if (index < 0) return dflt; - if (t == JANET_ARRAY) { - JanetArray *a = janet_unwrap_array(ds); - if (index >= a->count) return dflt; - return a->data[index]; - } else { - const Janet *t = janet_unwrap_tuple(ds); - if (index >= janet_tuple_length(t)) return dflt; - return t[index]; - } - } - case JANET_TABLE: { - JanetTable *flag = NULL; - Janet ret = janet_table_get_ex(janet_unwrap_table(ds), key, &flag); - if (flag == NULL) return dflt; - return ret; - } - case JANET_STRUCT: { - const JanetKV *st = janet_unwrap_struct(ds); - Janet ret = janet_struct_get(st, key); - if (janet_checktype(ret, JANET_NIL)) return dflt; - return ret; - } + Janet result = janet_get_permissive(argv[0], argv[1]); + if (argc == 3 && janet_checktype(result, JANET_NIL)) { + return argv[2]; } + return result; } static Janet janet_core_native(int32_t argc, Janet *argv) { diff --git a/src/core/value.c b/src/core/value.c index e6c4d75d..4e9f8bea 100644 --- a/src/core/value.c +++ b/src/core/value.c @@ -207,6 +207,52 @@ Janet janet_get(Janet ds, Janet key) { return value; } +Janet janet_get_permissive(Janet ds, Janet key) { + JanetType t = janet_type(ds); + switch (t) { + default: + return janet_wrap_nil(); + case JANET_STRING: + case JANET_SYMBOL: + case JANET_KEYWORD: { + if (!janet_checkint(key)) return janet_wrap_nil(); + int32_t index = janet_unwrap_integer(key); + if (index < 0) return janet_wrap_nil(); + const uint8_t *str = janet_unwrap_string(ds); + if (index >= janet_string_length(str)) return janet_wrap_nil(); + return janet_wrap_integer(str[index]); + } + case JANET_ABSTRACT: { + 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); + } + case JANET_ARRAY: + case JANET_TUPLE: { + if (!janet_checkint(key)) return janet_wrap_nil(); + int32_t index = janet_unwrap_integer(key); + if (index < 0) return janet_wrap_nil(); + if (t == JANET_ARRAY) { + JanetArray *a = janet_unwrap_array(ds); + if (index >= a->count) return janet_wrap_nil(); + return a->data[index]; + } else { + const Janet *t = janet_unwrap_tuple(ds); + if (index >= janet_tuple_length(t)) return janet_wrap_nil(); + return t[index]; + } + } + case JANET_TABLE: { + return janet_table_get(janet_unwrap_table(ds), key); + } + case JANET_STRUCT: { + const JanetKV *st = janet_unwrap_struct(ds); + return janet_struct_get(st, key); + } + } +} + Janet janet_getindex(Janet ds, int32_t index) { Janet value; if (index < 0) janet_panic("expected non-negative index"); diff --git a/src/include/janet.h b/src/include/janet.h index 02219c8d..eda37ae5 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -1285,6 +1285,7 @@ JANET_API int32_t janet_hash(Janet x); JANET_API int janet_compare(Janet x, Janet y); JANET_API int janet_cstrcmp(const uint8_t *str, const char *other); JANET_API Janet janet_get(Janet ds, Janet key); +JANET_API Janet janet_get_permissive(Janet ds, Janet key); JANET_API Janet janet_getindex(Janet ds, int32_t index); JANET_API int32_t janet_length(Janet x); JANET_API Janet janet_lengthv(Janet x);