431 lines
11 KiB
C
431 lines
11 KiB
C
#include "../fx/type.h"
|
|
|
|
#include <fx/macros.h>
|
|
#include <fx/reflection/type.h>
|
|
#include <fx/type.h>
|
|
|
|
struct fx_type_registration;
|
|
|
|
#define FX_REFLECTION_TYPE_TYPE_FUNCTION_ITERATOR \
|
|
(fx_type_function_iterator_get_type())
|
|
#define FX_REFLECTION_TYPE_TYPE_PROPERTY_ITERATOR \
|
|
(fx_type_property_iterator_get_type())
|
|
|
|
FX_DECLARE_TYPE(fx_type_function_iterator);
|
|
FX_DECLARE_TYPE(fx_type_property_iterator);
|
|
|
|
FX_TYPE_CLASS_DECLARATION_BEGIN(fx_type_function_iterator)
|
|
FX_TYPE_CLASS_DECLARATION_END(fx_type_function_iterator)
|
|
|
|
FX_TYPE_CLASS_DECLARATION_BEGIN(fx_type_property_iterator)
|
|
FX_TYPE_CLASS_DECLARATION_END(fx_type_property_iterator)
|
|
|
|
FX_API fx_type_id fx_type_function_iterator_get_type();
|
|
FX_API fx_type_id fx_type_property_iterator_get_type();
|
|
|
|
struct fx_type_p {
|
|
struct fx_type_info *ty_info;
|
|
fx_assembly *ty_assembly;
|
|
};
|
|
|
|
struct fx_type_function_iterator_p {
|
|
struct fx_namemap *it_src;
|
|
struct fx_namemap_entry *it_cur;
|
|
fx_value it_value;
|
|
};
|
|
|
|
struct fx_type_property_iterator_p {
|
|
const fx_type_info *it_cur_type;
|
|
struct fx_namemap *it_src;
|
|
struct fx_namemap_entry *it_cur;
|
|
fx_value it_value;
|
|
};
|
|
|
|
/*** PRIVATE FUNCTIONS ********************************************************/
|
|
|
|
extern struct fx_type_info *fx_type_info_get_by_id(const union fx_type_id *key);
|
|
extern struct fx_type_info *fx_type_info_get_by_name(const char *name);
|
|
extern fx_function *fx_type_info_get_function_by_name(
|
|
const struct fx_type_info *ty,
|
|
const char *name);
|
|
|
|
static const fx_assembly *type_get_assembly(const struct fx_type_p *ty)
|
|
{
|
|
return ty->ty_assembly;
|
|
}
|
|
|
|
static fx_status type_set_assembly(struct fx_type_p *ty, fx_assembly *assembly)
|
|
{
|
|
ty->ty_assembly = assembly;
|
|
return FX_SUCCESS;
|
|
}
|
|
|
|
static const char *type_get_name(const struct fx_type_p *ty)
|
|
{
|
|
return ty->ty_info->ty_name;
|
|
}
|
|
|
|
static fx_type_flags type_get_flags(const struct fx_type_p *ty)
|
|
{
|
|
return ty->ty_info->ty_flags;
|
|
}
|
|
|
|
const fx_function *type_get_function(
|
|
const struct fx_type_p *ty,
|
|
const char *name)
|
|
{
|
|
return fx_type_info_get_function_by_name(ty->ty_info, name);
|
|
}
|
|
|
|
fx_iterator *type_get_functions(const struct fx_type_p *ty)
|
|
{
|
|
fx_type_function_iterator *it_obj
|
|
= fx_object_create(FX_REFLECTION_TYPE_TYPE_FUNCTION_ITERATOR);
|
|
struct fx_type_function_iterator_p *it = fx_object_get_private(
|
|
it_obj,
|
|
FX_REFLECTION_TYPE_TYPE_FUNCTION_ITERATOR);
|
|
|
|
it->it_src = &ty->ty_info->ty_functions;
|
|
it->it_cur = fx_namemap_first(it->it_src);
|
|
|
|
return it_obj;
|
|
}
|
|
|
|
const fx_property *type_get_property(
|
|
const struct fx_type_p *ty,
|
|
const char *name)
|
|
{
|
|
struct fx_type_info *cur = ty->ty_info;
|
|
while (cur) {
|
|
const fx_property *prop
|
|
= fx_type_info_get_property_by_name(cur, name);
|
|
if (prop) {
|
|
return prop;
|
|
}
|
|
|
|
if (fx_type_id_compare(&cur->ty_id, FX_TYPE_OBJECT) == 0) {
|
|
break;
|
|
}
|
|
|
|
cur = fx_type_info_get_by_id(&cur->ty_parent_id);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static fx_iterator *type_get_properties(const struct fx_type_p *ty)
|
|
{
|
|
fx_type_property_iterator *it_obj
|
|
= fx_object_create(FX_REFLECTION_TYPE_TYPE_PROPERTY_ITERATOR);
|
|
struct fx_type_property_iterator_p *it = fx_object_get_private(
|
|
it_obj,
|
|
FX_REFLECTION_TYPE_TYPE_PROPERTY_ITERATOR);
|
|
|
|
it->it_cur_type = ty->ty_info;
|
|
it->it_src = &ty->ty_info->ty_properties;
|
|
it->it_cur = fx_namemap_first(it->it_src);
|
|
while (!it->it_cur) {
|
|
if (fx_type_id_compare(&it->it_cur_type->ty_id, FX_TYPE_OBJECT)
|
|
== 0) {
|
|
break;
|
|
}
|
|
|
|
const struct fx_type_info *next_type
|
|
= fx_type_info_get_by_id(&it->it_cur_type
|
|
->ty_parent_id);
|
|
if (!next_type) {
|
|
break;
|
|
}
|
|
|
|
it->it_cur_type = next_type;
|
|
it->it_cur = fx_namemap_first(&it->it_cur_type->ty_properties);
|
|
}
|
|
|
|
if (!it->it_cur) {
|
|
fx_iterator_set_status(it_obj, FX_ERR_NO_DATA);
|
|
}
|
|
|
|
struct fx_type_property *prop
|
|
= fx_unbox(struct fx_type_property, it->it_cur, p_entry);
|
|
it->it_value = FX_VALUE_OBJECT_REF(prop->p_prop);
|
|
|
|
return it_obj;
|
|
}
|
|
|
|
static fx_type_id type_get_id(const struct fx_type_p *ty)
|
|
{
|
|
return &ty->ty_info->ty_id;
|
|
}
|
|
|
|
static const fx_type *type_get_parent(const struct fx_type_p *ty)
|
|
{
|
|
if (fx_type_id_compare(&ty->ty_info->ty_id, FX_TYPE_OBJECT) == 0) {
|
|
return NULL;
|
|
}
|
|
|
|
return fx_type_get_by_id(&ty->ty_info->ty_parent_id);
|
|
}
|
|
|
|
static void *type_get_interface(
|
|
const struct fx_type_p *ty,
|
|
fx_type_id interface_id)
|
|
{
|
|
return fx_class_get_interface(ty->ty_info->ty_class, interface_id);
|
|
}
|
|
|
|
/*** PUBLIC FUNCTIONS *********************************************************/
|
|
|
|
fx_type *__fx_type_create(struct fx_type_info *type_info)
|
|
{
|
|
fx_type *out = fx_object_create(FX_REFLECTION_TYPE_TYPE);
|
|
if (!out) {
|
|
return NULL;
|
|
}
|
|
|
|
struct fx_type_p *p
|
|
= fx_object_get_private(out, FX_REFLECTION_TYPE_TYPE);
|
|
p->ty_info = type_info;
|
|
|
|
return out;
|
|
}
|
|
|
|
const fx_assembly *fx_type_get_assembly(const fx_type *ty)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC_0(
|
|
FX_REFLECTION_TYPE_TYPE,
|
|
type_get_assembly,
|
|
ty);
|
|
}
|
|
|
|
fx_status fx_type_set_assembly(fx_type *ty, fx_assembly *assembly)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC(
|
|
FX_REFLECTION_TYPE_TYPE,
|
|
type_set_assembly,
|
|
ty,
|
|
assembly);
|
|
}
|
|
|
|
const char *fx_type_get_name(const fx_type *ty)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC_0(FX_REFLECTION_TYPE_TYPE, type_get_name, ty);
|
|
}
|
|
|
|
fx_type_flags fx_type_get_flags(const fx_type *ty)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC_0(FX_REFLECTION_TYPE_TYPE, type_get_flags, ty);
|
|
}
|
|
|
|
const fx_function *fx_type_get_function(const fx_type *ty, const char *name)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC(
|
|
FX_REFLECTION_TYPE_TYPE,
|
|
type_get_function,
|
|
ty,
|
|
name);
|
|
}
|
|
|
|
fx_iterator *fx_type_get_functions(const fx_type *ty)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC_0(
|
|
FX_REFLECTION_TYPE_TYPE,
|
|
type_get_functions,
|
|
ty);
|
|
}
|
|
|
|
const fx_property *fx_type_get_property(const fx_type *ty, const char *name)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC(
|
|
FX_REFLECTION_TYPE_TYPE,
|
|
type_get_property,
|
|
ty,
|
|
name);
|
|
}
|
|
|
|
fx_iterator *fx_type_get_properties(const fx_type *ty)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC_0(
|
|
FX_REFLECTION_TYPE_TYPE,
|
|
type_get_properties,
|
|
ty);
|
|
}
|
|
|
|
const fx_type *fx_type_get_by_id(fx_type_id id)
|
|
{
|
|
struct fx_type_info *ty = fx_type_info_get_by_id(id);
|
|
return ty ? ty->ty_metatype : NULL;
|
|
}
|
|
|
|
const fx_type *fx_type_get_by_name(const char *name)
|
|
{
|
|
struct fx_type_info *ty = fx_type_info_get_by_name(name);
|
|
return ty ? ty->ty_metatype : NULL;
|
|
}
|
|
|
|
fx_type_id fx_type_get_id(const fx_type *ty)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC_0(FX_REFLECTION_TYPE_TYPE, type_get_id, ty);
|
|
}
|
|
|
|
const fx_type *fx_type_get_parent(const fx_type *ty)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC_0(
|
|
FX_REFLECTION_TYPE_TYPE,
|
|
type_get_parent,
|
|
ty);
|
|
}
|
|
|
|
void *fx_type_get_interface(const fx_type *ty, fx_type_id interface_id)
|
|
{
|
|
FX_CLASS_DISPATCH_STATIC(
|
|
FX_REFLECTION_TYPE_TYPE,
|
|
type_get_interface,
|
|
ty,
|
|
interface_id);
|
|
}
|
|
|
|
/*** VIRTUAL FUNCTIONS ********************************************************/
|
|
|
|
static void type_init(fx_object *obj, void *priv)
|
|
{
|
|
}
|
|
|
|
static void type_fini(fx_object *obj, void *priv)
|
|
{
|
|
}
|
|
|
|
/*** ITERATOR FUNCTIONS *******************************************************/
|
|
|
|
static enum fx_status function_iterator_move_next(const fx_iterator *obj)
|
|
{
|
|
struct fx_type_function_iterator_p *it = fx_object_get_private(
|
|
obj,
|
|
FX_REFLECTION_TYPE_TYPE_FUNCTION_ITERATOR);
|
|
if (!it->it_cur) {
|
|
return FX_ERR_NO_DATA;
|
|
}
|
|
|
|
fx_value_unset(&it->it_value);
|
|
it->it_cur = fx_namemap_next(it->it_src, it->it_cur);
|
|
if (!it->it_cur) {
|
|
return FX_ERR_NO_DATA;
|
|
}
|
|
|
|
struct fx_type_function *func
|
|
= fx_unbox(struct fx_type_function, it->it_cur, f_entry);
|
|
it->it_value = FX_VALUE_OBJECT_REF(func->f_func);
|
|
|
|
return FX_SUCCESS;
|
|
}
|
|
|
|
static const fx_value *function_iterator_get_value(const fx_iterator *obj)
|
|
{
|
|
struct fx_type_function_iterator_p *it = fx_object_get_private(
|
|
obj,
|
|
FX_REFLECTION_TYPE_TYPE_FUNCTION_ITERATOR);
|
|
if (!it->it_cur) {
|
|
return NULL;
|
|
}
|
|
|
|
return &it->it_value;
|
|
}
|
|
|
|
static enum fx_status property_iterator_move_next(const fx_iterator *obj)
|
|
{
|
|
struct fx_type_property_iterator_p *it = fx_object_get_private(
|
|
obj,
|
|
FX_REFLECTION_TYPE_TYPE_PROPERTY_ITERATOR);
|
|
if (!it->it_cur) {
|
|
return FX_ERR_NO_DATA;
|
|
}
|
|
|
|
it->it_cur = fx_namemap_next(it->it_src, it->it_cur);
|
|
if (!it->it_cur) {
|
|
if (fx_type_id_compare(&it->it_cur_type->ty_id, FX_TYPE_OBJECT)
|
|
== 0) {
|
|
return FX_ERR_NO_DATA;
|
|
}
|
|
|
|
const struct fx_type_info *next_type
|
|
= fx_type_info_get_by_id(&it->it_cur_type
|
|
->ty_parent_id);
|
|
if (!next_type) {
|
|
return FX_ERR_NO_DATA;
|
|
}
|
|
|
|
it->it_cur_type = next_type;
|
|
it->it_cur = fx_namemap_first(&it->it_cur_type->ty_properties);
|
|
}
|
|
|
|
if (!it->it_cur) {
|
|
return FX_ERR_NO_DATA;
|
|
}
|
|
|
|
struct fx_type_property *prop
|
|
= fx_unbox(struct fx_type_property, it->it_cur, p_entry);
|
|
it->it_value = FX_VALUE_OBJECT_REF(prop->p_prop);
|
|
|
|
return FX_SUCCESS;
|
|
}
|
|
|
|
static const fx_value *property_iterator_get_value(const fx_iterator *obj)
|
|
{
|
|
struct fx_type_property_iterator_p *it = fx_object_get_private(
|
|
obj,
|
|
FX_REFLECTION_TYPE_TYPE_PROPERTY_ITERATOR);
|
|
if (!it->it_cur) {
|
|
return NULL;
|
|
}
|
|
|
|
struct fx_type_property *prop
|
|
= fx_unbox(struct fx_type_property, it->it_cur, p_entry);
|
|
|
|
return &it->it_value;
|
|
}
|
|
|
|
/*** CLASS DEFINITION *********************************************************/
|
|
|
|
FX_TYPE_CLASS_BEGIN(fx_type)
|
|
FX_TYPE_CLASS_END(fx_type)
|
|
|
|
FX_TYPE_DEFINITION_BEGIN(fx_type)
|
|
FX_TYPE_ID(0xec8b2679, 0x5c73, 0x4ec9, 0xa04e, 0x3f72881b5b5a);
|
|
FX_TYPE_NAME("fx.reflection.type");
|
|
FX_TYPE_CLASS(fx_type_class);
|
|
FX_TYPE_INSTANCE_PRIVATE(struct fx_type_p);
|
|
FX_TYPE_INSTANCE_INIT(type_init);
|
|
FX_TYPE_INSTANCE_FINI(type_fini);
|
|
FX_TYPE_DEFINITION_END(fx_type)
|
|
|
|
FX_TYPE_CLASS_BEGIN(fx_type_function_iterator)
|
|
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_iterator, FX_TYPE_ITERATOR)
|
|
FX_INTERFACE_ENTRY(it_move_next) = function_iterator_move_next;
|
|
FX_INTERFACE_ENTRY(it_erase) = NULL;
|
|
FX_INTERFACE_ENTRY(it_get_value) = function_iterator_get_value;
|
|
FX_TYPE_VTABLE_INTERFACE_END(fx_iterator, FX_TYPE_ITERATOR)
|
|
FX_TYPE_CLASS_END(fx_type_function_iterator)
|
|
|
|
FX_TYPE_DEFINITION_BEGIN(fx_type_function_iterator)
|
|
FX_TYPE_ID(0xb29012d5, 0x4d6c, 0x4e3c, 0x9fe5, 0x7d1a8a9e1075);
|
|
FX_TYPE_NAME("fx.reflection.type.function_iterator");
|
|
FX_TYPE_EXTENDS(FX_TYPE_ITERATOR);
|
|
FX_TYPE_CLASS(fx_type_class);
|
|
FX_TYPE_INSTANCE_PRIVATE(struct fx_type_function_iterator_p);
|
|
FX_TYPE_DEFINITION_END(fx_type_function_iterator)
|
|
|
|
FX_TYPE_CLASS_BEGIN(fx_type_property_iterator)
|
|
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_iterator, FX_TYPE_ITERATOR)
|
|
FX_INTERFACE_ENTRY(it_move_next) = property_iterator_move_next;
|
|
FX_INTERFACE_ENTRY(it_erase) = NULL;
|
|
FX_INTERFACE_ENTRY(it_get_value) = property_iterator_get_value;
|
|
FX_TYPE_VTABLE_INTERFACE_END(fx_iterator, FX_TYPE_ITERATOR)
|
|
FX_TYPE_CLASS_END(fx_type_property_iterator)
|
|
|
|
FX_TYPE_DEFINITION_BEGIN(fx_type_property_iterator)
|
|
FX_TYPE_ID(0x91fcbdd4, 0x7c54, 0x48c2, 0xa5a4, 0x186f76efd84c);
|
|
FX_TYPE_NAME("fx.reflection.type.property_iterator");
|
|
FX_TYPE_EXTENDS(FX_TYPE_ITERATOR);
|
|
FX_TYPE_CLASS(fx_type_property_iterator_class);
|
|
FX_TYPE_INSTANCE_PRIVATE(struct fx_type_property_iterator_p);
|
|
FX_TYPE_DEFINITION_END(fx_type_property_iterator)
|