From 11fc7a6ca9e23670203b7caca9d355711550881c Mon Sep 17 00:00:00 2001 From: Max Wash Date: Wed, 14 Jan 2026 18:17:34 +0000 Subject: [PATCH] mie: implement an interface system for ops this system allows dialects to register named interfaces, which are collections of function pointers. an op can then implement this interface, providing callbacks for the interface's virtual function pointers. C code can request a pointer to an op's implementation of a given interface and call virtual functions with no knowledge required about the op itself. this functonality will also be extended to types, attributes, and dialects themselves. --- mie/ctx.c | 25 +++++++++ mie/dialect/dialect.c | 7 +++ mie/dialect/func/op/func.c | 7 +++ mie/include/mie/ctx.h | 3 ++ mie/include/mie/dialect/dialect.h | 4 ++ .../mie/interface/interface-definition.h | 17 ++++++ mie/include/mie/interface/interface-map.h | 22 ++++++++ mie/include/mie/interface/interface.h | 19 +++++++ mie/include/mie/ir/op-definition.h | 4 ++ mie/include/mie/macros.h | 41 ++++++++++++-- mie/interface/interface-definition.c | 28 ++++++++++ mie/interface/interface-map.c | 54 +++++++++++++++++++ mie/interface/interface.c | 26 +++++++++ mie/ir/op-definition.c | 7 +++ 14 files changed, 261 insertions(+), 3 deletions(-) create mode 100644 mie/include/mie/interface/interface-definition.h create mode 100644 mie/include/mie/interface/interface-map.h create mode 100644 mie/include/mie/interface/interface.h create mode 100644 mie/interface/interface-definition.c create mode 100644 mie/interface/interface-map.c create mode 100644 mie/interface/interface.c diff --git a/mie/ctx.c b/mie/ctx.c index f0ca476..2b489e8 100644 --- a/mie/ctx.c +++ b/mie/ctx.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -185,6 +186,30 @@ const struct mie_attribute_definition *mie_ctx_get_attribute_definition( return b_unbox(struct mie_attribute_definition, target, a_id); } +const struct mie_interface_definition *mie_ctx_get_interface_definition( + const struct mie_ctx *ctx, const char *dialect_name, + const char *interface_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 interface_name_rope = B_ROPE_CSTR(interface_name); + mie_id_init_ns( + &id, mie_id_map_get_ns(&dialect->d_interfaces), + &interface_name_rope); + target = mie_id_map_get(&dialect->d_interfaces, &id); + + return b_unbox(struct mie_interface_definition, target, if_id); +} + struct mie_type *mie_ctx_get_type( struct mie_ctx *ctx, const char *dialect_name, const char *type_name) { diff --git a/mie/dialect/dialect.c b/mie/dialect/dialect.c index fbacad9..6c74a3b 100644 --- a/mie/dialect/dialect.c +++ b/mie/dialect/dialect.c @@ -19,6 +19,10 @@ MIE_ID(0x86, 0x76, 0xcb, 0xfb, 0xc8, 0xe5, 0x40, 0x7d, 0xa3, 0x84, \ 0x93, 0xe3, 0xa5, 0x29, 0x74, 0xfe) +#define INTERFACE_NS_ID \ + MIE_ID(0xc5, 0x85, 0x7f, 0x8a, 0x7d, 0xe4, 0x4d, 0x03, 0x88, 0x8d, \ + 0x34, 0x32, 0xbf, 0x29, 0x5c, 0x72) + struct mie_dialect *mie_dialect_create( struct mie_ctx *ctx, const char *name, size_t size) { @@ -51,6 +55,9 @@ struct mie_dialect *mie_dialect_create( mie_id attribute_ns = ATTRIBUTE_NS_ID; mie_id_map_init(&out->d_attributes, &attribute_ns); + mie_id interface_ns = INTERFACE_NS_ID; + mie_id_map_init(&out->d_interfaces, &interface_ns); + b_rope name_rope = B_ROPE_CSTR(name); mie_id_map_put(&ctx->ctx_dialects, &out->d_id, &name_rope); diff --git a/mie/dialect/func/op/func.c b/mie/dialect/func/op/func.c index 5a9ca29..9ea79ed 100644 --- a/mie/dialect/func/op/func.c +++ b/mie/dialect/func/op/func.c @@ -1,4 +1,8 @@ +#include +#include #include +#include +#include #include #include @@ -15,4 +19,7 @@ static enum mie_status parse(struct mie_parser *parser, struct mie_op *out) MIE_OP_DEFINITION_BEGIN(mie_func_func, "func") MIE_OP_DEFINITION_PRINT(print); MIE_OP_DEFINITION_PARSE(parse); + MIE_OP_INTERFACE_BEGIN("builtin", "symbol", struct mie_symbol) + MIE_OP_INTERFACE_FUNC(sym_get_name) = NULL; + MIE_OP_INTERFACE_END() MIE_OP_DEFINITION_END() diff --git a/mie/include/mie/ctx.h b/mie/include/mie/ctx.h index f92ee06..6474989 100644 --- a/mie/include/mie/ctx.h +++ b/mie/include/mie/ctx.h @@ -44,6 +44,9 @@ MIE_API const struct mie_trait_definition *mie_ctx_get_trait_definition( MIE_API const struct mie_attribute_definition *mie_ctx_get_attribute_definition( const struct mie_ctx *ctx, const char *dialect_name, const char *attrib_name); +MIE_API const struct mie_interface_definition *mie_ctx_get_interface_definition( + const struct mie_ctx *ctx, const char *dialect_name, + const char *iface_name); MIE_API struct mie_type *mie_ctx_get_type( struct mie_ctx *ctx, const char *dialect_name, const char *type_name); MIE_API const struct mie_trait *mie_ctx_get_trait( diff --git a/mie/include/mie/dialect/dialect.h b/mie/include/mie/dialect/dialect.h index 3838351..5ab5932 100644 --- a/mie/include/mie/dialect/dialect.h +++ b/mie/include/mie/dialect/dialect.h @@ -25,6 +25,8 @@ struct mie_dialect { struct mie_id_map d_traits; /* map of struct mie_attribute_definition */ struct mie_id_map d_attributes; + /* map of struct mie_interface_definition */ + struct mie_id_map d_interfaces; enum mie_status (*d_cleanup)(struct mie_dialect *); }; @@ -40,5 +42,7 @@ MIE_API const struct mie_trait_definition *mie_dialect_get_trait( const struct mie_dialect *dialect, const char *name); MIE_API const struct mie_attribute_definition *mie_dialect_get_attribute( const struct mie_dialect *dialect, const char *name); +MIE_API const struct mie_interface_definition *mie_dialect_get_interface( + const struct mie_dialect *dialect, const char *name); #endif diff --git a/mie/include/mie/interface/interface-definition.h b/mie/include/mie/interface/interface-definition.h new file mode 100644 index 0000000..c40551a --- /dev/null +++ b/mie/include/mie/interface/interface-definition.h @@ -0,0 +1,17 @@ +#ifndef MIE_INTERFACE_INTERFACE_DEFINITION_H_ +#define MIE_INTERFACE_INTERFACE_DEFINITION_H_ + +#include +#include + +struct mie_interface_definition { + mie_id if_id; + const struct mie_dialect *if_parent; + char *if_name; + size_t if_size; +}; + +MIE_API struct mie_interface_definition *mie_interface_definition_create( + struct mie_dialect *parent, const char *name); + +#endif diff --git a/mie/include/mie/interface/interface-map.h b/mie/include/mie/interface/interface-map.h new file mode 100644 index 0000000..26c7918 --- /dev/null +++ b/mie/include/mie/interface/interface-map.h @@ -0,0 +1,22 @@ +#ifndef MIE_INTERFACE_INTERFACE_MAP_H_ +#define MIE_INTERFACE_INTERFACE_MAP_H_ + +#include +#include + +struct mie_interface; + +struct mie_interface_map { + struct mie_id_map m_entries; +}; + +MIE_API void mie_interface_map_init(struct mie_interface_map *map); +MIE_API void mie_interface_map_cleanup(struct mie_interface_map *map); + +MIE_API enum mie_status mie_interface_map_put( + struct mie_interface_map *map, struct mie_interface *iface); +MIE_API const struct mie_interface *mie_interface_map_get( + const struct mie_interface_map *map, const char *dialect, + const char *iface); + +#endif diff --git a/mie/include/mie/interface/interface.h b/mie/include/mie/interface/interface.h new file mode 100644 index 0000000..d4bee55 --- /dev/null +++ b/mie/include/mie/interface/interface.h @@ -0,0 +1,19 @@ +#ifndef MIE_INTERFACE_INTERFACE_H_ +#define MIE_INTERFACE_INTERFACE_H_ + +#include +#include + +struct mie_dialect; +struct mie_interface_definition; + +struct mie_interface { + mie_id if_id; + const struct mie_interface_definition *if_def; +}; + +MIE_API struct mie_interface *mie_interface_create( + const struct mie_interface_definition *def); +MIE_API void mie_interface_destroy(struct mie_interface *iface); + +#endif diff --git a/mie/include/mie/ir/op-definition.h b/mie/include/mie/ir/op-definition.h index d00f9d2..6ee44b7 100644 --- a/mie/include/mie/ir/op-definition.h +++ b/mie/include/mie/ir/op-definition.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -96,6 +97,7 @@ struct mie_op_definition { char *op_name; struct mie_trait_table op_traits; + struct mie_interface_map op_iface; const struct mie_op_param op_params[MIE_OP_MAX_PARAMS]; const struct mie_op_result op_results[MIE_OP_MAX_RESULTS]; @@ -108,5 +110,7 @@ MIE_API struct mie_op_definition *mie_op_definition_create( MIE_API enum mie_status mie_op_definition_add_trait( struct mie_op_definition *op, const struct mie_trait *trait); +MIE_API enum mie_status mie_op_definition_add_interface( + struct mie_op_definition *op, struct mie_interface *inface); #endif diff --git a/mie/include/mie/macros.h b/mie/include/mie/macros.h index a15d5a2..b1df773 100644 --- a/mie/include/mie/macros.h +++ b/mie/include/mie/macros.h @@ -12,7 +12,8 @@ struct mie_op_definition *op = NULL; \ struct mie_type_definition *type = NULL; \ struct mie_trait_definition *trait = NULL; \ - struct mie_attribute_definition *attribute = NULL; + struct mie_attribute_definition *attribute = NULL; \ + struct mie_interface_definition *interface = NULL; #define __MIE_DIALECT_END() \ return self; \ @@ -27,7 +28,9 @@ if (!op) { \ return NULL; \ } \ - const struct mie_trait *trait = NULL; + const struct mie_trait *trait = NULL; \ + struct mie_interface *i = NULL; \ + const struct mie_interface_definition *id = NULL; #define __MIE_OP_DEFINITION_END() \ return op; \ @@ -76,6 +79,20 @@ return attribute; \ } +#define __MIE_INTERFACE_DEFINITION_BEGIN(func_prefix, iface_name) \ + struct mie_interface_definition *func_prefix##_interface_create( \ + struct mie_dialect *d, struct mie_ctx *ctx) \ + { \ + struct mie_interface_definition *i \ + = mie_interface_definition_create(d, iface_name); \ + if (!i) { \ + return NULL; \ + } + +#define __MIE_INTERFACE_DEFINITION_END() \ + return i; \ + } + #define __MIE_DIALECT_INIT(func) func(self) #define __MIE_DIALECT_CLEANUP(func) self->d_cleanup = (func) #define __MIE_DIALECT_ADD_OP(op_id) \ @@ -90,11 +107,14 @@ extern struct mie_trait_definition *trait_id##_trait_create( \ struct mie_dialect *, struct mie_ctx *); \ trait = trait_id##_trait_create(self, ctx) - #define __MIE_DIALECT_ADD_ATTRIBUTE(attribute_id) \ extern struct mie_attribute_definition *attribute_id##_attribute_create( \ struct mie_dialect *, struct mie_ctx *); \ attribute = attribute_id##_attribute_create(self, ctx) +#define __MIE_DIALECT_ADD_INTERFACE(interface_id) \ + extern struct mie_interface_definition *interface_id##_interface_create( \ + struct mie_dialect *, struct mie_ctx *); \ + interface = interface_id##_interface_create(self, ctx) #define MIE_DIALECT_BEGIN(c_sym, c_struct, name) \ __MIE_DIALECT_BEGIN(c_sym, c_struct, name) @@ -105,6 +125,7 @@ #define MIE_DIALECT_ADD_TYPE(c_sym) __MIE_DIALECT_ADD_TYPE(c_sym) #define MIE_DIALECT_ADD_TRAIT(c_sym) __MIE_DIALECT_ADD_TRAIT(c_sym) #define MIE_DIALECT_ADD_ATTRIBUTE(c_sym) __MIE_DIALECT_ADD_ATTRIBUTE(c_sym) +#define MIE_DIALECT_ADD_INTERFACE(c_sym) __MIE_DIALECT_ADD_INTERFACE(c_sym) #define MIE_OP_DEFINITION_BEGIN(c_sym, op) __MIE_OP_DEFINITION_BEGIN(c_sym, op) #define MIE_OP_DEFINITION_END() __MIE_OP_DEFINITION_END() @@ -113,6 +134,15 @@ #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_OP_INTERFACE_BEGIN(dialect_name, if_name, c_struct) \ + id = mie_ctx_get_interface_definition(ctx, dialect_name, if_name); \ + if (id) { \ + c_struct *iface = (c_struct *)mie_interface_create(id); +#define MIE_OP_INTERFACE_FUNC(func_name) iface->func_name + +#define MIE_OP_INTERFACE_END() \ + mie_op_definition_add_interface(op, (struct mie_interface *)iface); \ + } #define MIE_TYPE_DEFINITION_BEGIN(c_sym, type) \ __MIE_TYPE_DEFINITION_BEGIN(c_sym, type) @@ -149,4 +179,9 @@ #define MIE_ATTRIBUTE_DEFINITION_PRINT(func) attribute->a_print = (func) #define MIE_ATTRIBUTE_DEFINITION_PARSE(func) attribute->a_parse = (func) +#define MIE_INTERFACE_DEFINITION_BEGIN(c_sym, iface) \ + __MIE_INTERFACE_DEFINITION_BEGIN(c_sym, iface) +#define MIE_INTERFACE_DEFINITION_END() __MIE_INTERFACE_DEFINITION_END() +#define MIE_INTERFACE_DEFINITION_STRUCT(name) i->if_size = sizeof(name) + #endif diff --git a/mie/interface/interface-definition.c b/mie/interface/interface-definition.c new file mode 100644 index 0000000..f647de3 --- /dev/null +++ b/mie/interface/interface-definition.c @@ -0,0 +1,28 @@ +#include +#include +#include + +struct mie_interface_definition *mie_interface_definition_create( + struct mie_dialect *parent, const char *name) +{ + struct mie_interface_definition *out = malloc(sizeof *out); + if (!out) { + return NULL; + } + + memset(out, 0x0, sizeof *out); + + out->if_name = b_strdup(name); + if (!out->if_name) { + free(out); + return NULL; + } + + out->if_parent = parent; + out->if_size = 0; + + b_rope name_rope = B_ROPE_CSTR(name); + mie_id_map_put(&parent->d_interfaces, &out->if_id, &name_rope); + + return out; +} diff --git a/mie/interface/interface-map.c b/mie/interface/interface-map.c new file mode 100644 index 0000000..3f05a1f --- /dev/null +++ b/mie/interface/interface-map.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include + +#define INTERFACE_NS_ID \ + MIE_ID(0xd2, 0x40, 0x70, 0x93, 0x4b, 0x2b, 0x46, 0xb2, 0x96, 0x48, \ + 0x69, 0xe4, 0x0a, 0x0d, 0x70, 0x55) + +void mie_interface_map_init(struct mie_interface_map *map) +{ + memset(map, 0x0, sizeof *map); + + mie_id ns_id = INTERFACE_NS_ID; + mie_id_map_init(&map->m_entries, &ns_id); +} + +void mie_interface_map_cleanup(struct mie_interface_map *map) +{ + /* TODO */ +} + +enum mie_status mie_interface_map_put( + struct mie_interface_map *map, struct mie_interface *iface) +{ + struct mie_id_builder id_ctx; + mie_id_builder_begin(&id_ctx, mie_id_map_get_ns(&map->m_entries)); + mie_id_builder_add_cstr(&id_ctx, iface->if_def->if_parent->d_name); + mie_id_builder_add_char(&id_ctx, '.'); + mie_id_builder_add_cstr(&id_ctx, iface->if_def->if_name); + mie_id_builder_end(&id_ctx, &iface->if_id); + + mie_id_map_put_id(&map->m_entries, &iface->if_id); + + return MIE_SUCCESS; +} + +const struct mie_interface *mie_interface_map_get( + const struct mie_interface_map *map, const char *dialect_name, + const char *iface_name) +{ + mie_id id; + struct mie_id_builder id_ctx; + mie_id_builder_begin(&id_ctx, mie_id_map_get_ns(&map->m_entries)); + mie_id_builder_add_cstr(&id_ctx, dialect_name); + mie_id_builder_add_char(&id_ctx, '.'); + mie_id_builder_add_cstr(&id_ctx, iface_name); + mie_id_builder_end(&id_ctx, &id); + + const mie_id *result = mie_id_map_get(&map->m_entries, &id); + const struct mie_interface *iface + = b_unbox(const struct mie_interface, result, if_id); + return iface; +} diff --git a/mie/interface/interface.c b/mie/interface/interface.c new file mode 100644 index 0000000..82aeaae --- /dev/null +++ b/mie/interface/interface.c @@ -0,0 +1,26 @@ +#include +#include + +struct mie_interface *mie_interface_create( + const struct mie_interface_definition *def) +{ + if (def->if_size < sizeof(struct mie_interface)) { + return NULL; + } + + struct mie_interface *out = malloc(def->if_size); + if (!out) { + return NULL; + } + + memset(out, 0x0, def->if_size); + + out->if_def = def; + + return out; +} + +void mie_interface_destroy(struct mie_interface *iface) +{ + free(iface); +} diff --git a/mie/ir/op-definition.c b/mie/ir/op-definition.c index 285c832..a9fc34b 100644 --- a/mie/ir/op-definition.c +++ b/mie/ir/op-definition.c @@ -18,6 +18,7 @@ struct mie_op_definition *mie_op_definition_create( out->op_parent = parent; mie_trait_table_init(&out->op_traits); + mie_interface_map_init(&out->op_iface); b_rope name_rope = B_ROPE_CSTR(name); mie_id_map_put(&parent->d_ops, &out->op_id, &name_rope); @@ -30,3 +31,9 @@ enum mie_status mie_op_definition_add_trait( { return mie_trait_table_put(&op->op_traits, trait); } + +enum mie_status mie_op_definition_add_interface( + struct mie_op_definition *op, struct mie_interface *interface) +{ + return mie_interface_map_put(&op->op_iface, interface); +}