From af48912f11962f1b717360911884b80e5fcab990 Mon Sep 17 00:00:00 2001 From: "J.-F. Cap" Date: Sun, 24 Feb 2019 02:02:54 +0100 Subject: [PATCH] Simplify Abstract type introspection --- src/core/io.c | 3 ++ src/core/marsh.c | 31 ++++++++-------- src/core/parse.c | 3 ++ src/core/peg.c | 3 ++ src/core/typedarray.c | 83 ++++++++++++++++++++++++------------------- src/core/util.c | 62 ++++++++++++++------------------ src/include/janet.h | 34 +++++++++--------- 7 files changed, 115 insertions(+), 104 deletions(-) diff --git a/src/core/io.c b/src/core/io.c index 44904517..e4b5b28c 100644 --- a/src/core/io.c +++ b/src/core/io.c @@ -53,9 +53,12 @@ static Janet io_file_get(void *p, Janet); JanetAbstractType cfun_io_filetype = { "core/file", + 0, cfun_io_gc, NULL, io_file_get, + NULL, + NULL, NULL }; diff --git a/src/core/marsh.c b/src/core/marsh.c index 58a598f9..b32129e3 100644 --- a/src/core/marsh.c +++ b/src/core/marsh.c @@ -292,16 +292,17 @@ void janet_marshal_janet(JanetMarshalContext *ctx, Janet x) { static void marshal_one_abstract(MarshalState *st, Janet x, int flags) { - const JanetAbstractType *at = janet_abstract_type(janet_unwrap_abstract(x)); - const JanetAbstractTypeInfo *info = janet_get_abstract_type_info_byname(at->name); - if (info && info->marshal) { + void *abstract = janet_unwrap_abstract(x); + const JanetAbstractType *at = janet_abstract_type(abstract); + if (at->marshal) { MARK_SEEN(); JanetMarshalContext context = {st, NULL, flags, NULL}; pushbyte(st, LB_ABSTRACT); - pushint(st, info->tag); - info->marshal(janet_unwrap_abstract(x), &context); + pushint(st, at->id); + pushint(st, janet_abstract_size(abstract)); + at->marshal(abstract, &context); } else { - janet_panicf("try to marshal unregistered absttact type, cannot marshal %p", x); + janet_panicf("try to marshal unregistered abstract type, cannot marshal %p", x); } } @@ -462,9 +463,9 @@ static void marshal_one(MarshalState *st, Janet x, int flags) { return; } case JANET_ABSTRACT: { - marshal_one_abstract(st, x, flags); - return; - } + marshal_one_abstract(st, x, flags); + return; + } case JANET_FUNCTION: { pushbyte(st, LB_FUNCTION); JanetFunction *func = janet_unwrap_function(x); @@ -932,13 +933,13 @@ void janet_unmarshal_janet(JanetMarshalContext *ctx, Janet *out) { } static const uint8_t *unmarshal_one_abstract(UnmarshalState *st, const uint8_t *data, Janet *out, int flags) { - uint32_t tag = readint(st, &data); - const JanetAbstractTypeInfo *info = janet_get_abstract_type_info(tag); - if (info == NULL) return NULL; - if (info->unmarshal) { - void *p = janet_abstract(info->at, info->size); + uint32_t id = readint(st, &data); + const JanetAbstractType *at = janet_get_abstract_type(id); + if (at == NULL) return NULL; + if (at->unmarshal) { + void *p = janet_abstract(at, readint(st, &data)); JanetMarshalContext context = {NULL, st, flags, data}; - info->unmarshal(p, &context); + at->unmarshal(p, &context); *out = janet_wrap_abstract(p); return data; } diff --git a/src/core/parse.c b/src/core/parse.c index 841440b3..2c33454d 100644 --- a/src/core/parse.c +++ b/src/core/parse.c @@ -624,9 +624,12 @@ static Janet parserget(void *p, Janet key); static JanetAbstractType janet_parse_parsertype = { "core/parser", + 0, parsergc, parsermark, parserget, + NULL, + NULL, NULL }; diff --git a/src/core/peg.c b/src/core/peg.c index 2ab2244f..19ca9254 100644 --- a/src/core/peg.c +++ b/src/core/peg.c @@ -981,9 +981,12 @@ static int peg_mark(void *p, size_t size) { static JanetAbstractType peg_type = { "core/peg", + 0, NULL, peg_mark, NULL, + NULL, + NULL, NULL }; diff --git a/src/core/typedarray.c b/src/core/typedarray.c index 20d25b7d..9d960ac6 100644 --- a/src/core/typedarray.c +++ b/src/core/typedarray.c @@ -136,18 +136,17 @@ static void ta_buffer_unmarshal(void *p, JanetMarshalContext *ctx) { } -static const JanetAbstractType ta_buffer_type = {"ta/buffer", ta_buffer_gc, NULL, NULL, NULL}; - -static const JanetAbstractTypeInfo ta_buffer_typeinfo = { - &ta_buffer_type, - sizeof(TA_Buffer), +static const JanetAbstractType ta_buffer_type = { + "ta/buffer", 1000, - 0, + ta_buffer_gc, + NULL, + NULL, + NULL, ta_buffer_marshal, ta_buffer_unmarshal, }; - typedef struct { TA_Buffer *buffer; void *data; /* pointer inside buffer->data */ @@ -252,15 +251,13 @@ void ta_put_##type(void *p, Janet key,Janet value) { \ return view; \ }; -#define DEFINE_VIEW_ABSTRACT_TYPE(type) static const JanetAbstractType ta_view_##type##_t = {"ta/"#type,NULL,ta_mark,ta_get_##type,ta_put_##type}; #define BUILD_TYPE(type) \ DEFINE_VIEW_TYPE(type) \ DEFINE_VIEW_GETTER(type) \ DEFINE_VIEW_SETTER(type) \ -DEFINE_VIEW_INITIALIZER(type) \ -DEFINE_VIEW_ABSTRACT_TYPE(type) +DEFINE_VIEW_INITIALIZER(type) BUILD_TYPE(uint8) BUILD_TYPE(int8) @@ -277,28 +274,42 @@ BUILD_TYPE(float64) #undef DEFINE_VIEW_GETTER #undef DEFINE_VIEW_SETTER #undef DEFINE_VIEW_INITIALIZER + + +#define DEFINE_VIEW_ABSTRACT_TYPE(type,tag) \ +{ \ + "ta/"#type, \ + tag, \ + NULL, \ + ta_mark, \ + ta_get_##type, \ + ta_put_##type, \ + ta_view_marshal, \ + ta_view_unmarshal \ +} + +static const JanetAbstractType ta_array_types[] = { + DEFINE_VIEW_ABSTRACT_TYPE(uint8, 1001), + DEFINE_VIEW_ABSTRACT_TYPE(int8, 1002), + DEFINE_VIEW_ABSTRACT_TYPE(uint16, 1003), + DEFINE_VIEW_ABSTRACT_TYPE(int16, 1004), + DEFINE_VIEW_ABSTRACT_TYPE(uint32, 1005), + DEFINE_VIEW_ABSTRACT_TYPE(int32, 1006), + DEFINE_VIEW_ABSTRACT_TYPE(uint64, 1007), + DEFINE_VIEW_ABSTRACT_TYPE(int64, 1008), + DEFINE_VIEW_ABSTRACT_TYPE(float32, 1009), + DEFINE_VIEW_ABSTRACT_TYPE(float64, 1010) +}; + #undef DEFINE_VIEW_ABSTRACT_TYPE -#define VIEW_ABSTRACT_INFO_INIT(type,salt) {&ta_view_##type##_t,sizeof(TA_View),salt,0,ta_view_marshal,ta_view_unmarshal} -static const JanetAbstractTypeInfo ta_array_types[] = { - VIEW_ABSTRACT_INFO_INIT(uint8, 1001), - VIEW_ABSTRACT_INFO_INIT(int8, 1002), - VIEW_ABSTRACT_INFO_INIT(uint16, 1003), - VIEW_ABSTRACT_INFO_INIT(int16, 1004), - VIEW_ABSTRACT_INFO_INIT(uint32, 1005), - VIEW_ABSTRACT_INFO_INIT(int32, 1006), - VIEW_ABSTRACT_INFO_INIT(uint64, 1007), - VIEW_ABSTRACT_INFO_INIT(int64, 1008), - VIEW_ABSTRACT_INFO_INIT(float32, 1009), - VIEW_ABSTRACT_INFO_INIT(float64, 1010), -}; static int is_ta_type(Janet x) { if (janet_checktype(x, JANET_ABSTRACT)) { const JanetAbstractType *at = janet_abstract_type(janet_unwrap_abstract(x)); for (size_t i = 0; i < TA_COUNT_TYPES; i++) { - if (at == ta_array_types[i].at) return 1; + if (at == ta_array_types + i) return 1; } } return 0; @@ -331,7 +342,7 @@ static Janet cfun_typed_array_new(int32_t argc, Janet *argv) { buffer = (TA_Buffer *)janet_getabstract(argv, 4, &ta_buffer_type); } } - TA_View *view = janet_abstract(ta_array_types[type].at, sizeof(TA_View)); + TA_View *view = janet_abstract(&ta_array_types[type], sizeof(TA_View)); switch (type) { CASE_TYPE_INITIALIZE(uint8); CASE_TYPE_INITIALIZE(int8); @@ -389,23 +400,21 @@ static Janet cfun_typed_array_properties(int32_t argc, Janet *argv) { /* TODO for test it's not the good place for this function */ static Janet cfun_abstract_properties(int32_t argc, Janet *argv) { janet_fixarity(argc, 1); - JanetAbstractTypeInfo *info; + const JanetAbstractType *at; if (janet_checktype(argv[0], JANET_KEYWORD)) { const uint8_t *keyw = janet_unwrap_keyword(argv[0]); - info = janet_get_abstract_type_info_byname((const char *)keyw); + at = janet_get_abstract_type_byname((const char *)keyw); } else { - uint32_t tag = (uint32_t)janet_getinteger(argv, 0); - info = janet_get_abstract_type_info(tag); + uint32_t id = (uint32_t)janet_getinteger(argv, 0); + at = janet_get_abstract_type(id); } - if (info == NULL) { + if (at == NULL) { return janet_wrap_nil(); } - JanetKV *props = janet_struct_begin(5); - janet_struct_put(props, janet_ckeywordv("tag"), janet_wrap_number(info->tag)); - janet_struct_put(props, janet_ckeywordv("salt"), janet_wrap_number(info->salt)); - janet_struct_put(props, janet_ckeywordv("name"), janet_ckeywordv(info->at->name)); - janet_struct_put(props, janet_ckeywordv("size"), janet_wrap_number(info->size)); - janet_struct_put(props, janet_ckeywordv("marshal"), janet_wrap_boolean((info->marshal != NULL) && (info->unmarshal != NULL))); + JanetKV *props = janet_struct_begin(3); + janet_struct_put(props, janet_ckeywordv("id"), janet_wrap_number(at->id)); + janet_struct_put(props, janet_ckeywordv("name"), janet_ckeywordv(at->name)); + janet_struct_put(props, janet_ckeywordv("marshal"), janet_wrap_boolean((at->marshal != NULL) && (at->unmarshal != NULL))); return janet_wrap_struct(janet_struct_end(props)); } @@ -527,7 +536,7 @@ static const JanetReg ta_cfuns[] = { /* Module entry point */ void janet_lib_typed_array(JanetTable *env) { janet_core_cfuns(env, NULL, ta_cfuns); - janet_register_abstract_type(&ta_buffer_typeinfo); + janet_register_abstract_type(&ta_buffer_type); for (size_t i = 0; i < TA_COUNT_TYPES; i++) { janet_register_abstract_type(ta_array_types + i); } diff --git a/src/core/util.c b/src/core/util.c index 9093cdc5..8777ae0a 100644 --- a/src/core/util.c +++ b/src/core/util.c @@ -286,58 +286,50 @@ void janet_cfuns(JanetTable *env, const char *regprefix, const JanetReg *cfuns) /* Abstract type introspection */ -static const JanetAbstractType type_info = {"core/type_info", NULL, NULL, NULL, NULL}; +static const JanetAbstractType type_wrap = {"core/type_info", 0, NULL, NULL, NULL, NULL, NULL, NULL}; -static uint32_t janet_abstract_type_gentag(const char *name, uint32_t salt) { - /* something smarter should propably done here ? */ - int32_t len = strlen(name); - const char *end = name + len; - uint32_t hash = 5381 + salt; - while (name < end) - hash = (hash << 5) + hash + *name++; - return (int32_t) hash; -} +typedef struct { + const JanetAbstractType *at; +} JanetAbstractTypeWrap; -void janet_register_abstract_type(const JanetAbstractTypeInfo *info) { - JanetAbstractTypeInfo *abstract = (JanetAbstractTypeInfo *)janet_abstract(&type_info, sizeof(JanetAbstractTypeInfo)); - memcpy(abstract, info, sizeof(JanetAbstractTypeInfo)); - abstract->tag = janet_abstract_type_gentag(info->at->name, info->salt); - if (!(janet_checktype(janet_table_get(janet_vm_registry, janet_wrap_number(abstract->tag)), JANET_NIL)) || - !(janet_checktype(janet_table_get(janet_vm_registry, janet_ckeywordv(abstract->at->name)), JANET_NIL))) { - janet_panic("Register abstract type fail, a type with same name or tag exist"); + +void janet_register_abstract_type(const JanetAbstractType *at) { + JanetAbstractTypeWrap *abstract = (JanetAbstractTypeWrap *)janet_abstract(&type_wrap, sizeof(JanetAbstractTypeWrap)); + abstract->at = at; + if (!(janet_checktype(janet_table_get(janet_vm_registry, janet_wrap_number(at->id)), JANET_NIL)) || + !(janet_checktype(janet_table_get(janet_vm_registry, janet_ckeywordv(at->name)), JANET_NIL))) { + janet_panic("Register abstract type fail, a type with same name or id exists"); } - janet_table_put(janet_vm_registry, janet_wrap_number(abstract->tag), janet_wrap_abstract(abstract)); - janet_table_put(janet_vm_registry, janet_ckeywordv(abstract->at->name), janet_wrap_abstract(abstract)); + janet_table_put(janet_vm_registry, janet_wrap_number(at->id), janet_wrap_abstract(abstract)); + janet_table_put(janet_vm_registry, janet_ckeywordv(at->name), janet_wrap_abstract(abstract)); } -JanetAbstractTypeInfo *janet_get_abstract_type_info(uint32_t tag) { - Janet info = janet_table_get(janet_vm_registry, janet_wrap_number(tag)); - if (janet_checktype(info, JANET_NIL)) { +const JanetAbstractType *janet_get_abstract_type(uint32_t id) { + Janet twrap = janet_table_get(janet_vm_registry, janet_wrap_number(id)); + if (janet_checktype(twrap, JANET_NIL)) { return NULL; } - if (!janet_checktype(info, JANET_ABSTRACT) || (janet_abstract_type(janet_unwrap_abstract(info)) != &type_info)) { - janet_panic("expected type_info"); + if (!janet_checktype(twrap, JANET_ABSTRACT) || (janet_abstract_type(janet_unwrap_abstract(twrap)) != &type_wrap)) { + janet_panic("expected abstract type"); } - JanetAbstractTypeInfo *type_info = (JanetAbstractTypeInfo *)janet_unwrap_abstract(info); - return type_info; + JanetAbstractTypeWrap *w = (JanetAbstractTypeWrap *)janet_unwrap_abstract(twrap); + return w->at; } -JanetAbstractTypeInfo *janet_get_abstract_type_info_byname(const char *name) { - Janet info = janet_table_get(janet_vm_registry, janet_ckeywordv(name)); - if (janet_checktype(info, JANET_NIL)) { +const JanetAbstractType *janet_get_abstract_type_byname(const char *name) { + Janet twrap = janet_table_get(janet_vm_registry, janet_ckeywordv(name)); + if (janet_checktype(twrap, JANET_NIL)) { return NULL; } - if (!janet_checktype(info, JANET_ABSTRACT) || (janet_abstract_type(janet_unwrap_abstract(info)) != &type_info)) { - janet_panic("expected type_info"); + if (!janet_checktype(twrap, JANET_ABSTRACT) || (janet_abstract_type(janet_unwrap_abstract(twrap)) != &type_wrap)) { + janet_panic("expected abstract type"); } - JanetAbstractTypeInfo *type_info = (JanetAbstractTypeInfo *)janet_unwrap_abstract(info); - return type_info; + JanetAbstractTypeWrap *w = (JanetAbstractTypeWrap *)janet_unwrap_abstract(twrap); + return w->at; } - - #ifndef JANET_BOOTSTRAP void janet_core_def(JanetTable *env, const char *name, Janet x, const void *p) { (void) p; diff --git a/src/include/janet.h b/src/include/janet.h index b732d47a..75655955 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -804,13 +804,23 @@ struct JanetParser { int lookback; }; +typedef struct { + void *m_state; /* void* to not expose MarshalState ?*/ + void *u_state; + int flags; + const uint8_t *data; +} JanetMarshalContext; + /* Defines an abstract type */ struct JanetAbstractType { const char *name; + uint32_t id; int (*gc)(void *data, size_t len); int (*gcmark)(void *data, size_t len); Janet(*get)(void *data, Janet key); void (*put)(void *data, Janet key, Janet value); + void (*marshal)(void *p, JanetMarshalContext *ctx); + void (*unmarshal)(void *p, JanetMarshalContext *ctx); }; struct JanetReg { @@ -1241,12 +1251,7 @@ JANET_API JanetRange janet_getslice(int32_t argc, const Janet *argv); JANET_API int32_t janet_gethalfrange(const Janet *argv, int32_t n, int32_t length, const char *which); JANET_API int32_t janet_getargindex(const Janet *argv, int32_t n, int32_t length, const char *which); -typedef struct { - void *m_state; /* void* to not expose MarshalState ?*/ - void *u_state; - int flags; - const uint8_t *data; -} JanetMarshalContext; + JANET_API void janet_marshal_int(JanetMarshalContext *ctx, int32_t value); JANET_API void janet_marshal_byte(JanetMarshalContext *ctx, uint8_t value); @@ -1260,19 +1265,14 @@ JANET_API void janet_unmarshal_byte(JanetMarshalContext *ctx, uint8_t *b); JANET_API void janet_unmarshal_bytes(JanetMarshalContext *ctx, uint8_t *dest, int32_t len); JANET_API void janet_unmarshal_janet(JanetMarshalContext *ctx, Janet *out); -typedef struct { - const JanetAbstractType *at; - size_t size; /* abstract type size */ - const uint32_t salt; /* salt */ - uint32_t tag; /* unique tag computed by janet (hash of name and salt) */ - void (* marshal)(void *p, JanetMarshalContext *ctx); - void (* unmarshal)(void *p, JanetMarshalContext *ctx); -} JanetAbstractTypeInfo; -JANET_API void janet_register_abstract_type(const JanetAbstractTypeInfo *info); -JANET_API JanetAbstractTypeInfo *janet_get_abstract_type_info(uint32_t tag); -JANET_API JanetAbstractTypeInfo *janet_get_abstract_type_info_byname(const char *name); + + +JANET_API void janet_register_abstract_type(const JanetAbstractType *at); + +JANET_API const JanetAbstractType *janet_get_abstract_type(uint32_t id); +JANET_API const JanetAbstractType *janet_get_abstract_type_byname(const char *name);