fx.reflection: implement retrieving functions and properties from fx_type
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
#ifndef FX_REFLECTION_TYPE_H_
|
||||
#define FX_REFLECTION_TYPE_H_
|
||||
|
||||
#include <fx/iterator.h>
|
||||
#include <fx/macros.h>
|
||||
#include <fx/reflection/assembly.h>
|
||||
#include <fx/reflection/function.h>
|
||||
#include <fx/reflection/property.h>
|
||||
|
||||
FX_DECLS_BEGIN;
|
||||
|
||||
@@ -17,14 +20,27 @@ FX_TYPE_CLASS_DECLARATION_END(fx_type)
|
||||
|
||||
FX_API fx_type_id fx_type_get_type();
|
||||
|
||||
FX_API const fx_assembly *fx_type_get_assembly(const fx_type *ty);
|
||||
FX_API fx_status fx_type_set_assembly(fx_type *ty, fx_assembly *assembly);
|
||||
|
||||
FX_API const char *fx_type_get_name(const fx_type *ty);
|
||||
FX_API fx_type_flags fx_type_get_flags(const fx_type *ty);
|
||||
FX_API const fx_function *fx_type_get_function(
|
||||
const fx_type *ty,
|
||||
const char *name);
|
||||
FX_API fx_iterator *fx_type_get_functions(const fx_type *ty);
|
||||
FX_API const fx_property *fx_type_get_property(
|
||||
const fx_type *ty,
|
||||
const char *name);
|
||||
FX_API fx_iterator *fx_type_get_properties(const fx_type *ty);
|
||||
|
||||
FX_API const fx_type *fx_type_get_by_id(fx_type_id id);
|
||||
FX_API const fx_type *fx_type_get_by_name(const char *name);
|
||||
|
||||
FX_API fx_type_id fx_type_get_id(const fx_type *ty);
|
||||
FX_API const fx_type *fx_type_get_parent(const fx_type *ty);
|
||||
FX_API void *fx_type_get_interface(const fx_type *ty, fx_type_id interface_id);
|
||||
|
||||
FX_API fx_type *__fx_type_create(struct fx_type_info *opaque);
|
||||
|
||||
#endif
|
||||
|
||||
+318
-3
@@ -1,11 +1,42 @@
|
||||
#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;
|
||||
};
|
||||
|
||||
struct fx_type_property_iterator_p {
|
||||
const fx_type_info *it_cur_type;
|
||||
struct fx_namemap *it_src;
|
||||
struct fx_namemap_entry *it_cur;
|
||||
};
|
||||
|
||||
/*** PRIVATE FUNCTIONS ********************************************************/
|
||||
@@ -16,11 +47,27 @@ 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)
|
||||
@@ -28,6 +75,98 @@ const fx_function *type_get_function(
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -45,11 +184,33 @@ fx_type *__fx_type_create(struct fx_type_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(
|
||||
@@ -59,6 +220,31 @@ const fx_function *fx_type_get_function(const fx_type *ty, const char *name)
|
||||
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);
|
||||
@@ -71,6 +257,28 @@ const fx_type *fx_type_get_by_name(const char *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)
|
||||
@@ -81,12 +289,87 @@ 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;
|
||||
}
|
||||
|
||||
it->it_cur = fx_namemap_next(it->it_src, it->it_cur);
|
||||
return it->it_cur ? FX_SUCCESS : FX_ERR_NO_DATA;
|
||||
}
|
||||
|
||||
static 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 FX_VALUE_EMPTY;
|
||||
}
|
||||
|
||||
struct fx_type_function *func = fx_unbox(
|
||||
struct fx_type_function,
|
||||
it->it_cur,
|
||||
f_entry);
|
||||
|
||||
return FX_VALUE_OBJECT(func->f_func);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return it->it_cur ? FX_SUCCESS : FX_ERR_NO_DATA;
|
||||
}
|
||||
|
||||
static 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 FX_VALUE_EMPTY;
|
||||
}
|
||||
|
||||
struct fx_type_property *prop = fx_unbox(
|
||||
struct fx_type_property,
|
||||
it->it_cur,
|
||||
p_entry);
|
||||
|
||||
return FX_VALUE_OBJECT(prop->p_prop);
|
||||
}
|
||||
|
||||
/*** CLASS DEFINITION *********************************************************/
|
||||
|
||||
FX_TYPE_CLASS_BEGIN(fx_type)
|
||||
FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
||||
FX_INTERFACE_ENTRY(to_string) = NULL;
|
||||
FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
||||
FX_TYPE_CLASS_END(fx_type)
|
||||
|
||||
FX_TYPE_DEFINITION_BEGIN(fx_type)
|
||||
@@ -97,3 +380,35 @@ FX_TYPE_DEFINITION_BEGIN(fx_type)
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user