mirror of
https://github.com/janet-lang/janet
synced 2024-12-27 17:00:27 +00:00
Abstract type getters can indicate key absence.
This change to the c api allows abstract types to indicate to the runtime if a key was absent, or if it meant to return nil.
This commit is contained in:
parent
4c5734c2ee
commit
57ccfb692c
@ -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[] = {
|
||||
|
@ -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) {
|
||||
|
@ -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 */
|
||||
|
@ -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[] = {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user