Compare commits
12 Commits
87270b686c
...
18c9d30c60
| Author | SHA1 | Date | |
|---|---|---|---|
| 18c9d30c60 | |||
| 716b939d4f | |||
| 5aae7dff6b | |||
| 32264d693c | |||
| fd35c2b03e | |||
| bf7d8cfb75 | |||
| 85ff8b7eaa | |||
| dab3fec6b8 | |||
| 7d44a6ec98 | |||
| 7b5173127c | |||
| 6777c09f67 | |||
| d75ec65721 |
+7
-3
@@ -1,5 +1,5 @@
|
|||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
project(fx C)
|
project(fx C ASM)
|
||||||
|
|
||||||
include (TestBigEndian)
|
include (TestBigEndian)
|
||||||
|
|
||||||
@@ -9,6 +9,8 @@ set(CMAKE_C_EXTENSIONS OFF)
|
|||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
|
||||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
|
|
||||||
|
set(fx_source_root ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
set(fx_build_root ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
file(GLOB _all_assemblies assemblies/*
|
file(GLOB _all_assemblies assemblies/*
|
||||||
LIST_DIRECTORIES TRUE)
|
LIST_DIRECTORIES TRUE)
|
||||||
|
|
||||||
@@ -33,8 +35,10 @@ message(STATUS "Floating point support: ${fx_enable_floating_point}")
|
|||||||
|
|
||||||
set(fx_system_name ${CMAKE_SYSTEM_NAME})
|
set(fx_system_name ${CMAKE_SYSTEM_NAME})
|
||||||
string(TOLOWER ${fx_system_name} fx_system_name)
|
string(TOLOWER ${fx_system_name} fx_system_name)
|
||||||
|
set(fx_system_arch ${CMAKE_SYSTEM_PROCESSOR})
|
||||||
|
string(TOLOWER ${fx_system_arch} fx_system_arch)
|
||||||
|
|
||||||
message(STATUS "System name: ${fx_system_name}")
|
message(STATUS "Target system: ${fx_system_name}-${fx_system_arch}")
|
||||||
|
|
||||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)
|
||||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib)
|
||||||
@@ -46,4 +50,4 @@ foreach (assembly ${fx_assemblies})
|
|||||||
add_subdirectory(assemblies/${assembly})
|
add_subdirectory(assemblies/${assembly})
|
||||||
endforeach (assembly)
|
endforeach (assembly)
|
||||||
|
|
||||||
add_executable(dynamic-test test/dynamic-test.c)
|
add_subdirectory(test)
|
||||||
|
|||||||
+10
-3
@@ -20,7 +20,7 @@ function(add_fx_assembly)
|
|||||||
set(assembly_sources ${CMAKE_CURRENT_SOURCE_DIR}/assembly.c)
|
set(assembly_sources ${CMAKE_CURRENT_SOURCE_DIR}/assembly.c)
|
||||||
|
|
||||||
foreach (dir ${arg_NAMESPACES})
|
foreach (dir ${arg_NAMESPACES})
|
||||||
add_subdirectory(../../${dir} ../../namespaces/${dir})
|
add_subdirectory(${fx_source_root}/${dir} ${fx_build_root}/namespaces/${dir})
|
||||||
set(assembly_sources ${assembly_sources} ${namespace_sources})
|
set(assembly_sources ${assembly_sources} ${namespace_sources})
|
||||||
set(assembly_include_paths ${assembly_include_paths} ${namespace_include_paths})
|
set(assembly_include_paths ${assembly_include_paths} ${namespace_include_paths})
|
||||||
endforeach (dir)
|
endforeach (dir)
|
||||||
@@ -80,7 +80,10 @@ macro(export_fx_namespace_details ns_name)
|
|||||||
|
|
||||||
file(GLOB sys_sources
|
file(GLOB sys_sources
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/*.c
|
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/*.c
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/*.h)
|
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/*.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/${fx_system_arch}/*.c
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/${fx_system_arch}/*.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/${fx_system_arch}/*.S)
|
||||||
file(GLOB headers include/${namespace_path}/*.h)
|
file(GLOB headers include/${namespace_path}/*.h)
|
||||||
set(namespace_sources
|
set(namespace_sources
|
||||||
${namespace_sources}
|
${namespace_sources}
|
||||||
@@ -89,8 +92,12 @@ macro(export_fx_namespace_details ns_name)
|
|||||||
${sys_sources}
|
${sys_sources}
|
||||||
${headers}
|
${headers}
|
||||||
PARENT_SCOPE)
|
PARENT_SCOPE)
|
||||||
|
set(internal_include_dirs
|
||||||
|
${internal_include_dirs}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/include
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/sys/${fx_system_name}/${fx_system_arch}/include
|
||||||
|
PARENT_SCOPE)
|
||||||
set(internal_libs ${internal_libs} PARENT_SCOPE)
|
set(internal_libs ${internal_libs} PARENT_SCOPE)
|
||||||
set(internal_include_dirs ${internal_include_dirs} PARENT_SCOPE)
|
|
||||||
set(internal_defines ${internal_defines} PARENT_SCOPE)
|
set(internal_defines ${internal_defines} PARENT_SCOPE)
|
||||||
endmacro(export_fx_namespace_details)
|
endmacro(export_fx_namespace_details)
|
||||||
|
|
||||||
|
|||||||
+3
-17
@@ -1,4 +1,5 @@
|
|||||||
#include <fx/collections/dict.h>
|
#include <fx/collections/dict.h>
|
||||||
|
#include <fx/hash.h>
|
||||||
#include <fx/status.h>
|
#include <fx/status.h>
|
||||||
#include <fx/stream.h>
|
#include <fx/stream.h>
|
||||||
#include <fx/string.h>
|
#include <fx/string.h>
|
||||||
@@ -47,21 +48,6 @@ static FX_BST_DEFINE_SIMPLE_INSERT(
|
|||||||
bk_hash,
|
bk_hash,
|
||||||
put_bucket);
|
put_bucket);
|
||||||
|
|
||||||
uint64_t fx_cstr_hash(const char *s)
|
|
||||||
{
|
|
||||||
#define FNV1_OFFSET_BASIS 0xcbf29ce484222325
|
|
||||||
#define FNV1_PRIME 0x100000001b3
|
|
||||||
uint64_t hash = FNV1_OFFSET_BASIS;
|
|
||||||
size_t i = 0;
|
|
||||||
|
|
||||||
for (i = 0; s[i]; i++) {
|
|
||||||
hash ^= s[i];
|
|
||||||
hash *= FNV1_PRIME;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** PRIVATE FUNCTIONS ********************************************************/
|
/*** PRIVATE FUNCTIONS ********************************************************/
|
||||||
|
|
||||||
static struct fx_dict_bucket *create_bucket(void)
|
static struct fx_dict_bucket *create_bucket(void)
|
||||||
@@ -91,7 +77,7 @@ static fx_status dict_put(
|
|||||||
const char *key,
|
const char *key,
|
||||||
fx_object *value)
|
fx_object *value)
|
||||||
{
|
{
|
||||||
uint64_t hash = fx_cstr_hash(key);
|
uint64_t hash = fx_hash_cstr(key);
|
||||||
struct fx_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
|
struct fx_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
|
||||||
if (!bucket) {
|
if (!bucket) {
|
||||||
bucket = create_bucket();
|
bucket = create_bucket();
|
||||||
@@ -148,7 +134,7 @@ static fx_status dict_put_sk(
|
|||||||
|
|
||||||
static fx_object *dict_at(const struct fx_dict_p *dict, const char *key)
|
static fx_object *dict_at(const struct fx_dict_p *dict, const char *key)
|
||||||
{
|
{
|
||||||
uint64_t hash = fx_cstr_hash(key);
|
uint64_t hash = fx_hash_cstr(key);
|
||||||
struct fx_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
|
struct fx_dict_bucket *bucket = get_bucket(&dict->d_buckets, hash);
|
||||||
if (!bucket) {
|
if (!bucket) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@@ -1,256 +0,0 @@
|
|||||||
#ifndef FX_DS_NUMBER_H
|
|
||||||
#define FX_DS_NUMBER_H
|
|
||||||
|
|
||||||
#include <fx/macros.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
FX_DECLS_BEGIN;
|
|
||||||
|
|
||||||
#define FX_INT8(v) (fx_number_create_int8(v))
|
|
||||||
#define FX_INT16(v) (fx_number_create_int16(v))
|
|
||||||
#define FX_INT32(v) (fx_number_create_int32(v))
|
|
||||||
#define FX_INT64(v) (fx_number_create_int64(v))
|
|
||||||
#define FX_FLOAT32(v) (fx_number_create_float32(v))
|
|
||||||
#define FX_FLOAT64(v) (fx_number_create_float64(v))
|
|
||||||
#define FX_CHAR(v) (fx_number_create_char(v))
|
|
||||||
#define FX_SHORT(v) (fx_number_create_short(v))
|
|
||||||
#define FX_INT(v) (fx_number_create_int(v))
|
|
||||||
#define FX_LONG(v) (fx_number_create_long(v))
|
|
||||||
#define FX_LONGLONG(v) (fx_number_create_longlong(v))
|
|
||||||
#define FX_FLOAT(v) (fx_number_create_float(v))
|
|
||||||
#define FX_DOUBLE(v) (fx_number_create_double(v))
|
|
||||||
#define FX_SIZE_T(v) (fx_number_create_size_t(v))
|
|
||||||
|
|
||||||
#define FX_RV_INT8(v) FX_RV(fx_number_create_int8(v))
|
|
||||||
#define FX_RV_INT16(v) FX_RV(fx_number_create_int16(v))
|
|
||||||
#define FX_RV_INT32(v) FX_RV(fx_number_create_int32(v))
|
|
||||||
#define FX_RV_INT64(v) FX_RV(fx_number_create_int64(v))
|
|
||||||
#define FX_RV_FLOAT32(v) FX_RV(fx_number_create_float32(v))
|
|
||||||
#define FX_RV_FLOAT64(v) FX_RV(fx_number_create_float64(v))
|
|
||||||
#define FX_RV_CHAR(v) FX_RV(fx_number_create_char(v))
|
|
||||||
#define FX_RV_SHORT(v) FX_RV(fx_number_create_short(v))
|
|
||||||
#define FX_RV_INT(v) FX_RV(fx_number_create_int(v))
|
|
||||||
#define FX_RV_LONG(v) FX_RV(fx_number_create_long(v))
|
|
||||||
#define FX_RV_LONGLONG(v) FX_RV(fx_number_create_longlong(v))
|
|
||||||
#define FX_RV_FLOAT(v) FX_RV(fx_number_create_float(v))
|
|
||||||
#define FX_RV_DOUBLE(v) FX_RV(fx_number_create_double(v))
|
|
||||||
#define FX_RV_SIZE_T(v) FX_RV(fx_number_create_size_t(v))
|
|
||||||
|
|
||||||
#define FX_NUMBER_IVAL(p) (fx_number_get_size_t(p))
|
|
||||||
#define FX_NUMBER_FVAL(p) (fx_number_get_double(p))
|
|
||||||
|
|
||||||
#define FX_TYPE_NUMBER (fx_number_get_type())
|
|
||||||
|
|
||||||
FX_DECLARE_TYPE(fx_number);
|
|
||||||
|
|
||||||
FX_TYPE_CLASS_DECLARATION_BEGIN(fx_number)
|
|
||||||
FX_TYPE_CLASS_DECLARATION_END(fx_number)
|
|
||||||
|
|
||||||
typedef enum fx_number_type {
|
|
||||||
FX_NUMBER_INT8,
|
|
||||||
FX_NUMBER_INT16,
|
|
||||||
FX_NUMBER_INT32,
|
|
||||||
FX_NUMBER_INT64,
|
|
||||||
FX_NUMBER_FLOAT32,
|
|
||||||
FX_NUMBER_FLOAT64,
|
|
||||||
FX_NUMBER_CHAR,
|
|
||||||
FX_NUMBER_SHORT,
|
|
||||||
FX_NUMBER_INT,
|
|
||||||
FX_NUMBER_LONG,
|
|
||||||
FX_NUMBER_LONGLONG,
|
|
||||||
FX_NUMBER_FLOAT,
|
|
||||||
FX_NUMBER_DOUBLE,
|
|
||||||
FX_NUMBER_SIZE_T,
|
|
||||||
FX_NUMBER_HANDLE,
|
|
||||||
FX_NUMBER_TYPE_COUNT,
|
|
||||||
|
|
||||||
FX_NUMBER_BYTE = FX_NUMBER_INT8,
|
|
||||||
FX_NUMBER_WORD = FX_NUMBER_INT16,
|
|
||||||
FX_NUMBER_DWORD = FX_NUMBER_INT32,
|
|
||||||
FX_NUMBER_QWORD = FX_NUMBER_INT64,
|
|
||||||
} fx_number_type;
|
|
||||||
|
|
||||||
FX_API fx_type fx_number_get_type(void);
|
|
||||||
|
|
||||||
FX_API fx_number *fx_number_create(fx_number_type type, void *value_ptr);
|
|
||||||
|
|
||||||
static inline fx_number *fx_number_create_int8(int8_t value)
|
|
||||||
{
|
|
||||||
return fx_number_create(FX_NUMBER_INT8, &value);
|
|
||||||
}
|
|
||||||
static inline fx_number *fx_number_create_int16(int16_t value)
|
|
||||||
{
|
|
||||||
return fx_number_create(FX_NUMBER_INT16, &value);
|
|
||||||
}
|
|
||||||
static inline fx_number *fx_number_create_int32(int32_t value)
|
|
||||||
{
|
|
||||||
return fx_number_create(FX_NUMBER_INT32, &value);
|
|
||||||
}
|
|
||||||
static inline fx_number *fx_number_create_int64(int64_t value)
|
|
||||||
{
|
|
||||||
return fx_number_create(FX_NUMBER_INT64, &value);
|
|
||||||
}
|
|
||||||
static inline fx_number *fx_number_create_float32(float value)
|
|
||||||
{
|
|
||||||
return fx_number_create(FX_NUMBER_FLOAT32, &value);
|
|
||||||
}
|
|
||||||
static inline fx_number *fx_number_create_float64(double value)
|
|
||||||
{
|
|
||||||
return fx_number_create(FX_NUMBER_FLOAT64, &value);
|
|
||||||
}
|
|
||||||
static inline fx_number *fx_number_create_char(char value)
|
|
||||||
{
|
|
||||||
return fx_number_create(FX_NUMBER_CHAR, &value);
|
|
||||||
}
|
|
||||||
static inline fx_number *fx_number_create_short(short value)
|
|
||||||
{
|
|
||||||
return fx_number_create(FX_NUMBER_SHORT, &value);
|
|
||||||
}
|
|
||||||
static inline fx_number *fx_number_create_int(int value)
|
|
||||||
{
|
|
||||||
return fx_number_create(FX_NUMBER_INT, &value);
|
|
||||||
}
|
|
||||||
static inline fx_number *fx_number_create_long(long value)
|
|
||||||
{
|
|
||||||
return fx_number_create(FX_NUMBER_LONG, &value);
|
|
||||||
}
|
|
||||||
static inline fx_number *fx_number_create_longlong(long long value)
|
|
||||||
{
|
|
||||||
return fx_number_create(FX_NUMBER_LONGLONG, &value);
|
|
||||||
}
|
|
||||||
static inline fx_number *fx_number_create_float(float value)
|
|
||||||
{
|
|
||||||
return fx_number_create(FX_NUMBER_FLOAT, &value);
|
|
||||||
}
|
|
||||||
static inline fx_number *fx_number_create_double(double value)
|
|
||||||
{
|
|
||||||
return fx_number_create(FX_NUMBER_DOUBLE, &value);
|
|
||||||
}
|
|
||||||
static inline fx_number *fx_number_create_size_t(size_t value)
|
|
||||||
{
|
|
||||||
return fx_number_create(FX_NUMBER_SIZE_T, &value);
|
|
||||||
}
|
|
||||||
|
|
||||||
FX_API fx_number_type fx_number_get_number_type(const fx_number *number);
|
|
||||||
FX_API int fx_number_get_value(
|
|
||||||
const fx_number *number,
|
|
||||||
fx_number_type type,
|
|
||||||
void *value_ptr);
|
|
||||||
|
|
||||||
static inline int8_t fx_number_get_int8(const fx_number *number)
|
|
||||||
{
|
|
||||||
int8_t v;
|
|
||||||
fx_number_get_value(number, FX_NUMBER_INT8, &v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int16_t fx_number_get_int16(const fx_number *number)
|
|
||||||
{
|
|
||||||
int16_t v;
|
|
||||||
fx_number_get_value(number, FX_NUMBER_INT16, &v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int32_t fx_number_get_int32(const fx_number *number)
|
|
||||||
{
|
|
||||||
int32_t v;
|
|
||||||
fx_number_get_value(number, FX_NUMBER_INT32, &v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int64_t fx_number_get_int64(const fx_number *number)
|
|
||||||
{
|
|
||||||
int64_t v;
|
|
||||||
fx_number_get_value(number, FX_NUMBER_INT64, &v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline float fx_number_get_float32(const fx_number *number)
|
|
||||||
{
|
|
||||||
float v;
|
|
||||||
fx_number_get_value(number, FX_NUMBER_FLOAT32, &v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline double fx_number_get_float64(const fx_number *number)
|
|
||||||
{
|
|
||||||
double v;
|
|
||||||
fx_number_get_value(number, FX_NUMBER_FLOAT64, &v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline char fx_number_get_char(const fx_number *number)
|
|
||||||
{
|
|
||||||
char v;
|
|
||||||
fx_number_get_value(number, FX_NUMBER_CHAR, &v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline short fx_number_get_short(const fx_number *number)
|
|
||||||
{
|
|
||||||
short v;
|
|
||||||
fx_number_get_value(number, FX_NUMBER_SHORT, &v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int fx_number_get_int(const fx_number *number)
|
|
||||||
{
|
|
||||||
int v;
|
|
||||||
fx_number_get_value(number, FX_NUMBER_INT, &v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline long fx_number_get_long(const fx_number *number)
|
|
||||||
{
|
|
||||||
long v;
|
|
||||||
fx_number_get_value(number, FX_NUMBER_LONG, &v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline long long fx_number_get_longlong(const fx_number *number)
|
|
||||||
{
|
|
||||||
long long v;
|
|
||||||
fx_number_get_value(number, FX_NUMBER_LONGLONG, &v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline float fx_number_get_float(const fx_number *number)
|
|
||||||
{
|
|
||||||
float v;
|
|
||||||
fx_number_get_value(number, FX_NUMBER_FLOAT, &v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline double fx_number_get_double(const fx_number *number)
|
|
||||||
{
|
|
||||||
double v;
|
|
||||||
fx_number_get_value(number, FX_NUMBER_DOUBLE, &v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline size_t fx_number_get_size_t(const fx_number *number)
|
|
||||||
{
|
|
||||||
size_t v;
|
|
||||||
fx_number_get_value(number, FX_NUMBER_SIZE_T, &v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
FX_API bool fx_number_is_integer(const fx_number *number);
|
|
||||||
FX_API bool fx_number_is_float(const fx_number *number);
|
|
||||||
FX_API bool fx_number_is_inf(const fx_number *number);
|
|
||||||
FX_API bool fx_number_is_inf_positive(const fx_number *number);
|
|
||||||
FX_API bool fx_number_is_inf_negative(const fx_number *number);
|
|
||||||
FX_API bool fx_number_is_nan(const fx_number *number);
|
|
||||||
FX_API bool fx_number_is_nan_positive(const fx_number *number);
|
|
||||||
FX_API bool fx_number_is_nan_negative(const fx_number *number);
|
|
||||||
|
|
||||||
FX_API void fx_number_set_inf_positive(fx_number *number, bool v);
|
|
||||||
FX_API void fx_number_set_inf_negative(fx_number *number, bool v);
|
|
||||||
FX_API void fx_number_set_nan_positive(fx_number *number, bool v);
|
|
||||||
FX_API void fx_number_set_nan_negative(fx_number *number, bool v);
|
|
||||||
|
|
||||||
FX_API size_t fx_number_data_size(const fx_number *number);
|
|
||||||
|
|
||||||
FX_DECLS_END;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,86 @@
|
|||||||
|
#include <fx/macros.h>
|
||||||
|
#include <fx/reflection/function.h>
|
||||||
|
#include <fx/string.h>
|
||||||
|
#include <fx/value.h>
|
||||||
|
#include <platform/callvm.h>
|
||||||
|
|
||||||
|
struct fx_function_context_p {
|
||||||
|
struct callvm ctx_vm;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*** PRIVATE FUNCTIONS ********************************************************/
|
||||||
|
|
||||||
|
static fx_status function_context_reset(
|
||||||
|
const struct fx_function_context_p *func)
|
||||||
|
{
|
||||||
|
return FX_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static fx_status function_context_push_arg(
|
||||||
|
const struct fx_function_context_p *func,
|
||||||
|
const fx_value *arg)
|
||||||
|
{
|
||||||
|
return FX_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** PUBLIC FUNCTIONS *********************************************************/
|
||||||
|
|
||||||
|
FX_API fx_function *fx_function_context_create(void)
|
||||||
|
{
|
||||||
|
fx_function_context *ctx
|
||||||
|
= fx_object_create(FX_REFLECTION_TYPE_FUNCTION_CONTEXT);
|
||||||
|
if (!ctx) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fx_function_context_p *p = fx_object_get_private(
|
||||||
|
ctx,
|
||||||
|
FX_REFLECTION_TYPE_FUNCTION_CONTEXT);
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
FX_API void fx_function_context_reset(fx_function_context *ctx)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_V0(
|
||||||
|
FX_REFLECTION_TYPE_FUNCTION_CONTEXT,
|
||||||
|
function_context_reset,
|
||||||
|
ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
FX_API void fx_function_context_push_arg(
|
||||||
|
fx_function_context *ctx,
|
||||||
|
const fx_value *value)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_V(
|
||||||
|
FX_REFLECTION_TYPE_FUNCTION_CONTEXT,
|
||||||
|
function_context_push_arg,
|
||||||
|
ctx,
|
||||||
|
value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** VIRTUAL FUNCTIONS ********************************************************/
|
||||||
|
|
||||||
|
static void function_context_init(fx_object *obj, void *priv)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void function_context_fini(fx_object *obj, void *priv)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** CLASS DEFINITION *********************************************************/
|
||||||
|
|
||||||
|
FX_TYPE_CLASS_DEFINITION_BEGIN(fx_function_context)
|
||||||
|
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_context)
|
||||||
|
|
||||||
|
FX_TYPE_DEFINITION_BEGIN(fx_function_context)
|
||||||
|
FX_TYPE_ID(0x97d98a1a, 0x6312, 0x409e, 0xb47d, 0xc5d80daf9e50);
|
||||||
|
FX_TYPE_CLASS(fx_function_context_class);
|
||||||
|
FX_TYPE_INSTANCE_PRIVATE(struct fx_function_context_p);
|
||||||
|
FX_TYPE_INSTANCE_INIT(function_context_init);
|
||||||
|
FX_TYPE_INSTANCE_FINI(function_context_fini);
|
||||||
|
FX_TYPE_DEFINITION_END(fx_function_context)
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
#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)
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
#ifndef FX_REFLECTION_FUNCTION_H_
|
||||||
|
#define FX_REFLECTION_FUNCTION_H_
|
||||||
|
|
||||||
|
#include <fx/macros.h>
|
||||||
|
#include <fx/status.h>
|
||||||
|
#include <fx/value.h>
|
||||||
|
|
||||||
|
FX_DECLS_BEGIN;
|
||||||
|
|
||||||
|
#define FX_REFLECTION_TYPE_FUNCTION (fx_function_get_type())
|
||||||
|
#define FX_REFLECTION_TYPE_FUNCTION_CONTEXT (fx_function_context_get_type())
|
||||||
|
|
||||||
|
typedef enum fx_function_flags {
|
||||||
|
FX_FUNCTION_F_NONE = 0x00u,
|
||||||
|
FX_FUNCTION_F_STATIC = 0x01u,
|
||||||
|
FX_FUNCTION_F_VIRTUAL = 0x02u,
|
||||||
|
FX_FUNCTION_F_VARARG = 0x04u,
|
||||||
|
} fx_function_flags;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define FX_FUNCTION_VALUE(type) \
|
||||||
|
((fx_function_value) { \
|
||||||
|
.v_type = FX_FUNCTION_V_PRIMITIVE, \
|
||||||
|
.v_primitive = (type), \
|
||||||
|
})
|
||||||
|
|
||||||
|
typedef enum fx_function_value_type {
|
||||||
|
FX_FUNCTION_V_NONE = 0,
|
||||||
|
FX_FUNCTION_V_PRIMITIVE,
|
||||||
|
FX_FUNCTION_V_OBJECT,
|
||||||
|
} fx_function_value_type;
|
||||||
|
|
||||||
|
typedef struct fx_function_value {
|
||||||
|
fx_function_value_type v_type;
|
||||||
|
union {
|
||||||
|
fx_value_type v_primitive;
|
||||||
|
fx_type v_object;
|
||||||
|
};
|
||||||
|
} fx_function_value;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void (*fx_function_impl)();
|
||||||
|
|
||||||
|
FX_DECLARE_TYPE(fx_function);
|
||||||
|
FX_DECLARE_TYPE(fx_function_context);
|
||||||
|
|
||||||
|
FX_TYPE_CLASS_DECLARATION_BEGIN(fx_function)
|
||||||
|
FX_TYPE_CLASS_DECLARATION_END(fx_function)
|
||||||
|
|
||||||
|
FX_TYPE_CLASS_DECLARATION_BEGIN(fx_function_context)
|
||||||
|
FX_TYPE_CLASS_DECLARATION_END(fx_function_context)
|
||||||
|
|
||||||
|
FX_API fx_type fx_function_get_type();
|
||||||
|
FX_API fx_type fx_function_context_get_type();
|
||||||
|
|
||||||
|
FX_API fx_function_context *fx_function_context_create(void);
|
||||||
|
FX_API void fx_function_context_reset(fx_function_context *ctx);
|
||||||
|
FX_API void fx_function_context_push_arg(
|
||||||
|
fx_function_context *ctx,
|
||||||
|
const fx_value *value);
|
||||||
|
|
||||||
|
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_API fx_status
|
||||||
|
fx_function_bind(const fx_function *func, const fx_value *args, size_t nr_args);
|
||||||
|
FX_API fx_status fx_function_invoke(
|
||||||
|
const fx_function *func,
|
||||||
|
const fx_value *args,
|
||||||
|
size_t nr_args,
|
||||||
|
fx_value *return_value);
|
||||||
|
FX_API fx_status fx_function_invoke_with_context(
|
||||||
|
const fx_function *func,
|
||||||
|
const fx_function_context *ctx,
|
||||||
|
fx_value *return_value);
|
||||||
|
|
||||||
|
FX_DECLS_END;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#ifndef FX_REFLECTION_PROPERTY_H_
|
||||||
|
#define FX_REFLECTION_PROPERTY_H_
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
#include <platform/callvm.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
switch (arg->v_type.t_primitive) {
|
||||||
|
case FX_VALUE_TYPE_DOUBLE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
callvm_push_int(&vm, (uintptr_t)arg->v_pointer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void callvm_reset(struct callvm *vm, unsigned int max_fixed_args)
|
||||||
|
{
|
||||||
|
vm->vm_arg_int_count = 0;
|
||||||
|
vm->vm_arg_double_count = 0;
|
||||||
|
vm->vm_arg_fixed = max_fixed_args;
|
||||||
|
vm->vm_arg_excess_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void expand_excess(struct callvm *vm)
|
||||||
|
{
|
||||||
|
size_t new_capacity = vm->vm_arg_excess_max * 2;
|
||||||
|
if (!new_capacity) {
|
||||||
|
new_capacity = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *buf = realloc(
|
||||||
|
vm->vm_arg_excess,
|
||||||
|
new_capacity * sizeof *vm->vm_arg_excess);
|
||||||
|
|
||||||
|
if (!buf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm->vm_arg_excess = buf;
|
||||||
|
vm->vm_arg_excess_max = new_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void push_excess(struct callvm *vm, uintptr_t value)
|
||||||
|
{
|
||||||
|
if (vm->vm_arg_excess_count + 1 > vm->vm_arg_excess_max) {
|
||||||
|
expand_excess(vm);
|
||||||
|
}
|
||||||
|
|
||||||
|
vm->vm_arg_excess[vm->vm_arg_excess_count++] = value;
|
||||||
|
vm->vm_arg_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void push_int(struct callvm *vm, uintptr_t value)
|
||||||
|
{
|
||||||
|
if (vm->vm_arg_int_count >= MAX_INT_ARGS) {
|
||||||
|
push_excess(vm, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm->vm_arg_int[vm->vm_arg_int_count++] = value;
|
||||||
|
vm->vm_arg_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void push_double(struct callvm *vm, double value)
|
||||||
|
{
|
||||||
|
if (vm->vm_arg_double_count >= MAX_DOUBLE_ARGS) {
|
||||||
|
push_excess(vm, *(uintptr_t *)&value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm->vm_arg_double[vm->vm_arg_double_count++] = value;
|
||||||
|
vm->vm_arg_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void callvm_push(struct callvm *vm, const fx_value *value)
|
||||||
|
{
|
||||||
|
if (vm->vm_arg_count >= vm->vm_arg_fixed) {
|
||||||
|
push_excess(vm, (uintptr_t)value->v_pointer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (value->v_type.t_primitive) {
|
||||||
|
case FX_VALUE_TYPE_DOUBLE:
|
||||||
|
push_double(vm, value->v_double);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
push_int(vm, (uintptr_t)value->v_pointer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern uintptr_t callvm_invoke_i(fx_function_impl impl, struct callvm *vm);
|
||||||
|
extern double callvm_invoke_d(fx_function_impl impl, struct callvm *vm);
|
||||||
|
extern void callvm_invoke_v(fx_function_impl impl, struct callvm *vm);
|
||||||
|
|
||||||
|
fx_value callvm_invoke(
|
||||||
|
struct callvm *vm,
|
||||||
|
fx_function_impl impl,
|
||||||
|
fx_value_type return_type)
|
||||||
|
{
|
||||||
|
switch (return_type) {
|
||||||
|
case FX_VALUE_TYPE_NONE:
|
||||||
|
callvm_invoke_v(impl, vm);
|
||||||
|
break;
|
||||||
|
case FX_VALUE_TYPE_DOUBLE:
|
||||||
|
return FX_VALUE_DOUBLE(callvm_invoke_d(impl, vm));
|
||||||
|
default:
|
||||||
|
return FX_VALUE_INT(callvm_invoke_i(impl, vm));
|
||||||
|
}
|
||||||
|
|
||||||
|
return FX_VALUE_EMPTY;
|
||||||
|
}
|
||||||
@@ -0,0 +1,178 @@
|
|||||||
|
.global _callvm_invoke_i
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
# x0 = (function ptr) impl
|
||||||
|
# x1 = (struct callvm) context
|
||||||
|
_callvm_invoke_i:
|
||||||
|
# save the stack frame and link pointer
|
||||||
|
stp x29, x30, [sp, #-16]!
|
||||||
|
mov x29, sp
|
||||||
|
|
||||||
|
# store function pointer for later
|
||||||
|
mov x16, x0
|
||||||
|
mov x15, x1
|
||||||
|
|
||||||
|
# First, set up the fixed arguments
|
||||||
|
# x8 = fixed arg count
|
||||||
|
ldr x8, [x15, #0]
|
||||||
|
|
||||||
|
# arg[0]
|
||||||
|
cmp x8, #0
|
||||||
|
ble .iv.idone
|
||||||
|
ldr x0, [x15, #48]
|
||||||
|
|
||||||
|
# arg[1]
|
||||||
|
cmp x8, #1
|
||||||
|
ble .iv.idone
|
||||||
|
ldr x1, [x15, #56]
|
||||||
|
|
||||||
|
# arg[2]
|
||||||
|
cmp x8, #2
|
||||||
|
ble .iv.idone
|
||||||
|
ldr x2, [x15, #64]
|
||||||
|
|
||||||
|
# arg[3]
|
||||||
|
cmp x8, #3
|
||||||
|
ble .iv.idone
|
||||||
|
ldr x3, [x15, #72]
|
||||||
|
|
||||||
|
# arg[4]
|
||||||
|
cmp x8, #4
|
||||||
|
ble .iv.idone
|
||||||
|
ldr x4, [x15, #80]
|
||||||
|
|
||||||
|
# arg[5]
|
||||||
|
cmp x8, #5
|
||||||
|
ble .iv.idone
|
||||||
|
ldr x5, [x15, #88]
|
||||||
|
|
||||||
|
# arg[6]
|
||||||
|
cmp x8, #6
|
||||||
|
ble .iv.idone
|
||||||
|
ldr x6, [x15, #96]
|
||||||
|
|
||||||
|
# arg[7]
|
||||||
|
cmp x8, #7
|
||||||
|
ble .iv.idone
|
||||||
|
ldr x7, [x15, #104]
|
||||||
|
|
||||||
|
.iv.idone:
|
||||||
|
# Next, set up the fixed double arguments
|
||||||
|
# x8 = fixed double arg count
|
||||||
|
ldr x8, [x15, #8]
|
||||||
|
|
||||||
|
# arg[0]
|
||||||
|
cmp x8, #0
|
||||||
|
ble .iv.vdone
|
||||||
|
ldr d0, [x15, #112]
|
||||||
|
|
||||||
|
# arg[1]
|
||||||
|
cmp x8, #1
|
||||||
|
ble .iv.vdone
|
||||||
|
ldr d1, [x15, #120]
|
||||||
|
|
||||||
|
# arg[2]
|
||||||
|
cmp x8, #2
|
||||||
|
ble .iv.vdone
|
||||||
|
ldr d2, [x15, #128]
|
||||||
|
|
||||||
|
# arg[3]
|
||||||
|
cmp x8, #3
|
||||||
|
ble .iv.vdone
|
||||||
|
ldr d3, [x15, #136]
|
||||||
|
|
||||||
|
# arg[4]
|
||||||
|
cmp x8, #4
|
||||||
|
ble .iv.vdone
|
||||||
|
ldr d4, [x15, #144]
|
||||||
|
|
||||||
|
# arg[5]
|
||||||
|
cmp x8, #5
|
||||||
|
ble .iv.vdone
|
||||||
|
ldr d5, [x15, #152]
|
||||||
|
|
||||||
|
# arg[6]
|
||||||
|
cmp x8, #6
|
||||||
|
ble .iv.vdone
|
||||||
|
ldr d6, [x15, #160]
|
||||||
|
|
||||||
|
# arg[7]
|
||||||
|
cmp x8, #7
|
||||||
|
ble .iv.vdone
|
||||||
|
ldr d7, [x15, #168]
|
||||||
|
|
||||||
|
.iv.vdone:
|
||||||
|
# Finally, set up the variable arguments
|
||||||
|
|
||||||
|
# x8 = excess arg count
|
||||||
|
ldr x8, [x15, #32]
|
||||||
|
|
||||||
|
# calculate the amount of stack space needed for the varargs
|
||||||
|
mov x10, #0x10
|
||||||
|
mul x12, x8, x10
|
||||||
|
|
||||||
|
# x19 is caller-saved, and we'll need x12 later
|
||||||
|
str x19, [sp, #-16]!
|
||||||
|
mov x19, x12
|
||||||
|
|
||||||
|
# allocate the stack space
|
||||||
|
sub sp, sp, x19
|
||||||
|
mov x13, sp
|
||||||
|
|
||||||
|
# get a pointer to the end of the stack vararg buffer
|
||||||
|
#mov x14, #8
|
||||||
|
#mul x14, x14, x11
|
||||||
|
#add x13, x13, x14
|
||||||
|
|
||||||
|
# x8: number of var args (decrements with every iteration)
|
||||||
|
# x9: arg src buffer (increments with every iteration)
|
||||||
|
# x13: var arg dest pointer (starts at the end, decrements with every iteration)
|
||||||
|
ldr x9, [x15, #176]
|
||||||
|
|
||||||
|
.iv.loop:
|
||||||
|
cmp x8, #0
|
||||||
|
beq .iv.loop.end
|
||||||
|
|
||||||
|
# read the arg value from the src pointer
|
||||||
|
ldr x14, [x9]
|
||||||
|
|
||||||
|
# write it to the stack, and increment the dest pointer
|
||||||
|
str x14, [x13]
|
||||||
|
add x13, x13, #8
|
||||||
|
|
||||||
|
# increment the src pointer, decrement the arg count
|
||||||
|
sub x8, x8, #1
|
||||||
|
add x9, x9, #8
|
||||||
|
b .iv.loop
|
||||||
|
.iv.loop.end:
|
||||||
|
|
||||||
|
# call the function implementation
|
||||||
|
blr x16
|
||||||
|
|
||||||
|
# de-allocate the stack varargs buffer (the size is now stored in x19)
|
||||||
|
add sp, sp, x19
|
||||||
|
|
||||||
|
# restore the saved value of x19,
|
||||||
|
ldr x19, [sp], #16
|
||||||
|
|
||||||
|
# restore the saved stack frame and link pointer
|
||||||
|
ldp x29,x30, [sp], #16
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
.global _callvm_invoke_d
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
# x0 = (function ptr) impl
|
||||||
|
# x1 = (struct callvm) context
|
||||||
|
_callvm_invoke_d:
|
||||||
|
b _callvm_invoke_i
|
||||||
|
|
||||||
|
|
||||||
|
.global _callvm_invoke_v
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
# x0 = (function ptr) impl
|
||||||
|
# x1 = (struct callvm) context
|
||||||
|
_callvm_invoke_v:
|
||||||
|
b _callvm_invoke_i
|
||||||
@@ -0,0 +1,221 @@
|
|||||||
|
.global _fx_function_invoke_i
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
# x0 = (function ptr) impl
|
||||||
|
# x1 = (fx_value[]) args
|
||||||
|
# x2 = (size_t) nr args
|
||||||
|
_fx_function_invoke_i:
|
||||||
|
# save the stack frame and link pointer
|
||||||
|
stp x29, x30, [sp, #-16]!
|
||||||
|
|
||||||
|
# store function pointer for later
|
||||||
|
str x0, [sp, #-16]!
|
||||||
|
# move arg array of of x1 and x2, so that they can be initialised for
|
||||||
|
# the function call
|
||||||
|
mov x8, x1
|
||||||
|
mov x9, x2
|
||||||
|
|
||||||
|
# arg[0]
|
||||||
|
cmp x9, #0
|
||||||
|
ble .i.done
|
||||||
|
ldr x0, [x8, #8]
|
||||||
|
|
||||||
|
# arg[1]
|
||||||
|
cmp x9, #1
|
||||||
|
ble .i.done
|
||||||
|
ldr x1, [x8, #24]
|
||||||
|
|
||||||
|
# arg[2]
|
||||||
|
cmp x9, #2
|
||||||
|
ble .i.done
|
||||||
|
ldr x2, [x8, #40]
|
||||||
|
|
||||||
|
# arg[3]
|
||||||
|
cmp x9, #3
|
||||||
|
ble .i.done
|
||||||
|
ldr x3, [x8, #56]
|
||||||
|
|
||||||
|
# arg[4]
|
||||||
|
cmp x9, #4
|
||||||
|
ble .i.done
|
||||||
|
ldr x4, [x8, #72]
|
||||||
|
|
||||||
|
# arg[5]
|
||||||
|
cmp x9, #5
|
||||||
|
ble .i.done
|
||||||
|
ldr x5, [x8, #88]
|
||||||
|
|
||||||
|
# arg[6]
|
||||||
|
cmp x9, #6
|
||||||
|
ble .i.done
|
||||||
|
ldr x6, [x8, #104]
|
||||||
|
|
||||||
|
# arg[7]
|
||||||
|
cmp x9, #7
|
||||||
|
ble .i.done
|
||||||
|
ldr x7, [x8, #120]
|
||||||
|
|
||||||
|
.i.done:
|
||||||
|
ldr x8, [sp], #16
|
||||||
|
blr x8
|
||||||
|
|
||||||
|
# restore the saved stack frame and link pointer
|
||||||
|
ldp x29,x30, [sp], #16
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
.global _fx_function_invoke_d
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
_fx_function_invoke_d:
|
||||||
|
mov x0, 888
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
.global _fx_function_invoke_v
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
_fx_function_invoke_v:
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.global _fx_function_invoke_iv
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
# x0 = (function ptr) impl
|
||||||
|
# x1 = (fx_value[]) args
|
||||||
|
# x2 = (size_t) nr fixed args
|
||||||
|
# x3 = (size_t) nr var args
|
||||||
|
_fx_function_invoke_iv:
|
||||||
|
# save the stack frame and link pointer
|
||||||
|
stp x29, x30, [sp, #-16]!
|
||||||
|
mov x29, sp
|
||||||
|
|
||||||
|
# store function pointer for later
|
||||||
|
mov x15, x0
|
||||||
|
# move arg array of of x1,x2,x3, so that they can be initialised for
|
||||||
|
# the function call
|
||||||
|
mov x9, x1
|
||||||
|
mov x10, x2
|
||||||
|
mov x11, x3
|
||||||
|
|
||||||
|
# First, set up the fixed arguments
|
||||||
|
|
||||||
|
# arg[0]
|
||||||
|
cmp x10, #0
|
||||||
|
ble .iv.done
|
||||||
|
ldr x0, [x9, #8]
|
||||||
|
add x9, x9, #16
|
||||||
|
|
||||||
|
# arg[1]
|
||||||
|
cmp x10, #1
|
||||||
|
ble .iv.done
|
||||||
|
ldr x1, [x9, #8]
|
||||||
|
add x9, x9, #16
|
||||||
|
|
||||||
|
# arg[2]
|
||||||
|
cmp x10, #2
|
||||||
|
ble .iv.done
|
||||||
|
ldr x2, [x9, #8]
|
||||||
|
add x9, x9, #16
|
||||||
|
|
||||||
|
# arg[3]
|
||||||
|
cmp x10, #3
|
||||||
|
ble .iv.done
|
||||||
|
ldr x3, [x9, #8]
|
||||||
|
add x9, x9, #16
|
||||||
|
|
||||||
|
# arg[4]
|
||||||
|
cmp x10, #4
|
||||||
|
ble .iv.done
|
||||||
|
ldr x4, [x9, #8]
|
||||||
|
add x9, x9, #16
|
||||||
|
|
||||||
|
# arg[5]
|
||||||
|
cmp x10, #5
|
||||||
|
ble .iv.done
|
||||||
|
ldr x5, [x9, #8]
|
||||||
|
add x9, x9, #16
|
||||||
|
|
||||||
|
# arg[6]
|
||||||
|
cmp x10, #6
|
||||||
|
ble .iv.done
|
||||||
|
ldr x6, [x9, #8]
|
||||||
|
add x9, x9, #16
|
||||||
|
|
||||||
|
# arg[7]
|
||||||
|
cmp x10, #7
|
||||||
|
ble .iv.done
|
||||||
|
ldr x7, [x9, #8]
|
||||||
|
add x9, x9, #16
|
||||||
|
|
||||||
|
.iv.done:
|
||||||
|
# Next, set up the variable arguments
|
||||||
|
|
||||||
|
# calculate the amount of stack space needed for the varargs
|
||||||
|
mov x10, #0x10
|
||||||
|
mul x12, x11, x10
|
||||||
|
#and x12, x12, #0x10
|
||||||
|
#mov x10, #0x10
|
||||||
|
#add x12, x12, x10
|
||||||
|
|
||||||
|
# x19 is caller-saved, and we'll need x12 later
|
||||||
|
str x19, [sp, #-16]!
|
||||||
|
mov x19, x12
|
||||||
|
|
||||||
|
# allocate the stack space
|
||||||
|
sub sp, sp, x19
|
||||||
|
mov x13, sp
|
||||||
|
|
||||||
|
# get a pointer to the end of the stack vararg buffer
|
||||||
|
#mov x14, #8
|
||||||
|
#mul x14, x14, x11
|
||||||
|
#add x13, x13, x14
|
||||||
|
|
||||||
|
# x9: arg src buffer (starts at varargs, increments with every iteration)
|
||||||
|
# x11: number of var args (decrements with every iteration)
|
||||||
|
# x13: var arg dest pointer (starts at the end, decrements with every iteration)
|
||||||
|
.iv.loop:
|
||||||
|
cmp x11, #0
|
||||||
|
beq .iv.loop.end
|
||||||
|
|
||||||
|
# read the arg value from the src pointer
|
||||||
|
ldr x14, [x9, #8]
|
||||||
|
|
||||||
|
# write it to the stack, and increment the dest pointer
|
||||||
|
str x14, [x13]
|
||||||
|
add x13, x13, #8
|
||||||
|
|
||||||
|
# increment the src pointer, decrement the arg count
|
||||||
|
sub x11, x11, #1
|
||||||
|
add x9, x9, #16
|
||||||
|
b .iv.loop
|
||||||
|
.iv.loop.end:
|
||||||
|
|
||||||
|
# call the function implementation
|
||||||
|
blr x15
|
||||||
|
|
||||||
|
# de-allocate the stack varargs buffer (the size is now stored in x19)
|
||||||
|
add sp, sp, x19
|
||||||
|
|
||||||
|
# restore the saved value of x19,
|
||||||
|
ldr x19, [sp], #16
|
||||||
|
|
||||||
|
# restore the saved stack frame and link pointer
|
||||||
|
ldp x29,x30, [sp], #16
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
.global _fx_function_invoke_dv
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
_fx_function_invoke_dv:
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
.global _fx_function_invoke_vv
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
_fx_function_invoke_vv:
|
||||||
|
ret
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef FX_REFLECTION_DARWIN_ARM64_CALLVM_H_
|
||||||
|
#define FX_REFLECTION_DARWIN_ARM64_CALLVM_H_
|
||||||
|
|
||||||
|
#include <fx/reflection/function.h>
|
||||||
|
#include <fx/value.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define MAX_FIXED_ARGS ((unsigned int)-1)
|
||||||
|
#define MAX_DOUBLE_ARGS 8
|
||||||
|
#define MAX_INT_ARGS 8
|
||||||
|
|
||||||
|
/* dyn-dispatch.S depends on the layout of this struct */
|
||||||
|
struct callvm {
|
||||||
|
uint64_t vm_arg_int_count;
|
||||||
|
uint64_t vm_arg_double_count;
|
||||||
|
|
||||||
|
/* any args pushed after this limit is reached will be stored in the
|
||||||
|
* excess buffer. used for calling varargs functions */
|
||||||
|
uint64_t vm_arg_count, vm_arg_fixed;
|
||||||
|
|
||||||
|
uint64_t vm_arg_excess_count;
|
||||||
|
uint64_t vm_arg_excess_max;
|
||||||
|
|
||||||
|
uintptr_t vm_arg_int[MAX_INT_ARGS];
|
||||||
|
double vm_arg_double[MAX_DOUBLE_ARGS];
|
||||||
|
uintptr_t *vm_arg_excess;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void callvm_reset(struct callvm *vm, unsigned int max_fixed_args);
|
||||||
|
extern void callvm_push(struct callvm *vm, const fx_value *value);
|
||||||
|
extern fx_value callvm_invoke(
|
||||||
|
struct callvm *vm,
|
||||||
|
fx_function_impl impl,
|
||||||
|
fx_value_type return_type);
|
||||||
|
|
||||||
|
#endif
|
||||||
+15
-12
@@ -1,14 +1,17 @@
|
|||||||
|
#include <fx/bool.h>
|
||||||
#include <fx/collections/array.h>
|
#include <fx/collections/array.h>
|
||||||
#include <fx/collections/datetime.h>
|
#include <fx/collections/datetime.h>
|
||||||
#include <fx/collections/dict.h>
|
#include <fx/collections/dict.h>
|
||||||
#include <fx/collections/hashmap.h>
|
#include <fx/collections/hashmap.h>
|
||||||
#include <fx/collections/number.h>
|
#include <fx/double.h>
|
||||||
#include <fx/error.h>
|
#include <fx/error.h>
|
||||||
|
#include <fx/int.h>
|
||||||
#include <fx/serial/ctx.h>
|
#include <fx/serial/ctx.h>
|
||||||
#include <fx/serial/toml.h>
|
#include <fx/serial/toml.h>
|
||||||
#include <fx/status.h>
|
#include <fx/status.h>
|
||||||
#include <fx/string.h>
|
#include <fx/string.h>
|
||||||
#include <fx/stringstream.h>
|
#include <fx/stringstream.h>
|
||||||
|
#include <fx/uint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -1688,22 +1691,22 @@ static fx_result parse_string(struct ctx *ctx, fx_object **result)
|
|||||||
static fx_result parse_int(struct ctx *ctx, fx_object **result)
|
static fx_result parse_int(struct ctx *ctx, fx_object **result)
|
||||||
{
|
{
|
||||||
struct token *tok = peek_token(ctx);
|
struct token *tok = peek_token(ctx);
|
||||||
fx_number *val = FX_LONGLONG(tok->tok_value.i.v);
|
fx_int *val = fx_int_create(tok->tok_value.i.v);
|
||||||
if (!val) {
|
if (!val) {
|
||||||
return FX_RESULT_ERR(NO_MEMORY);
|
return FX_RESULT_ERR(NO_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tok->tok_value.i.inf) {
|
if (tok->tok_value.i.inf) {
|
||||||
if (tok->tok_value.i.v >= 0) {
|
if (tok->tok_value.i.v >= 0) {
|
||||||
fx_number_set_inf_positive(val, true);
|
fx_int_set_value_inf(val);
|
||||||
} else {
|
} else {
|
||||||
fx_number_set_inf_negative(val, true);
|
fx_int_set_value_inf_negative(val);
|
||||||
}
|
}
|
||||||
} else if (tok->tok_value.i.nan) {
|
} else if (tok->tok_value.i.nan) {
|
||||||
if (tok->tok_value.i.v >= 0) {
|
if (tok->tok_value.i.v >= 0) {
|
||||||
fx_number_set_nan_positive(val, true);
|
fx_int_set_value_nan(val);
|
||||||
} else {
|
} else {
|
||||||
fx_number_set_nan_negative(val, true);
|
fx_int_set_value_nan_negative(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1714,22 +1717,22 @@ static fx_result parse_int(struct ctx *ctx, fx_object **result)
|
|||||||
static fx_result parse_float(struct ctx *ctx, fx_object **result)
|
static fx_result parse_float(struct ctx *ctx, fx_object **result)
|
||||||
{
|
{
|
||||||
struct token *tok = peek_token(ctx);
|
struct token *tok = peek_token(ctx);
|
||||||
fx_number *val = FX_DOUBLE(tok->tok_value.f.v);
|
fx_double *val = fx_double_create(tok->tok_value.f.v);
|
||||||
if (!val) {
|
if (!val) {
|
||||||
return FX_RESULT_ERR(NO_MEMORY);
|
return FX_RESULT_ERR(NO_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tok->tok_value.f.inf) {
|
if (tok->tok_value.f.inf) {
|
||||||
if (tok->tok_value.f.v >= 0) {
|
if (tok->tok_value.f.v >= 0) {
|
||||||
fx_number_set_inf_positive(val, true);
|
fx_double_set_value_inf(val);
|
||||||
} else {
|
} else {
|
||||||
fx_number_set_inf_negative(val, true);
|
fx_double_set_value_inf_negative(val);
|
||||||
}
|
}
|
||||||
} else if (tok->tok_value.f.nan) {
|
} else if (tok->tok_value.f.nan) {
|
||||||
if (tok->tok_value.f.v >= 0) {
|
if (tok->tok_value.f.v >= 0) {
|
||||||
fx_number_set_nan_positive(val, true);
|
fx_double_set_value_nan(val);
|
||||||
} else {
|
} else {
|
||||||
fx_number_set_nan_negative(val, true);
|
fx_double_set_value_nan_negative(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1740,7 +1743,7 @@ static fx_result parse_float(struct ctx *ctx, fx_object **result)
|
|||||||
static fx_result parse_bool(struct ctx *ctx, fx_object **result)
|
static fx_result parse_bool(struct ctx *ctx, fx_object **result)
|
||||||
{
|
{
|
||||||
struct token *tok = peek_token(ctx);
|
struct token *tok = peek_token(ctx);
|
||||||
fx_number *val = FX_INT8(tok->tok_value.b);
|
fx_bool *val = fx_bool_create(tok->tok_value.b);
|
||||||
if (!val) {
|
if (!val) {
|
||||||
return FX_RESULT_ERR(NO_MEMORY);
|
return FX_RESULT_ERR(NO_MEMORY);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
#include <fx/bool.h>
|
||||||
|
#include <fx/stream.h>
|
||||||
|
|
||||||
|
/*** PRIVATE DATA *************************************************************/
|
||||||
|
|
||||||
|
struct fx_bool_p {
|
||||||
|
bool b_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*** PRIVATE FUNCTIONS ********************************************************/
|
||||||
|
|
||||||
|
static void bool_set_value(struct fx_bool_p *i, bool v)
|
||||||
|
{
|
||||||
|
i->b_value = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool bool_get_value(struct fx_bool_p *i)
|
||||||
|
{
|
||||||
|
return i->b_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** PUBLIC FUNCTIONS *********************************************************/
|
||||||
|
|
||||||
|
fx_bool *fx_bool_create(bool value)
|
||||||
|
{
|
||||||
|
fx_bool *i = fx_object_create(FX_TYPE_BOOL);
|
||||||
|
if (!i) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fx_bool_p *p = fx_object_get_private(i, FX_TYPE_BOOL);
|
||||||
|
p->b_value = value;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_bool_set_value(fx_bool *i, bool v)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_V(FX_TYPE_BOOL, bool_set_value, i, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_bool_get_value(const fx_bool *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_BOOL, bool_get_value, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** VIRTUAL FUNCTIONS ********************************************************/
|
||||||
|
|
||||||
|
static void bool_init(fx_object *obj, void *priv)
|
||||||
|
{
|
||||||
|
struct fx_bool_p *i = priv;
|
||||||
|
|
||||||
|
i->b_value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bool_fini(fx_object *obj, void *priv)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bool_to_string(const fx_object *obj, fx_stream *out)
|
||||||
|
{
|
||||||
|
struct fx_bool_p *i = fx_object_get_private(obj, FX_TYPE_BOOL);
|
||||||
|
if (i->b_value == false) {
|
||||||
|
fx_stream_write_cstr(out, "false", NULL);
|
||||||
|
} else {
|
||||||
|
fx_stream_write_cstr(out, "true", NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** CLASS DEFINITION *********************************************************/
|
||||||
|
|
||||||
|
FX_TYPE_CLASS_DEFINITION_BEGIN(fx_bool)
|
||||||
|
FX_TYPE_CLASS_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
||||||
|
FX_INTERFACE_ENTRY(to_string) = bool_to_string;
|
||||||
|
FX_TYPE_CLASS_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
||||||
|
FX_TYPE_CLASS_DEFINITION_END(fx_bool)
|
||||||
|
|
||||||
|
FX_TYPE_DEFINITION_BEGIN(fx_bool)
|
||||||
|
FX_TYPE_ID(0x9c8453bf, 0xfc92, 0x4b0a, 0xbcaf, 0xd0c6cdba9310);
|
||||||
|
FX_TYPE_CLASS(fx_bool_class);
|
||||||
|
FX_TYPE_INSTANCE_PRIVATE(struct fx_bool_p);
|
||||||
|
FX_TYPE_INSTANCE_INIT(bool_init);
|
||||||
|
FX_TYPE_INSTANCE_FINI(bool_fini);
|
||||||
|
FX_TYPE_DEFINITION_END(fx_bool)
|
||||||
+280
@@ -0,0 +1,280 @@
|
|||||||
|
#include <fx/double.h>
|
||||||
|
#include <fx/stream.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*** PRIVATE DATA *************************************************************/
|
||||||
|
|
||||||
|
enum double_type {
|
||||||
|
DOUBLE_REGULAR = 0,
|
||||||
|
DOUBLE_INF_POSITIVE,
|
||||||
|
DOUBLE_INF_NEGATIVE,
|
||||||
|
DOUBLE_NAN_POSITIVE,
|
||||||
|
DOUBLE_NAN_NEGATIVE,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fx_double_p {
|
||||||
|
enum double_type i_type;
|
||||||
|
double i_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*** PRIVATE FUNCTIONS ********************************************************/
|
||||||
|
|
||||||
|
static bool double_get_value(const struct fx_double_p *i)
|
||||||
|
{
|
||||||
|
return i->i_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void double_set_value(struct fx_double_p *i, double v)
|
||||||
|
{
|
||||||
|
i->i_type = DOUBLE_REGULAR;
|
||||||
|
i->i_value = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void double_set_value_nan(struct fx_double_p *i)
|
||||||
|
{
|
||||||
|
i->i_type = DOUBLE_NAN_POSITIVE;
|
||||||
|
i->i_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void double_set_value_nan_negative(struct fx_double_p *i)
|
||||||
|
{
|
||||||
|
i->i_type = DOUBLE_NAN_NEGATIVE;
|
||||||
|
i->i_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void double_set_value_inf(struct fx_double_p *i)
|
||||||
|
{
|
||||||
|
i->i_type = DOUBLE_INF_POSITIVE;
|
||||||
|
i->i_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void double_set_value_inf_negative(struct fx_double_p *i)
|
||||||
|
{
|
||||||
|
i->i_type = DOUBLE_INF_NEGATIVE;
|
||||||
|
i->i_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool double_is_nan(struct fx_double_p *i)
|
||||||
|
{
|
||||||
|
return i->i_type == DOUBLE_NAN_POSITIVE
|
||||||
|
|| i->i_type == DOUBLE_NAN_NEGATIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool double_is_nan_positive(struct fx_double_p *i)
|
||||||
|
{
|
||||||
|
return i->i_type == DOUBLE_NAN_POSITIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool double_is_nan_negative(struct fx_double_p *i)
|
||||||
|
{
|
||||||
|
return i->i_type == DOUBLE_NAN_NEGATIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool double_is_inf(struct fx_double_p *i)
|
||||||
|
{
|
||||||
|
return i->i_type == DOUBLE_INF_POSITIVE
|
||||||
|
|| i->i_type == DOUBLE_INF_NEGATIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool double_is_inf_positive(struct fx_double_p *i)
|
||||||
|
{
|
||||||
|
return i->i_type == DOUBLE_INF_POSITIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool double_is_inf_negative(struct fx_double_p *i)
|
||||||
|
{
|
||||||
|
return i->i_type == DOUBLE_INF_NEGATIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** PUBLIC FUNCTIONS *********************************************************/
|
||||||
|
|
||||||
|
fx_double *fx_double_create(double value)
|
||||||
|
{
|
||||||
|
fx_double *i = fx_object_create(FX_TYPE_DOUBLE);
|
||||||
|
if (!i) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fx_double_p *p = fx_object_get_private(i, FX_TYPE_DOUBLE);
|
||||||
|
p->i_type = DOUBLE_REGULAR;
|
||||||
|
p->i_value = value;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_double *fx_double_create_nan(void)
|
||||||
|
{
|
||||||
|
fx_double *i = fx_object_create(FX_TYPE_DOUBLE);
|
||||||
|
if (!i) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fx_double_p *p = fx_object_get_private(i, FX_TYPE_DOUBLE);
|
||||||
|
p->i_type = DOUBLE_NAN_POSITIVE;
|
||||||
|
p->i_value = 0;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_double *fx_double_create_nan_negative(void)
|
||||||
|
{
|
||||||
|
fx_double *i = fx_object_create(FX_TYPE_DOUBLE);
|
||||||
|
if (!i) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fx_double_p *p = fx_object_get_private(i, FX_TYPE_DOUBLE);
|
||||||
|
p->i_type = DOUBLE_NAN_NEGATIVE;
|
||||||
|
p->i_value = 0;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_double *fx_double_create_inf(void)
|
||||||
|
{
|
||||||
|
fx_double *i = fx_object_create(FX_TYPE_DOUBLE);
|
||||||
|
if (!i) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fx_double_p *p = fx_object_get_private(i, FX_TYPE_DOUBLE);
|
||||||
|
p->i_type = DOUBLE_INF_POSITIVE;
|
||||||
|
p->i_value = 0;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_double *fx_double_create_inf_negative(void)
|
||||||
|
{
|
||||||
|
fx_double *i = fx_object_create(FX_TYPE_DOUBLE);
|
||||||
|
if (!i) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fx_double_p *p = fx_object_get_private(i, FX_TYPE_DOUBLE);
|
||||||
|
p->i_type = DOUBLE_INF_NEGATIVE;
|
||||||
|
p->i_value = 0;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
double fx_double_get_value(const fx_double *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_DOUBLE, double_get_value, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_double_set_value(fx_double *i, double v)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_V(FX_TYPE_DOUBLE, double_set_value, i, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_double_set_value_nan(fx_double *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_V0(FX_TYPE_DOUBLE, double_set_value_nan, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_double_set_value_nan_negative(fx_double *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_V0(
|
||||||
|
FX_TYPE_DOUBLE,
|
||||||
|
double_set_value_nan_negative,
|
||||||
|
i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_double_set_value_inf(fx_double *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_V0(FX_TYPE_DOUBLE, double_set_value_inf, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_double_set_value_inf_negative(fx_double *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_V0(
|
||||||
|
FX_TYPE_DOUBLE,
|
||||||
|
double_set_value_inf_negative,
|
||||||
|
i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_double_is_nan(const fx_double *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_DOUBLE, double_is_nan, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_double_is_nan_positive(const fx_double *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_DOUBLE, double_is_nan_positive, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_double_is_nan_negative(const fx_double *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_DOUBLE, double_is_nan_negative, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_double_is_inf(const fx_double *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_DOUBLE, double_is_inf, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_double_is_inf_positive(const fx_double *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_DOUBLE, double_is_inf_positive, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_double_is_inf_negative(const fx_double *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_DOUBLE, double_is_inf_negative, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** VIRTUAL FUNCTIONS ********************************************************/
|
||||||
|
|
||||||
|
static void double_init(fx_object *obj, void *priv)
|
||||||
|
{
|
||||||
|
struct fx_double_p *i = priv;
|
||||||
|
|
||||||
|
i->i_type = DOUBLE_REGULAR;
|
||||||
|
i->i_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void double_fini(fx_object *obj, void *priv)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void double_to_string(const fx_object *obj, fx_stream *out)
|
||||||
|
{
|
||||||
|
struct fx_double_p *i = fx_object_get_private(obj, FX_TYPE_DOUBLE);
|
||||||
|
switch (i->i_type) {
|
||||||
|
case DOUBLE_REGULAR:
|
||||||
|
fx_stream_write_fmt(out, NULL, "%" PRIdPTR, i->i_value);
|
||||||
|
break;
|
||||||
|
case DOUBLE_INF_POSITIVE:
|
||||||
|
fx_stream_write_cstr(out, "inf", NULL);
|
||||||
|
break;
|
||||||
|
case DOUBLE_INF_NEGATIVE:
|
||||||
|
fx_stream_write_cstr(out, "-inf", NULL);
|
||||||
|
break;
|
||||||
|
case DOUBLE_NAN_POSITIVE:
|
||||||
|
fx_stream_write_cstr(out, "NaN", NULL);
|
||||||
|
break;
|
||||||
|
case DOUBLE_NAN_NEGATIVE:
|
||||||
|
fx_stream_write_cstr(out, "-NaN", NULL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** CLASS DEFINITION *********************************************************/
|
||||||
|
|
||||||
|
FX_TYPE_CLASS_DEFINITION_BEGIN(fx_double)
|
||||||
|
FX_TYPE_CLASS_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
||||||
|
FX_INTERFACE_ENTRY(to_string) = double_to_string;
|
||||||
|
FX_TYPE_CLASS_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
||||||
|
FX_TYPE_CLASS_DEFINITION_END(fx_double)
|
||||||
|
|
||||||
|
FX_TYPE_DEFINITION_BEGIN(fx_double)
|
||||||
|
FX_TYPE_ID(0x3b20f57a, 0x2ddf, 0x4682, 0x81c4, 0x4fe404a6524e);
|
||||||
|
FX_TYPE_CLASS(fx_double_class);
|
||||||
|
FX_TYPE_INSTANCE_PRIVATE(struct fx_double_p);
|
||||||
|
FX_TYPE_INSTANCE_INIT(double_init);
|
||||||
|
FX_TYPE_INSTANCE_FINI(double_fini);
|
||||||
|
FX_TYPE_DEFINITION_END(fx_double)
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#ifndef FX_BOOL_H_
|
||||||
|
#define FX_BOOL_H_
|
||||||
|
|
||||||
|
#include <fx/macros.h>
|
||||||
|
|
||||||
|
FX_DECLS_BEGIN;
|
||||||
|
|
||||||
|
#define FX_TYPE_BOOL (fx_bool_get_type())
|
||||||
|
|
||||||
|
FX_DECLARE_TYPE(fx_bool);
|
||||||
|
|
||||||
|
FX_TYPE_CLASS_DECLARATION_BEGIN(fx_bool)
|
||||||
|
FX_TYPE_CLASS_DECLARATION_END(fx_bool)
|
||||||
|
|
||||||
|
FX_API fx_type fx_bool_get_type(void);
|
||||||
|
|
||||||
|
FX_API fx_bool *fx_bool_create(bool value);
|
||||||
|
|
||||||
|
FX_API void fx_bool_set_value(fx_bool *i, bool v);
|
||||||
|
|
||||||
|
FX_API bool fx_bool_get_value(const fx_bool *i);
|
||||||
|
|
||||||
|
FX_DECLS_END;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#ifndef FX_DOUBLE_H_
|
||||||
|
#define FX_DOUBLE_H_
|
||||||
|
|
||||||
|
#include <fx/macros.h>
|
||||||
|
|
||||||
|
FX_DECLS_BEGIN;
|
||||||
|
|
||||||
|
#define FX_TYPE_DOUBLE (fx_double_get_type())
|
||||||
|
|
||||||
|
FX_DECLARE_TYPE(fx_double);
|
||||||
|
|
||||||
|
FX_TYPE_CLASS_DECLARATION_BEGIN(fx_double)
|
||||||
|
FX_TYPE_CLASS_DECLARATION_END(fx_double)
|
||||||
|
|
||||||
|
FX_API fx_type fx_double_get_type(void);
|
||||||
|
|
||||||
|
FX_API fx_double *fx_double_create(double value);
|
||||||
|
FX_API fx_double *fx_double_create_nan(void);
|
||||||
|
FX_API fx_double *fx_double_create_nan_negative(void);
|
||||||
|
FX_API fx_double *fx_double_create_inf(void);
|
||||||
|
FX_API fx_double *fx_double_create_inf_negative(void);
|
||||||
|
|
||||||
|
FX_API void fx_double_set_value(fx_double *i, double v);
|
||||||
|
FX_API void fx_double_set_value_nan(fx_double *i);
|
||||||
|
FX_API void fx_double_set_value_nan_negative(fx_double *i);
|
||||||
|
FX_API void fx_double_set_value_inf(fx_double *i);
|
||||||
|
FX_API void fx_double_set_value_inf_negative(fx_double *i);
|
||||||
|
|
||||||
|
FX_API bool fx_double_is_nan(const fx_double *i);
|
||||||
|
FX_API bool fx_double_is_nan_positive(const fx_double *i);
|
||||||
|
FX_API bool fx_double_is_nan_negative(const fx_double *i);
|
||||||
|
FX_API bool fx_double_is_inf(const fx_double *i);
|
||||||
|
FX_API bool fx_double_is_inf_positive(const fx_double *i);
|
||||||
|
FX_API bool fx_double_is_inf_negative(const fx_double *i);
|
||||||
|
|
||||||
|
FX_API double fx_double_get_value(const fx_double *i);
|
||||||
|
|
||||||
|
FX_DECLS_END;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#ifndef FX_ENUM_H_
|
||||||
|
#define FX_ENUM_H_
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#ifndef FX_INT_H_
|
||||||
|
#define FX_INT_H_
|
||||||
|
|
||||||
|
#include <fx/macros.h>
|
||||||
|
|
||||||
|
FX_DECLS_BEGIN;
|
||||||
|
|
||||||
|
#define FX_TYPE_INT (fx_int_get_type())
|
||||||
|
|
||||||
|
FX_DECLARE_TYPE(fx_int);
|
||||||
|
|
||||||
|
FX_TYPE_CLASS_DECLARATION_BEGIN(fx_int)
|
||||||
|
FX_TYPE_CLASS_DECLARATION_END(fx_int)
|
||||||
|
|
||||||
|
FX_API fx_type fx_int_get_type(void);
|
||||||
|
|
||||||
|
FX_API fx_int *fx_int_create(intptr_t value);
|
||||||
|
FX_API fx_int *fx_int_create_nan(void);
|
||||||
|
FX_API fx_int *fx_int_create_nan_negative(void);
|
||||||
|
FX_API fx_int *fx_int_create_inf(void);
|
||||||
|
FX_API fx_int *fx_int_create_inf_negative(void);
|
||||||
|
|
||||||
|
FX_API void fx_int_set_value(fx_int *i, intptr_t v);
|
||||||
|
FX_API void fx_int_set_value_nan(fx_int *i);
|
||||||
|
FX_API void fx_int_set_value_nan_negative(fx_int *i);
|
||||||
|
FX_API void fx_int_set_value_inf(fx_int *i);
|
||||||
|
FX_API void fx_int_set_value_inf_negative(fx_int *i);
|
||||||
|
|
||||||
|
FX_API bool fx_int_is_nan(const fx_int *i);
|
||||||
|
FX_API bool fx_int_is_nan_positive(const fx_int *i);
|
||||||
|
FX_API bool fx_int_is_nan_negative(const fx_int *i);
|
||||||
|
FX_API bool fx_int_is_inf(const fx_int *i);
|
||||||
|
FX_API bool fx_int_is_inf_positive(const fx_int *i);
|
||||||
|
FX_API bool fx_int_is_inf_negative(const fx_int *i);
|
||||||
|
|
||||||
|
FX_API intptr_t fx_int_get_value(const fx_int *i);
|
||||||
|
|
||||||
|
FX_DECLS_END;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef FX_UINT_H_
|
||||||
|
#define FX_UINT_H_
|
||||||
|
|
||||||
|
#include <fx/macros.h>
|
||||||
|
|
||||||
|
FX_DECLS_BEGIN;
|
||||||
|
|
||||||
|
#define FX_TYPE_UINT (fx_uint_get_type())
|
||||||
|
|
||||||
|
FX_DECLARE_TYPE(fx_uint);
|
||||||
|
|
||||||
|
FX_TYPE_CLASS_DECLARATION_BEGIN(fx_uint)
|
||||||
|
FX_TYPE_CLASS_DECLARATION_END(fx_uint)
|
||||||
|
|
||||||
|
FX_API fx_type fx_uint_get_type(void);
|
||||||
|
|
||||||
|
FX_API fx_uint *fx_uint_create(uintptr_t value);
|
||||||
|
FX_API fx_uint *fx_uint_create_nan(void);
|
||||||
|
FX_API fx_uint *fx_uint_create_inf(void);
|
||||||
|
|
||||||
|
FX_API void fx_uint_set_value(fx_uint *i, uintptr_t v);
|
||||||
|
FX_API void fx_uint_set_value_nan(fx_uint *i);
|
||||||
|
FX_API void fx_uint_set_value_inf(fx_uint *i);
|
||||||
|
|
||||||
|
FX_API bool fx_uint_is_nan(const fx_uint *i);
|
||||||
|
FX_API bool fx_uint_is_inf(const fx_uint *i);
|
||||||
|
|
||||||
|
FX_API uintptr_t fx_uint_get_value(const fx_uint *i);
|
||||||
|
|
||||||
|
FX_DECLS_END;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
#ifndef FX_VALUE_H_
|
||||||
|
#define FX_VALUE_H_
|
||||||
|
|
||||||
|
#include <fx/object.h>
|
||||||
|
#include <fx/type.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define FX_VALUE_EMPTY ((fx_value) {})
|
||||||
|
#define FX_VALUE_BOOL(v) \
|
||||||
|
((fx_value) { \
|
||||||
|
.v_type.t_primitive = FX_VALUE_TYPE_BOOL, \
|
||||||
|
.v_bool = (v), \
|
||||||
|
})
|
||||||
|
#define FX_VALUE_INT(v) \
|
||||||
|
((fx_value) { \
|
||||||
|
.v_type.t_primitive = FX_VALUE_TYPE_INT, \
|
||||||
|
.v_int = (v), \
|
||||||
|
})
|
||||||
|
#define FX_VALUE_UINT(v) \
|
||||||
|
((fx_value) { \
|
||||||
|
.v_type.t_primitive = FX_VALUE_TYPE_UINT, \
|
||||||
|
.v_uint = (v), \
|
||||||
|
})
|
||||||
|
#define FX_VALUE_DOUBLE(v) \
|
||||||
|
((fx_value) { \
|
||||||
|
.v_type.t_primitive = FX_VALUE_TYPE_DOUBLE, \
|
||||||
|
.v_double = (v), \
|
||||||
|
})
|
||||||
|
#define FX_VALUE_CSTR(v) \
|
||||||
|
((fx_value) { \
|
||||||
|
.v_type.t_primitive = FX_VALUE_TYPE_CSTR, \
|
||||||
|
.v_cstr = (v), \
|
||||||
|
})
|
||||||
|
#define FX_VALUE_POINTER(v) \
|
||||||
|
((fx_value) { \
|
||||||
|
.v_type.t_primitive = FX_VALUE_TYPE_POINTER, \
|
||||||
|
.v_pointer = (v), \
|
||||||
|
})
|
||||||
|
|
||||||
|
typedef enum fx_value_type {
|
||||||
|
FX_VALUE_TYPE_NONE = 0,
|
||||||
|
FX_VALUE_TYPE_BOOL,
|
||||||
|
FX_VALUE_TYPE_INT,
|
||||||
|
FX_VALUE_TYPE_UINT,
|
||||||
|
FX_VALUE_TYPE_DOUBLE,
|
||||||
|
FX_VALUE_TYPE_CSTR,
|
||||||
|
FX_VALUE_TYPE_POINTER,
|
||||||
|
|
||||||
|
/* any value greater than this represents an object fx_type */
|
||||||
|
__FX_VALUE_TYPE_OBJECT_BOUNDARY = 1024,
|
||||||
|
} fx_value_type;
|
||||||
|
|
||||||
|
typedef struct fx_value {
|
||||||
|
union {
|
||||||
|
fx_value_type t_primitive;
|
||||||
|
fx_type t_object;
|
||||||
|
} v_type;
|
||||||
|
|
||||||
|
union {
|
||||||
|
bool v_bool;
|
||||||
|
intptr_t v_int;
|
||||||
|
uintptr_t v_uint;
|
||||||
|
double v_double;
|
||||||
|
const char *v_cstr;
|
||||||
|
void *v_pointer;
|
||||||
|
fx_object *v_object;
|
||||||
|
};
|
||||||
|
} fx_value;
|
||||||
|
|
||||||
|
FX_API void fx_value_init(fx_value *v, fx_type type);
|
||||||
|
FX_API void fx_value_init_primitive(fx_value *v, fx_value_type type);
|
||||||
|
|
||||||
|
FX_API void fx_value_unset(fx_value *v);
|
||||||
|
|
||||||
|
FX_API void fx_value_set_bool(fx_value *v, bool b);
|
||||||
|
FX_API void fx_value_set_int(fx_value *v, intptr_t i);
|
||||||
|
FX_API void fx_value_set_uint(fx_value *v, uintptr_t u);
|
||||||
|
FX_API void fx_value_set_double(fx_value *v, double d);
|
||||||
|
FX_API void fx_value_set_static_cstr(fx_value *v, const char *cstr);
|
||||||
|
FX_API void fx_value_set_pointer(fx_value *v, void *p);
|
||||||
|
FX_API void fx_value_set_object(fx_value *v, fx_object *obj);
|
||||||
|
|
||||||
|
FX_API bool fx_value_is_bool(const fx_value *v);
|
||||||
|
FX_API bool fx_value_is_int(const fx_value *v);
|
||||||
|
FX_API bool fx_value_is_uint(const fx_value *v);
|
||||||
|
FX_API bool fx_value_is_double(const fx_value *v);
|
||||||
|
FX_API bool fx_value_is_string(const fx_value *v);
|
||||||
|
FX_API bool fx_value_is_pointer(const fx_value *v);
|
||||||
|
FX_API bool fx_value_is_object(const fx_value *v, fx_type type);
|
||||||
|
|
||||||
|
FX_API bool fx_value_get_bool(const fx_value *v);
|
||||||
|
FX_API intptr_t fx_value_get_int(const fx_value *v);
|
||||||
|
FX_API uintptr_t fx_value_get_uint(const fx_value *v);
|
||||||
|
FX_API double fx_value_get_double(const fx_value *v);
|
||||||
|
FX_API const char *fx_value_get_cstr(const fx_value *v);
|
||||||
|
FX_API void *fx_value_get_pointer(fx_value *v);
|
||||||
|
FX_API const void *fx_value_get_pointer_c(const fx_value *v);
|
||||||
|
FX_API fx_object *fx_value_get_object(fx_value *v);
|
||||||
|
FX_API const fx_object *fx_value_get_object_c(const fx_value *v);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,272 @@
|
|||||||
|
#include <fx/int.h>
|
||||||
|
#include <fx/stream.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*** PRIVATE DATA *************************************************************/
|
||||||
|
|
||||||
|
enum int_type {
|
||||||
|
INT_REGULAR = 0,
|
||||||
|
INT_INF_POSITIVE,
|
||||||
|
INT_INF_NEGATIVE,
|
||||||
|
INT_NAN_POSITIVE,
|
||||||
|
INT_NAN_NEGATIVE,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fx_int_p {
|
||||||
|
enum int_type i_type;
|
||||||
|
intptr_t i_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*** PRIVATE FUNCTIONS ********************************************************/
|
||||||
|
|
||||||
|
static bool int_get_value(const struct fx_int_p *i)
|
||||||
|
{
|
||||||
|
return i->i_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void int_set_value(struct fx_int_p *i, intptr_t v)
|
||||||
|
{
|
||||||
|
i->i_type = INT_REGULAR;
|
||||||
|
i->i_value = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void int_set_value_nan(struct fx_int_p *i)
|
||||||
|
{
|
||||||
|
i->i_type = INT_NAN_POSITIVE;
|
||||||
|
i->i_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void int_set_value_nan_negative(struct fx_int_p *i)
|
||||||
|
{
|
||||||
|
i->i_type = INT_NAN_NEGATIVE;
|
||||||
|
i->i_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void int_set_value_inf(struct fx_int_p *i)
|
||||||
|
{
|
||||||
|
i->i_type = INT_INF_POSITIVE;
|
||||||
|
i->i_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void int_set_value_inf_negative(struct fx_int_p *i)
|
||||||
|
{
|
||||||
|
i->i_type = INT_INF_NEGATIVE;
|
||||||
|
i->i_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool int_is_nan(struct fx_int_p *i)
|
||||||
|
{
|
||||||
|
return i->i_type == INT_NAN_POSITIVE || i->i_type == INT_NAN_NEGATIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool int_is_nan_positive(struct fx_int_p *i)
|
||||||
|
{
|
||||||
|
return i->i_type == INT_NAN_POSITIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool int_is_nan_negative(struct fx_int_p *i)
|
||||||
|
{
|
||||||
|
return i->i_type == INT_NAN_NEGATIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool int_is_inf(struct fx_int_p *i)
|
||||||
|
{
|
||||||
|
return i->i_type == INT_INF_POSITIVE || i->i_type == INT_INF_NEGATIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool int_is_inf_positive(struct fx_int_p *i)
|
||||||
|
{
|
||||||
|
return i->i_type == INT_INF_POSITIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool int_is_inf_negative(struct fx_int_p *i)
|
||||||
|
{
|
||||||
|
return i->i_type == INT_INF_NEGATIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** PUBLIC FUNCTIONS *********************************************************/
|
||||||
|
|
||||||
|
fx_int *fx_int_create(intptr_t value)
|
||||||
|
{
|
||||||
|
fx_int *i = fx_object_create(FX_TYPE_INT);
|
||||||
|
if (!i) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fx_int_p *p = fx_object_get_private(i, FX_TYPE_INT);
|
||||||
|
p->i_type = INT_REGULAR;
|
||||||
|
p->i_value = value;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_int *fx_int_create_nan(void)
|
||||||
|
{
|
||||||
|
fx_int *i = fx_object_create(FX_TYPE_INT);
|
||||||
|
if (!i) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fx_int_p *p = fx_object_get_private(i, FX_TYPE_INT);
|
||||||
|
p->i_type = INT_NAN_POSITIVE;
|
||||||
|
p->i_value = 0;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_int *fx_int_create_nan_negative(void)
|
||||||
|
{
|
||||||
|
fx_int *i = fx_object_create(FX_TYPE_INT);
|
||||||
|
if (!i) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fx_int_p *p = fx_object_get_private(i, FX_TYPE_INT);
|
||||||
|
p->i_type = INT_NAN_NEGATIVE;
|
||||||
|
p->i_value = 0;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_int *fx_int_create_inf(void)
|
||||||
|
{
|
||||||
|
fx_int *i = fx_object_create(FX_TYPE_INT);
|
||||||
|
if (!i) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fx_int_p *p = fx_object_get_private(i, FX_TYPE_INT);
|
||||||
|
p->i_type = INT_INF_POSITIVE;
|
||||||
|
p->i_value = 0;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_int *fx_int_create_inf_negative(void)
|
||||||
|
{
|
||||||
|
fx_int *i = fx_object_create(FX_TYPE_INT);
|
||||||
|
if (!i) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fx_int_p *p = fx_object_get_private(i, FX_TYPE_INT);
|
||||||
|
p->i_type = INT_INF_NEGATIVE;
|
||||||
|
p->i_value = 0;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
intptr_t fx_int_get_value(const fx_int *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_INT, int_get_value, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_int_set_value(fx_int *i, intptr_t v)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_V(FX_TYPE_INT, int_set_value, i, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_int_set_value_nan(fx_int *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_V0(FX_TYPE_INT, int_set_value_nan, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_int_set_value_nan_negative(fx_int *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_V0(FX_TYPE_INT, int_set_value_nan_negative, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_int_set_value_inf(fx_int *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_V0(FX_TYPE_INT, int_set_value_inf, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_int_set_value_inf_negative(fx_int *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_V0(FX_TYPE_INT, int_set_value_inf_negative, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_int_is_nan(const fx_int *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_INT, int_is_nan, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_int_is_nan_positive(const fx_int *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_INT, int_is_nan_positive, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_int_is_nan_negative(const fx_int *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_INT, int_is_nan_negative, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_int_is_inf(const fx_int *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_INT, int_is_inf, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_int_is_inf_positive(const fx_int *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_INT, int_is_inf_positive, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_int_is_inf_negative(const fx_int *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_INT, int_is_inf_negative, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** VIRTUAL FUNCTIONS ********************************************************/
|
||||||
|
|
||||||
|
static void int_init(fx_object *obj, void *priv)
|
||||||
|
{
|
||||||
|
struct fx_int_p *i = priv;
|
||||||
|
|
||||||
|
i->i_type = INT_REGULAR;
|
||||||
|
i->i_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void int_fini(fx_object *obj, void *priv)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void int_to_string(const fx_object *obj, fx_stream *out)
|
||||||
|
{
|
||||||
|
struct fx_int_p *i = fx_object_get_private(obj, FX_TYPE_INT);
|
||||||
|
switch (i->i_type) {
|
||||||
|
case INT_REGULAR:
|
||||||
|
fx_stream_write_fmt(out, NULL, "%" PRIdPTR, i->i_value);
|
||||||
|
break;
|
||||||
|
case INT_INF_POSITIVE:
|
||||||
|
fx_stream_write_cstr(out, "inf", NULL);
|
||||||
|
break;
|
||||||
|
case INT_INF_NEGATIVE:
|
||||||
|
fx_stream_write_cstr(out, "-inf", NULL);
|
||||||
|
break;
|
||||||
|
case INT_NAN_POSITIVE:
|
||||||
|
fx_stream_write_cstr(out, "NaN", NULL);
|
||||||
|
break;
|
||||||
|
case INT_NAN_NEGATIVE:
|
||||||
|
fx_stream_write_cstr(out, "-NaN", NULL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** CLASS DEFINITION *********************************************************/
|
||||||
|
|
||||||
|
FX_TYPE_CLASS_DEFINITION_BEGIN(fx_int)
|
||||||
|
FX_TYPE_CLASS_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
||||||
|
FX_INTERFACE_ENTRY(to_string) = int_to_string;
|
||||||
|
FX_TYPE_CLASS_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
||||||
|
FX_TYPE_CLASS_DEFINITION_END(fx_int)
|
||||||
|
|
||||||
|
FX_TYPE_DEFINITION_BEGIN(fx_int)
|
||||||
|
FX_TYPE_ID(0x3b20f57a, 0x2ddf, 0x4682, 0x81c4, 0x4fe404a6524e);
|
||||||
|
FX_TYPE_CLASS(fx_int_class);
|
||||||
|
FX_TYPE_INSTANCE_PRIVATE(struct fx_int_p);
|
||||||
|
FX_TYPE_INSTANCE_INIT(int_init);
|
||||||
|
FX_TYPE_INSTANCE_FINI(int_fini);
|
||||||
|
FX_TYPE_DEFINITION_END(fx_int)
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
#include <fx/stream.h>
|
||||||
|
#include <fx/uint.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*** PRIVATE DATA *************************************************************/
|
||||||
|
|
||||||
|
enum uint_type {
|
||||||
|
UINT_REGULAR = 0,
|
||||||
|
UINT_INF,
|
||||||
|
UINT_NAN,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fx_uint_p {
|
||||||
|
enum uint_type i_type;
|
||||||
|
uintptr_t i_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*** PRIVATE FUNCTIONS ********************************************************/
|
||||||
|
|
||||||
|
static uintptr_t uint_get_value(const struct fx_uint_p *i)
|
||||||
|
{
|
||||||
|
return i->i_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uint_set_value(struct fx_uint_p *i, uintptr_t v)
|
||||||
|
{
|
||||||
|
i->i_type = UINT_REGULAR;
|
||||||
|
i->i_value = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uint_set_value_nan(struct fx_uint_p *i)
|
||||||
|
{
|
||||||
|
i->i_type = UINT_NAN;
|
||||||
|
i->i_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uint_set_value_inf(struct fx_uint_p *i)
|
||||||
|
{
|
||||||
|
i->i_type = UINT_INF;
|
||||||
|
i->i_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool uint_is_nan(struct fx_uint_p *i)
|
||||||
|
{
|
||||||
|
return i->i_type == UINT_NAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool uint_is_inf(struct fx_uint_p *i)
|
||||||
|
{
|
||||||
|
return i->i_type == UINT_INF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** PUBLIC FUNCTIONS *********************************************************/
|
||||||
|
|
||||||
|
fx_uint *fx_uint_create(uintptr_t value)
|
||||||
|
{
|
||||||
|
fx_uint *i = fx_object_create(FX_TYPE_UINT);
|
||||||
|
if (!i) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fx_uint_p *p = fx_object_get_private(i, FX_TYPE_UINT);
|
||||||
|
p->i_type = UINT_REGULAR;
|
||||||
|
p->i_value = value;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_uint *fx_uint_create_nan(void)
|
||||||
|
{
|
||||||
|
fx_uint *i = fx_object_create(FX_TYPE_UINT);
|
||||||
|
if (!i) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fx_uint_p *p = fx_object_get_private(i, FX_TYPE_UINT);
|
||||||
|
p->i_type = UINT_NAN;
|
||||||
|
p->i_value = 0;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_uint *fx_uint_create_inf(void)
|
||||||
|
{
|
||||||
|
fx_uint *i = fx_object_create(FX_TYPE_UINT);
|
||||||
|
if (!i) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fx_uint_p *p = fx_object_get_private(i, FX_TYPE_UINT);
|
||||||
|
p->i_type = UINT_INF;
|
||||||
|
p->i_value = 0;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t fx_uint_get_value(const fx_uint *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_UINT, uint_get_value, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_uint_set_value(fx_uint *i, uintptr_t v)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_V(FX_TYPE_UINT, uint_set_value, i, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_uint_set_value_nan(fx_uint *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_V0(FX_TYPE_UINT, uint_set_value_nan, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_uint_set_value_inf(fx_uint *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_V0(FX_TYPE_UINT, uint_set_value_inf, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_uint_is_nan(const fx_uint *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_UINT, uint_is_nan, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_uint_is_inf(const fx_uint *i)
|
||||||
|
{
|
||||||
|
FX_CLASS_DISPATCH_STATIC_0(FX_TYPE_UINT, uint_is_inf, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** VIRTUAL FUNCTIONS ********************************************************/
|
||||||
|
|
||||||
|
static void uint_init(fx_object *obj, void *priv)
|
||||||
|
{
|
||||||
|
struct fx_uint_p *i = priv;
|
||||||
|
|
||||||
|
i->i_type = UINT_REGULAR;
|
||||||
|
i->i_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uint_fini(fx_object *obj, void *priv)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uint_to_string(const fx_object *obj, fx_stream *out)
|
||||||
|
{
|
||||||
|
struct fx_uint_p *i = fx_object_get_private(obj, FX_TYPE_UINT);
|
||||||
|
switch (i->i_type) {
|
||||||
|
case UINT_REGULAR:
|
||||||
|
fx_stream_write_fmt(out, NULL, "%" PRIdPTR, i->i_value);
|
||||||
|
break;
|
||||||
|
case UINT_INF:
|
||||||
|
fx_stream_write_cstr(out, "inf", NULL);
|
||||||
|
break;
|
||||||
|
case UINT_NAN:
|
||||||
|
fx_stream_write_cstr(out, "NaN", NULL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** CLASS DEFINITION *********************************************************/
|
||||||
|
|
||||||
|
FX_TYPE_CLASS_DEFINITION_BEGIN(fx_uint)
|
||||||
|
FX_TYPE_CLASS_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
||||||
|
FX_INTERFACE_ENTRY(to_string) = uint_to_string;
|
||||||
|
FX_TYPE_CLASS_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
||||||
|
FX_TYPE_CLASS_DEFINITION_END(fx_uint)
|
||||||
|
|
||||||
|
FX_TYPE_DEFINITION_BEGIN(fx_uint)
|
||||||
|
FX_TYPE_ID(0x79aee484, 0x5dd5, 0x463a, 0xb0c8, 0x60873abdf088);
|
||||||
|
FX_TYPE_CLASS(fx_uint_class);
|
||||||
|
FX_TYPE_INSTANCE_PRIVATE(struct fx_uint_p);
|
||||||
|
FX_TYPE_INSTANCE_INIT(uint_init);
|
||||||
|
FX_TYPE_INSTANCE_FINI(uint_fini);
|
||||||
|
FX_TYPE_DEFINITION_END(fx_uint)
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <fx/collections/uuid.h>
|
|
||||||
#include <fx/string.h>
|
#include <fx/string.h>
|
||||||
#include <fx/stringstream.h>
|
#include <fx/stringstream.h>
|
||||||
|
#include <fx/uuid.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
+248
@@ -0,0 +1,248 @@
|
|||||||
|
#include <fx/bool.h>
|
||||||
|
#include <fx/double.h>
|
||||||
|
#include <fx/int.h>
|
||||||
|
#include <fx/string.h>
|
||||||
|
#include <fx/uint.h>
|
||||||
|
#include <fx/value.h>
|
||||||
|
|
||||||
|
void fx_value_init(fx_value *v, fx_type type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_value_init_primitive(fx_value *v, fx_value_type type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_value_unset(fx_value *v)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_value_set_bool(fx_value *v, bool b)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_value_set_int(fx_value *v, intptr_t i)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_value_set_uint(fx_value *v, uintptr_t u)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_value_set_double(fx_value *v, double d)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_value_set_static_cstr(fx_value *v, const char *cstr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_value_set_pointer(fx_value *v, void *p)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void fx_value_set_object(fx_value *v, fx_object *obj)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_value_is_bool(const fx_value *v)
|
||||||
|
{
|
||||||
|
if (v->v_type.t_primitive == FX_VALUE_TYPE_BOOL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v->v_type.t_primitive > __FX_VALUE_TYPE_OBJECT_BOUNDARY) {
|
||||||
|
if (fx_type_id_compare(v->v_type.t_object, FX_TYPE_BOOL)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_value_is_int(const fx_value *v)
|
||||||
|
{
|
||||||
|
if (v->v_type.t_primitive == FX_VALUE_TYPE_INT) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v->v_type.t_primitive > __FX_VALUE_TYPE_OBJECT_BOUNDARY) {
|
||||||
|
if (fx_type_id_compare(v->v_type.t_object, FX_TYPE_INT)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_value_is_uint(const fx_value *v)
|
||||||
|
{
|
||||||
|
if (v->v_type.t_primitive == FX_VALUE_TYPE_UINT) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v->v_type.t_primitive > __FX_VALUE_TYPE_OBJECT_BOUNDARY) {
|
||||||
|
if (fx_type_id_compare(v->v_type.t_object, FX_TYPE_UINT)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_value_is_double(const fx_value *v)
|
||||||
|
{
|
||||||
|
if (v->v_type.t_primitive == FX_VALUE_TYPE_DOUBLE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v->v_type.t_primitive > __FX_VALUE_TYPE_OBJECT_BOUNDARY) {
|
||||||
|
if (fx_type_id_compare(v->v_type.t_object, FX_TYPE_DOUBLE)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_value_is_string(const fx_value *v)
|
||||||
|
{
|
||||||
|
if (v->v_type.t_primitive == FX_VALUE_TYPE_CSTR) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v->v_type.t_primitive > __FX_VALUE_TYPE_OBJECT_BOUNDARY) {
|
||||||
|
if (fx_type_id_compare(v->v_type.t_object, FX_TYPE_STRING)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_value_is_pointer(const fx_value *v)
|
||||||
|
{
|
||||||
|
return (v->v_type.t_primitive == FX_VALUE_TYPE_POINTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_value_is_object(const fx_value *v, fx_type type)
|
||||||
|
{
|
||||||
|
if (v->v_type.t_primitive > __FX_VALUE_TYPE_OBJECT_BOUNDARY) {
|
||||||
|
if (fx_type_id_compare(v->v_type.t_object, type)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fx_value_get_bool(const fx_value *v)
|
||||||
|
{
|
||||||
|
if (v->v_type.t_primitive == FX_VALUE_TYPE_BOOL) {
|
||||||
|
return v->v_bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v->v_type.t_primitive > __FX_VALUE_TYPE_OBJECT_BOUNDARY) {
|
||||||
|
if (fx_type_id_compare(v->v_type.t_object, FX_TYPE_BOOL)) {
|
||||||
|
return fx_bool_get_value(v->v_object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
intptr_t fx_value_get_int(const fx_value *v)
|
||||||
|
{
|
||||||
|
if (v->v_type.t_primitive == FX_VALUE_TYPE_INT) {
|
||||||
|
return v->v_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v->v_type.t_primitive > __FX_VALUE_TYPE_OBJECT_BOUNDARY) {
|
||||||
|
if (fx_type_id_compare(v->v_type.t_object, FX_TYPE_INT)) {
|
||||||
|
return fx_int_get_value(v->v_object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t fx_value_get_uint(const fx_value *v)
|
||||||
|
{
|
||||||
|
if (v->v_type.t_primitive == FX_VALUE_TYPE_UINT) {
|
||||||
|
return v->v_uint;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v->v_type.t_primitive > __FX_VALUE_TYPE_OBJECT_BOUNDARY) {
|
||||||
|
if (fx_type_id_compare(v->v_type.t_object, FX_TYPE_UINT)) {
|
||||||
|
return fx_uint_get_value(v->v_object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double fx_value_get_double(const fx_value *v)
|
||||||
|
{
|
||||||
|
if (v->v_type.t_primitive == FX_VALUE_TYPE_DOUBLE) {
|
||||||
|
return v->v_uint;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v->v_type.t_primitive > __FX_VALUE_TYPE_OBJECT_BOUNDARY) {
|
||||||
|
if (fx_type_id_compare(v->v_type.t_object, FX_TYPE_DOUBLE)) {
|
||||||
|
return fx_double_get_value(v->v_object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *fx_value_get_cstr(const fx_value *v)
|
||||||
|
{
|
||||||
|
if (v->v_type.t_primitive == FX_VALUE_TYPE_CSTR) {
|
||||||
|
return v->v_cstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v->v_type.t_primitive > __FX_VALUE_TYPE_OBJECT_BOUNDARY) {
|
||||||
|
if (fx_type_id_compare(v->v_type.t_object, FX_TYPE_STRING)) {
|
||||||
|
return fx_string_get_cstr(v->v_object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *fx_value_get_pointer(fx_value *v)
|
||||||
|
{
|
||||||
|
if (v->v_type.t_primitive == FX_VALUE_TYPE_POINTER) {
|
||||||
|
return v->v_pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *fx_value_get_pointer_c(const fx_value *v)
|
||||||
|
{
|
||||||
|
if (v->v_type.t_primitive == FX_VALUE_TYPE_POINTER) {
|
||||||
|
return v->v_pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_object *fx_value_get_object(fx_value *v)
|
||||||
|
{
|
||||||
|
if (v->v_type.t_primitive > __FX_VALUE_TYPE_OBJECT_BOUNDARY) {
|
||||||
|
return v->v_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fx_object *fx_value_get_object_c(const fx_value *v)
|
||||||
|
{
|
||||||
|
if (v->v_type.t_primitive > __FX_VALUE_TYPE_OBJECT_BOUNDARY) {
|
||||||
|
return v->v_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
file(GLOB test_sources *.c)
|
||||||
|
|
||||||
|
foreach (f ${test_sources})
|
||||||
|
get_filename_component(test_name ${f} NAME_WLE)
|
||||||
|
add_executable(${test_name} ${f})
|
||||||
|
target_link_libraries(${test_name} ${fx_assemblies})
|
||||||
|
endforeach (f)
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#include <dlfcn.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
printf("dynamic loader\n");
|
||||||
|
void *assembly = dlopen(argv[1], RTLD_LAZY);
|
||||||
|
if (!assembly) {
|
||||||
|
printf("cannot load %s\n", argv[1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *(*asm_info)(void) = dlsym(assembly, "__fx_assembly_get");
|
||||||
|
if (!asm_info) {
|
||||||
|
printf("cannot find assembly info for %s", argv[1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
asm_info();
|
||||||
|
printf("OK\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+3
-3
@@ -1,8 +1,8 @@
|
|||||||
#include <fx/core/stream.h>
|
|
||||||
#include <fx/core/stringstream.h>
|
|
||||||
#include <fx/ds/string.h>
|
|
||||||
#include <fx/io/file.h>
|
#include <fx/io/file.h>
|
||||||
#include <fx/io/path.h>
|
#include <fx/io/path.h>
|
||||||
|
#include <fx/stream.h>
|
||||||
|
#include <fx/string.h>
|
||||||
|
#include <fx/stringstream.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int main(int argc, const char **argv)
|
int main(int argc, const char **argv)
|
||||||
|
|||||||
+3
-3
@@ -1,8 +1,8 @@
|
|||||||
#include <fx/core/stream.h>
|
|
||||||
#include <fx/core/stringstream.h>
|
|
||||||
#include <fx/ds/string.h>
|
|
||||||
#include <fx/io/file.h>
|
#include <fx/io/file.h>
|
||||||
#include <fx/io/path.h>
|
#include <fx/io/path.h>
|
||||||
|
#include <fx/stream.h>
|
||||||
|
#include <fx/string.h>
|
||||||
|
#include <fx/stringstream.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int main(int argc, const char **argv)
|
int main(int argc, const char **argv)
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#include <fx/reflection/function.h>
|
||||||
|
#include <fx/value.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
fx_value_type arg_types[] = {
|
||||||
|
FX_VALUE_TYPE_CSTR,
|
||||||
|
};
|
||||||
|
|
||||||
|
fx_function *func = fx_function_create(
|
||||||
|
"test_function",
|
||||||
|
FX_FUNCTION_F_VARARG,
|
||||||
|
(fx_function_impl)printf,
|
||||||
|
arg_types,
|
||||||
|
1,
|
||||||
|
FX_VALUE_TYPE_INT);
|
||||||
|
|
||||||
|
fx_value args[] = {
|
||||||
|
FX_VALUE_CSTR("Hello %s! You are number %lf\n"),
|
||||||
|
FX_VALUE_CSTR("Jonh"),
|
||||||
|
FX_VALUE_DOUBLE(2.5),
|
||||||
|
};
|
||||||
|
|
||||||
|
fx_value result = FX_VALUE_EMPTY;
|
||||||
|
int r = fx_function_invoke(func, args, 3, &result);
|
||||||
|
printf("%" PRIdPTR "\n", result.v_int);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+42
-14
@@ -1,22 +1,50 @@
|
|||||||
#include <dlfcn.h>
|
#include <fx/reflection/function.h>
|
||||||
|
#include <fx/value.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static double test_function(int a, double b, int c, ...)
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
va_list args;
|
||||||
|
va_start(args, c);
|
||||||
|
int d = va_arg(args, int);
|
||||||
|
double e = va_arg(args, double);
|
||||||
|
int f = va_arg(args, int);
|
||||||
|
printf("a=%d, b=%lf, c=%d, d=%d, e=%lf, f=%d\n", a, b, c, d, e, f);
|
||||||
|
return (a + b + c + d + e + f) + 0.5;
|
||||||
|
#else
|
||||||
|
printf("a=%d, b=%lf, c=%d\n", a, b, c);
|
||||||
|
return 32;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, const char **argv)
|
int main(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
printf("dynamic loader\n");
|
fx_value_type arg_types[] = {
|
||||||
void *assembly = dlopen(argv[1], RTLD_LAZY);
|
FX_VALUE_TYPE_INT,
|
||||||
if (!assembly) {
|
FX_VALUE_TYPE_DOUBLE,
|
||||||
printf("cannot load %s\n", argv[1]);
|
FX_VALUE_TYPE_INT,
|
||||||
return -1;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
const void *(*asm_info)(void) = dlsym(assembly, "__fx_assembly_get");
|
fx_function *func = fx_function_create(
|
||||||
if (!asm_info) {
|
"test_function",
|
||||||
printf("cannot find assembly info for %s", argv[1]);
|
FX_FUNCTION_F_VARARG,
|
||||||
return -1;
|
(fx_function_impl)test_function,
|
||||||
}
|
arg_types,
|
||||||
|
3,
|
||||||
|
FX_VALUE_TYPE_DOUBLE);
|
||||||
|
|
||||||
asm_info();
|
fx_value args[] = {
|
||||||
printf("OK\n");
|
FX_VALUE_INT(1),
|
||||||
|
FX_VALUE_DOUBLE(2.5),
|
||||||
|
FX_VALUE_INT(3),
|
||||||
|
FX_VALUE_INT(4),
|
||||||
|
FX_VALUE_DOUBLE(5.5),
|
||||||
|
FX_VALUE_INT(6),
|
||||||
|
};
|
||||||
|
|
||||||
|
fx_value result = FX_VALUE_EMPTY;
|
||||||
|
int r = fx_function_invoke(func, args, 6, &result);
|
||||||
|
printf("%lf\n", result.v_double);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static double another_function(int a, double b, int c)
|
||||||
|
{
|
||||||
|
printf("a=%d, b=%lf, c=%d\n", a, b, c);
|
||||||
|
return 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_function(int a, int b, int c, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, c);
|
||||||
|
int d = va_arg(args, int);
|
||||||
|
int e = va_arg(args, int);
|
||||||
|
int f = va_arg(args, int);
|
||||||
|
int g = va_arg(args, int);
|
||||||
|
int h = va_arg(args, int);
|
||||||
|
int i = va_arg(args, int);
|
||||||
|
int j = va_arg(args, int);
|
||||||
|
printf("a=%d, b=%d, c=%d, d=%d, e=%d, f=%d, g=%d, h=%d, i=%d, j=%d\n",
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
c,
|
||||||
|
d,
|
||||||
|
e,
|
||||||
|
f,
|
||||||
|
g,
|
||||||
|
h,
|
||||||
|
i,
|
||||||
|
j);
|
||||||
|
return a + b + c + d + e;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
test_function(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
|
||||||
|
another_function(1, 2.5, 5);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user