Files
fx/fx.reflection/function.c
T

141 lines
3.3 KiB
C

#include <fx/macros.h>
#include <fx/reflection/function.h>
#include <fx/string.h>
#include <fx/value.h>
#include <platform/callvm.h>
struct fx_function_p {
char *func_name;
fx_function_flags func_flags;
fx_function_impl func_impl;
fx_value_type func_return_type;
fx_value_type *func_arg_types;
/* number of explicit arguments that the function takes.
* if the FX_FUNCTION_F_VARARG flag is set, the function supports a
* variable number of arguments, which may be handled differently by the
* ABI */
size_t func_nr_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_invoke(
const struct fx_function_p *func,
const fx_value *args,
size_t nr_args,
fx_value *return_value)
{
if (nr_args < func->func_nr_args) {
return FX_ERR_INVALID_ARGUMENT;
}
if (nr_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;
struct callvm vm = {0};
callvm_reset(&vm, nr_fixed_args);
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);
callvm_reset(&vm, 0);
return FX_SUCCESS;
}
/*** PUBLIC FUNCTIONS *********************************************************/
FX_API fx_function *fx_function_create(
const char *name,
fx_function_flags flags,
fx_function_impl impl,
const fx_value_type *args,
size_t nr_args,
fx_value_type return_type)
{
fx_function *func = fx_object_create(FX_REFLECTION_TYPE_FUNCTION);
if (!func) {
return NULL;
}
struct fx_function_p *p
= fx_object_get_private(func, FX_REFLECTION_TYPE_FUNCTION);
p->func_name = fx_strdup(name);
p->func_flags = flags;
p->func_impl = impl;
p->func_nr_args = nr_args;
p->func_return_type = return_type;
p->func_arg_types = calloc(nr_args, sizeof *args);
for (size_t i = 0; i < nr_args; i++) {
p->func_arg_types[i] = args[i];
}
return func;
}
FX_API fx_status fx_function_invoke(
const fx_function *func,
const fx_value *args,
size_t nr_args,
fx_value *return_value)
{
FX_CLASS_DISPATCH_STATIC(
FX_REFLECTION_TYPE_FUNCTION,
function_invoke,
func,
args,
nr_args,
return_value);
}
/*** VIRTUAL FUNCTIONS
* ********************************************************/
static void function_init(fx_object *obj, void *priv)
{
}
static void function_fini(fx_object *obj, void *priv)
{
struct fx_function_p *p = priv;
if (p->func_name) {
free(p->func_name);
}
if (p->func_arg_types) {
free(p->func_arg_types);
}
}
/*** CLASS DEFINITION
* *********************************************************/
FX_TYPE_CLASS_DEFINITION_BEGIN(fx_function)
FX_TYPE_CLASS_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
FX_INTERFACE_ENTRY(to_string) = NULL;
FX_TYPE_CLASS_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
FX_TYPE_CLASS_DEFINITION_END(fx_function)
FX_TYPE_DEFINITION_BEGIN(fx_function)
FX_TYPE_ID(0x09e40174, 0x7443, 0x486e, 0xad21, 0xcc9374762e7e);
FX_TYPE_CLASS(fx_function_class);
FX_TYPE_INSTANCE_PRIVATE(struct fx_function_p);
FX_TYPE_INSTANCE_INIT(function_init);
FX_TYPE_INSTANCE_FINI(function_fini);
FX_TYPE_DEFINITION_END(fx_function)