fx.reflection: function: update invocation to support new value-types

This commit is contained in:
2026-05-17 17:11:02 +01:00
parent f1258489d1
commit 61182e0153
4 changed files with 196 additions and 23 deletions
+43 -7
View File
@@ -1,6 +1,7 @@
#include <fx/macros.h> #include <fx/macros.h>
#include <fx/reflection/function.h> #include <fx/reflection/function.h>
#include <fx/string.h> #include <fx/string.h>
#include <fx/value-type.h>
#include <fx/value.h> #include <fx/value.h>
#include <platform/callvm.h> #include <platform/callvm.h>
@@ -8,8 +9,8 @@ struct fx_function_p {
char *func_name; char *func_name;
fx_function_flags func_flags; fx_function_flags func_flags;
fx_function_impl func_impl; fx_function_impl func_impl;
fx_value_type func_return_type; fx_type_id func_return_type;
fx_value_type *func_arg_types; fx_type_id *func_arg_types;
/* number of explicit arguments that the function takes. /* number of explicit arguments that the function takes.
* if the FX_FUNCTION_F_VARARG flag is set, the function supports a * if the FX_FUNCTION_F_VARARG flag is set, the function supports a
* variable number of arguments, which may be handled differently by the * variable number of arguments, which may be handled differently by the
@@ -61,6 +62,28 @@ static fx_status function_bind(
return FX_SUCCESS; return FX_SUCCESS;
} }
static void push_arg(
const fx_value *arg,
fx_type_id param_type,
struct callvm *vm)
{
if (!param_type) {
callvm_push(vm, arg);
return;
}
unsigned int param_value_type = __fx_type_get_value_type(param_type);
if (param_value_type == __FX_VALUE_TYPE_CSTR
&& fx_value_is_type(arg, FX_TYPE_STRING)) {
fx_value cstr = FX_CSTR(
fx_string_get_cstr(fx_value_get_object_c(arg)));
callvm_push(vm, &cstr);
return;
}
callvm_push(vm, arg);
}
static fx_status function_invoke( static fx_status function_invoke(
const struct fx_function_p *func, const struct fx_function_p *func,
const fx_value *args, const fx_value *args,
@@ -84,14 +107,27 @@ static fx_status function_invoke(
struct callvm vm = {0}; struct callvm vm = {0};
callvm_reset(&vm, nr_fixed_args); callvm_reset(&vm, nr_fixed_args);
size_t param_index = 0;
for (size_t i = 0; i < func->func_nr_bound_args; i++) { for (size_t i = 0; i < func->func_nr_bound_args; i++) {
const fx_value *arg = &func->func_bound_args[i]; const fx_value *arg = &func->func_bound_args[i];
callvm_push(&vm, arg); fx_type_id param_type = NULL;
if (param_index < func->func_nr_args) {
param_type = func->func_arg_types[param_index];
}
push_arg(arg, param_type, &vm);
param_index++;
} }
for (size_t i = 0; i < nr_args; i++) { for (size_t i = 0; i < nr_args; i++) {
const fx_value *arg = &args[i]; const fx_value *arg = &args[i];
callvm_push(&vm, arg); fx_type_id param_type = NULL;
if (param_index < func->func_nr_args) {
param_type = func->func_arg_types[param_index];
}
push_arg(arg, param_type, &vm);
param_index++;
} }
*return_value = callvm_invoke( *return_value = callvm_invoke(
@@ -109,9 +145,9 @@ fx_function *fx_function_create(
const char *name, const char *name,
fx_function_flags flags, fx_function_flags flags,
fx_function_impl impl, fx_function_impl impl,
const fx_value_type *args, const fx_type_id *args,
size_t nr_args, size_t nr_args,
fx_value_type return_type) fx_type_id return_type)
{ {
fx_function *func = fx_object_create(FX_REFLECTION_TYPE_FUNCTION); fx_function *func = fx_object_create(FX_REFLECTION_TYPE_FUNCTION);
if (!func) { if (!func) {
@@ -122,7 +158,7 @@ fx_function *fx_function_create(
func, func,
FX_REFLECTION_TYPE_FUNCTION); FX_REFLECTION_TYPE_FUNCTION);
if (nr_args == 1 && args[0] == FX_VALUE_TYPE_NONE) { if (nr_args == 1 && args[0] == NULL) {
nr_args = 0; nr_args = 0;
} }
@@ -32,9 +32,9 @@ FX_API fx_function *fx_function_create(
const char *name, const char *name,
fx_function_flags flags, fx_function_flags flags,
fx_function_impl impl, fx_function_impl impl,
const fx_value_type *args, const fx_type_id *args,
size_t nr_args, size_t nr_args,
fx_value_type return_type); fx_type_id return_type);
FX_API fx_status FX_API fx_status
fx_function_bind(fx_function *func, 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( FX_API fx_status fx_function_invoke(
+143 -13
View File
@@ -1,3 +1,6 @@
#include <fx/type.h>
#include <fx/value-type.h>
#include <fx/value.h>
#include <platform/callvm.h> #include <platform/callvm.h>
#include <stdlib.h> #include <stdlib.h>
@@ -77,13 +80,88 @@ void callvm_push(struct callvm *vm, const fx_value *value)
return; return;
} }
switch (value->v_type.t_primitive) { if (!fx_type_is_value_type(value->v_type)) {
case FX_VALUE_TYPE_DOUBLE: push_int(vm, (uintptr_t)value->v_object);
return;
}
unsigned int value_type = __fx_type_get_value_type(value->v_type);
switch (value_type) {
case __FX_VALUE_TYPE_BOOL:
push_int(vm, value->v_bool);
break;
case __FX_VALUE_TYPE_I16:
push_int(vm, value->v_i16);
break;
case __FX_VALUE_TYPE_U16:
push_int(vm, value->v_u16);
break;
case __FX_VALUE_TYPE_I32:
push_int(vm, value->v_i32);
break;
case __FX_VALUE_TYPE_U32:
push_int(vm, value->v_u32);
break;
case __FX_VALUE_TYPE_I64:
push_int(vm, value->v_i64);
break;
case __FX_VALUE_TYPE_U64:
push_int(vm, value->v_u64);
break;
case __FX_VALUE_TYPE_IPTR:
push_int(vm, value->v_iptr);
break;
case __FX_VALUE_TYPE_UPTR:
push_int(vm, value->v_uptr);
break;
case __FX_VALUE_TYPE_SBYTE:
push_int(vm, value->v_sbyte);
break;
case __FX_VALUE_TYPE_BYTE:
push_int(vm, value->v_byte);
break;
case __FX_VALUE_TYPE_SHORT:
push_int(vm, value->v_short);
break;
case __FX_VALUE_TYPE_USHORT:
push_int(vm, value->v_ushort);
break;
case __FX_VALUE_TYPE_INT:
push_int(vm, value->v_int);
break;
case __FX_VALUE_TYPE_UINT:
push_int(vm, value->v_uint);
break;
case __FX_VALUE_TYPE_LONG:
push_int(vm, value->v_long);
break;
case __FX_VALUE_TYPE_ULONG:
push_int(vm, value->v_ulong);
break;
case __FX_VALUE_TYPE_LONGLONG:
push_int(vm, value->v_longlong);
break;
case __FX_VALUE_TYPE_ULONGLONG:
push_int(vm, value->v_ulonglong);
break;
case __FX_VALUE_TYPE_SIZE:
push_int(vm, value->v_size);
break;
case __FX_VALUE_TYPE_FLOAT:
push_double(vm, value->v_float);
break;
case __FX_VALUE_TYPE_DOUBLE:
push_double(vm, value->v_double); push_double(vm, value->v_double);
break; break;
default: case __FX_VALUE_TYPE_CSTR:
push_int(vm, (uintptr_t)value->v_cstr);
break;
case __FX_VALUE_TYPE_POINTER:
push_int(vm, (uintptr_t)value->v_pointer); push_int(vm, (uintptr_t)value->v_pointer);
break; break;
default:
break;
} }
} }
@@ -94,17 +172,69 @@ extern void callvm_invoke_v(fx_function_impl impl, struct callvm *vm);
fx_value callvm_invoke( fx_value callvm_invoke(
struct callvm *vm, struct callvm *vm,
fx_function_impl impl, fx_function_impl impl,
fx_value_type return_type) fx_type_id return_type)
{ {
switch (return_type) { if (!fx_type_is_value_type(return_type)) {
case FX_VALUE_TYPE_NONE: uintptr_t v = callvm_invoke_i(impl, vm);
callvm_invoke_v(impl, vm); fx_value result = {
break; .v_type = return_type,
case FX_VALUE_TYPE_DOUBLE: .v_object = (fx_object *)v,
return FX_VALUE_DOUBLE(callvm_invoke_d(impl, vm)); };
default: return result;
return FX_VALUE_INT(callvm_invoke_i(impl, vm));
} }
return FX_VALUE_EMPTY; unsigned int value_type = __fx_type_get_value_type(return_type);
switch (value_type) {
case __FX_VALUE_TYPE_BOOL:
return FX_BOOL(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_I16:
return FX_I16(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_U16:
return FX_U16(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_I32:
return FX_I32(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_U32:
return FX_U32(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_I64:
return FX_I64(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_U64:
return FX_U64(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_IPTR:
return FX_IPTR(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_UPTR:
return FX_UPTR(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_SBYTE:
return FX_SBYTE(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_BYTE:
return FX_BYTE(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_SHORT:
return FX_SHORT(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_USHORT:
return FX_USHORT(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_INT:
return FX_INT(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_UINT:
return FX_UINT(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_LONG:
return FX_LONG(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_ULONG:
return FX_ULONG(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_LONGLONG:
return FX_LONGLONG(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_ULONGLONG:
return FX_ULONGLONG(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_SIZE:
return FX_SIZE(callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_FLOAT:
return FX_FLOAT(callvm_invoke_d(impl, vm));
case __FX_VALUE_TYPE_DOUBLE:
return FX_DOUBLE(callvm_invoke_d(impl, vm));
case __FX_VALUE_TYPE_CSTR:
return FX_CSTR((const char *)callvm_invoke_i(impl, vm));
case __FX_VALUE_TYPE_POINTER:
return FX_POINTER((void *)callvm_invoke_i(impl, vm));
default:
return FX_VALUE_EMPTY;
}
} }
@@ -5,6 +5,11 @@
#include <fx/value.h> #include <fx/value.h>
#include <stdint.h> #include <stdint.h>
#define CALLVM_INVOKE_PROTOTYPE(suffix) \
fx_value callvm_invoke_##suffix( \
struct callvm *vm, \
fx_function_impl impl)
#define MAX_FIXED_ARGS ((unsigned int)-1) #define MAX_FIXED_ARGS ((unsigned int)-1)
#define MAX_DOUBLE_ARGS 8 #define MAX_DOUBLE_ARGS 8
#define MAX_INT_ARGS 8 #define MAX_INT_ARGS 8
@@ -26,11 +31,13 @@ struct callvm {
uintptr_t *vm_arg_excess; uintptr_t *vm_arg_excess;
}; };
typedef fx_value (*callvm_invoke_impl)(struct callvm *, fx_function_impl);
extern void callvm_reset(struct callvm *vm, unsigned int max_fixed_args); extern void callvm_reset(struct callvm *vm, unsigned int max_fixed_args);
extern void callvm_push(struct callvm *vm, const fx_value *value); extern void callvm_push(struct callvm *vm, const fx_value *value);
extern fx_value callvm_invoke( extern fx_value callvm_invoke(
struct callvm *vm, struct callvm *vm,
fx_function_impl impl, fx_function_impl impl,
fx_value_type return_type); fx_type_id return_type);
#endif #endif