From cd886cefff576961a11f323034b8ff1d207af29f Mon Sep 17 00:00:00 2001 From: Patrick Wuttke Date: Tue, 21 May 2024 23:44:46 +0200 Subject: [PATCH] More foundation for more reflection. --- LibConf | 1 + include/iwa/class.hpp | 71 --------------- include/iwa/instance.hpp | 4 +- include/iwa/object.hpp | 10 +- include/iwa/type_meta.hpp | 186 ++++++++++++++++++++++++++++++++++++++ include/iwa/window.hpp | 7 ++ source/instance.cpp | 2 + source/type_meta.cpp | 18 ++++ source/window.cpp | 2 + 9 files changed, 223 insertions(+), 78 deletions(-) delete mode 100644 include/iwa/class.hpp create mode 100644 include/iwa/type_meta.hpp create mode 100644 source/type_meta.cpp diff --git a/LibConf b/LibConf index aba334f..e33889e 100644 --- a/LibConf +++ b/LibConf @@ -55,6 +55,7 @@ src_files = Split(""" source/shader_module.cpp source/swapchain.cpp source/texture.cpp + source/type_meta.cpp source/window.cpp source/app/vulkan_application.cpp diff --git a/include/iwa/class.hpp b/include/iwa/class.hpp deleted file mode 100644 index a80d4b2..0000000 --- a/include/iwa/class.hpp +++ /dev/null @@ -1,71 +0,0 @@ - -#pragma once - -#if !defined(IWA_CLASS_HPP_INCLUDED) -#define IWA_CLASS_HPP_INCLUDED - -#include -#include - -namespace iwa -{ -struct Function -{ - const char* name; -}; - -struct ClassCreationArgs -{ - const class Class* parent = nullptr; - std::string name; - std::vector functions; -}; - -class Class -{ -private: - const Class* mParent; - std::string mName; - std::vector mFunctions; -public: - explicit Class(ClassCreationArgs args) noexcept : mParent(args.parent), mName(std::move(args.name)) {} - - [[nodiscard]] const std::string& getName() const noexcept { return mName; } - [[nodiscard]] const Class* getParent() const noexcept { return mParent; } -}; - -class ClassBuilder -{ -private: - const Class* mParent = nullptr; - std::string mName; - std::vector mFunctions; -public: - explicit ClassBuilder(std::string name) noexcept : mName(std::move(name)) {} - - ClassBuilder& setParent(const Class* parent) noexcept - { - mParent = parent; - return *this; - } - - Class make() noexcept - { - return Class({ - .parent = mParent, - .name = std::move(mName), - .functions = std::move(mFunctions) - }); - } - - template - ClassBuilder& addFunction(const char* name, TFunction func) - { - (void) func; - mFunctions.push_back({.name = name}); - return *this; - } -}; -} - -#endif // !defined(IWA_CLASS_HPP_INCLUDED) diff --git a/include/iwa/instance.hpp b/include/iwa/instance.hpp index 174d2cf..97f9b61 100644 --- a/include/iwa/instance.hpp +++ b/include/iwa/instance.hpp @@ -112,7 +112,7 @@ public: } // reflection - static inline void buildClass(ClassBuilder& builder) noexcept; + static inline void buildClass(ClassBuilder& builder) noexcept; private: void runDeleters(bool runAll = false); @@ -156,7 +156,7 @@ mijin::FuturePtr> Instance::runOnMainThread(TFun }(std::forward(function))); } -void Instance::buildClass(ClassBuilder& builder) noexcept +void Instance::buildClass(ClassBuilder& builder) noexcept { super_t::buildClass(builder); diff --git a/include/iwa/object.hpp b/include/iwa/object.hpp index c699c76..421516f 100644 --- a/include/iwa/object.hpp +++ b/include/iwa/object.hpp @@ -15,7 +15,7 @@ #include #include #include -#include "iwa/class.hpp" +#include "iwa/type_meta.hpp" #if !defined(IWA_OBJECTPTR_TRACKING) # if !defined(KAZAN_RELEASE) @@ -427,14 +427,14 @@ public: { static const Class myClass = [](std::string&& name) { - ClassBuilder builder(std::move(name)); + ClassBuilder builder(std::move(name)); TConcrete::buildClass(builder); return builder.make(); }(impl::getClassNameFromSourceLocation(std::source_location::current())); return myClass; } - static void buildClass(ClassBuilder& builder) noexcept + static void buildClass(ClassBuilder& builder) noexcept { if constexpr (!std::is_same_v) { @@ -469,14 +469,14 @@ public: { static const Class myClass = [](std::string&& name) { - ClassBuilder builder(std::move(name)); + ClassBuilder builder(std::move(name)); TConcrete::buildClass(builder); return builder.make(); }(impl::getClassNameFromSourceLocation(std::source_location::current())); return myClass; } - static void buildClass(ClassBuilder& builder) noexcept + static void buildClass(ClassBuilder& builder) noexcept { if constexpr (!std::is_same_v) { diff --git a/include/iwa/type_meta.hpp b/include/iwa/type_meta.hpp new file mode 100644 index 0000000..ed99c1c --- /dev/null +++ b/include/iwa/type_meta.hpp @@ -0,0 +1,186 @@ + +#pragma once + +#if !defined(IWA_CLASS_HPP_INCLUDED) +#define IWA_CLASS_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace iwa +{ +struct Function +{ + const char* name; +}; + +struct Property +{ + const char* name; +}; + +struct ClassCreationArgs +{ + const class Class* parent = nullptr; + std::string name; + std::vector functions; + std::vector properties; +}; + +class Class +{ +private: + const Class* mParent; + std::string mName; + std::vector mFunctions; + std::vector mProperties; +public: + explicit Class(ClassCreationArgs args) noexcept : mParent(args.parent), mName(std::move(args.name)), + mFunctions(std::move(args.functions)), mProperties(std::move(args.properties)) {} + + [[nodiscard]] const Class* getParent() const noexcept { return mParent; } + [[nodiscard]] const std::string& getName() const noexcept { return mName; } + [[nodiscard]] const std::vector& getFunctions() const noexcept { return mFunctions; } + [[nodiscard]] const std::vector& getProperties() const noexcept { return mProperties; } +}; + +template +class ClassBuilder +{ +private: + const Class* mParent = nullptr; + std::string mName; + std::vector mFunctions; + std::vector mProperties; +public: + explicit ClassBuilder(std::string name) noexcept : mName(std::move(name)) {} + + ClassBuilder& setParent(const Class* parent) noexcept + { + mParent = parent; + return *this; + } + + [[nodiscard]] Class make() noexcept + { + return Class({ + .parent = mParent, + .name = std::move(mName), + .functions = std::move(mFunctions), + .properties = std::move(mProperties) + }); + } + + template + ClassBuilder& addFunction(const char* name, TFunction func) + { + (void) func; + mFunctions.push_back({.name = name}); + return *this; + } + + template + ClassBuilder& addProperty(const char* name, TField TObject::* field) + { + (void) field; + mProperties.push_back({.name = name}); + return *this; + } +}; + +template +class ClassRegisterer +{ +public: + ClassRegisterer() noexcept { + registerClass(&TObject::getClassObject()); + } +}; +#define IWA_REGISTER_CLASS(clazz) \ +namespace \ +{ \ +[[maybe_unused]] ClassRegisterer gRegisterer; \ +} + +struct StructCreationArgs +{ + std::string name; +}; + +class Struct +{ +private: + std::string mName; +public: + explicit Struct(StructCreationArgs args) noexcept : mName(std::move(args.name)) {} + + [[nodiscard]] const std::string& getName() const noexcept { return mName; } +}; + +template +class StructBuilder +{ +private: + std::string mName; +public: + explicit StructBuilder(std::string name) noexcept : mName(std::move(name)) {} + + [[nodiscard]] Struct make() noexcept + { + return Struct({ + .name = std::move(mName) + }); + } +}; + +void registerClass(const Class* clazz) noexcept; +[[nodiscard]] std::span getRegisteredClasses() noexcept; + +template +void buildStruct(StructBuilder& /* builder */) noexcept +{ + static_assert(mijin::always_false_v, "Missing buildStruct() function."); +} + +namespace impl +{ +[[nodiscard]] constexpr std::string getStructNameFromSourceLocation(const std::source_location& sourceLocation) noexcept +{ + const char* ERROR_NAME = ""; +#if MIJIN_COMPILER == MIJIN_COMPILER_GCC || MIJIN_COMPILER == MIJIN_COMPILER_CLANG + const std::string_view functionName = sourceLocation.function_name(); + const std::size_t pos = functionName.find("TStruct = "); + if (pos == std::string_view::npos) + { + return ERROR_NAME; + } + const std::size_t begin = pos + 10; + const std::size_t end = functionName.find(']', begin); + if (end == std::string_view::npos) + { + return ERROR_NAME; + } + return std::string(functionName.substr(begin, end - begin)); +#else + return ""; +#endif +} +} + +template +const Struct& reflectStruct() noexcept +{ + static const Struct theStruct = [](std::string&& name) + { + StructBuilder builder(std::move(name)); + buildStruct(builder); + return builder.make(); + }(impl::getStructNameFromSourceLocation(std::source_location::current())); + return theStruct; +} +} + +#endif // !defined(IWA_CLASS_HPP_INCLUDED) diff --git a/include/iwa/window.hpp b/include/iwa/window.hpp index 1ab05ac..4d25b63 100644 --- a/include/iwa/window.hpp +++ b/include/iwa/window.hpp @@ -81,6 +81,13 @@ public: mijin::Signal<> mouseLeft; mijin::Signal<> closeRequested; }; + +// reflection +template<> +inline void buildStruct(StructBuilder& builder) noexcept +{ + (void) builder; +} } #endif //IWA_WINDOW_HPP_INCLUDED diff --git a/source/instance.cpp b/source/instance.cpp index 3f5585e..a60361b 100644 --- a/source/instance.cpp +++ b/source/instance.cpp @@ -13,6 +13,8 @@ VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE namespace iwa { +IWA_REGISTER_CLASS(Instance) + namespace { void buildDefaultInstanceExtensionList(std::vector& outExtensions) noexcept diff --git a/source/type_meta.cpp b/source/type_meta.cpp new file mode 100644 index 0000000..27ffed0 --- /dev/null +++ b/source/type_meta.cpp @@ -0,0 +1,18 @@ +#include "iwa/type_meta.hpp" + +namespace iwa +{ +namespace +{ +std::vector gClassRegistry; +} +void registerClass(const Class* clazz) noexcept +{ + gClassRegistry.push_back(clazz); +} + +std::span getRegisteredClasses() noexcept +{ + return gClassRegistry; +} +} \ No newline at end of file diff --git a/source/window.cpp b/source/window.cpp index 7492ee3..1fda41c 100644 --- a/source/window.cpp +++ b/source/window.cpp @@ -9,6 +9,8 @@ namespace iwa { inline constexpr const char* WINDOW_DATA_NAME = "iwa_window"; +IWA_REGISTER_CLASS(Window) + namespace { Window* gLastEventWindow = nullptr;