From c6be14392567620645d5381eeed24ce734ac7793 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Thu, 8 Jan 2026 22:26:32 +0000 Subject: [PATCH] mie: trait: add function callback to perform trait-specific validation on an object --- mie/include/mie/macros.h | 32 +++++++++++++++++++++++++++----- mie/include/mie/trait/trait.h | 22 ++++++++++++++++++++++ 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/mie/include/mie/macros.h b/mie/include/mie/macros.h index 4c182d3..7357e3f 100644 --- a/mie/include/mie/macros.h +++ b/mie/include/mie/macros.h @@ -43,6 +43,20 @@ return type; \ } +#define __MIE_TRAIT_DEFINITION_BEGIN(func_prefix, trait_name) \ + struct mie_trait_definition *func_prefix##_trait_create( \ + struct mie_dialect *d, struct mie_ctx *ctx) \ + { \ + struct mie_trait_definition *trait \ + = mie_trait_definition_create(d, trait_name); \ + if (!trait) { \ + return NULL; \ + } + +#define __MIE_TRAIT_DEFINITION_END() \ + return trait; \ + } + #define __MIE_DIALECT_ADD_OP(op_id) \ extern struct mie_op_definition *op_id##_op_create( \ struct mie_dialect *, struct mie_ctx *); \ @@ -51,11 +65,16 @@ extern struct mie_type_definition *type_id##_type_create( \ 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( \ + struct mie_dialect *, struct mie_ctx *); \ + type = type_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() #define MIE_DIALECT_ADD_OP(c_sym) __MIE_DIALECT_ADD_OP(c_sym) #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_OP_DEFINITION_BEGIN(c_sym, op) __MIE_OP_DEFINITION_BEGIN(c_sym, op) #define MIE_OP_DEFINITION_END() __MIE_OP_DEFINITION_END() @@ -75,10 +94,13 @@ #define MIE_TYPE_DEFINITION_INIT(func) type->ty_init = (func) #define MIE_TYPE_DEFINITION_CLEANUP(func) type->ty_cleanup = (func) -#define MIE_DIALECT_TRAIT_BEGIN(c_sym, trait) -#define MIE_DIALECT_TRAIT_END() -#define MIE_DIALECT_TRAIT_STRUCT(name) -#define MIE_DIALECT_TRAIT_PRINT(func) -#define MIE_DIALECT_TRAIT_CLEANUP(func) +#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) #endif diff --git a/mie/include/mie/trait/trait.h b/mie/include/mie/trait/trait.h index 02b83b5..00e367a 100644 --- a/mie/include/mie/trait/trait.h +++ b/mie/include/mie/trait/trait.h @@ -13,12 +13,29 @@ enum mie_trait_flags { 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; @@ -29,6 +46,11 @@ struct mie_trait_definition { 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 *); }; /* used to link an op/type/etc to a trait. if the trait is parametised, this