From f3062222cb2af7dc2c5282b19fb610838d7b8fa8 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Tue, 5 May 2026 21:16:31 +0100 Subject: [PATCH] fx: support for registering callable functions with types --- assemblies/fx.cmdline/assembly.c | 4 +- assemblies/fx.compression/assembly.c | 4 +- assemblies/fx.io/assembly.c | 8 +-- assemblies/fx.runtime/assembly.c | 4 +- assemblies/fx.serial/assembly.c | 4 +- assemblies/fx.term/assembly.c | 4 +- fx.reflection/function.c | 22 ++++++-- .../include/fx/reflection/function.h | 3 ++ fx.reflection/include/fx/reflection/type.h | 4 ++ fx.reflection/type.c | 19 +++++++ fx/class.c | 9 +++- fx/include/fx/macros.h | 54 +++++++++++++++++-- fx/include/fx/type.h | 8 ++- fx/string.c | 14 +++++ fx/type.c | 40 ++++++++++++++ fx/type.h | 6 ++- 16 files changed, 182 insertions(+), 25 deletions(-) diff --git a/assemblies/fx.cmdline/assembly.c b/assemblies/fx.cmdline/assembly.c index 66c7676..574bb51 100644 --- a/assemblies/fx.cmdline/assembly.c +++ b/assemblies/fx.cmdline/assembly.c @@ -1,7 +1,7 @@ #include #include -FX_ASSEMBLY_BEGIN() +FX_ASSEMBLY_BEGIN(fx_cmdline) FX_ASSEMBLY_NAME("fx.cmdline"); FX_ASSEMBLY_VERSION(1, 0, 0, 0); -FX_ASSEMBLY_END() +FX_ASSEMBLY_END(fx_cmdline) diff --git a/assemblies/fx.compression/assembly.c b/assemblies/fx.compression/assembly.c index e0cfaf5..8e4ad40 100644 --- a/assemblies/fx.compression/assembly.c +++ b/assemblies/fx.compression/assembly.c @@ -1,7 +1,7 @@ #include #include -FX_ASSEMBLY_BEGIN() +FX_ASSEMBLY_BEGIN(fx_compression) FX_ASSEMBLY_NAME("fx.compression"); FX_ASSEMBLY_VERSION(1, 0, 0, 0); -FX_ASSEMBLY_END() +FX_ASSEMBLY_END(fx_compression) diff --git a/assemblies/fx.io/assembly.c b/assemblies/fx.io/assembly.c index 429a461..0e943f7 100644 --- a/assemblies/fx.io/assembly.c +++ b/assemblies/fx.io/assembly.c @@ -1,7 +1,7 @@ #include #include -FX_ASSEMBLY_BEGIN() -FX_ASSEMBLY_NAME("fx.io"); -FX_ASSEMBLY_VERSION(1, 0, 0, 0); -FX_ASSEMBLY_END() +FX_ASSEMBLY_BEGIN(fx_io) + FX_ASSEMBLY_NAME("fx.io"); + FX_ASSEMBLY_VERSION(1, 0, 0, 0); +FX_ASSEMBLY_END(fx_io) diff --git a/assemblies/fx.runtime/assembly.c b/assemblies/fx.runtime/assembly.c index 664289c..4c32baf 100644 --- a/assemblies/fx.runtime/assembly.c +++ b/assemblies/fx.runtime/assembly.c @@ -1,7 +1,7 @@ #include #include -FX_ASSEMBLY_BEGIN() +FX_ASSEMBLY_BEGIN(fx_runtime) FX_ASSEMBLY_NAME("fx.runtime"); FX_ASSEMBLY_VERSION(1, 0, 0, 0); FX_ASSEMBLY_EXPORT_TYPE("fx", "stream", fx_stream); @@ -9,4 +9,4 @@ FX_ASSEMBLY_BEGIN() FX_ASSEMBLY_EXPORT_TYPE("fx", "stringstream", fx_stringstream); FX_ASSEMBLY_EXPORT_TYPE("fx", "iterator", fx_iterator); FX_ASSEMBLY_EXPORT_TYPE("fx.reflection", "assembly", fx_assembly); -FX_ASSEMBLY_END() +FX_ASSEMBLY_END(fx_runtime) diff --git a/assemblies/fx.serial/assembly.c b/assemblies/fx.serial/assembly.c index 8230f45..4fd0c75 100644 --- a/assemblies/fx.serial/assembly.c +++ b/assemblies/fx.serial/assembly.c @@ -1,7 +1,7 @@ #include #include -FX_ASSEMBLY_BEGIN() +FX_ASSEMBLY_BEGIN(fx_serial) FX_ASSEMBLY_NAME("fx.serial"); FX_ASSEMBLY_VERSION(1, 0, 0, 0); -FX_ASSEMBLY_END() +FX_ASSEMBLY_END(fx_serial) diff --git a/assemblies/fx.term/assembly.c b/assemblies/fx.term/assembly.c index bd6637b..299338a 100644 --- a/assemblies/fx.term/assembly.c +++ b/assemblies/fx.term/assembly.c @@ -1,7 +1,7 @@ #include #include -FX_ASSEMBLY_BEGIN() +FX_ASSEMBLY_BEGIN(fx_term) FX_ASSEMBLY_NAME("fx.term"); FX_ASSEMBLY_VERSION(1, 0, 0, 0); -FX_ASSEMBLY_END() +FX_ASSEMBLY_END(fx_term) diff --git a/fx.reflection/function.c b/fx.reflection/function.c index 588f68c..67e4881 100644 --- a/fx.reflection/function.c +++ b/fx.reflection/function.c @@ -22,6 +22,11 @@ struct fx_function_p { /*** PRIVATE FUNCTIONS ********************************************************/ +static const char *function_get_name(const struct fx_function_p *func) +{ + return func->func_name; +} + static fx_status function_bind( struct fx_function_p *func, fx_value *args, @@ -98,10 +103,9 @@ static fx_status function_invoke( return FX_SUCCESS; } -/*** PUBLIC FUNCTIONS - * *********************************************************/ +/*** PUBLIC FUNCTIONS *********************************************************/ -FX_API fx_function *fx_function_create( +fx_function *fx_function_create( const char *name, fx_function_flags flags, fx_function_impl impl, @@ -118,6 +122,10 @@ FX_API fx_function *fx_function_create( func, FX_REFLECTION_TYPE_FUNCTION); + if (nr_args == 1 && args[0] == FX_VALUE_TYPE_NONE) { + nr_args = 0; + } + p->func_name = fx_strdup(name); p->func_flags = flags; p->func_impl = impl; @@ -131,6 +139,14 @@ FX_API fx_function *fx_function_create( return func; } +const char *fx_function_get_name(const fx_function *func) +{ + FX_CLASS_DISPATCH_STATIC_0( + FX_REFLECTION_TYPE_FUNCTION, + function_get_name, + func); +} + fx_status fx_function_bind(fx_function *func, fx_value *args, size_t nr_args) { FX_CLASS_DISPATCH_STATIC( diff --git a/fx.reflection/include/fx/reflection/function.h b/fx.reflection/include/fx/reflection/function.h index ea943af..24f19f7 100644 --- a/fx.reflection/include/fx/reflection/function.h +++ b/fx.reflection/include/fx/reflection/function.h @@ -14,6 +14,7 @@ typedef enum fx_function_flags { FX_FUNCTION_F_STATIC = 0x01u, FX_FUNCTION_F_VIRTUAL = 0x02u, FX_FUNCTION_F_VARARG = 0x04u, + FX_FUNCTION_F_CONSTRUCTOR = 0x08u, } fx_function_flags; typedef void (*fx_function_impl)(); @@ -25,6 +26,8 @@ FX_TYPE_CLASS_DECLARATION_END(fx_function) FX_API fx_type_id fx_function_get_type(); +FX_API const char *fx_function_get_name(const fx_function *func); + FX_API fx_function *fx_function_create( const char *name, fx_function_flags flags, diff --git a/fx.reflection/include/fx/reflection/type.h b/fx.reflection/include/fx/reflection/type.h index 6921bf5..3d839b0 100644 --- a/fx.reflection/include/fx/reflection/type.h +++ b/fx.reflection/include/fx/reflection/type.h @@ -2,6 +2,7 @@ #define FX_REFLECTION_TYPE_H_ #include +#include FX_DECLS_BEGIN; @@ -17,6 +18,9 @@ FX_TYPE_CLASS_DECLARATION_END(fx_type) FX_API fx_type_id fx_type_get_type(); FX_API const char *fx_type_get_name(const fx_type *ty); +FX_API const fx_function *fx_type_get_function( + const fx_type *ty, + const char *name); FX_API const fx_type *fx_type_get_by_id(fx_type_id id); FX_API const fx_type *fx_type_get_by_name(const char *name); diff --git a/fx.reflection/type.c b/fx.reflection/type.c index 01e5acd..2de9904 100644 --- a/fx.reflection/type.c +++ b/fx.reflection/type.c @@ -12,12 +12,22 @@ struct fx_type_p { extern struct fx_type_info *fx_type_info_get_by_id(const union fx_type_id *key); extern struct fx_type_info *fx_type_info_get_by_name(const char *name); +extern fx_function *fx_type_info_get_function_by_name( + const struct fx_type_info *ty, + const char *name); static const char *type_get_name(const struct fx_type_p *ty) { return ty->ty_info->ty_name; } +const fx_function *type_get_function( + const struct fx_type_p *ty, + const char *name) +{ + return fx_type_info_get_function_by_name(ty->ty_info, name); +} + /*** PUBLIC FUNCTIONS *********************************************************/ fx_type *__fx_type_create(struct fx_type_info *type_info) @@ -40,6 +50,15 @@ const char *fx_type_get_name(const fx_type *ty) FX_CLASS_DISPATCH_STATIC_0(FX_REFLECTION_TYPE_TYPE, type_get_name, ty); } +const fx_function *fx_type_get_function(const fx_type *ty, const char *name) +{ + FX_CLASS_DISPATCH_STATIC( + FX_REFLECTION_TYPE_TYPE, + type_get_function, + ty, + name); +} + const fx_type *fx_type_get_by_id(fx_type_id id) { struct fx_type_info *ty = fx_type_info_get_by_id(id); diff --git a/fx/class.c b/fx/class.c index 9924e83..6d1f67a 100644 --- a/fx/class.c +++ b/fx/class.c @@ -73,9 +73,16 @@ fx_result fx_class_instantiate( c_entry); const struct fx_type_info *class_info = comp->c_type; void *class_data = (char *)out + comp->c_class_data_offset; + struct fx_type_info *main_class_param = NULL; + if (class_info == type) { + main_class_param = type; + } if (class_info->ty_class_init) { - class_info->ty_class_init(out, class_data); + class_info->ty_class_init( + out, + main_class_param, + class_data); } entry = fx_queue_next(entry); diff --git a/fx/include/fx/macros.h b/fx/include/fx/macros.h index 3e52885..8f44d27 100644 --- a/fx/include/fx/macros.h +++ b/fx/include/fx/macros.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #define __FX_IFACE_I0(p, x) p##x @@ -13,7 +14,10 @@ /* Type definitions macros (for use in .c source file) */ #define FX_TYPE_CLASS_BEGIN(type_name) \ - static void type_name##_class_init(fx_class *p, void *d) \ + static void type_name##_class_init( \ + fx_class *p, \ + fx_type_info *ty, \ + void *d) \ { #define FX_TYPE_CLASS_END(type_name) } @@ -21,9 +25,49 @@ static void type_name##_type_functionality_init(void *opaque) \ { #define FX_TYPE_FUNCTIONALITY_END(type_name) } -#define FX_TYPE_CONSTRUCTOR(name, impl, ...) -#define FX_TYPE_METHOD(return_type, name, impl, ...) -#define FX_TYPE_FUNCTION(return_type, name, impl, ...) +#define FX_TYPE_CONSTRUCTOR(name, impl, flags, ...) \ + do { \ + if (ty) { \ + fx_value_type args[] = {__VA_ARGS__}; \ + fx_function *func = fx_function_create( \ + name, \ + FX_FUNCTION_F_CONSTRUCTOR \ + | FX_FUNCTION_F_STATIC | (flags), \ + (fx_function_impl)impl, \ + args, \ + sizeof args / sizeof args[0], \ + FX_VALUE_TYPE_POINTER); \ + fx_type_add_function(ty, func); \ + } \ + } while (0) +#define FX_TYPE_METHOD(return_type, name, impl, flags, ...) \ + do { \ + if (ty) { \ + fx_value_type args[] = {__VA_ARGS__}; \ + fx_function *func = fx_function_create( \ + name, \ + (flags), \ + (fx_function_impl)impl, \ + args, \ + sizeof args / sizeof args[0], \ + return_type); \ + fx_type_add_function(ty, func); \ + } \ + } while (0) +#define FX_TYPE_FUNCTION(return_type, name, impl, ...) \ + do { \ + if (ty) { \ + fx_value_type args[] = {__VA_ARGS__}; \ + fx_function *func = fx_function_create( \ + name, \ + FX_FUNCTION_F_STATIC | (flags), \ + (fx_function_impl)impl, \ + args, \ + sizeof args / sizeof args[0], \ + return_type); \ + fx_type_add_function(ty, func); \ + } \ + } while (0) #define FX_TYPE_VTABLE_INTERFACE_BEGIN(interface_name, interface_id) \ interface_name##_class *__FX_IFACE_I1(iface, __LINE__) \ @@ -43,7 +87,7 @@ #define FX_TYPE_DEFINITION_BEGIN(name) \ static fx_type_info name##_type_info = {0}; \ - static void name##_class_init(fx_class *, void *); \ + static void name##_class_init(fx_class *, fx_type_info *, void *); \ static void name##_type_init(void) \ { \ fx_type_info *type_info = &name##_type_info; \ diff --git a/fx/include/fx/type.h b/fx/include/fx/type.h index 91956af..a533e02 100644 --- a/fx/include/fx/type.h +++ b/fx/include/fx/type.h @@ -14,8 +14,12 @@ struct _fx_class; struct _fx_object; +struct fx_type_info; -typedef void (*fx_class_init_function)(struct _fx_class *, void *); +typedef void (*fx_class_init_function)( + struct _fx_class *, + struct fx_type_info *, + void *); typedef void (*fx_instance_init_function)(struct _fx_object *, void *); typedef void (*fx_instance_fini_function)(struct _fx_object *, void *); @@ -86,5 +90,7 @@ static inline int fx_type_id_compare(fx_type_id a, fx_type_id b) } FX_API fx_result fx_type_register(fx_type_info *info); +FX_API fx_result +fx_type_add_function(fx_type_info *info, struct _fx_object *func); #endif diff --git a/fx/string.c b/fx/string.c index 94385c8..d60d799 100644 --- a/fx/string.c +++ b/fx/string.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -1716,6 +1717,19 @@ FX_TYPE_CLASS_BEGIN(fx_string) FX_INTERFACE_ENTRY(it_begin) = iterator_begin; FX_INTERFACE_ENTRY(it_cbegin) = iterator_cbegin; FX_TYPE_VTABLE_INTERFACE_END(fx_iterable, FX_TYPE_ITERABLE) + + FX_TYPE_CONSTRUCTOR("create", fx_string_create, 0, FX_VALUE_TYPE_NONE); + FX_TYPE_CONSTRUCTOR( + "create_from_cstr", + fx_string_create_from_cstr, + 1, + FX_VALUE_TYPE_CSTR); + FX_TYPE_METHOD( + FX_VALUE_TYPE_CSTR, + "get_cstr", + fx_string_get_cstr, + 0, + FX_VALUE_TYPE_POINTER); FX_TYPE_CLASS_END(fx_string) FX_TYPE_DEFINITION_BEGIN(fx_string) diff --git a/fx/type.c b/fx/type.c index 319e402..5288222 100644 --- a/fx/type.c +++ b/fx/type.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -343,6 +344,29 @@ fx_result fx_type_register(struct fx_type_info *info) return FX_RESULT_SUCCESS; } +fx_result fx_type_add_function(fx_type_info *info, struct _fx_object *func) +{ + const char *name = fx_function_get_name(func); + struct fx_namemap_entry *entry = fx_namemap_get( + &info->ty_functions, + name); + if (entry) { + return FX_RESULT_ERR(NAME_EXISTS); + } + + struct fx_type_function *ty_func = malloc(sizeof *ty_func); + if (!ty_func) { + return FX_RESULT_ERR(NO_MEMORY); + } + + memset(ty_func, 0x0, sizeof *ty_func); + + ty_func->f_func = func; + fx_namemap_put(&info->ty_functions, name, &ty_func->f_entry); + + return FX_RESULT_SUCCESS; +} + struct fx_type_info *fx_type_info_get_by_id(const union fx_type_id *key) { return get_type(&type_idmap, key); @@ -357,3 +381,19 @@ struct fx_type_info *fx_type_info_get_by_name(const char *name) return fx_unbox(struct fx_type_info, entry, ty_namemap_entry); } + +fx_function *fx_type_info_get_function_by_name( + const struct fx_type_info *ty, + const char *name) +{ + fx_namemap_entry *entry = fx_namemap_get(&ty->ty_functions, name); + if (!entry) { + return NULL; + } + + struct fx_type_function *func = fx_unbox( + struct fx_type_function, + entry, + f_entry); + return func->f_func; +} diff --git a/fx/type.h b/fx/type.h index 061da32..93c2b4f 100644 --- a/fx/type.h +++ b/fx/type.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -20,7 +21,7 @@ struct fx_type_component { struct fx_type_function { struct fx_namemap_entry f_entry; - struct fx_function *f_func; + fx_function *f_func; }; extern struct fx_type_registration *fx_type_get_registration(fx_type_id id); @@ -29,5 +30,8 @@ extern struct fx_type_component *fx_type_get_component( const union fx_type_id *key); extern struct fx_type_info *fx_type_info_get_by_id(const union fx_type_id *key); extern struct fx_type_info *fx_type_info_get_by_name(const char *name); +extern fx_function *fx_type_info_get_function_by_name( + const struct fx_type_info *ty, + const char *name); #endif