From b8e270b9628592441e42555e1cbeb70bdb105aa9 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Mon, 4 May 2026 22:53:45 +0100 Subject: [PATCH] fx.reflection: function: implementing pre-binding argument values to functions --- fx.reflection/function.c | 79 ++++++++++++++++--- .../include/fx/reflection/function.h | 2 +- 2 files changed, 67 insertions(+), 14 deletions(-) diff --git a/fx.reflection/function.c b/fx.reflection/function.c index 73d7626..66d9870 100644 --- a/fx.reflection/function.c +++ b/fx.reflection/function.c @@ -15,14 +15,46 @@ struct fx_function_p { * variable number of arguments, which may be handled differently by the * ABI */ size_t func_nr_args; + + fx_value *func_bound_args; + size_t func_nr_bound_args, func_max_bound_args; }; /*** PRIVATE FUNCTIONS ********************************************************/ -extern intptr_t fx_function_invoke_i( - fx_function_impl impl, - const fx_value *args, - size_t nr_args); +static fx_status function_bind( + struct fx_function_p *func, + fx_value *args, + size_t nr_args) +{ + if (func->func_nr_bound_args) { + fx_value_unset_array( + func->func_bound_args, + func->func_nr_bound_args); + } + + if (!args || !nr_args) { + func->func_nr_bound_args = 0; + return FX_SUCCESS; + } + + if (nr_args > func->func_max_bound_args) { + fx_value *buf = realloc( + func->func_bound_args, + nr_args * sizeof *buf); + if (!buf) { + return FX_ERR_NO_MEMORY; + } + + func->func_bound_args = buf; + func->func_max_bound_args = nr_args; + } + + fx_value_copy_array(func->func_bound_args, args, nr_args); + func->func_nr_bound_args = nr_args; + + return FX_SUCCESS; +} static fx_status function_invoke( const struct fx_function_p *func, @@ -30,34 +62,44 @@ static fx_status function_invoke( size_t nr_args, fx_value *return_value) { - if (nr_args < func->func_nr_args) { + size_t total_args = nr_args + func->func_nr_bound_args; + + if (total_args < func->func_nr_args) { return FX_ERR_INVALID_ARGUMENT; } - if (nr_args > func->func_nr_args + if (total_args > func->func_nr_args && !(func->func_flags & FX_FUNCTION_F_VARARG)) { return FX_ERR_INVALID_ARGUMENT; } size_t nr_fixed_args = func->func_nr_args; - size_t nr_var_args = nr_args - nr_fixed_args; + size_t nr_var_args = total_args - nr_fixed_args; struct callvm vm = {0}; callvm_reset(&vm, nr_fixed_args); + for (size_t i = 0; i < func->func_nr_bound_args; i++) { + const fx_value *arg = &func->func_bound_args[i]; + callvm_push(&vm, arg); + } + for (size_t i = 0; i < nr_args; i++) { const fx_value *arg = &args[i]; callvm_push(&vm, arg); } - *return_value - = callvm_invoke(&vm, func->func_impl, func->func_return_type); + *return_value = callvm_invoke( + &vm, + func->func_impl, + func->func_return_type); callvm_reset(&vm, 0); return FX_SUCCESS; } -/*** PUBLIC FUNCTIONS *********************************************************/ +/*** PUBLIC FUNCTIONS + * *********************************************************/ FX_API fx_function *fx_function_create( const char *name, @@ -72,8 +114,9 @@ FX_API fx_function *fx_function_create( return NULL; } - struct fx_function_p *p - = fx_object_get_private(func, FX_REFLECTION_TYPE_FUNCTION); + struct fx_function_p *p = fx_object_get_private( + func, + FX_REFLECTION_TYPE_FUNCTION); p->func_name = fx_strdup(name); p->func_flags = flags; @@ -88,7 +131,17 @@ FX_API fx_function *fx_function_create( return func; } -FX_API fx_status fx_function_invoke( +fx_status fx_function_bind(fx_function *func, fx_value *args, size_t nr_args) +{ + FX_CLASS_DISPATCH_STATIC( + FX_REFLECTION_TYPE_FUNCTION, + function_bind, + func, + args, + nr_args); +} + +fx_status fx_function_invoke( const fx_function *func, const fx_value *args, size_t nr_args, diff --git a/fx.reflection/include/fx/reflection/function.h b/fx.reflection/include/fx/reflection/function.h index 03d78ec..201fce7 100644 --- a/fx.reflection/include/fx/reflection/function.h +++ b/fx.reflection/include/fx/reflection/function.h @@ -67,7 +67,7 @@ FX_API fx_function *fx_function_create( size_t nr_args, fx_value_type return_type); FX_API fx_status -fx_function_bind(const fx_function *func, const fx_value *args, size_t nr_args); +fx_function_bind(fx_function *func, fx_value *args, size_t nr_args); FX_API fx_status fx_function_invoke( const fx_function *func, const fx_value *args,