diff --git a/mie/ctx.c b/mie/ctx.c index 8741347..5cb3b03 100644 --- a/mie/ctx.c +++ b/mie/ctx.c @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include @@ -23,285 +25,6 @@ MIE_ID(0xf5, 0x4e, 0xc5, 0x8c, 0xc0, 0x1e, 0x48, 0x47, 0xb5, 0xf4, \ 0x7b, 0xb9, 0x6b, 0x47, 0xca, 0x48) -struct ctx_int_cache_entry { - b_btree_node i_node; - // struct mie_type i_type; - b_btree i_values; -}; - -struct ctx_int_value_cache_entry { - b_btree_node i_node; - // struct mie_int i_value; -}; - -#if 0 - -B_BTREE_DEFINE_SIMPLE_INSERT( - struct ctx_int_cache_entry, i_node, i_type.t_width, put_cached_int_type) -B_BTREE_DEFINE_SIMPLE_GET( - struct ctx_int_cache_entry, unsigned int, i_node, i_type.t_width, - get_cached_int_type) - -B_BTREE_DEFINE_SIMPLE_INSERT( - struct ctx_int_value_cache_entry, i_node, i_value.i_value, - put_cached_int_value) -B_BTREE_DEFINE_SIMPLE_GET( - struct ctx_int_value_cache_entry, int64_t, i_node, i_value.i_value, - get_cached_int_value) - -struct mie_ctx *mie_ctx_create(void) -{ - struct mie_ctx *out = malloc(sizeof *out); - - if (!out) { - return NULL; - } - - memset(out, 0x0, sizeof *out); - - out->ctx_true = MIE_CONST(mie_ctx_get_int(out, 1, 1)); - out->ctx_false = MIE_CONST(mie_ctx_get_int(out, 0, 1)); - - out->ctx_null = malloc(sizeof *out->ctx_null); - if (!out->ctx_null) { - mie_ctx_destroy(out); - return NULL; - } - - mie_value_init(out->ctx_null, MIE_VALUE_NONE); - - out->ctx_sel_cache = b_hashmap_create(free, free); - out->ctx_string_cache = b_hashmap_create(free, free); - - return out; -} - -void mie_ctx_destroy(struct mie_ctx *ctx) -{ - ctx->ctx_true = NULL; - ctx->ctx_false = NULL; - - b_btree_node *node = b_btree_first(&ctx->ctx_int_cache); - while (node) { - struct ctx_int_cache_entry *entry - = b_unbox(struct ctx_int_cache_entry, node, i_node); - b_btree_node *next = b_btree_next(node); - b_btree_delete(&ctx->ctx_int_cache, node); - - b_btree_node *node2 = b_btree_first(&entry->i_values); - while (node2) { - struct ctx_int_value_cache_entry *value = b_unbox( - struct ctx_int_value_cache_entry, node2, i_node); - b_btree_node *next2 = b_btree_next(node2); - b_btree_delete(&entry->i_values, node2); - free(value); - node2 = next2; - } - - free(entry); - node = next; - } - - const size_t nr_types = sizeof ctx->ctx_types / sizeof ctx->ctx_types[0]; - for (size_t i = 0; i < nr_types; i++) { - if (ctx->ctx_types[i]) { - mie_value_destroy(MIE_VALUE(ctx->ctx_types[i])); - ctx->ctx_types[i] = NULL; - } - } - - if (ctx->ctx_null) { - mie_value_destroy(ctx->ctx_null); - } - - b_hashmap_unref(ctx->ctx_sel_cache); - - free(ctx); -} - -struct mie_type *mie_ctx_get_type(struct mie_ctx *ctx, enum mie_type_id type_id) -{ - if (type_id == MIE_TYPE_INT) { - return NULL; - } - - if (ctx->ctx_types[type_id]) { - return ctx->ctx_types[type_id]; - } - - struct mie_type *type = mie_type_create(); - if (!type) { - return NULL; - } - - type->t_id = type_id; - - ctx->ctx_types[type_id] = type; - return type; -} - -struct mie_value *mie_ctx_get_null(struct mie_ctx *ctx) -{ - return ctx->ctx_null; -} - -struct mie_type *mie_ctx_get_int_type(struct mie_ctx *ctx, unsigned int nr_bits) -{ - struct ctx_int_cache_entry *entry - = get_cached_int_type(&ctx->ctx_int_cache, nr_bits); - - if (entry) { - return &entry->i_type; - } - - entry = malloc(sizeof *entry); - if (!entry) { - return NULL; - } - - memset(entry, 0x0, sizeof *entry); - - entry->i_type.t_id = MIE_TYPE_INT; - entry->i_type.t_width = nr_bits; - - put_cached_int_type(&ctx->ctx_int_cache, entry); - return &entry->i_type; -} - -struct mie_value *mie_ctx_get_bool(struct mie_ctx *ctx, bool val) -{ - return MIE_VALUE(val ? ctx->ctx_true : ctx->ctx_false); -} - -struct mie_value *mie_ctx_get_int( - struct mie_ctx *ctx, long long val, unsigned int nr_bits) -{ - struct ctx_int_cache_entry *entry - = get_cached_int_type(&ctx->ctx_int_cache, nr_bits); - - if (!entry) { - entry = malloc(sizeof *entry); - if (!entry) { - return NULL; - } - - memset(entry, 0x0, sizeof *entry); - - entry->i_type.t_id = MIE_TYPE_INT; - entry->i_type.t_width = nr_bits; - - put_cached_int_type(&ctx->ctx_int_cache, entry); - } - - struct ctx_int_value_cache_entry *value - = get_cached_int_value(&entry->i_values, val); - if (value) { - return MIE_VALUE(&value->i_value); - } - - value = malloc(sizeof *value); - if (!value) { - return NULL; - } - - memset(value, 0x0, sizeof *value); - - mie_const_init(&value->i_value.i_base, &entry->i_type); - value->i_value.i_value = val; - - put_cached_int_value(&entry->i_values, value); - - return MIE_VALUE(&value->i_value); -} - -struct mie_value *mie_ctx_get_selector(struct mie_ctx *ctx, const char *sel) -{ - b_hashmap_key key = { - .key_data = sel, - .key_size = strlen(sel), - }; - - const b_hashmap_value *cache_entry - = b_hashmap_get(ctx->ctx_sel_cache, &key); - - if (cache_entry) { - return cache_entry->value_data; - } - - struct mie_selector *sel_value = malloc(sizeof *sel_value); - if (!sel_value) { - return NULL; - } - - struct mie_type *sel_type = mie_ctx_get_type(ctx, MIE_TYPE_SELECTOR); - mie_const_init(&sel_value->sel_base, sel_type); - sel_value->sel_value = b_strdup(sel); - - key.key_data = sel_value->sel_value; - - b_hashmap_value hashmap_value = { - .value_data = sel_value, - .value_size = sizeof *sel_value, - }; - - b_hashmap_put(ctx->ctx_sel_cache, &key, &hashmap_value); - - return MIE_VALUE(sel_value); -} - -struct mie_value *mie_ctx_get_string(struct mie_ctx *ctx, const char *s) -{ - b_hashmap_key key = { - .key_data = s, - .key_size = strlen(s), - }; - - const b_hashmap_value *cache_entry - = b_hashmap_get(ctx->ctx_string_cache, &key); - - if (cache_entry) { - return cache_entry->value_data; - } - - struct mie_string *string_value = malloc(sizeof *string_value); - if (!string_value) { - return NULL; - } - - struct mie_type *string_type = mie_ctx_get_type(ctx, MIE_TYPE_STR); - mie_const_init(&string_value->s_base, string_type); - string_value->s_value = b_strdup(s); - - key.key_data = string_value->s_value; - - b_hashmap_value hashmap_value = { - .value_data = string_value, - .value_size = sizeof *string_value, - }; - - b_hashmap_put(ctx->ctx_string_cache, &key, &hashmap_value); - - return MIE_VALUE(string_value); -} - -struct mie_value *mie_ctx_create_array(struct mie_ctx *ctx) -{ - struct mie_type *array_type = mie_ctx_get_type(ctx, MIE_TYPE_ARRAY); - struct mie_array *array = malloc(sizeof *array); - - if (!array) { - return NULL; - } - - memset(array, 0x0, sizeof *array); - mie_const_init(&array->a_base, array_type); - - array->a_values = b_list_create(); - - return MIE_VALUE(array); -} -#endif - struct mie_ctx *mie_ctx_create(void) { struct mie_ctx *out = malloc(sizeof *out); @@ -328,7 +51,7 @@ struct mie_ctx *mie_ctx_create(void) bool mie_ctx_resolve_op(const struct mie_ctx *ctx, struct mie_op *op) { bool fully_resolved = MIE_TEST_FLAGS( - op->op_flags, MIE_OP_F_OP_RESOLVED | MIE_OP_F_ARGS_RESOLVED); + op->op_flags, MIE_OP_F_OP_RESOLVED | MIE_OP_F_ARG_RESOLVED); if (fully_resolved) { return true; @@ -406,11 +129,32 @@ struct mie_type_definition *mie_ctx_get_type_definition( return b_unbox(struct mie_type_definition, target, ty_id); } +const struct mie_trait_definition *mie_ctx_get_trait_definition( + const struct mie_ctx *ctx, const char *dialect_name, const char *trait_name) +{ + b_rope dialect_name_rope = B_ROPE_CSTR(dialect_name); + mie_id id; + mie_id_init_ns( + &id, mie_id_map_get_ns(&ctx->ctx_dialects), &dialect_name_rope); + + mie_id *target = mie_id_map_get(&ctx->ctx_dialects, &id); + struct mie_dialect *dialect = b_unbox(struct mie_dialect, target, d_id); + if (!dialect) { + return NULL; + } + + b_rope trait_name_rope = B_ROPE_CSTR(trait_name); + mie_id_init_ns(&id, mie_id_map_get_ns(&dialect->d_traits), &trait_name_rope); + target = mie_id_map_get(&dialect->d_traits, &id); + + return b_unbox(struct mie_trait_definition, target, tr_id); +} + struct mie_type *mie_ctx_get_type( struct mie_ctx *ctx, const char *dialect_name, const char *type_name) { char full_name[256]; - snprintf(full_name, sizeof full_name, "%s.%s", dialect_name, dialect_name); + snprintf(full_name, sizeof full_name, "%s.%s", dialect_name, type_name); b_rope full_name_rope = B_ROPE_CSTR(full_name); mie_id id; @@ -453,6 +197,53 @@ struct mie_type *mie_ctx_get_type( return type; } +const struct mie_trait *mie_ctx_get_trait( + struct mie_ctx *ctx, const char *dialect_name, const char *trait_name) +{ + char full_name[256]; + snprintf(full_name, sizeof full_name, "%s.%s", dialect_name, trait_name); + b_rope full_name_rope = B_ROPE_CSTR(full_name); + + mie_id id; + mie_id_init_ns(&id, mie_id_map_get_ns(&ctx->ctx_traits), &full_name_rope); + + mie_id *target = mie_id_map_get(&ctx->ctx_traits, &id); + struct mie_trait *trait = b_unbox(struct mie_trait, target, tr_id); + if (trait) { + return trait; + } + + const struct mie_trait_definition *trait_info + = mie_ctx_get_trait_definition(ctx, dialect_name, trait_name); + if (!trait_info /* || (trait_info->ty_flags & MIE_DIALECT_TYPE_PARAMETISED) */) { + /* cannot initialise unknown or parametised traits */ + return NULL; + } + + if (trait_info->tr_data_size < sizeof(struct mie_trait)) { + /* invalid trait info */ + return NULL; + } + + trait = malloc(trait_info->tr_data_size); + if (!trait) { + return NULL; + } + + memset(trait, 0x0, sizeof *trait); + + trait->tr_def = trait_info; + trait->tr_name = b_bstr_fmt("%s.%s", dialect_name, trait_name); + + if (trait_info->tr_init) { + trait_info->tr_init(trait_info, trait); + } + + mie_id_map_put(&ctx->ctx_traits, &trait->tr_id, &full_name_rope); + + return trait; +} + struct mie_type *mie_ctx_get_storage_type( struct mie_ctx *ctx, const struct mie_type **parts, size_t nr_parts) { diff --git a/mie/include/mie/ctx.h b/mie/include/mie/ctx.h index be126b7..686c16d 100644 --- a/mie/include/mie/ctx.h +++ b/mie/include/mie/ctx.h @@ -40,9 +40,12 @@ MIE_API struct mie_dialect *mie_ctx_get_dialect( const struct mie_ctx *ctx, const char *name); MIE_API struct mie_type_definition *mie_ctx_get_type_definition( const struct mie_ctx *ctx, const char *dialect_name, const char *type_name); +MIE_API const struct mie_trait_definition *mie_ctx_get_trait_definition( + const struct mie_ctx *ctx, const char *dialect_name, + const char *trait_name); MIE_API struct mie_type *mie_ctx_get_type( struct mie_ctx *ctx, const char *dialect_name, const char *type_name); -MIE_API struct mie_type *mie_ctx_get_trait( +MIE_API const struct mie_trait *mie_ctx_get_trait( struct mie_ctx *ctx, const char *dialect_name, const char *trait_name); MIE_API struct mie_type *mie_ctx_get_storage_type( struct mie_ctx *ctx, const struct mie_type **parts, size_t nr_parts); diff --git a/mie/include/mie/ir/op-definition.h b/mie/include/mie/ir/op-definition.h index 35eca8e..d00f9d2 100644 --- a/mie/include/mie/ir/op-definition.h +++ b/mie/include/mie/ir/op-definition.h @@ -106,4 +106,7 @@ struct mie_op_definition { MIE_API struct mie_op_definition *mie_op_definition_create( struct mie_dialect *parent, const char *name); +MIE_API enum mie_status mie_op_definition_add_trait( + struct mie_op_definition *op, const struct mie_trait *trait); + #endif diff --git a/mie/include/mie/macros.h b/mie/include/mie/macros.h index 7357e3f..f4202d5 100644 --- a/mie/include/mie/macros.h +++ b/mie/include/mie/macros.h @@ -9,7 +9,8 @@ return NULL; \ } \ struct mie_op_definition *op = NULL; \ - struct mie_type_definition *type = NULL; + struct mie_type_definition *type = NULL; \ + struct mie_trait_definition *trait = NULL; #define __MIE_DIALECT_END() \ return self; \ @@ -23,7 +24,8 @@ = mie_op_definition_create(d, op_name); \ if (!op) { \ return NULL; \ - } + } \ + const struct mie_trait *trait = NULL; #define __MIE_OP_DEFINITION_END() \ return op; \ @@ -37,7 +39,8 @@ = mie_type_definition_create(d, type_name); \ if (!type) { \ return NULL; \ - } + } \ + const struct mie_trait *trait = NULL; #define __MIE_TYPE_DEFINITION_END() \ return type; \ @@ -66,9 +69,9 @@ struct mie_dialect *, struct mie_ctx *); \ type = type_id##_type_create(self, ctx) #define __MIE_DIALECT_ADD_TRAIT(trait_id) \ - extern struct mie_trait_definition *type_id##_trait_create( \ + extern struct mie_trait_definition *trait_id##_trait_create( \ struct mie_dialect *, struct mie_ctx *); \ - type = type_id##_trait_create(self, ctx) + trait = trait_id##_trait_create(self, ctx) #define MIE_DIALECT_BEGIN(c_sym, name) __MIE_DIALECT_BEGIN(c_sym, name) #define MIE_DIALECT_END() __MIE_DIALECT_END() @@ -80,6 +83,9 @@ #define MIE_OP_DEFINITION_END() __MIE_OP_DEFINITION_END() #define MIE_OP_DEFINITION_PRINT(func) op->op_print = (func) #define MIE_OP_DEFINITION_PARSE(func) op->op_parse = (func) +#define MIE_OP_DEFINITION_TRAIT(trait_dialect, trait_name) \ + trait = mie_ctx_get_trait(ctx, trait_dialect, trait_name); \ + mie_op_definition_add_trait(op, trait); #define MIE_TYPE_DEFINITION_BEGIN(c_sym, type) \ __MIE_TYPE_DEFINITION_BEGIN(c_sym, type) @@ -93,14 +99,18 @@ #define MIE_TYPE_DEFINITION_BUILD_ID(func) type->ty_build_id = (func) #define MIE_TYPE_DEFINITION_INIT(func) type->ty_init = (func) #define MIE_TYPE_DEFINITION_CLEANUP(func) type->ty_cleanup = (func) +#define MIE_TYPE_DEFINITION_TRAIT(trait_dialect, trait_name) \ + trait = mie_ctx_get_trait(ctx, trait_dialect, trait_name); \ + mie_type_definition_add_trait(type, trait); #define MIE_TRAIT_DEFINITION_BEGIN(c_sym, trait) \ __MIE_TRAIT_DEFINITION_BEGIN(c_sym, trait) -#define MIE_TRAIT_DEFINITION_END() __MIE_TRAIT_DEFINITION_END() -#define MIE_TRAIT_DEFINITION_STRUCT(name) trait->tr_data_size = sizeof(name) -#define MIE_TRAIT_DEFINITION_PRINT(func) trait->tr_print = (func) -#define MIE_TRAIT_DEFINITION_BUILD_ID(func) trait->tr_build_id = (func) -#define MIE_TRAIT_DEFINITION_CLEANUP(func) trait->tr_cleanup(func) -#define MIE_TRAIT_DEFINITION_VALIDATE(func) trait->tr_validate(func) +#define MIE_TRAIT_DEFINITION_END() __MIE_TRAIT_DEFINITION_END() +#define MIE_TRAIT_DEFINITION_TARGETS(targets) trait->tr_target = (targets) +#define MIE_TRAIT_DEFINITION_STRUCT(name) trait->tr_data_size = sizeof(name) +#define MIE_TRAIT_DEFINITION_PRINT(func) trait->tr_print = (func) +#define MIE_TRAIT_DEFINITION_BUILD_ID(func) trait->tr_build_id = (func) +#define MIE_TRAIT_DEFINITION_CLEANUP(func) trait->tr_cleanup = (func) +#define MIE_TRAIT_DEFINITION_VALIDATE(func) trait->tr_validate = (func) #endif diff --git a/mie/include/mie/trait/trait-definition.h b/mie/include/mie/trait/trait-definition.h new file mode 100644 index 0000000..99b78d3 --- /dev/null +++ b/mie/include/mie/trait/trait-definition.h @@ -0,0 +1,64 @@ +#ifndef MIE_TRAIT_TRAIT_DEFINITION_H_ +#define MIE_TRAIT_TRAIT_DEFINITION_H_ + +#include +#include +#include + +struct mie_trait; +struct mie_dialect; + +enum mie_trait_flags { + /* a trait user can only apply the trait once. this is assumed to be the + * case unless a trait is parametised, in which case this flag can be + * used to prevent more than one specialisation from being used. */ + MIE_TRAIT_F_UNIQUE = 0x01u, + MIE_TRAIT_F_PARAMETISED = 0x02u, +}; + +/* describe exactly which objects a trait can be applied to */ +enum mie_trait_target_type { + MIE_TRAIT_TARGET_NONE = 0x00u, + MIE_TRAIT_TARGET_OP = 0x01u, + MIE_TRAIT_TARGET_TYPE = 0x02u, +}; + +struct mie_trait_target { + enum mie_trait_target_type target_type; + union { + const struct mie_type *ptr_type; + const struct mie_op *ptr_op; + } target_ptr; +}; + +/* used to define a trait */ +struct mie_trait_definition { + /* ID for the generic trait */ + mie_id tr_id; + char *tr_name; + struct mie_dialect *tr_parent; + enum mie_trait_flags tr_flags; + /* compatible target bitmask */ + enum mie_trait_target_type tr_target; + + /* the size of any corresponding struct mie_trait instances */ + size_t tr_data_size; + + void (*tr_init)(const struct mie_trait_definition *, struct mie_trait *); + enum mie_status (*tr_build_id)( + const struct mie_trait_definition *, const struct mie_trait *, + struct mie_id_builder *); + enum mie_status (*tr_print)( + const struct mie_trait_definition *, const struct mie_trait *, + b_stream *); + enum mie_status (*tr_cleanup)( + const struct mie_trait_definition *, struct mie_trait *); + enum mie_status (*tr_validate)( + const struct mie_trait_definition *, const struct mie_trait *, + const struct mie_trait_target *); +}; + +MIE_API struct mie_trait_definition *mie_trait_definition_create( + struct mie_dialect *parent, const char *name); + +#endif diff --git a/mie/include/mie/trait/trait-table.h b/mie/include/mie/trait/trait-table.h index 83c4da3..4936a10 100644 --- a/mie/include/mie/trait/trait-table.h +++ b/mie/include/mie/trait/trait-table.h @@ -15,6 +15,9 @@ struct mie_trait_table { struct mie_trait_table_iterator { const struct mie_trait *it_trait; + int _f; + struct mie_id_map_iterator _n; + const struct mie_trait_table *_m; b_queue_entry *_e; }; @@ -32,6 +35,9 @@ MIE_API enum mie_status mie_trait_table_get_generic( const char *trait_name, struct mie_trait_table_iterator *it); MIE_API enum mie_status mie_trait_table_put( struct mie_trait_table *table, const struct mie_trait *trait); +MIE_API enum mie_status mie_trait_table_iterate( + const struct mie_trait_table *table, + int (*func)(const struct mie_trait *, void *), void *arg); MIE_API enum mie_status mie_trait_table_iterator_move_next( struct mie_trait_table_iterator *it); diff --git a/mie/include/mie/trait/trait.h b/mie/include/mie/trait/trait.h index 00e367a..1cd1cee 100644 --- a/mie/include/mie/trait/trait.h +++ b/mie/include/mie/trait/trait.h @@ -3,62 +3,18 @@ #include -struct mie_trait; - -enum mie_trait_flags { - /* a trait user can only apply the trait once. this is assumed to be the - * case unless a trait is parametised, in which case this flag can be - * used to prevent more than one specialisation from being used. */ - MIE_TRAIT_F_UNIQUE = 0x01u, - MIE_TRAIT_F_PARAMETISED = 0x02u, -}; - -/* describe exactly which objects a trait can be applied to */ -enum mie_trait_target_type { - MIE_TRAIT_TARGET_NONE = 0x00u, - MIE_TRAIT_TARGET_OP = 0x01u, - MIE_TRAIT_TARGET_TYPE = 0x02u, -}; - -struct mie_trait_target { - enum mie_trait_target_type target_type; - union { - const struct mie_type *ptr_type; - const struct mie_op *ptr_op; - } target_ptr; -}; - -/* used to define a trait */ -struct mie_trait_definition { - /* ID for the generic trait */ - mie_id tr_id; - char *tr_name; - enum mie_trait_flags tr_flags; - /* compatible target bitmask */ - enum mie_trait_target_type tr_target; - - /* the size of any corresponding struct mie_trait instances */ - size_t tr_data_size; - - enum mie_status (*tr_build_id)( - const struct mie_trait_definition *, const struct mie_trait *, - struct mie_id_builder *); - enum mie_status (*tr_print)( - const struct mie_trait_definition *, const struct mie_trait *, - b_stream *); - enum mie_status (*tr_cleanup)( - const struct mie_trait_definition *, struct mie_trait *); - enum mie_status (*tr_validate)( - const struct mie_trait_definition *, const struct mie_trait *, - const struct mie_trait_target *); -}; +struct mie_dialect; +struct mie_trait_definition; /* used to link an op/type/etc to a trait. if the trait is parametised, this * struct includes any parameter values. */ struct mie_trait { /* this is NOT the same as tr_def->tr_id */ mie_id tr_id; + char *tr_name; const struct mie_trait_definition *tr_def; }; +MIE_API void mie_trait_print(const struct mie_trait *type, b_stream *out); + #endif diff --git a/mie/include/mie/type/type-definition.h b/mie/include/mie/type/type-definition.h index a0a1362..564a5c5 100644 --- a/mie/include/mie/type/type-definition.h +++ b/mie/include/mie/type/type-definition.h @@ -33,4 +33,7 @@ struct mie_type_definition { MIE_API struct mie_type_definition *mie_type_definition_create( struct mie_dialect *parent, const char *name); +MIE_API enum mie_status mie_type_definition_add_trait( + struct mie_type_definition *type, const struct mie_trait *trait); + #endif diff --git a/mie/ir/op-definition.c b/mie/ir/op-definition.c index 0175d1c..285c832 100644 --- a/mie/ir/op-definition.c +++ b/mie/ir/op-definition.c @@ -17,9 +17,16 @@ struct mie_op_definition *mie_op_definition_create( } out->op_parent = parent; + mie_trait_table_init(&out->op_traits); b_rope name_rope = B_ROPE_CSTR(name); mie_id_map_put(&parent->d_ops, &out->op_id, &name_rope); return out; } + +enum mie_status mie_op_definition_add_trait( + struct mie_op_definition *op, const struct mie_trait *trait) +{ + return mie_trait_table_put(&op->op_traits, trait); +} diff --git a/mie/trait/trait-definition.c b/mie/trait/trait-definition.c new file mode 100644 index 0000000..6f4f34b --- /dev/null +++ b/mie/trait/trait-definition.c @@ -0,0 +1,25 @@ +#include +#include +#include + +struct mie_trait_definition *mie_trait_definition_create( + struct mie_dialect *parent, const char *name) +{ + struct mie_trait_definition *out = malloc(sizeof *out); + if (!out) { + return NULL; + } + + out->tr_name = b_strdup(name); + if (!out->tr_name) { + free(out); + return NULL; + } + + out->tr_parent = parent; + + b_rope name_rope = B_ROPE_CSTR(name); + mie_id_map_put(&parent->d_traits, &out->tr_id, &name_rope); + + return out; +} diff --git a/mie/trait/trait-table.c b/mie/trait/trait-table.c index cda592b..f15eecd 100644 --- a/mie/trait/trait-table.c +++ b/mie/trait/trait-table.c @@ -1,3 +1,5 @@ +#include +#include #include #include @@ -29,7 +31,6 @@ static struct unique_trait *unique_trait_create(const struct mie_trait *trait) } memset(out, 0x0, sizeof *out); - out->u_id = trait->tr_id; out->u_trait = trait; return out; @@ -48,7 +49,6 @@ static struct generic_trait *generic_trait_create(const struct mie_trait *trait) } memset(out, 0x0, sizeof *out); - out->g_id = trait->tr_def->tr_id; struct unique_trait *entry = unique_trait_create(trait); if (!entry) { @@ -113,12 +113,55 @@ const struct mie_trait *mie_trait_table_get_unique( static enum mie_status put_unique_trait( struct mie_trait_table *table, const struct mie_trait *trait) { + struct unique_trait *unique = unique_trait_create(trait); + if (!unique) { + return MIE_ERR_NO_MEMORY; + } + + struct mie_id_builder id_ctx; + mie_id_builder_begin(&id_ctx, mie_id_map_get_ns(&table->tr_unique)); + mie_id_builder_add_cstr(&id_ctx, trait->tr_def->tr_parent->d_name); + mie_id_builder_add_char(&id_ctx, '.'); + mie_id_builder_add_cstr(&id_ctx, trait->tr_def->tr_name); + mie_id_builder_end(&id_ctx, &unique->u_id); + + mie_id_map_put_id(&table->tr_unique, &unique->u_id); + return MIE_SUCCESS; } static enum mie_status put_generic_trait( struct mie_trait_table *table, const struct mie_trait *trait) { + mie_id id; + struct mie_id_builder id_ctx; + mie_id_builder_begin(&id_ctx, mie_id_map_get_ns(&table->tr_generic)); + mie_id_builder_add_cstr(&id_ctx, trait->tr_def->tr_parent->d_name); + mie_id_builder_add_char(&id_ctx, '.'); + mie_id_builder_add_cstr(&id_ctx, trait->tr_def->tr_name); + mie_id_builder_end(&id_ctx, &id); + + mie_id *target = mie_id_map_get(&table->tr_generic, &id); + struct generic_trait *generic + = b_unbox(struct generic_trait, target, g_id); + if (!generic) { + generic = generic_trait_create(trait); + + if (!generic) { + return MIE_ERR_NO_MEMORY; + } + + generic->g_id = id; + mie_id_map_put_id(&table->tr_generic, &generic->g_id); + } + + struct unique_trait *unique = unique_trait_create(trait); + if (!unique) { + return MIE_ERR_NO_MEMORY; + } + + b_queue_push_back(&generic->g_traits, &unique->u_id.e_entry); + return MIE_SUCCESS; } @@ -163,6 +206,51 @@ enum mie_status mie_trait_table_get_generic( return MIE_SUCCESS; } +enum mie_status mie_trait_table_iterate( + const struct mie_trait_table *table, + int (*func)(const struct mie_trait *, void *), void *arg) +{ + struct mie_id_map_iterator it = {0}; + mie_id_map_iterator_begin(&it, &table->tr_unique); + int ret = 0; + + while (it.it_id) { + const struct unique_trait *trait + = b_unbox(struct unique_trait, it.it_id, u_id); + ret = func(trait->u_trait, arg); + + if (ret != 0) { + return MIE_SUCCESS; + } + + mie_id_map_iterator_move_next(&it); + } + + mie_id_map_iterator_begin(&it, &table->tr_generic); + + while (it.it_id) { + const struct generic_trait *trait_group + = b_unbox(struct generic_trait, it.it_id, g_id); + + const b_queue_entry *cur = b_queue_first(&trait_group->g_traits); + while (cur) { + const struct unique_trait *trait + = b_unbox(struct unique_trait, cur, u_id.e_entry); + ret = func(trait->u_trait, arg); + + if (ret != 0) { + return MIE_SUCCESS; + } + + cur = b_queue_next(cur); + } + + mie_id_map_iterator_move_next(&it); + } + + return MIE_SUCCESS; +} + enum mie_status mie_trait_table_iterator_move_next( struct mie_trait_table_iterator *it) { diff --git a/mie/trait/trait.c b/mie/trait/trait.c new file mode 100644 index 0000000..576e21a --- /dev/null +++ b/mie/trait/trait.c @@ -0,0 +1,15 @@ +#include +#include + +void mie_trait_print(const struct mie_trait *trait, b_stream *out) +{ + if (trait->tr_name) { + b_stream_write_string(out, trait->tr_name, NULL); + } else if (trait->tr_def && trait->tr_def->tr_print) { + trait->tr_def->tr_print(trait->tr_def, trait, out); + } else if (trait->tr_def->tr_name) { + b_stream_write_string(out, trait->tr_def->tr_name, NULL); + } else { + b_stream_write_string(out, "", NULL); + } +} diff --git a/mie/type/type-definition.c b/mie/type/type-definition.c index a163d6f..e550156 100644 --- a/mie/type/type-definition.c +++ b/mie/type/type-definition.c @@ -17,9 +17,16 @@ struct mie_type_definition *mie_type_definition_create( } out->ty_parent = parent; + mie_trait_table_init(&out->ty_traits); b_rope name_rope = B_ROPE_CSTR(name); mie_id_map_put(&parent->d_types, &out->ty_id, &name_rope); return out; } + +enum mie_status mie_type_definition_add_trait( + struct mie_type_definition *type, const struct mie_trait *trait) +{ + return mie_trait_table_put(&type->ty_traits, trait); +}