fx.reflection: function: implementing pre-binding argument values to functions
This commit is contained in:
+66
-13
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user