diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 649cc94..c228c62 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,30 +9,30 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-22.04, windows-latest] + os: [ubuntu-24.04, windows-latest] build: [Debug, Release] arch: [x86, x64] - cxx: [g++, clang++-17, ClangCl, v143] + cxx: [g++-14, clang++-19, ClangCl, v143] exclude: - - os: ubuntu-22.04 + - os: ubuntu-24.04 cxx: v143 - - os: ubuntu-22.04 + - os: ubuntu-24.04 cxx: ClangCl - os: windows-latest - cxx: g++ + cxx: g++-14 - os: windows-latest - cxx: clang++-17 + cxx: clang++-19 include: - - cxx: g++ - c: gcc - - cxx: clang++-17 - c: clang-17 - - os: ubuntu-22.04 + - cxx: g++-14 + c: gcc-14 + - cxx: clang++-19 + c: clang-19 + - os: ubuntu-24.04 arch: x86 cmake_args: "-DCMAKE_CXX_FLAGS=-m32" - - os: ubuntu-22.04 + - os: ubuntu-24.04 arch: x64 cmake_args: "-DCMAKE_CXX_FLAGS=-m64" - os: windows-latest @@ -48,21 +48,28 @@ jobs: - name: Clone uses: actions/checkout@v4 - - if: matrix.os == 'ubuntu-22.04' && matrix.arch == 'x86' + - if: matrix.os == 'ubuntu-24.04' && matrix.arch == 'x86' name: Prepare Linux for cross-compilation run: | sudo apt update - sudo apt install g++-multilib + sudo apt install g++-14-multilib - - if: matrix.cxx == 'clang++-17' - name: Installing Clang 17 + - if: matrix.cxx == 'g++-14' + name: Installing G++ 14 + run: | + sudo apt update + sudo apt install gcc-14 g++-14 + + - if: matrix.cxx == 'clang++-19' + name: Installing Clang 19 run: | wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - sudo apt-add-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main" + sudo apt-add-repository "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main" sudo apt update - sudo apt install clang-17 + sudo apt install gcc-14 g++-14 # clang-19 needs stdc++14.2 see https://github.com/llvm/llvm-project/issues/102336 + sudo apt install clang-19 - - if: matrix.os == 'ubuntu-22.04' + - if: matrix.os == 'ubuntu-24.04' name: Configure (Linux) run: > mkdir build && cd build && cmake .. diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e21612..9979036 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,16 +13,16 @@ if(PROJECT_IS_TOP_LEVEL OR NOT LANGULUS) include(LangulusUtilities.cmake) # Add all Langulus libraries - fetch_langulus_module(Core GIT_TAG 393d95b6ab13fc5846bda8a3044e4ca62f02fd5a) - fetch_langulus_module(Logger GIT_TAG 69626cd4c738195df0929a1cd867317422506e61) - fetch_langulus_module(RTTI GIT_TAG 720e675b1ea114156c309fe44871e03557e0a64f) + fetch_langulus_module(Core GIT_TAG 35756f11d2f9c475f27b094b8d4c82cd453969fc) + fetch_langulus_module(Logger GIT_TAG dafbeb825071ec60d8403254143f75606151a7e6) + fetch_langulus_module(RTTI GIT_TAG fc49750884ac943dff4261ac5b8dfb2c148423d7) if(LANGULUS_FEATURE_MANAGED_MEMORY) - fetch_langulus_module(Fractalloc GIT_TAG b4917194b18c139969fb9d0a14bf993ee5f2582a) + fetch_langulus_module(Fractalloc GIT_TAG 66408e8557b1bb3c80615909129342bcebd3fb9f) endif() - fetch_langulus_module(SIMD GIT_TAG 6611cf422e3c8157b88c086f30966afbf4e7dc6c) - fetch_langulus_module(Anyness GIT_TAG 7e433990052d2cf4c1dbd73afdddb1c697d92c56) - fetch_langulus_module(Flow GIT_TAG 4a0b0f349e5a6f543114b9269f96f55adc025a60) - fetch_langulus_module(Math GIT_TAG 1d5612eeccb31b1dc21371977899237330342662) + fetch_langulus_module(SIMD GIT_TAG ead5493049e2800b4c3c02d385c0c6314efac69c) + fetch_langulus_module(Anyness GIT_TAG 46a6513d6bcf3d532e9bf746b50d1299692eb96a) + fetch_langulus_module(Flow GIT_TAG 06000427afccf13016738140d09850f0b8cf837b) + fetch_langulus_module(Math GIT_TAG d25c6d59a8ffd352d94c260d102a53217e12c42d) endif() file(GLOB_RECURSE @@ -32,7 +32,7 @@ file(GLOB_RECURSE ) # Build and install Entity library -add_library(LangulusEntity ${LANGULUS_LIBRARY_TYPE} +add_langulus_library(LangulusEntity $ $ $<$:$> diff --git a/include/Langulus/AI.hpp b/include/Langulus/AI.hpp index f932e92..8188234 100644 --- a/include/Langulus/AI.hpp +++ b/include/Langulus/AI.hpp @@ -36,6 +36,8 @@ namespace Langulus::A struct Mind : virtual AIUnit { LANGULUS_BASES(AIUnit); Mind() : Resolvable {this} {} + + virtual Many Interpret(const Langulus::Text&) = 0; }; } // namespace Langulus::A \ No newline at end of file diff --git a/include/Langulus/Asset.hpp b/include/Langulus/Asset.hpp index 63e760c..e930b43 100644 --- a/include/Langulus/Asset.hpp +++ b/include/Langulus/Asset.hpp @@ -6,7 +6,7 @@ /// SPDX-License-Identifier: GPL-3.0-or-later /// #pragma once -#include "../Entity/Thing.hpp" +#include "IO.hpp" #include #include @@ -26,7 +26,10 @@ namespace Langulus::A Ref mFolder; public: - const Ref& GetFolder() const noexcept; + // @attention never delete stuff from this call! Do it on + // Update() instead + virtual void RequestGarbageCollection() = 0; + auto GetFolder() const noexcept -> const Ref&; }; @@ -43,38 +46,34 @@ namespace Langulus::A protected: // Map of lists of generated data - mutable DataListMap mDataListMap; + DataListMap mDataListMap; public: Asset() : Resolvable {this} {} - void Detach(); - virtual bool Generate(TMeta, Offset = 0) { return true; } template - void Commit(auto&&) const; + void Commit(auto&&); template - NOD() const Data* GetData(Offset = 0) const noexcept; - NOD() const Data* GetData(TMeta, Offset = 0) const noexcept; - + NOD() auto GetData(Offset = 0) noexcept -> Data*; template - NOD() const DataList* GetDataList() const noexcept; - NOD() const DataList* GetDataList(TMeta) const noexcept; + NOD() auto GetData(Offset = 0) const noexcept -> Data const*; - NOD() DataListMap const& GetDataListMap() const noexcept; + NOD() auto GetData(TMeta, Offset = 0) noexcept -> Data*; + NOD() auto GetData(TMeta, Offset = 0) const noexcept -> Data const*; - protected: template - NOD() Data* GetData(Offset = 0) noexcept; - NOD() Data* GetData(TMeta, Offset = 0) noexcept; - + NOD() auto GetDataList() noexcept -> DataList*; template - NOD() DataList* GetDataList() noexcept; - NOD() DataList* GetDataList(TMeta) noexcept; + NOD() auto GetDataList() const noexcept -> DataList const*; + + NOD() auto GetDataList(TMeta) noexcept -> DataList*; + NOD() auto GetDataList(TMeta) const noexcept -> DataList const*; - NOD() DataListMap& GetDataListMap() noexcept; + NOD() auto GetDataListMap() noexcept -> DataListMap&; + NOD() auto GetDataListMap() const noexcept -> DataListMap const&; }; } // namespace Langulus::A diff --git a/include/Langulus/Asset.inl b/include/Langulus/Asset.inl index 541edc8..6facb16 100644 --- a/include/Langulus/Asset.inl +++ b/include/Langulus/Asset.inl @@ -15,7 +15,7 @@ namespace Langulus::A /// Retrieve the asset module's repository folder /// @return a reference to the folder interface LANGULUS(INLINED) - const Ref& AssetModule::GetFolder() const noexcept { + auto AssetModule::GetFolder() const noexcept -> const Ref& { return mFolder; } @@ -23,12 +23,12 @@ namespace Langulus::A /// @attention this doesn't generate any data /// @return a reference to the contents LANGULUS(INLINED) - Asset::DataListMap const& Asset::GetDataListMap() const noexcept { + auto Asset::GetDataListMap() const noexcept -> DataListMap const& { return mDataListMap; } LANGULUS(INLINED) - Asset::DataListMap& Asset::GetDataListMap() noexcept { + auto Asset::GetDataListMap() noexcept -> DataListMap& { return mDataListMap; } @@ -37,7 +37,7 @@ namespace Langulus::A /// @param index - the Nth data associated to the trait /// @return a pointer to the data entry, or nullptr if none exists template LANGULUS(INLINED) - Asset::Data* Asset::GetData(Offset index) noexcept { + auto Asset::GetData(Offset index) noexcept -> Data* { TMeta trait; if constexpr (CT::Trait) trait = MetaTraitOf(); @@ -45,7 +45,7 @@ namespace Langulus::A } template LANGULUS(INLINED) - Asset::Data const* Asset::GetData(Offset index) const noexcept { + auto Asset::GetData(Offset index) const noexcept -> Data const* { return const_cast(this)->GetData(index); } @@ -54,7 +54,7 @@ namespace Langulus::A /// @param index - the Nth data associated to the trait /// @return a pointer to the data entry, or nullptr if none exists LANGULUS(INLINED) - Asset::Data* Asset::GetData(TMeta trait, Offset index) noexcept { + auto Asset::GetData(TMeta trait, Offset index) noexcept -> Data* { if (not Generate(trait, index)) return nullptr; @@ -65,7 +65,7 @@ namespace Langulus::A } LANGULUS(INLINED) - Asset::Data const* Asset::GetData(TMeta trait, Offset index) const noexcept { + auto Asset::GetData(TMeta trait, Offset index) const noexcept -> Data const* { return const_cast(this)->GetData(trait, index); } @@ -73,7 +73,7 @@ namespace Langulus::A /// @tparam T - the trait to search for /// @return a pointer to the data list, or nullptr if none exists template LANGULUS(INLINED) - Asset::DataList* Asset::GetDataList() noexcept { + auto Asset::GetDataList() noexcept -> DataList* { TMeta trait; if constexpr (CT::Trait) trait = MetaTraitOf(); @@ -81,7 +81,7 @@ namespace Langulus::A } template LANGULUS(INLINED) - Asset::DataList const* Asset::GetDataList() const noexcept { + auto Asset::GetDataList() const noexcept -> DataList const* { return const_cast(this)->GetDataList(); } @@ -89,7 +89,7 @@ namespace Langulus::A /// @param trait - the trait to search for /// @return a pointer to the data list, or nullptr if none exists LANGULUS(INLINED) - Asset::DataList* Asset::GetDataList(TMeta trait) noexcept { + auto Asset::GetDataList(TMeta trait) noexcept -> DataList* { if (not const_cast(this)->Generate(trait)) return nullptr; @@ -98,7 +98,7 @@ namespace Langulus::A } LANGULUS(INLINED) - const Asset::DataList* Asset::GetDataList(TMeta trait) const noexcept { + auto Asset::GetDataList(TMeta trait) const noexcept -> const DataList* { return const_cast(this)->GetDataList(trait); } @@ -114,7 +114,7 @@ namespace Langulus::A /// you don't use factories, and just want some local content /// representation. template LANGULUS(INLINED) - void Asset::Commit(auto&& content) const { + void Asset::Commit(auto&& content) { TMeta trait; if constexpr (CT::Trait) trait = MetaTraitOf(); @@ -127,10 +127,4 @@ namespace Langulus::A mDataListMap.Insert(trait, S::Nest(content)); } - /// Detach the asset - inline void Asset::Detach() { - mDataListMap.Reset(); - ProducedFrom::Detach(); - } - } // namespace Langulus::A diff --git a/include/Langulus/IO.hpp b/include/Langulus/IO.hpp index 5f74c49..c444baf 100644 --- a/include/Langulus/IO.hpp +++ b/include/Langulus/IO.hpp @@ -20,6 +20,8 @@ namespace Langulus::A /// Abstract file system module /// struct FileSystem : virtual Module { + LANGULUS_BASES(Module); + protected: // Working directory path // This is the only full path that is exposed to the system, @@ -30,8 +32,6 @@ namespace Langulus::A Path mMainDataPath; public: - LANGULUS_BASES(Module); - NOD() virtual auto GetFile (const Path&) -> Ref = 0; NOD() virtual auto GetFolder(const Path&) -> Ref = 0; @@ -44,6 +44,9 @@ namespace Langulus::A /// Abstract file interface /// struct File : virtual Unit { + LANGULUS(PRODUCER) FileSystem; + LANGULUS_BASES(Unit); + protected: Path mFilePath; bool mExists {}; @@ -51,10 +54,14 @@ namespace Langulus::A Size mByteCount {}; bool mIsReadOnly {}; - public: - LANGULUS(PRODUCER) FileSystem; - LANGULUS_BASES(Unit); + // Parent directory substring, mapped onto mFilePath + Token mParentDirectory; + // File name after all directories, mapped onto mFilePath + Token mFileName; + // The extension of the filename, mapped onto mFilePath + Token mFileExtension; + public: NOD() virtual auto ReadAs (DMeta) const -> Many = 0; NOD() virtual auto RelativeFile (const Path&) const -> Ref = 0; NOD() virtual auto RelativeFolder(const Path&) const -> Ref = 0; @@ -68,35 +75,50 @@ namespace Langulus::A template NOD() T ReadAs() const; + + /// /// Abstract file reader stream struct Reader { protected: - File* mFile; - Offset mProgress {}; + Ref mFile; + Offset mProgress = 0; public: Reader() = delete; - Reader(File* f) : mFile {f} {} + virtual ~Reader() {} + + Reader(File* f) + : mFile {f} {} virtual auto Read(Many&) -> Offset = 0; - auto GetFile() const noexcept { return mFile; } + auto GetFile() const noexcept -> const Ref& { + return mFile; + } }; + + /// /// Abstract file writer stream struct Writer { protected: - File* mFile; - Offset mProgress {}; - bool mAppend = false; + Ref mFile; + Offset mProgress = 0; + bool mAppend = false; public: Writer() = delete; - Writer(File* f, bool append) : mFile {f}, mAppend {append} {} + virtual ~Writer() {} + + Writer(File* f, bool append) + : mFile {f} + , mAppend{append} {} virtual auto Write(const Many&) -> Offset = 0; - auto GetFile() const noexcept { return mFile; } + auto GetFile() const noexcept -> const Ref& { + return mFile; + } }; NOD() virtual auto NewReader() const -> Ref = 0; @@ -108,15 +130,15 @@ namespace Langulus::A /// Abstract folder interface /// struct Folder : virtual Unit { + LANGULUS(PRODUCER) FileSystem; + LANGULUS_BASES(Unit); + protected: Path mFolderPath; bool mExists = false; bool mIsReadOnly = false; public: - LANGULUS(PRODUCER) FileSystem; - LANGULUS_BASES(Unit); - NOD() virtual auto RelativeFile (const Path&) const -> Ref = 0; NOD() virtual auto RelativeFolder(const Path&) const -> Ref = 0; diff --git a/include/Langulus/IO.inl b/include/Langulus/IO.inl index 0f62a9e..0fa7155 100644 --- a/include/Langulus/IO.inl +++ b/include/Langulus/IO.inl @@ -15,14 +15,14 @@ namespace Langulus::A /// Get the current working path (where the main exe was executed) /// @return the path LANGULUS(INLINED) - const Path& FileSystem::GetWorkingPath() const noexcept { + auto FileSystem::GetWorkingPath() const noexcept -> const Path& { return mWorkingPath; } /// Get the current data path, like GetWorkingPath() / "data" /// @return the path LANGULUS(INLINED) - const Path& FileSystem::GetDataPath() const noexcept { + auto FileSystem::GetDataPath() const noexcept -> const Path& { return mMainDataPath; } @@ -58,7 +58,7 @@ namespace Langulus::A /// Get the full path of the file /// @return a reference to the path LANGULUS(INLINED) - const Path& File::GetFilePath() const noexcept { + auto File::GetFilePath() const noexcept -> const Path& { return mFilePath; } @@ -88,7 +88,7 @@ namespace Langulus::A /// Get the full path of the folder /// @return a reference to the path LANGULUS(INLINED) - const Path& Folder::GetFolderPath() const noexcept { + auto Folder::GetFolderPath() const noexcept -> const Path& { return mFolderPath; } diff --git a/include/Langulus/Image.hpp b/include/Langulus/Image.hpp index 7dd9237..7f7532d 100644 --- a/include/Langulus/Image.hpp +++ b/include/Langulus/Image.hpp @@ -57,18 +57,18 @@ namespace Langulus::A LANGULUS_BASES(Asset); Image() : Resolvable {this} {} - NOD() virtual Ref GetLOD(const Math::LOD&) const { return {}; } - NOD() virtual void* GetGPUHandle() const noexcept { return nullptr; } + NOD() virtual auto GetLOD(const Math::LOD&) const -> Ref { return {}; } + NOD() virtual auto GetGPUHandle() const noexcept -> void* { return nullptr; } - NOD() DMeta GetFormat() const noexcept; - NOD() ImageView const& GetView() const noexcept; - NOD() ImageView& GetView() noexcept; + NOD() auto GetFormat() const noexcept -> DMeta; + NOD() auto GetView() const noexcept -> ImageView const&; + NOD() auto GetView() noexcept -> ImageView&; template auto ForEachPixel(F&&) const; template class S, CT::Block B> requires CT::Intent> - void Upload(S&&) const; + void Upload(S&&); /// /// Iteration @@ -76,9 +76,9 @@ namespace Langulus::A template struct Iterator; - NOD() auto begin() noexcept -> Iterator; + NOD() auto begin() noexcept -> Iterator; NOD() auto begin() const noexcept -> Iterator; - NOD() auto end() const noexcept -> A::IteratorEnd { return {}; } + NOD() auto end() const noexcept -> A::IteratorEnd { return {}; } }; @@ -108,17 +108,17 @@ namespace Langulus::A constexpr Iterator(Iterator&&) noexcept = default; constexpr Iterator(const A::IteratorEnd&) noexcept; - constexpr Iterator& operator = (const Iterator&) noexcept = default; - constexpr Iterator& operator = (Iterator&&) noexcept = default; + constexpr auto operator = (const Iterator&) noexcept -> Iterator& = default; + constexpr auto operator = (Iterator&&) noexcept -> Iterator& = default; NOD() constexpr bool operator == (const Iterator&) const noexcept; NOD() constexpr bool operator == (const A::IteratorEnd&) const noexcept; // Prefix operator - constexpr Iterator& operator ++ () noexcept; + constexpr auto operator ++ () noexcept -> Iterator&; // Suffix operator - NOD() constexpr Iterator operator ++ (int) noexcept; + NOD() constexpr auto operator ++ (int) noexcept -> Iterator; constexpr explicit operator bool() const noexcept; constexpr operator Iterator() const noexcept requires Mutable; @@ -135,7 +135,7 @@ namespace Langulus::A LANGULUS_BASES(Image); Font() - : Resolvable {this} + : Resolvable {this} , ProducedFrom {nullptr, {}} {} }; diff --git a/include/Langulus/Image.inl b/include/Langulus/Image.inl index a19fafd..91879fe 100644 --- a/include/Langulus/Image.inl +++ b/include/Langulus/Image.inl @@ -84,21 +84,21 @@ namespace Langulus::A /// Get the pixel format of the texture /// @return the pixel format type LANGULUS(INLINED) - DMeta Image::GetFormat() const noexcept { + auto Image::GetFormat() const noexcept -> DMeta { return mView.mFormat; } /// Get the texture view (const) /// @return the texture view LANGULUS(INLINED) - const ImageView& Image::GetView() const noexcept { + auto Image::GetView() const noexcept -> const ImageView& { return mView; } /// Get the texture view /// @return the texture view LANGULUS(INLINED) - ImageView& Image::GetView() noexcept { + auto Image::GetView() noexcept -> ImageView& { return mView; } @@ -157,7 +157,7 @@ namespace Langulus::A /// @param data - the block of data template class S, CT::Block B> requires CT::Intent> LANGULUS(INLINED) - void Image::Upload(S&& data) const { + void Image::Upload(S&& data) { // Check if provided data matches the view requirements LANGULUS_ASSERT(mView.GetBytesize() == data->GetBytesize(), Image, "Data is of the wrong size"); @@ -221,7 +221,7 @@ namespace Langulus::A /// @attention assumes iterator points to a valid element /// @return the modified iterator template LANGULUS(INLINED) - constexpr Image::Iterator& Image::Iterator::operator ++ () noexcept { + constexpr auto Image::Iterator::operator ++ () noexcept -> Iterator& { mValue += mImage->GetView().GetPixelBytesize(); return *this; } @@ -230,7 +230,7 @@ namespace Langulus::A /// @attention assumes iterator points to a valid element /// @return the previous value of the iterator template LANGULUS(INLINED) - constexpr Image::Iterator Image::Iterator::operator ++ (int) noexcept { + constexpr auto Image::Iterator::operator ++ (int) noexcept -> Iterator { const auto backup = *this; operator ++ (); return backup; diff --git a/include/Langulus/Material.hpp b/include/Langulus/Material.hpp index 6603ad9..6762c0e 100644 --- a/include/Langulus/Material.hpp +++ b/include/Langulus/Material.hpp @@ -73,13 +73,13 @@ namespace Langulus LANGULUS_BASES(Asset); using Asset::Asset; - NOD() virtual Ref GetLOD(const Math::LOD&) const = 0; + NOD() virtual auto GetLOD(const Math::LOD&) const -> Ref = 0; - NOD() const TraitList& GetInputs(RefreshRate) const; - NOD() const TraitList& GetInputs(Offset) const; + NOD() auto GetInputs(RefreshRate) const -> const TraitList&; + NOD() auto GetInputs(Offset) const -> const TraitList&; - NOD() const TraitList& GetOutputs(RefreshRate) const; - NOD() const TraitList& GetOutputs(Offset) const; + NOD() auto GetOutputs(RefreshRate) const -> const TraitList&; + NOD() auto GetOutputs(Offset) const -> const TraitList&; protected: mutable TraitList mInputs[RefreshRate::InputCount]; diff --git a/include/Langulus/Mesh.hpp b/include/Langulus/Mesh.hpp index ad88c4c..10693bd 100644 --- a/include/Langulus/Mesh.hpp +++ b/include/Langulus/Mesh.hpp @@ -20,6 +20,8 @@ namespace Langulus /// Vertex/index buffer view /// struct MeshView { + using MapModeType = Math::MapModeType; + // Number of primitives uint32_t mPrimitiveCount = 0; // Starting primitive @@ -33,11 +35,11 @@ namespace Langulus // Double-sidedness bool mBilateral = false; // Texture mapping mode - Math::MapModeType mTextureMapping = Math::MapModeType::Auto; + MapModeType mTextureMapping = MapModeType::Auto; bool operator == (const MeshView&) const noexcept; - NOD() MeshView Decay() const; + NOD() auto Decay() const -> MeshView; NOD() Hash GetHash() const noexcept; }; @@ -51,6 +53,9 @@ namespace Langulus::A /// struct Mesh : Asset { protected: + using MapModeType = Math::MapModeType; + using Vec2u = Math::Vec2u; + using Vec3u = Math::Vec3u; MeshView mView; public: @@ -58,32 +63,32 @@ namespace Langulus::A Mesh() : Resolvable {this} {} template - NOD() bool CheckTopology() const; - NOD() DMeta GetTopology() const noexcept; - NOD() Math::MapModeType GetTextureMapper() const noexcept; + NOD() bool CheckTopology() const; + NOD() auto GetTopology() const noexcept -> DMeta; + NOD() auto GetTextureMapper() const noexcept -> MapModeType; - NOD() MeshView const& GetView() const noexcept; - NOD() MeshView& GetView() noexcept; + NOD() auto GetView() const noexcept -> MeshView const&; + NOD() auto GetView() noexcept -> MeshView&; - NOD() virtual Ref GetLOD(const Math::LOD&) const = 0; + NOD() virtual auto GetLOD(const Math::LOD&) const -> Ref = 0; // Point utilities NOD() bool MadeOfPoints() const noexcept; - NOD() Count GetPointCount() const; + NOD() auto GetPointCount() const -> Count; template NOD() Many GetPointTrait(Offset) const; // Line utilities NOD() bool MadeOfLines() const noexcept; - NOD() Count GetLineCount() const; - NOD() Math::Vec2u GetLineIndices(Offset) const; + NOD() auto GetLineCount() const -> Count; + NOD() auto GetLineIndices(Offset) const -> Vec2u; template NOD() Many GetLineTrait(Offset) const; // Triangle utilities NOD() bool MadeOfTriangles() const noexcept; - NOD() Count GetTriangleCount() const; - NOD() Math::Vec3u GetTriangleIndices(Offset) const; + NOD() auto GetTriangleCount() const -> Count; + NOD() auto GetTriangleIndices(Offset) const -> Vec3u; template NOD() Many GetTriangleTrait(Offset) const; @@ -93,8 +98,8 @@ namespace Langulus::A Count ForEachVertex(auto&&) const; protected: - NOD() Math::Vec2u InnerGetIndices(const Data*, const Math::Vec2u&) const; - NOD() Math::Vec3u InnerGetIndices(const Data*, const Math::Vec3u&) const; + NOD() Vec2u InnerGetIndices(const Data*, const Vec2u&) const; + NOD() Vec3u InnerGetIndices(const Data*, const Vec3u&) const; template Count ForEachVertexInner(Types, auto&& call) const; @@ -105,10 +110,10 @@ namespace Langulus::A template T ForEachVertex_PrepareIndexStream() const; - template + template auto PickVertex(Offset i, const CT::Trait auto& data, const CT::Trait auto& indices) const; - template + template auto GenerateVertex(Offset i, const auto& data, const auto& indices, std::index_sequence&&) const; }; diff --git a/include/Langulus/Mesh.inl b/include/Langulus/Mesh.inl index 5fb6416..63584de 100644 --- a/include/Langulus/Mesh.inl +++ b/include/Langulus/Mesh.inl @@ -30,7 +30,7 @@ namespace Langulus /// Decay the geometry view to a list of points /// @return the decayed view LANGULUS(INLINED) - MeshView MeshView::Decay() const { + auto MeshView::Decay() const -> MeshView { LANGULUS_ASSERT(mPrimitiveCount and mTopology, Convert, "Bad vertex view"); if (mTopology->template Is()) return *this; @@ -77,14 +77,14 @@ namespace Langulus::A /// Get the topology of the geometry /// @return the topology type LANGULUS(INLINED) - DMeta Mesh::GetTopology() const noexcept { + auto Mesh::GetTopology() const noexcept -> DMeta { return mView.mTopology; } /// Get the texture mapping mode /// @return the texture mapping mode LANGULUS(INLINED) - Math::MapModeType Mesh::GetTextureMapper() const noexcept { + auto Mesh::GetTextureMapper() const noexcept -> MapModeType { return mView.mTextureMapping; } @@ -100,14 +100,14 @@ namespace Langulus::A /// Get the geometry view (const) /// @return the geometry view LANGULUS(INLINED) - const MeshView& Mesh::GetView() const noexcept { + auto Mesh::GetView() const noexcept -> const MeshView& { return mView; } /// Get the geometry view /// @return the geometry view LANGULUS(INLINED) - MeshView& Mesh::GetView() noexcept { + auto Mesh::GetView() noexcept -> MeshView& { return mView; } @@ -115,7 +115,7 @@ namespace Langulus::A /// @param indices - index buffer /// @param where - line indices /// @return the (eventually indirected) line indices - inline Math::Vec2u Mesh::InnerGetIndices(const Data* indices, const Math::Vec2u& where) const { + inline auto Mesh::InnerGetIndices(const Data* indices, const Vec2u& where) const -> Vec2u { if (not indices or not *indices) return where; @@ -142,14 +142,15 @@ namespace Langulus::A }; } - LANGULUS_THROW(Access, "Trying to get index from incompatible index buffer"); + LANGULUS_THROW(Access, + "Trying to get index from incompatible index buffer"); } /// Helper that indirects in case there is an index buffer /// @param indices - index buffer /// @param where - triangle indices /// @return the (eventually indirected) triangle indices - inline Math::Vec3u Mesh::InnerGetIndices(const Data* indices, const Math::Vec3u& where) const { + inline auto Mesh::InnerGetIndices(const Data* indices, const Vec3u& where) const -> Vec3u { if (not indices or not *indices) return where; @@ -177,7 +178,8 @@ namespace Langulus::A }; } - LANGULUS_THROW(Access, "Trying to get index from incompatible index buffer"); + LANGULUS_THROW(Access, + "Trying to get index from incompatible index buffer"); } /// Is topology a point list? @@ -196,7 +198,7 @@ namespace Langulus::A } template - Anyness::Many Mesh::GetPointTrait(Offset) const { + Many Mesh::GetPointTrait(Offset) const { TODO(); return {}; } @@ -262,8 +264,7 @@ namespace Langulus::A /// Get the point indices of a given line /// @param index - line index /// @return the point indices as a 32bit unsigned 2D vector - inline Math::Vec2u Mesh::GetLineIndices(Offset index) const { - using Math::Vec2u; + inline auto Mesh::GetLineIndices(Offset index) const -> Vec2u { const auto indices = GetData(); if (CheckTopology()) @@ -370,8 +371,7 @@ namespace Langulus::A /// @attention not optimized for iteration /// @param index - triangle index /// @return the indices as a 32bit unsigned 3D vector - inline Math::Vec3u Mesh::GetTriangleIndices(Offset index) const { - using Math::Vec3u; + inline auto Mesh::GetTriangleIndices(Offset index) const -> Vec3u { const auto indices = GetData(0); if (CheckTopology()) { @@ -606,19 +606,18 @@ namespace Langulus::A return {}; if (indices->GetCount() == 1) { - // Single index source will be used for all Ts + // Single index source will be used for all vertex traits return Disown((*indices)[0]); } // Multiple index sequences for different streams // Each sequence should be kept in a corresponding trait - for (auto& group : *indices) { - if (group.IsSimilar()) - return group.Get(); - } - - // No indices for T found - return {}; + T result; + indices->ForEachDeep([&result](const T& trait) noexcept { + result = trait; + return Loop::Break; + }); + return result; } /// Invoke 'call' with the required arguments @@ -723,7 +722,7 @@ namespace Langulus::A else LANGULUS_OOPS(Access, "Unsupported index format"); } - else LANGULUS_ERROR("Unsupported topology"); + else static_assert(false, "Unsupported topology"); } else LANGULUS_OOPS(Access, "Unsupported indexing strategy"); diff --git a/include/Langulus/UI.hpp b/include/Langulus/UI.hpp index 8ef3c0a..05562fe 100644 --- a/include/Langulus/UI.hpp +++ b/include/Langulus/UI.hpp @@ -10,59 +10,59 @@ #include "../Entity/Module.hpp" -namespace Langulus::A::UI +namespace Langulus::A { /// /// Abstract UI module /// - struct Module : virtual A::Module { + struct UIModule : virtual A::Module { LANGULUS_BASES(A::Module); - Module() : Resolvable {this}, A::Module {nullptr} {} + UIModule() : Resolvable {this}, A::Module {nullptr} {} }; /// /// Abstract UI unit /// - struct Unit : virtual A::Unit { - LANGULUS(PRODUCER) UI::Module; + struct UIUnit : virtual A::Unit { + LANGULUS(PRODUCER) UIModule; LANGULUS_BASES(A::Unit); - Unit() : Resolvable {this} {} + UIUnit() : Resolvable {this} {} }; /// /// Abstract UI system /// - struct System : virtual UI::Unit { - LANGULUS_BASES(UI::Unit); - System() : Resolvable {this} {} + struct UISystem : virtual UIUnit { + LANGULUS_BASES(UIUnit); + UISystem() : Resolvable {this} {} }; /// /// Abstract UI button /// - struct Button : virtual UI::Unit { - LANGULUS(PRODUCER) UI::System; - LANGULUS_BASES(UI::Unit); - Button() : Resolvable {this} {} + struct UIButton : virtual UIUnit { + LANGULUS(PRODUCER) UISystem; + LANGULUS_BASES(UIUnit); + UIButton() : Resolvable {this} {} }; /// /// Abstract UI text field /// - struct Text : virtual UI::Unit { - LANGULUS(PRODUCER) UI::System; - LANGULUS_BASES(UI::Unit); - Text() : Resolvable {this} {} + struct UILabel : virtual UIUnit { + LANGULUS(PRODUCER) UISystem; + LANGULUS_BASES(UIUnit); + UILabel() : Resolvable {this} {} }; /// /// Abstract UI input field /// - struct Input : virtual UI::Unit { - LANGULUS(PRODUCER) UI::System; - LANGULUS_BASES(UI::Unit); - Input() : Resolvable {this} {} + struct UIInput : virtual UIUnit { + LANGULUS(PRODUCER) UISystem; + LANGULUS_BASES(UIUnit); + UIInput() : Resolvable {this} {} }; -} // namespace Langulus::A::UI \ No newline at end of file +} // namespace Langulus::A \ No newline at end of file diff --git a/include/Langulus/User.hpp b/include/Langulus/User.hpp new file mode 100644 index 0000000..a583f7a --- /dev/null +++ b/include/Langulus/User.hpp @@ -0,0 +1,33 @@ +/// +/// Langulus::Entity +/// Copyright (c) 2013 Dimo Markov +/// Part of the Langulus framework, see https://langulus.com +/// +/// SPDX-License-Identifier: GPL-3.0-or-later +/// +#pragma once +#include "../Entity/Thing.hpp" +#include "../Entity/Module.hpp" + + +namespace Langulus::A +{ + + /// + /// Abstract user module + /// + struct UserModule : virtual Module { + LANGULUS_BASES(Module); + UserModule() : Resolvable {this}, Module {nullptr} {} + }; + + /// + /// Abstract user unit + /// + struct User : virtual Unit { + LANGULUS(PRODUCER) UserModule; + LANGULUS_BASES(Unit); + User() : Resolvable {this} {} + }; + +} // namespace Langulus::A \ No newline at end of file diff --git a/source/Common.hpp b/source/Common.hpp index 408211e..bfee6c5 100644 --- a/source/Common.hpp +++ b/source/Common.hpp @@ -33,3 +33,19 @@ namespace Langulus /// Make the rest of the code aware, that Langulus::Entity has been included #define LANGULUS_LIBRARY_ENTITY() 1 + +#if 0 + #define ENTITY_VERBOSE_ENABLED() 1 + #define ENTITY_VERBOSE_SELF(...) Logger::Info(this, ": ", __VA_ARGS__) + #define ENTITY_VERBOSE_SELF_TAB(...) const auto scoped = Logger::InfoTab(this, ": ", __VA_ARGS__) + #define ENTITY_VERBOSE(...) Logger::Append(__VA_ARGS__) + #define ENTITY_CREATION_VERBOSE_SELF(...) Logger::Verbose(Self(), __VA_ARGS__) + #define ENTITY_SELECTION_VERBOSE_SELF(...) Logger::Verbose(Self(), __VA_ARGS__) +#else + #define ENTITY_VERBOSE_ENABLED() 0 + #define ENTITY_VERBOSE_SELF(...) LANGULUS(NOOP) + #define ENTITY_VERBOSE_SELF_TAB(...) LANGULUS(NOOP) + #define ENTITY_VERBOSE(...) LANGULUS(NOOP) + #define ENTITY_CREATION_VERBOSE_SELF(...) LANGULUS(NOOP) + #define ENTITY_SELECTION_VERBOSE_SELF(...) LANGULUS(NOOP) +#endif diff --git a/source/Event.hpp b/source/Event.hpp index 57c42d4..f146253 100644 --- a/source/Event.hpp +++ b/source/Event.hpp @@ -69,6 +69,8 @@ namespace Langulus /// Events are often used as arguments for Verbs::Interact /// struct Event { + using Many = Anyness::Many; + LANGULUS_CONVERTS_TO(Anyness::Text); // Event type @@ -88,7 +90,7 @@ namespace Langulus Event(Event&&); template requires CT::UnfoldInsertable Event(T1&&, TN&&...); - Event(Describe&&); + Event(Describe); /// /// Assignment @@ -137,10 +139,10 @@ namespace Langulus EVENT() : Event {} { \ mType = MetaOf(); \ } \ - EVENT(Describe&& desc) { \ + EVENT(Describe descriptor) { \ mType = MetaOf(); \ - desc->ExtractData(mState); \ - desc->ExtractTrait(mPayload); \ + descriptor->ExtractData(mState); \ + descriptor->ExtractTrait(mPayload); \ } \ template \ EVENT(EventState state, T_&&...a) : Event {Forward(a)...} { \ @@ -162,10 +164,10 @@ namespace Langulus EVENT() : Event {} { \ mType = MetaOf(); \ } \ - EVENT(Describe&& desc) { \ + EVENT(Describe descriptor) { \ mType = MetaOf(); \ - desc->ExtractData(mState); \ - desc->ExtractTrait(mPayload); \ + descriptor->ExtractData(mState); \ + descriptor->ExtractTrait(mPayload); \ } \ template \ EVENT(EventState state, T_&&...a) : Event {Forward(a)...} { \ diff --git a/source/Event.inl b/source/Event.inl index f6cfa13..5e7f906 100644 --- a/source/Event.inl +++ b/source/Event.inl @@ -119,7 +119,7 @@ namespace Langulus /// Descriptor-construction /// @param other - event properties and payload to move LANGULUS(INLINED) - Event::Event(Describe&& desc) : Event {} { + Event::Event(Describe desc) : Event {} { LANGULUS_ASSERT(desc->ExtractData(mType), Construct, "Invalid event"); desc->ExtractData(mState); desc->ExtractTrait(mPayload); @@ -140,9 +140,9 @@ namespace Langulus mTimestamp = DeintCast(t1).mTimestamp; mPayload = S::Nest(DeintCast(t1).mPayload); } - else mPayload = Anyness::Many {Forward(t1)}; + else mPayload = Many {Forward(t1)}; } - else mPayload = Anyness::Many {Forward(t1), Forward(tn)...}; + else mPayload = Many {Forward(t1), Forward(tn)...}; } /// Refer-assignment @@ -178,7 +178,7 @@ namespace Langulus mTimestamp = DeintCast(rhs).mTimestamp; mPayload = S::Nest(DeintCast(rhs).mPayload); } - else mPayload = Anyness::Many {S::Nest(rhs)}; + else mPayload = Many {S::Nest(rhs)}; return *this; } diff --git a/source/Hierarchy-Seek.inl b/source/Hierarchy-Seek.inl index 319685a..9581a9d 100644 --- a/source/Hierarchy-Seek.inl +++ b/source/Hierarchy-Seek.inl @@ -24,19 +24,19 @@ namespace Langulus::Entity /// @param offset - the match to return /// @return a pointer to the found unit, or nullptr if not found TEMPLATE() template LANGULUS(INLINED) - const A::Unit* TME()::SeekUnit(DMeta type, Index offset) const { + auto TME()::SeekUnit(DMeta type, Index offset) const -> const A::Unit* { return const_cast(static_cast(this)) ->template SeekUnit(type, offset); } TEMPLATE() template LANGULUS(INLINED) - Decay* TME()::SeekUnit(Index offset) { + auto TME()::SeekUnit(Index offset) -> Decay* { return dynamic_cast*>(static_cast(this) ->template SeekUnit(MetaDataOf>(), offset)); } TEMPLATE() template LANGULUS(INLINED) - const Decay* TME()::SeekUnit(Index offset) const { + auto TME()::SeekUnit(Index offset) const -> const Decay* { return const_cast(this) ->template SeekUnit(offset); } @@ -49,19 +49,19 @@ namespace Langulus::Entity /// @param offset - the match to return /// @return a pointer to the found unit, or nullptr if not found TEMPLATE() template LANGULUS(INLINED) - const A::Unit* TME()::SeekUnitAux(const Neat& aux, DMeta type, Index offset) const { + auto TME()::SeekUnitAux(const Many& aux, DMeta type, Index offset) const -> const A::Unit* { return const_cast(static_cast(this)) ->template SeekUnitAux(aux, type, offset); } TEMPLATE() template LANGULUS(INLINED) - Decay* TME()::SeekUnitAux(const Neat& aux, Index offset) { + auto TME()::SeekUnitAux(const Many& aux, Index offset) -> Decay* { return dynamic_cast*>(static_cast(this) ->template SeekUnitAux(aux, MetaDataOf>(), offset)); } TEMPLATE() template LANGULUS(INLINED) - const Decay* TME()::SeekUnitAux(const Neat& aux, Index offset) const { + auto TME()::SeekUnitAux(const Many& aux, Index offset) const -> const Decay* { return const_cast(this) ->template SeekUnitAux(aux, offset); } @@ -73,19 +73,19 @@ namespace Langulus::Entity /// @param offset - the match to return /// @return a pointer to the found unit, or nullptr if not found TEMPLATE() template LANGULUS(INLINED) - const A::Unit* TME()::SeekUnitExt(DMeta type, const Neat& ext, Index offset) const { + auto TME()::SeekUnitExt(DMeta type, const Many& ext, Index offset) const -> const A::Unit* { return const_cast(static_cast(this)) ->template SeekUnitExt(type, ext, offset); } TEMPLATE() template LANGULUS(INLINED) - Decay* TME()::SeekUnitExt(const Neat& ext, Index offset) { + auto TME()::SeekUnitExt(const Many& ext, Index offset) -> Decay* { return dynamic_cast*>(static_cast(this) ->template SeekUnitExt(MetaDataOf>(), ext, offset)); } TEMPLATE() template LANGULUS(INLINED) - const Decay* TME()::SeekUnitExt(const Neat& ext, Index offset) const { + auto TME()::SeekUnitExt(const Many& ext, Index offset) const -> const Decay* { return const_cast(this) ->template SeekUnitExt(ext, offset); } @@ -99,19 +99,19 @@ namespace Langulus::Entity /// @param offset - the match to return /// @return a pointer to the found unit, or nullptr if not found TEMPLATE() template LANGULUS(INLINED) - const A::Unit* TME()::SeekUnitAuxExt(DMeta type, const Neat& aux, const Neat& ext, Index offset) const { + auto TME()::SeekUnitAuxExt(DMeta type, const Many& aux, const Many& ext, Index offset) const -> const A::Unit* { return const_cast(static_cast(this)) ->template SeekUnitAuxExt(type, aux, ext, offset); } TEMPLATE() template LANGULUS(INLINED) - Decay* TME()::SeekUnitAuxExt(const Neat& aux, const Neat& ext, Index offset) { + auto TME()::SeekUnitAuxExt(const Many& aux, const Many& ext, Index offset) -> Decay* { return dynamic_cast*>(static_cast(this) ->template SeekUnitAuxExt(MetaDataOf>(), aux, ext, offset)); } TEMPLATE() template LANGULUS(INLINED) - const Decay* TME()::SeekUnitAuxExt(const Neat& aux, const Neat& ext, Index offset) const { + auto TME()::SeekUnitAuxExt(const Many& aux, const Many& ext, Index offset) const -> const Decay* { return const_cast(this) ->template SeekUnitAuxExt(aux, ext, offset); } @@ -122,19 +122,19 @@ namespace Langulus::Entity /// @param offset - the match to return /// @return a pointer to the found unit, or nullptr if not found TEMPLATE() template LANGULUS(INLINED) - Trait TME()::SeekTrait(TMeta type, Index offset) const { + auto TME()::SeekTrait(TMeta type, Index offset) const -> Trait { return const_cast(static_cast(this)) ->template SeekTrait(type, offset); } TEMPLATE() template LANGULUS(INLINED) - Trait TME()::SeekTrait(Index offset) { + auto TME()::SeekTrait(Index offset) -> Trait { return static_cast(this) ->template SeekTrait(MetaTraitOf(), offset); } TEMPLATE() template LANGULUS(INLINED) - Trait TME()::SeekTrait(Index offset) const { + auto TME()::SeekTrait(Index offset) const -> Trait { return const_cast(this) ->template SeekTrait(offset); } @@ -146,19 +146,19 @@ namespace Langulus::Entity /// @param offset - the match to return /// @return a pointer to the found unit, or nullptr if not found TEMPLATE() template LANGULUS(INLINED) - Trait TME()::SeekTraitAux(const Neat& aux, TMeta type, Index offset) const { + auto TME()::SeekTraitAux(const Many& aux, TMeta type, Index offset) const -> Trait { return const_cast(static_cast(this)) ->template SeekTraitAux(aux, type, offset); } TEMPLATE() template LANGULUS(INLINED) - Trait TME()::SeekTraitAux(const Neat& aux, Index offset) { + auto TME()::SeekTraitAux(const Many& aux, Index offset) -> Trait { return static_cast(this) ->template SeekTraitAux(aux, MetaTraitOf(), offset); } TEMPLATE() template LANGULUS(INLINED) - Trait TME()::SeekTraitAux(const Neat& aux, Index offset) const { + auto TME()::SeekTraitAux(const Many& aux, Index offset) const -> Trait { return const_cast(this) ->template SeekTraitAux(aux, offset); } @@ -172,7 +172,7 @@ namespace Langulus::Entity } TEMPLATE() template LANGULUS(INLINED) - bool TME()::SeekValueAux(const Neat& aux, CT::NotTagged auto& output, Index offset) const { + bool TME()::SeekValueAux(const Many& aux, CT::NotTagged auto& output, Index offset) const { return static_cast(this) ->template SeekValueAux(MetaTraitOf(), aux, output, offset); } @@ -190,7 +190,7 @@ namespace Langulus::Entity } TEMPLATE() template LANGULUS(INLINED) - bool TME()::SeekValueAux(const Neat& aux, CT::Tagged auto& output, Index offset) const { + bool TME()::SeekValueAux(const Many& aux, CT::Tagged auto& output, Index offset) const { using T = Deref; auto lambda = [&]() { return static_cast(this)->template @@ -207,43 +207,43 @@ namespace Langulus::Entity /// Available only when managed reflection is enabled /// TEMPLATE() template LANGULUS(INLINED) - A::Unit* TME()::SeekUnit(const Token& dataToken, Index offset) { + auto TME()::SeekUnit(const Token& dataToken, Index offset) -> A::Unit* { return static_cast(this) ->template SeekUnit(RTTI::GetMetaData(dataToken), offset); } TEMPLATE() template LANGULUS(INLINED) - const A::Unit* TME()::SeekUnit(const Token& dataToken, Index offset) const { + auto TME()::SeekUnit(const Token& dataToken, Index offset) const -> const A::Unit* { return static_cast(this) ->template SeekUnit(RTTI::GetMetaData(dataToken), offset); } TEMPLATE() template LANGULUS(INLINED) - A::Unit* TME()::SeekUnitAux(const Neat& aux, const Token& dataToken, Index offset) { + auto TME()::SeekUnitAux(const Many& aux, const Token& dataToken, Index offset) -> A::Unit* { return static_cast(this) ->template SeekUnitAux(aux, RTTI::GetMetaData(dataToken), offset); } TEMPLATE() template LANGULUS(INLINED) - const A::Unit* TME()::SeekUnitAux(const Neat& aux, const Token& dataToken, Index offset) const { + auto TME()::SeekUnitAux(const Many& aux, const Token& dataToken, Index offset) const -> const A::Unit* { return static_cast(this) ->template SeekUnitAux(aux, RTTI::GetMetaData(dataToken), offset); } TEMPLATE() template LANGULUS(INLINED) - Trait TME()::SeekTrait(const Token& traitToken, Index offset) { + auto TME()::SeekTrait(const Token& traitToken, Index offset) -> Trait { return static_cast(this) ->template SeekTrait(RTTI::GetMetaTrait(traitToken), offset); } TEMPLATE() template LANGULUS(INLINED) - Trait TME()::SeekTrait(const Token& traitToken, Index offset) const { + auto TME()::SeekTrait(const Token& traitToken, Index offset) const -> Trait { return static_cast(this) ->template SeekTrait(RTTI::GetMetaTrait(traitToken), offset); } TEMPLATE() template LANGULUS(INLINED) - Trait TME()::SeekTraitAux(const Neat& aux, const Token& traitToken, Index offset) const { + auto TME()::SeekTraitAux(const Many& aux, const Token& traitToken, Index offset) const -> Trait { return static_cast(this) ->template SeekTraitAux(aux, RTTI::GetMetaTrait(traitToken), offset); } @@ -255,7 +255,7 @@ namespace Langulus::Entity } TEMPLATE() template LANGULUS(INLINED) - bool TME()::SeekValueAux(const Token& traitToken, const Neat& aux, CT::Data auto& output, Index offset) const { + bool TME()::SeekValueAux(const Token& traitToken, const Many& aux, CT::Data auto& output, Index offset) const { return static_cast(this) ->template SeekValueAux(RTTI::GetMetaTrait(traitToken), aux, output, offset); } @@ -276,7 +276,7 @@ namespace Langulus::Entity /// @param offset - which of the matches to return /// @return the found unit, or nullptr if no such unit was found template LANGULUS(INLINED) - A::Unit* Hierarchy::SeekUnit(DMeta meta, Index offset) { + auto Hierarchy::SeekUnit(DMeta meta, Index offset) -> A::Unit* { for (auto owner : *this) { A::Unit* result = owner->template SeekUnit(meta, offset); if (result) @@ -294,8 +294,8 @@ namespace Langulus::Entity /// @param offset - the index of the unit to return /// @return the unit if found, or nullptr otherwise template LANGULUS(INLINED) - A::Unit* Hierarchy::SeekUnitAux(const Neat& aux, DMeta meta, Index offset) { - const A::Unit* result {}; + auto Hierarchy::SeekUnitAux(const Many& aux, DMeta meta, Index offset) -> A::Unit* { + const A::Unit* result = nullptr; // Scan descriptor even if hierarchy is empty if constexpr (SEEK & Seek::Here) { @@ -320,9 +320,8 @@ namespace Langulus::Entity // If reached, then no unit was found in the descriptor // Let's delve into the hierarchy, by scanning for Traits::Parent // and Traits::Child inside the 'aux' - //return SeekValue(meta, output, offset); if constexpr (SEEK & Seek::Above) { - aux.ForEachTrait([&](const Traits::Parent& trait) -> LoopControl { + aux.ForEachDeep([&](const Traits::Parent& trait) -> LoopControl { trait.ForEach([&](const Thing& parent) { if (nullptr != (result = parent.SeekUnit(meta, offset))) // Value was found @@ -334,7 +333,7 @@ namespace Langulus::Entity } if constexpr (SEEK & Seek::Below) { - aux.ForEachTrait([&](const Traits::Child& trait) -> LoopControl { + aux.ForEachDeep([&](const Traits::Child& trait) -> LoopControl { trait.ForEach([&](const Thing& child) { if (nullptr != (result = child.SeekUnit(meta, offset))) // Value was found @@ -355,7 +354,7 @@ namespace Langulus::Entity /// @param offset - the index of the unit to return /// @return the unit if found, or nullptr otherwise template LANGULUS(INLINED) - A::Unit* Hierarchy::SeekUnitExt(DMeta type, const Neat& ext, Index offset) { + auto Hierarchy::SeekUnitExt(DMeta type, const Many& ext, Index offset) -> A::Unit* { for (auto owner : *this) { A::Unit* result = owner->template SeekUnitExt(type, ext, offset); if (result) @@ -374,9 +373,9 @@ namespace Langulus::Entity /// @param offset - the index of the unit to return /// @return a pointer to the found unit, or nullptr if not found template LANGULUS(INLINED) - A::Unit* Hierarchy::SeekUnitAuxExt(DMeta type, const Neat& aux, const Neat& ext, Index offset) { + auto Hierarchy::SeekUnitAuxExt(DMeta type, const Many& aux, const Many& ext, Index offset) -> A::Unit* { // Scan descriptor even if hierarchy is empty - A::Unit* result {}; + A::Unit* result = nullptr; aux.ForEachDeep([&](const A::Unit* u) { if (u->CastsTo(type)) { //TODO check construct arguments @@ -406,7 +405,7 @@ namespace Langulus::Entity /// @param offset - the offset to apply /// @return the trait, which is not empty, if trait was found template LANGULUS(INLINED) - Trait Hierarchy::SeekTrait(TMeta meta, Index offset) { + auto Hierarchy::SeekTrait(TMeta meta, Index offset) -> Trait { for (auto owner : *this) { auto result = owner->template SeekTrait(meta, offset); if (result) @@ -423,7 +422,7 @@ namespace Langulus::Entity /// @param offset - the number of the matching trait to use /// @return the trait, which is not empty, if trait was found template LANGULUS(INLINED) - Trait Hierarchy::SeekTraitAux(const Neat& aux, TMeta meta, Index offset) { + auto Hierarchy::SeekTraitAux(const Many& aux, TMeta meta, Index offset) -> Trait { // Scan descriptor Trait result; aux.ForEachDeep([&](const Trait& trait) { @@ -489,7 +488,7 @@ namespace Langulus::Entity /// @param offset - the number of the matching trait to use /// @return the trait, which is not empty, if trait was found template LANGULUS(INLINED) - bool Hierarchy::SeekValueAux(TMeta meta, const Neat& aux, CT::Data auto& output, Index offset) const { + bool Hierarchy::SeekValueAux(TMeta meta, const Many& aux, CT::Data auto& output, Index offset) const { using D = Deref; if constexpr (CT::Pinnable) { @@ -502,7 +501,7 @@ namespace Langulus::Entity if constexpr (SEEK & Seek::Here) { bool done = false; if (meta) { - aux.ForEachTrait([&](const Trait& trait) -> LoopControl { + aux.ForEachDeep([&](const Trait& trait) -> LoopControl { if (trait.IsTrait(meta)) { // Found match try { @@ -568,10 +567,9 @@ namespace Langulus::Entity // If reached, then no trait was found in the descriptor // Let's delve into the hierarchy, by scanning for Traits::Parent // and Traits::Child inside the 'aux' - //return SeekValue(meta, output, offset); bool done = false; if constexpr (SEEK & Seek::Above) { - aux.ForEachTrait([&](const Traits::Parent& trait) -> LoopControl { + aux.ForEachDeep([&](const Traits::Parent& trait) -> LoopControl { trait.ForEach([&](const Thing& parent) { if (parent.SeekValue(meta, output, offset)) { // Value was found @@ -580,12 +578,13 @@ namespace Langulus::Entity } return Loop::Continue; }); + return not done; }); } if constexpr (SEEK & Seek::Below) { - aux.ForEachTrait([&](const Traits::Child& trait) -> LoopControl { + aux.ForEachDeep([&](const Traits::Child& trait) -> LoopControl { trait.ForEach([&](const Thing& child) { if (child.SeekValue(meta, output, offset)) { // Value was found @@ -594,6 +593,7 @@ namespace Langulus::Entity } return Loop::Continue; }); + return not done; }); } diff --git a/source/Hierarchy.hpp b/source/Hierarchy.hpp index 00eae87..22d28fe 100644 --- a/source/Hierarchy.hpp +++ b/source/Hierarchy.hpp @@ -34,6 +34,7 @@ namespace Langulus::Entity /// /// Can't use virtuals, because we want these to be template functions, /// so that we retain the most of the static optimizations + /// TODO generalize these when deduce-this has been implemented well /// /*template NOD() Unit* SeekUnit(DMeta, Index = IndexFirst) = delete; @@ -71,82 +72,83 @@ namespace Langulus::Entity /// The rest of these functions are defined for every SeekInterface /// They all use static_cast(this) as execution context for the /// above functions, which should be defined in THIS + /// TODO generalize these when deduce-this has been implemented well /// - template - NOD() const A::Unit* SeekUnit(DMeta, Index = 0) const; - template - NOD() Decay* SeekUnit(Index = 0); - template - NOD() const Decay* SeekUnit(Index = 0) const; - - template - NOD() const A::Unit* SeekUnitAux(const Neat&, DMeta, Index = 0) const; - template - NOD() Decay* SeekUnitAux(const Neat&, Index = 0); - template - NOD() const Decay* SeekUnitAux(const Neat&, Index = 0) const; - - template - NOD() const A::Unit* SeekUnitExt(DMeta, const Neat&, Index = 0) const; - template - NOD() Decay* SeekUnitExt(const Neat&, Index = 0); - template - NOD() const Decay* SeekUnitExt(const Neat&, Index = 0) const; - - template - NOD() const A::Unit* SeekUnitAuxExt(DMeta, const Neat&, const Neat&, Index = 0) const; - template - NOD() Decay* SeekUnitAuxExt(const Neat&, const Neat&, Index = 0); - template - NOD() const Decay* SeekUnitAuxExt(const Neat&, const Neat&, Index = 0) const; - - template - NOD() Trait SeekTrait(TMeta, Index = 0) const; - template - NOD() Trait SeekTrait(Index = 0); - template - NOD() Trait SeekTrait(Index = 0) const; - - template - NOD() Trait SeekTraitAux(const Neat&, TMeta, Index = 0) const; - template - NOD() Trait SeekTraitAux(const Neat&, Index = 0); - template - NOD() Trait SeekTraitAux(const Neat&, Index = 0) const; + template NOD() + auto SeekUnit(DMeta, Index = 0) const -> const A::Unit*; + template NOD() + auto SeekUnit(Index = 0) -> Decay*; + template NOD() + auto SeekUnit(Index = 0) const -> const Decay*; + + template NOD() + auto SeekUnitAux(const Many&, DMeta, Index = 0) const -> const A::Unit*; + template NOD() + auto SeekUnitAux(const Many&, Index = 0) -> Decay*; + template NOD() + auto SeekUnitAux(const Many&, Index = 0) const -> const Decay*; + + template NOD() + auto SeekUnitExt(DMeta, const Many&, Index = 0) const -> const A::Unit*; + template NOD() + auto SeekUnitExt(const Many&, Index = 0) -> Decay*; + template NOD() + auto SeekUnitExt(const Many&, Index = 0) const -> const Decay*; + + template NOD() + auto SeekUnitAuxExt(DMeta, const Many&, const Many&, Index = 0) const -> const A::Unit*; + template NOD() + auto SeekUnitAuxExt(const Many&, const Many&, Index = 0) -> Decay*; + template NOD() + auto SeekUnitAuxExt(const Many&, const Many&, Index = 0) const -> const Decay*; + + template NOD() + auto SeekTrait(TMeta, Index = 0) const -> Trait; + template NOD() + auto SeekTrait(Index = 0) -> Trait; + template NOD() + auto SeekTrait(Index = 0) const -> Trait; + + template NOD() + auto SeekTraitAux(const Many&, TMeta, Index = 0) const -> Trait; + template NOD() + auto SeekTraitAux(const Many&, Index = 0) -> Trait; + template NOD() + auto SeekTraitAux(const Many&, Index = 0) const -> Trait; template bool SeekValue(CT::NotTagged auto&, Index = IndexFirst) const; template - bool SeekValueAux(const Neat&, CT::NotTagged auto&, Index = 0) const; + bool SeekValueAux(const Many&, CT::NotTagged auto&, Index = 0) const; template bool SeekValue(CT::Tagged auto&, Index = IndexFirst) const; template - bool SeekValueAux(const Neat&, CT::Tagged auto&, Index = 0) const; + bool SeekValueAux(const Many&, CT::Tagged auto&, Index = 0) const; - template - NOD() TMany GatherUnits(DMeta) const; - template - NOD() TMany GatherUnits(); - template - NOD() TMany GatherUnits() const; + template NOD() + auto GatherUnits(DMeta) const -> TMany ; + template NOD() + auto GatherUnits() -> TMany; + template NOD() + auto GatherUnits() const -> TMany; - template - NOD() TMany GatherUnitsExt(DMeta, const Neat&) const; - template - NOD() TMany GatherUnitsExt(const Neat&); - template - NOD() TMany GatherUnitsExt(const Neat&) const; + template NOD() + auto GatherUnitsExt(DMeta, const Many&) const -> TMany; + template NOD() + auto GatherUnitsExt(const Many&) -> TMany; + template NOD() + auto GatherUnitsExt(const Many&) const -> TMany; - template - NOD() TraitList GatherTraits(TMeta) const; - template - NOD() TraitList GatherTraits(); - template - NOD() TraitList GatherTraits() const; + template NOD() + auto GatherTraits(TMeta) const -> TraitList; + template NOD() + auto GatherTraits() -> TraitList; + template NOD() + auto GatherTraits() const -> TraitList; #if LANGULUS_FEATURE(MANAGED_REFLECTION) @@ -154,41 +156,41 @@ namespace Langulus::Entity /// Token based interface /// Available only when managed reflection is enabled /// - template - NOD() A::Unit* SeekUnit(const Token&, Index = 0); - template - NOD() const A::Unit* SeekUnit(const Token&, Index = 0) const; - - template - NOD() A::Unit* SeekUnitAux(const Neat&, const Token&, Index = 0); - template - NOD() const A::Unit* SeekUnitAux(const Neat&, const Token&, Index = 0) const; + template NOD() + auto SeekUnit(const Token&, Index = 0) -> A::Unit*; + template NOD() + auto SeekUnit(const Token&, Index = 0) const -> const A::Unit*; + + template NOD() + auto SeekUnitAux(const Many&, const Token&, Index = 0) -> A::Unit*; + template NOD() + auto SeekUnitAux(const Many&, const Token&, Index = 0) const -> const A::Unit*; - template - NOD() Trait SeekTrait(const Token&, Index = 0); - template - NOD() Trait SeekTrait(const Token&, Index = 0) const; + template NOD() + auto SeekTrait(const Token&, Index = 0) -> Trait; + template NOD() + auto SeekTrait(const Token&, Index = 0) const -> Trait; - template - NOD() Trait SeekTraitAux(const Neat&, const Token&, Index = 0); - template - NOD() Trait SeekTraitAux(const Neat&, const Token&, Index = 0) const; + template NOD() + auto SeekTraitAux(const Many&, const Token&, Index = 0) -> Trait; + template NOD() + auto SeekTraitAux(const Many&, const Token&, Index = 0) const -> Trait; template bool SeekValue(const Token&, CT::Data auto&, Index = 0) const; template - bool SeekValueAux(const Token&, const Neat&, CT::Data auto&, Index = 0) const; + bool SeekValueAux(const Token&, const Many&, CT::Data auto&, Index = 0) const; - template - NOD() TMany GatherUnits(const Token&); - template - NOD() TMany GatherUnits(const Token&) const; + template NOD() + auto GatherUnits(const Token&) -> TMany; + template NOD() + auto GatherUnits(const Token&) const -> TMany; - template - NOD() TraitList GatherTraits(const Token&); - template - NOD() TraitList GatherTraits(const Token&) const; + template NOD() + auto GatherTraits(const Token&) -> TraitList; + template NOD() + auto GatherTraits(const Token&) const -> TraitList; #endif }; @@ -219,24 +221,24 @@ namespace Langulus::Entity using SeekInterface::SeekValue; using SeekInterface::SeekValueAux; - template - NOD() A::Unit* SeekUnit(DMeta, Index = 0); - template - NOD() A::Unit* SeekUnitAux(const Neat&, DMeta, Index = 0); - template - NOD() A::Unit* SeekUnitExt(DMeta, const Neat&, Index = 0); - template - NOD() A::Unit* SeekUnitAuxExt(DMeta, const Neat&, const Neat&, Index = 0); + template NOD() + auto SeekUnit(DMeta, Index = 0) -> A::Unit*; + template NOD() + auto SeekUnitAux(const Many&, DMeta, Index = 0) -> A::Unit*; + template NOD() + auto SeekUnitExt(DMeta, const Many&, Index = 0) -> A::Unit*; + template NOD() + auto SeekUnitAuxExt(DMeta, const Many&, const Many&, Index = 0) -> A::Unit*; - template - NOD() Trait SeekTrait(TMeta, Index = 0); - template - NOD() Trait SeekTraitAux(const Neat&, TMeta, Index = 0); + template NOD() + auto SeekTrait(TMeta, Index = 0) -> Trait; + template NOD() + auto SeekTraitAux(const Many&, TMeta, Index = 0) -> Trait; template bool SeekValue(TMeta, CT::Data auto&, Index = 0) const; template - bool SeekValueAux(TMeta, const Neat&, CT::Data auto&, Index = 0) const; + bool SeekValueAux(TMeta, const Many&, CT::Data auto&, Index = 0) const; /// /// Gather @@ -245,16 +247,16 @@ namespace Langulus::Entity using SeekInterface::GatherUnitsExt; using SeekInterface::GatherTraits; - template - NOD() TMany GatherUnitsExt(DMeta, const Neat&); - template - NOD() TMany GatherUnits(DMeta); + template NOD() + auto GatherUnitsExt(DMeta, const Many&) -> TMany; + template NOD() + auto GatherUnits(DMeta) -> TMany; - template - NOD() TraitList GatherTraits(TMeta); + template NOD() + auto GatherTraits(TMeta) -> TraitList; - template - NOD() TMany GatherValues() const; + template NOD() + auto GatherValues() const -> TMany; }; } // namespace Langulus::Entity diff --git a/source/Module.hpp b/source/Module.hpp index 1ad0f2d..53294fd 100644 --- a/source/Module.hpp +++ b/source/Module.hpp @@ -59,18 +59,19 @@ namespace Langulus::A /// External module interface /// class Module : public virtual Resolvable { - LANGULUS(PRODUCER) Entity::Runtime; - LANGULUS(UNINSERTABLE) false; + public: + using Runtime = Entity::Runtime; + LANGULUS(PRODUCER) Runtime; LANGULUS_BASES(Resolvable); private: // Runtime that owns the module instance - Entity::Runtime* mRuntime; + Runtime* mRuntime; public: - Module(Entity::Runtime* runtime) IF_UNSAFE(noexcept) + Module(Runtime* runtime) IF_UNSAFE(noexcept) : Resolvable {this} - , mRuntime {runtime} {} + , mRuntime {runtime} {} Module() noexcept = delete; Module(const Module&) = delete; @@ -94,14 +95,16 @@ namespace Langulus::A }; using EntryFunction = void(*)(DMeta&, MetaList&); - using CreateFunction = Module*(*)(Entity::Runtime*, const Neat&); + using CreateFunction = Module*(*)(Runtime*, const Many&); using InfoFunction = const Info*(*)(); - NOD() Entity::Runtime* GetRuntime() const noexcept { + NOD() auto GetRuntime() const noexcept -> Runtime* { return mRuntime; } public: + virtual void Teardown() = 0; + virtual bool Update(Langulus::Time) { return true; } @@ -151,7 +154,7 @@ namespace Langulus::CT \ LANGULUS_EXPORT() \ ::Langulus::A::Module* LANGULUS_MODULE_CREATE() ( \ - ::Langulus::Entity::Runtime* rt, const ::Langulus::Anyness::Neat& desc) { \ + ::Langulus::Entity::Runtime* rt, const ::Langulus::Anyness::Many& desc) { \ static_assert(::Langulus::CT::DerivedFrom, \ "Langulus module class interface " \ #m " doesn't inherit ::Langulus::A::Module"); \ diff --git a/source/Runtime.cpp b/source/Runtime.cpp index 0c32097..9e855b1 100644 --- a/source/Runtime.cpp +++ b/source/Runtime.cpp @@ -20,12 +20,13 @@ #include "../include/Langulus/Input.hpp" #include "../include/Langulus/Life.hpp" #include "../include/Langulus/Network.hpp" +#include "../include/Langulus/User.hpp" #if LANGULUS_OS(WINDOWS) #include #endif -#if LANGULUS_OS(LINUX) +#if LANGULUS_OS(LINUX) or LANGULUS_COMPILER(WASM) #include #endif @@ -63,12 +64,10 @@ namespace Langulus::Entity void UnloadSharedLibrary(HMODULE library) { FreeLibrary(library); } - #elif LANGULUS_OS(LINUX) + #else void UnloadSharedLibrary(void* library) { dlclose(library); } - #else - #error Unsupported OS #endif /// Runtime construction @@ -76,28 +75,84 @@ namespace Langulus::Entity Runtime::Runtime(Thing* owner) noexcept : mOwner {owner} { VERBOSE(this, ": Initializing..."); + + // Reflect fundamentals + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + + Math::RegisterTraits(); + Math::RegisterVerbs(); + // We always prefer 'type' definitions that are in the main // boundary, to avoid segfaults when unloading libraries from // mModulesByType - it is indexed by a DMeta // So we make sure that the base modules are defined here (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); - (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); (void)MetaDataOf(); (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); (void)MetaDataOf(); (void)MetaDataOf(); + (void)MetaDataOf(); + (void)MetaDataOf(); (void)MetaDataOf(); (void)MetaDataOf(); (void)MetaDataOf(); + + (void)MetaDataOf(); + (void)MetaDataOf(); + VERBOSE(this, ": Initialized"); } @@ -105,8 +160,15 @@ namespace Langulus::Entity Runtime::~Runtime() { VERBOSE(this, ": Shutting down..."); - // Cycle through all libraries N^2 times, unloading anything - // that is no longer in use each time + // First-stage destruction: tear down any potential circular + // references + for (auto list : mModules) { + for (auto& mod : list.mValue) + mod->Teardown(); + } + + // Second-stage destruction: cycle through N libraries N^2 + // times, unloading anything that is no longer in use each time auto attempts = mLibraries.GetCount(); while (attempts) { for (auto library : KeepIterator(mLibraries)) { @@ -119,14 +181,14 @@ namespace Langulus::Entity // If after all attempts there's still active libraries, then // something is definitely not right. This will always result in - // a crash, since we can't really throw inside a destructor + // a crash, since we can't really throw inside a destructor. if (mLibraries) { Logger::Error(this, ": Can't unload last module(s): "); for (auto library : mLibraries) Logger::Append(library.mKey, " "); - Logger::Error(this, ": This likely involves a memory leak, " - "that withholds managed data, reflected by the given modules"); + Logger::Error(this, ": This likely involves a memory leak " + "that withholds managed data reflected by the given modules"); IF_LANGULUS_MANAGED_MEMORY(Allocator::CollectGarbage()); IF_LANGULUS_MEMORY_STATISTICS(Allocator::DumpPools()); @@ -138,7 +200,7 @@ namespace Langulus::Entity /// @param name - module name /// @param descriptor - module initialization descriptor /// @return the new module instance - A::Module* Runtime::InstantiateModule(const Token& name, const Neat& descriptor) { + auto Runtime::InstantiateModule(const Token& name, const Many& descriptor) -> A::Module* { // Load the library if not loaded yet const auto library = LoadSharedLibrary(name); @@ -210,7 +272,7 @@ namespace Langulus::Entity /// @param library - the library handle /// @param descriptor - module initialization descriptor /// @return the new module instance - A::Module* Runtime::InstantiateModule(const SharedLibrary& library, const Neat& descriptor) { + auto Runtime::InstantiateModule(const SharedLibrary& library, const Many& descriptor) -> A::Module* { if (not library.IsValid()) return nullptr; @@ -273,7 +335,7 @@ namespace Langulus::Entity /// the RTTI::Boundary /// @return the module handle (OS dependent) LANGULUS(NOINLINE) - Runtime::SharedLibrary Runtime::LoadSharedLibrary(const Token& name) { + auto Runtime::LoadSharedLibrary(const Token& name) -> SharedLibrary { // Check if this library is already loaded const auto preloaded = mLibraries.FindIt(name); if (preloaded) @@ -290,10 +352,8 @@ namespace Langulus::Entity // File postfix #if LANGULUS_OS(WINDOWS) path += ".dll"; - #elif LANGULUS_OS(LINUX) - path += ".so"; #else - #error Unsupported OS + path += ".so"; #endif // Make sure string ends with terminator @@ -302,10 +362,8 @@ namespace Langulus::Entity // Load the library #if LANGULUS_OS(WINDOWS) const auto dll = LoadLibraryA(path.GetRaw()); - #elif LANGULUS_OS(LINUX) + #else const auto dll = dlopen(path.GetRaw(), RTLD_NOW); - #else - #error Unsupported OS #endif if (not dll) { @@ -331,35 +389,33 @@ namespace Langulus::Entity GetProcAddress(dll, LANGULUS_MODULE_CREATE_TOKEN())); library.mInfo = reinterpret_cast( GetProcAddress(dll, LANGULUS_MODULE_INFO_TOKEN())); - #elif LANGULUS_OS(LINUX) + #else library.mEntry = reinterpret_cast( dlsym(dll, LANGULUS_MODULE_ENTRY_TOKEN())); library.mCreator = reinterpret_cast( dlsym(dll, LANGULUS_MODULE_CREATE_TOKEN())); library.mInfo = reinterpret_cast( dlsym(dll, LANGULUS_MODULE_INFO_TOKEN())); - #else - #error Unsupported OS #endif if (not library.mEntry) { Logger::Error("Module `", path, "` has no valid entry point - ", "the function " LANGULUS_MODULE_ENTRY_TOKEN() " is missing"); - (void)UnloadSharedLibrary(library); + (void) UnloadSharedLibrary(library); return {}; } if (not library.mCreator) { Logger::Error("Module `", path, "` has no valid instantiation point - ", "the function " LANGULUS_MODULE_CREATE_TOKEN() " is missing"); - (void)UnloadSharedLibrary(library); + (void) UnloadSharedLibrary(library); return {}; } if (not library.mInfo) { Logger::Error("Module `", path, "` has no valid information point - ", "the function " LANGULUS_MODULE_INFO_TOKEN() " is missing"); - (void)UnloadSharedLibrary(library); + (void) UnloadSharedLibrary(library); return {}; } @@ -371,8 +427,7 @@ namespace Langulus::Entity MetaList types; library.mEntry(library.mModuleType, types); if (types.IsEmpty()) { - Logger::Error( - "A module must register at least one type" + Logger::Error("A module must register at least one type" " - the module instantiation type"); (void)UnloadSharedLibrary(library); return {}; @@ -413,8 +468,7 @@ namespace Langulus::Entity mLibraries.Insert(name, library); // Do some info logging - Logger::Info( - "Module `", library.mInfo()->mName, + Logger::Info("Module `", library.mInfo()->mName, "` exposed the following types: ", Logger::DarkGreen); bool first = true; for (auto& t : types) { @@ -506,11 +560,9 @@ namespace Langulus::Entity #if LANGULUS_OS(WINDOWS) Entity::UnloadSharedLibrary( reinterpret_cast(library.mHandle)); - #elif LANGULUS_OS(LINUX) + #else Entity::UnloadSharedLibrary( reinterpret_cast(library.mHandle)); - #else - #error Unsupported OS #endif return true; } @@ -518,7 +570,7 @@ namespace Langulus::Entity /// Get the dependency module of a given type /// @param type - the type to search for /// @return the shared library handle, you should check if it's valid - Runtime::SharedLibrary Runtime::GetDependency(DMeta type) const noexcept { + auto Runtime::GetDependency(DMeta type) const noexcept -> SharedLibrary { if (type->mLibraryName == RTTI::MainBoundary) return {}; @@ -532,7 +584,7 @@ namespace Langulus::Entity /// Get a module instance by type /// @param type - the type to search for /// @return the module instance - const ModuleList& Runtime::GetModules(DMeta type) const noexcept { + auto Runtime::GetModules(DMeta type) const noexcept -> const ModuleList& { auto found = mModulesByType.FindIt(type); if (found) return found.GetValue(); @@ -545,14 +597,14 @@ namespace Langulus::Entity /// Get the dependency module of a given type by token /// @param token - type token /// @return the shared library handle, you should check if it's valid - Runtime::SharedLibrary Runtime::GetDependencyToken(const Token& token) const noexcept { + auto Runtime::GetDependencyToken(const Token& token) const noexcept -> SharedLibrary { return GetDependency(RTTI::GetMetaData(token)); } /// Get a module instance by type token /// @param token - type token /// @return the module instance, or nullptr if not found - const ModuleList& Runtime::GetModulesToken(const Token& token) const noexcept { + auto Runtime::GetModulesToken(const Token& token) const noexcept -> const ModuleList& { return GetModules(RTTI::GetMetaData(token)); } #endif @@ -579,7 +631,7 @@ namespace Langulus::Entity /// Get a file interface, relying on external modules to find it /// @param path - the path for the file /// @return the file interface, or nullptr if file doesn't exist - Ref Runtime::GetFile(const Path& path) { + auto Runtime::GetFile(const Path& path) -> Ref { auto& fileSystems = GetModules(); LANGULUS_ASSERT(fileSystems, Module, "Can't retrieve file `", path, "` - no file system module available"); @@ -589,7 +641,7 @@ namespace Langulus::Entity /// Get a folder interface, relying on external modules to find it /// @param path - the path for the folder /// @return the folder interface, or nullptr if folder doesn't exist - Ref Runtime::GetFolder(const Path& path) { + auto Runtime::GetFolder(const Path& path) -> Ref { auto& fileSystems = GetModules(); LANGULUS_ASSERT(fileSystems, Module, "Can't retrieve folder `", path, "` - no file system module available"); @@ -598,7 +650,7 @@ namespace Langulus::Entity /// Get the current working path (where the main exe was executed) /// @return the path - const Path& Runtime::GetWorkingPath() const { + auto Runtime::GetWorkingPath() const -> const Path& { auto& fileSystems = GetModules(); LANGULUS_ASSERT(fileSystems, Module, "Can't retrieve working path", " - no file system module available"); @@ -607,7 +659,7 @@ namespace Langulus::Entity /// Get the current data path, like GetWorkingPath() / "data" /// @return the path - const Path& Runtime::GetDataPath() const { + auto Runtime::GetDataPath() const -> const Path& { auto& fileSystems = GetModules(); LANGULUS_ASSERT(fileSystems, Module, "Can't retrieve data path", " - no file system module available"); diff --git a/source/Runtime.hpp b/source/Runtime.hpp index d6b354b..19543cd 100644 --- a/source/Runtime.hpp +++ b/source/Runtime.hpp @@ -61,12 +61,12 @@ namespace Langulus::Entity /// Explicit abandon construction, for optimized containment /// @param other - the library to abandon SharedLibrary(Abandoned&& other) noexcept - : mHandle {other->mHandle} - , mEntry {other->mEntry} - , mCreator {other->mCreator} - , mInfo {other->mInfo} - , mModuleType {other->mModuleType} - , mBoundary {other->mBoundary} + : mHandle {other->mHandle} + , mEntry {other->mEntry} + , mCreator {other->mCreator} + , mInfo {other->mInfo} + , mModuleType {other->mModuleType} + , mBoundary {other->mBoundary} , mMarkedForUnload {other->mMarkedForUnload} {} /// Check if the shared library handle is valid @@ -98,7 +98,7 @@ namespace Langulus::Entity protected: NOD() LANGULUS_API(ENTITY) - SharedLibrary LoadSharedLibrary(const Token&); + auto LoadSharedLibrary(const Token&) -> SharedLibrary; NOD() bool UnloadSharedLibrary(const SharedLibrary&); public: @@ -113,38 +113,38 @@ namespace Langulus::Entity NOD() auto GetOwner() const noexcept { return mOwner; } NOD() LANGULUS_API(ENTITY) - A::Module* InstantiateModule(const Token&, const Neat& = {}); + auto InstantiateModule(const Token&, const Many& = {}) -> A::Module*; NOD() LANGULUS_API(ENTITY) - A::Module* InstantiateModule(const SharedLibrary&, const Neat& = {}); + auto InstantiateModule(const SharedLibrary&, const Many& = {}) -> A::Module*; NOD() LANGULUS_API(ENTITY) - SharedLibrary GetDependency(DMeta) const noexcept; + auto GetDependency(DMeta) const noexcept -> SharedLibrary; NOD() LANGULUS_API(ENTITY) - const ModuleList& GetModules(DMeta) const noexcept; + auto GetModules(DMeta) const noexcept -> const ModuleList&; - template - NOD() const ModuleList& GetModules() const noexcept { + template NOD() + auto GetModules() const noexcept -> const ModuleList& { return GetModules(MetaDataOf()); } #if LANGULUS_FEATURE(MANAGED_REFLECTION) NOD() LANGULUS_API(ENTITY) - SharedLibrary GetDependencyToken(const Token&) const noexcept; + auto GetDependencyToken(const Token&) const noexcept -> SharedLibrary; NOD() LANGULUS_API(ENTITY) - const ModuleList& GetModulesToken(const Token&) const noexcept; + auto GetModulesToken(const Token&) const noexcept -> const ModuleList&; #endif NOD() LANGULUS_API(ENTITY) - Ref GetFile(const Path&); + auto GetFile(const Path&) -> Ref; NOD() LANGULUS_API(ENTITY) - Ref GetFolder(const Path&); + auto GetFolder(const Path&) -> Ref; NOD() LANGULUS_API(ENTITY) - const Path& GetWorkingPath() const; + auto GetWorkingPath() const -> const Path&; NOD() LANGULUS_API(ENTITY) - const Path& GetDataPath() const; + auto GetDataPath() const -> const Path&; LANGULUS_API(ENTITY) bool Update(Time); diff --git a/source/Thing-Gather.inl b/source/Thing-Gather.inl index a9ce6e2..40e75c3 100644 --- a/source/Thing-Gather.inl +++ b/source/Thing-Gather.inl @@ -9,16 +9,6 @@ #include "Thing.hpp" #include "Hierarchy-Gather.inl" -#if 0 - #define ENTITY_VERBOSE_ENABLED() 1 - #define ENTITY_VERBOSE_SELF(...) Logger::Verbose(Self(), __VA_ARGS__) - #define ENTITY_VERBOSE(...) Logger::Append(__VA_ARGS__) -#else - #define ENTITY_VERBOSE_ENABLED() 0 - #define ENTITY_VERBOSE_SELF(...) LANGULUS(NOOP) - #define ENTITY_VERBOSE(...) LANGULUS(NOOP) -#endif - namespace Langulus::Entity { @@ -37,7 +27,7 @@ namespace Langulus::Entity if (found) { auto& list = mUnitsAmbiguous.GetValue(found); for (auto& unit : list) - result << unit/*.Get()*/; + result << unit; } } @@ -186,7 +176,3 @@ namespace Langulus::Entity } } // namespace Langulus::Entity - -#undef ENTITY_VERBOSE_ENABLED -#undef ENTITY_VERBOSE_SELF -#undef ENTITY_VERBOSE diff --git a/source/Thing-Seek.inl b/source/Thing-Seek.inl index b155c76..fb7bfd0 100644 --- a/source/Thing-Seek.inl +++ b/source/Thing-Seek.inl @@ -9,16 +9,6 @@ #include "Thing.hpp" #include "Hierarchy-Seek.inl" -#if 0 - #define ENTITY_VERBOSE_ENABLED() 1 - #define ENTITY_VERBOSE_SELF(...) Logger::Verbose(Self(), __VA_ARGS__) - #define ENTITY_VERBOSE(...) Logger::Append(__VA_ARGS__) -#else - #define ENTITY_VERBOSE_ENABLED() 0 - #define ENTITY_VERBOSE_SELF(...) LANGULUS(NOOP) - #define ENTITY_VERBOSE(...) LANGULUS(NOOP) -#endif - namespace Langulus::Entity { @@ -29,7 +19,7 @@ namespace Langulus::Entity /// @param offset - which of the matches to return /// @return the found unit, or nullptr if no such unit was found template - A::Unit* Thing::SeekUnit(DMeta meta, Index offset) { + auto Thing::SeekUnit(DMeta meta, Index offset) -> A::Unit* { A::Unit* result = nullptr; if constexpr (SEEK & Seek::Here) { // Seek here if requested @@ -69,7 +59,7 @@ namespace Langulus::Entity /// @param offset - the index of the unit to return /// @return the unit if found, or nullptr otherwise template LANGULUS(INLINED) - A::Unit* Thing::SeekUnitAux(const Neat& aux, DMeta meta, Index offset) { + auto Thing::SeekUnitAux(const Many& aux, DMeta meta, Index offset) -> A::Unit* { A::Unit* result {}; aux.ForEachDeep([&](const A::Unit* unit) { if (unit->CastsTo(meta)) { @@ -99,7 +89,7 @@ namespace Langulus::Entity /// @param offset - the index of the unit to return /// @return the unit if found, or nullptr otherwise template LANGULUS(INLINED) - A::Unit* Thing::SeekUnitExt(DMeta type, const Neat& ext, Index offset) { + auto Thing::SeekUnitExt(DMeta type, const Many& ext, Index offset) -> A::Unit* { A::Unit* result = nullptr; if constexpr (SEEK & Seek::Here) { // Seek here if requested @@ -139,7 +129,7 @@ namespace Langulus::Entity /// @param offset - the Nth match to return /// @return a pointer to the found unit, or nullptr if not found template LANGULUS(INLINED) - A::Unit* Thing::SeekUnitAuxExt(DMeta type, const Neat& aux, const Neat& ext, Index offset) { + auto Thing::SeekUnitAuxExt(DMeta type, const Many& aux, const Many& ext, Index offset) -> A::Unit* { // Scan descriptor even if hierarchy is empty A::Unit* result {}; aux.ForEachDeep([&](const A::Unit* unit) { @@ -170,7 +160,7 @@ namespace Langulus::Entity /// @param offset - the offset to apply /// @return the trait, which is not empty, if trait was found template - Trait Thing::SeekTrait(TMeta meta, Index offset) { + auto Thing::SeekTrait(TMeta meta, Index offset) -> Trait { if constexpr (SEEK & Seek::Here) { // Seek here if requested auto output = GetTrait(meta, offset); @@ -209,7 +199,7 @@ namespace Langulus::Entity /// @param offset - the number of the matching trait to use /// @return the trait, which is not empty, if trait was found template LANGULUS(INLINED) - Trait Thing::SeekTraitAux(const Neat& aux, TMeta meta, Index offset) { + auto Thing::SeekTraitAux(const Many& aux, TMeta meta, Index offset) -> Trait { // Scan descriptor Trait result; aux.ForEachDeep([&](const Trait& trait) { @@ -264,10 +254,6 @@ namespace Langulus::Entity else output = temp.template AsCast(); - /*if constexpr (CT::Pinnable) - output = temp.template AsCast>(); - else - output = temp.template AsCast();*/ return true; } catch (...) { } @@ -305,7 +291,7 @@ namespace Langulus::Entity /// @return true if value has been found and rewritten template LANGULUS(INLINED) bool Thing::SeekValueAux( - TMeta meta, const Neat& aux, CT::Data auto& output, Index offset + TMeta meta, const Many& aux, CT::Data auto& output, Index offset ) const { using D = Deref; @@ -330,7 +316,7 @@ namespace Langulus::Entity // Didn't throw, but we're done only if offset matches done = offset == 0; --offset; - return not done; + return done ? Loop::Break : Loop::Continue; } catch (...) {} } @@ -350,9 +336,9 @@ namespace Langulus::Entity // Didn't throw, but we're done only if offset matches done = offset == 0; --offset; - return not done; + return done ? Loop::Break : Loop::Continue; } - catch(...) { } + catch(...) {} return Loop::Continue; }); @@ -373,8 +359,4 @@ namespace Langulus::Entity return SeekValue(meta, output, offset); } -} // namespace Langulus::Entity - -#undef ENTITY_VERBOSE_ENABLED -#undef ENTITY_VERBOSE_SELF -#undef ENTITY_VERBOSE \ No newline at end of file +} // namespace Langulus::Entity \ No newline at end of file diff --git a/source/Thing-Traits.cpp b/source/Thing-Traits.cpp index 2b5db03..8e0c3e2 100644 --- a/source/Thing-Traits.cpp +++ b/source/Thing-Traits.cpp @@ -9,18 +9,6 @@ #include "Thing.inl" #include "Thing-Seek.inl" -#if 0 - #define ENTITY_VERBOSE_ENABLED() 1 - #define ENTITY_VERBOSE_SELF(...) Logger::Verbose(this, ": ", __VA_ARGS__) - #define ENTITY_VERBOSE_SELF_TAB(...) const auto scoped = Logger::VerboseTab(this, ": ", __VA_ARGS__) - #define ENTITY_VERBOSE(...) Logger::Append(__VA_ARGS__) -#else - #define ENTITY_VERBOSE_ENABLED() 0 - #define ENTITY_VERBOSE_SELF(...) LANGULUS(NOOP) - #define ENTITY_VERBOSE_SELF_TAB(...) LANGULUS(NOOP) - #define ENTITY_VERBOSE(...) LANGULUS(NOOP) -#endif - namespace Langulus::Entity { @@ -29,7 +17,7 @@ namespace Langulus::Entity /// @param trait - trait id /// @param offset - offset of result to use /// @return a filled trait if fount, empty if not - Trait Thing::GetTrait(TMeta trait, Index offset) const { + auto Thing::GetTrait(TMeta trait, Index offset) const -> Trait { return GetTrait(Trait::FromMeta(trait, nullptr), offset); } @@ -37,7 +25,7 @@ namespace Langulus::Entity /// @param trait - trait id /// @param offset - offset of result to use /// @return a filled trait if fount, empty if not - Trait Thing::GetTrait(TMeta trait, Index offset) { + auto Thing::GetTrait(TMeta trait, Index offset) -> Trait { return GetTrait(Trait::FromMeta(trait, nullptr), offset); } @@ -45,7 +33,7 @@ namespace Langulus::Entity /// @param id - the trait to search for /// @param index - the index of the trait we seek /// @return a pointer to the trait, or nullptr if not found - Trait* Thing::GetLocalTrait(TMeta id, Index index) { + auto Thing::GetLocalTrait(TMeta id, Index index) -> Trait* { if (id) { // Search a typed trait const auto found = mTraits.FindIt(id); @@ -76,7 +64,7 @@ namespace Langulus::Entity /// @param id - the trait to search for /// @param offset - the index of the trait we seek /// @return a pointer to the trait, or nullptr if not found - const Trait* Thing::GetLocalTrait(TMeta id, Index offset) const { + auto Thing::GetLocalTrait(TMeta id, Index offset) const -> const Trait* { return const_cast(*this).GetLocalTrait(id, offset); } @@ -84,7 +72,7 @@ namespace Langulus::Entity /// @param id - trait to match /// @param index - offset of result to use /// @return a non-empty trait, if found - Trait Thing::GetTrait(const Trait& id, Index index) { + auto Thing::GetTrait(const Trait& id, Index index) -> Trait { if (id.GetTrait()) { // Handle some predefined traits here if (id.template IsTrait()) { @@ -124,14 +112,14 @@ namespace Langulus::Entity /// @param id - trait to match /// @param index - offset of result to use /// @return a non-empty trait, if found - Trait Thing::GetTrait(const Trait& id, Index index) const { + auto Thing::GetTrait(const Trait& id, Index index) const -> Trait { return const_cast(this)->GetTrait(id, index); } /// Add a new trait to the thing /// @param trait - trait to shallow copy /// @return the new trait instance - Trait* Thing::AddTrait(Trait trait) { + auto Thing::AddTrait(Trait trait) -> Trait* { const auto tmeta = trait.GetTrait(); auto found = mTraits.FindIt(tmeta); if (found) { @@ -148,7 +136,7 @@ namespace Langulus::Entity /// Remove a trait from the universal entity /// @param trait - type of trait to remove /// @return the number of removed traits - Count Thing::RemoveTrait(TMeta trait) { + auto Thing::RemoveTrait(TMeta trait) -> Count { const auto found = mTraits.FindIt(trait); if (found) { const auto removed = found.GetValue().GetCount(); @@ -164,7 +152,7 @@ namespace Langulus::Entity /// Remove an exact-matching trait from this entity /// @param trait - type and value to remove /// @return the number of removed traits - Count Thing::RemoveTrait(Trait trait) { + auto Thing::RemoveTrait(Trait trait) -> Count { const auto found = mTraits.FindIt(trait.GetTrait()); if (found) { const auto removed = found.GetValue().Remove(trait); @@ -181,7 +169,7 @@ namespace Langulus::Entity /// A fast check whether traits of the given type are inside this entity /// @param trait - type of trait to check /// @return the number of matching traits - Count Thing::HasTraits(TMeta trait) const { + auto Thing::HasTraits(TMeta trait) const -> Count { const auto found = mTraits.FindIt(trait); return found ? found.GetValue().GetCount() : 0; } @@ -189,7 +177,7 @@ namespace Langulus::Entity /// A fast check whether traits of the given type and value are inside /// @param trait - trait to search for /// @return the number of matching traits - Count Thing::HasTraits(const Trait& trait) const { + auto Thing::HasTraits(const Trait& trait) const -> Count { const auto found = mTraits.FindIt(trait.GetTrait()); if (not found) return 0; @@ -205,7 +193,7 @@ namespace Langulus::Entity /// Get traits /// @return the map of traits LANGULUS_API(ENTITY) - const TraitMap& Thing::GetTraits() const noexcept { + auto Thing::GetTraits() const noexcept -> const TraitMap& { return mTraits; } diff --git a/source/Thing-Verbs.cpp b/source/Thing-Verbs.cpp index 5772558..6885dea 100644 --- a/source/Thing-Verbs.cpp +++ b/source/Thing-Verbs.cpp @@ -8,54 +8,41 @@ #include "Thing.hpp" #include "Thing.inl" #include - -#if 0 - #define ENTITY_VERBOSE_ENABLED() 1 - #define ENTITY_VERBOSE_SELF(...) Logger::Verbose(this, ": ", __VA_ARGS__) - #define ENTITY_VERBOSE_SELF_TAB(...) const auto scoped = Logger::VerboseTab(this, ": ", __VA_ARGS__) - #define ENTITY_VERBOSE(...) Logger::Append(__VA_ARGS__) - #define ENTITY_CREATION_VERBOSE_SELF(...) Logger::Verbose(Self(), __VA_ARGS__) - #define ENTITY_SELECTION_VERBOSE_SELF(...) Logger::Verbose(Self(), __VA_ARGS__) -#else - #define ENTITY_VERBOSE_ENABLED() 0 - #define ENTITY_VERBOSE_SELF(...) LANGULUS(NOOP) - #define ENTITY_VERBOSE_SELF_TAB(...) LANGULUS(NOOP) - #define ENTITY_VERBOSE(...) LANGULUS(NOOP) - #define ENTITY_CREATION_VERBOSE_SELF(...) LANGULUS(NOOP) - #define ENTITY_SELECTION_VERBOSE_SELF(...) LANGULUS(NOOP) -#endif +#include namespace Langulus::Entity { - /// Find an AIAD component that can process speech and interpret using it - /// This function completely relies on external modules + /// Interpret and execute a natural message wherever possible in the + /// current context /// @param text - text to execute /// @return the results of the execution - Many Thing::Run(const Lingua& text) { + Many Thing::Say(const Text& text) { if (not text) return {}; - // Message is still contextless, we don't know where exactly to - // interpret it, so create message objects from the hierarchy, - // and try interpreting those to executable temporals - // Each trained AI in the hierarchy will produce its own - // interpretation - auto messages = CreateData( - Construct::From(static_cast(text))); - - Verbs::InterpretAs interpreter; - if (not Flow::DispatchFlat(messages, interpreter)) { - Logger::Error("Messages failed to interpret to temporal: ", messages); + // Get minds from the current context + auto minds = GatherUnits(); + if (not minds) { + Logger::Error(this, ": No minds - can't interpret message: ", text); + return {}; + } + + // Get a flow for executing the interpreted messages + auto flow = GetFlow(); + if (not flow) { + Logger::Error(this, ": No flow - can't execute message: ", text); return {}; } - // Execute the resulting scopes + // Interpret by each mind and then execute in flow Many results; - interpreter->ForEach([&](const Flow::Temporal& scope) { - results << Resolvable::Run(scope); - }); + for (auto& mind : minds) { + auto interpretation = mind->Interpret(text); + if (interpretation) + results << flow->Push(interpretation); + } return Abandon(results); } @@ -80,23 +67,6 @@ namespace Langulus::Entity } return flow->Push(Verbs::Do::In(this, Abandon(parsed))); - - /*if (not flow->Push(Verbs::Do::In(this, Abandon(parsed)))) { - // Couldn't push verbs - the flow probably has no future link - // points, or we're out of memory? - Logger::Error(this, ": Flow ", *flow, " couldn't Run code: ", code); - return {}; - } - - // Flow has changed, update it as if no time has passed, in order - // to execute any newly added parts, if in the proper time - // context. Anything produced as a side-effect will be returned. - // @attention, if you push a command that has time context before - // the current flow time, you'll be technically rewriting this - // thing's history - the entire timeline will be reverted back, - // and recomputed up to now (if that's possible). - flow->Update({}); - return {};*/ } /// Custom dispatcher, reflected via CT::Dispatcher @@ -173,13 +143,13 @@ namespace Langulus::Entity for (auto& unit : selectedUnits) { bool localMismatch = false; auto unitBlock = unit->GetBlock(); - construct.GetDescriptor().ForEach( + construct->ForEach( [&](const Many& part) { for (Offset i = 0; i < part.GetCount(); ++i) { auto element = part.GetElementResolved(i); Verbs::Select selector {element}; if (not Flow::DispatchFlat(unitBlock, selector)) { - // Abort on first failure + // Abort on first failure localMismatch = true; return Loop::Break; } diff --git a/source/Thing.cpp b/source/Thing.cpp index 72a3d32..fb09fbd 100644 --- a/source/Thing.cpp +++ b/source/Thing.cpp @@ -8,30 +8,20 @@ #include "Thing.hpp" #include "Thing.inl" -#if 0 - #define ENTITY_VERBOSE_ENABLED() 1 - #define ENTITY_VERBOSE_SELF(...) Logger::Info(this, ": ", __VA_ARGS__) - #define ENTITY_VERBOSE_SELF_TAB(...) const auto scoped = Logger::InfoTab(this, ": ", __VA_ARGS__) - #define ENTITY_VERBOSE(...) Logger::Append(__VA_ARGS__) -#else - #define ENTITY_VERBOSE_ENABLED() 0 - #define ENTITY_VERBOSE_SELF(...) LANGULUS(NOOP) - #define ENTITY_VERBOSE_SELF_TAB(...) LANGULUS(NOOP) - #define ENTITY_VERBOSE(...) LANGULUS(NOOP) -#endif - namespace Langulus::Entity { /// Default-constructor, always creates a parentless root thing Thing::Thing() : Resolvable {this} { - ENTITY_VERBOSE_SELF("Created (root, ", Reference(0), " references)"); + ENTITY_VERBOSE_SELF("Created (root, ", GetReferences(), " references)"); } /// Descriptor-constructor /// @param describe - instructions for creating the entity Thing::Thing(Describe&& describe) : Resolvable {this} { + ENTITY_VERBOSE_SELF_TAB("Created from descriptor: ", *describe); + if (*describe) { Verbs::Create creator {&(*describe)}; Create(creator); @@ -40,13 +30,13 @@ namespace Langulus::Entity if (mOwner) { ENTITY_VERBOSE_SELF( "Created as child to ", mOwner, - " (", Reference(0), " references; parent now has ", - mOwner->Reference(0), " references)" + " (", GetReferences(), " references; parent now has ", + mOwner->GetReferences(), " references)" ); } else { ENTITY_VERBOSE_SELF( - "Created (root, ", Reference(0), " references)" + "Created (root, ", GetReferences(), " references)" ); } } @@ -54,9 +44,12 @@ namespace Langulus::Entity /// Construct as a child of another thing /// @param parent - the thing that owns this thing /// @param descriptor - instructions for creating the thing - Thing::Thing(Thing* parent, const Neat& descriptor) + Thing::Thing(Thing* parent, const Many& descriptor) : Resolvable {this} - , mOwner {parent} { + , mOwner {parent} + { + ENTITY_VERBOSE_SELF_TAB("Created manually"); + if (parent) { parent->AddChild(this); mRuntime = parent->GetRuntime(); @@ -65,20 +58,20 @@ namespace Langulus::Entity if (descriptor) { // Create any subthings/traits/unit in this thing - Verbs::Create creator {&descriptor}; + Verbs::Create creator {descriptor}; Create(creator); } if (mOwner) { ENTITY_VERBOSE_SELF( "Created as child to ", mOwner, - " (", Reference(0), " references; parent now has ", - mOwner->Reference(0), " references)" + " (", GetReferences(), " references; parent now has ", + mOwner->GetReferences(), " references)" ); } else { ENTITY_VERBOSE_SELF( - "Created (root, ", Reference(0), " references)" + "Created (root, ", GetReferences(), " references)" ); } } @@ -89,14 +82,15 @@ namespace Langulus::Entity /// because 'other' is removed from its children /// @param other - move that entity Thing::Thing(Thing&& other) noexcept - : Resolvable {this} - , mChildren {Move(other.mChildren)} - , mRuntime {Move(other.mRuntime)} - , mFlow {Move(other.mFlow)} + : Resolvable {this} + , mRuntime {Move(other.mRuntime)} + , mFlow {Move(other.mFlow)} + , mChildren {Move(other.mChildren)} + , mUnitsList {Move(other.mUnitsList)} , mUnitsAmbiguous {Move(other.mUnitsAmbiguous)} - , mUnitsList {Move(other.mUnitsList)} - , mTraits {Move(other.mTraits)} - , mRefreshRequired {true} { + , mTraits {Move(other.mTraits)} + , mRefreshRequired{true} + { // Remap children for (auto& child : mChildren) child->mOwner = this; @@ -109,7 +103,7 @@ namespace Langulus::Entity if (other.mOwner) other.mOwner->RemoveChild(&other); - ENTITY_VERBOSE_SELF("moved from ", other); + ENTITY_VERBOSE_SELF("Moved from ", other); } /// Abandon constructor @@ -118,14 +112,15 @@ namespace Langulus::Entity /// because 'other' is duplicated in its children /// @param other - clone that entity Thing::Thing(Abandoned&& other) - : Resolvable {this} - , mChildren {Abandon(other->mChildren)} - , mRuntime {Abandon(other->mRuntime)} - , mFlow {Abandon(other->mFlow)} + : Resolvable {this} + , mRuntime {Abandon(other->mRuntime)} + , mFlow {Abandon(other->mFlow)} + , mChildren {Abandon(other->mChildren)} + , mUnitsList {Abandon(other->mUnitsList)} , mUnitsAmbiguous {Abandon(other->mUnitsAmbiguous)} - , mUnitsList {Abandon(other->mUnitsList)} - , mTraits {Abandon(other->mTraits)} - , mRefreshRequired {true} { + , mTraits {Abandon(other->mTraits)} + , mRefreshRequired{true} + { // Remap children for (auto& child : mChildren) child->mOwner = this; @@ -138,7 +133,7 @@ namespace Langulus::Entity if (other->mOwner) other->mOwner->RemoveChild(&*other); - ENTITY_VERBOSE_SELF("abandoned from ", *other); + ENTITY_VERBOSE_SELF("Abandoned from ", *other); } /// Clone constructor @@ -147,52 +142,96 @@ namespace Langulus::Entity /// because 'other' is duplicated in its children /// @param other - clone that entity Thing::Thing(Cloned&& other) - : Resolvable {this} - , mChildren {Clone(other->mChildren)} - , mRefreshRequired {true} { + : Resolvable {this} + , mChildren {Clone(other->mChildren)} + , mRefreshRequired{true} + { TODO(); //TODO clone flow and runtime if pinned, recreate modules if new runtime, // recreate units and traits, then recreate children - ENTITY_VERBOSE_SELF("cloned from ", *other); - } + ENTITY_VERBOSE_SELF("Cloned from ", *other); + } + + /// Destroy the thing + Thing::~Thing() { + // First stage destruction that severs all connections + // If Thing was on the stack, this will be the first time it's + // called. If it was on the managed heap, it would've been called + // from the Reference routine + Teardown(); + + LANGULUS_ASSUME(DevAssumes, GetReferences() <= 1, + "Can't teardown while this Thing is still used", " in ", + GetReferences(), " places" + ); + + // Destroy the entire herarchy under this Thing + ENTITY_VERBOSE_SELF_TAB("Destroying..."); + + #if ENTITY_VERBOSE_ENABLED() + for (auto& child : mChildren) { + if (child->GetReferences() != 1) { + Logger::Warning( + child, " can't be destroyed yet - has ", + child->GetReferences(), " uses instead of 1" + ); + } + } - /// Destructor - Thing::~Thing() IF_UNSAFE(noexcept) { - Detach(); + for (auto& unit : mUnitsList) { + if (unit->GetReferences() > 3) { + Logger::Warning( + unit, " can't be destroyed yet - has ", + unit->GetReferences(), " uses instead of 3 (or less)" + ); + } + } + #endif } - - /// A nested call to detach all parents of all children - void Thing::Detach() { - ENTITY_VERBOSE_SELF_TAB("Destroying (", Reference(0), " uses):"); - if (not mRuntime.IsLocked()) - mRuntime.Reset(); - if (not mFlow.IsLocked()) - mFlow.Reset(); + /// This is used for first-stage destruction, severing ties to avoid + /// circular dependencies. After this runs, there should be only one + /// reference remaining for this Thing + void Thing::Teardown() { + ENTITY_VERBOSE_SELF_TAB( + "Teardown initiated at ", GetReferences(), " uses..."); - mTraits.Reset(); + // Reset owner, so that only one reference to this Thing remains + // in the hierarchy: the owner's mChildren + mOwner.Reset(); - // Decouple all children from this - for (auto& child : mChildren) { - if (child->mOwner) { - ENTITY_VERBOSE_SELF("Decoupling child: ", child); - LANGULUS_ASSUME(DevAssumes, - child->mOwner == this, "Parent mismatch"); - child->mOwner.Reset(); - child->Detach(); - ENTITY_VERBOSE_SELF("...", Reference(0), " uses remain"); - } - } + // Traits might be exposing members in units. Make sure we + // dereference those first, so that units have as small number of + // references as possible + ENTITY_VERBOSE_SELF("Tearing off traits (name might change)"); + mTraits.Reset(); - // Decouple all units from this owner + // Decouple all units from this owner because units might get + // destroyed upon destroying mUnitsList and mUnitsAmbiguous, if + // the Units were created on the stack. + // If they still have owners, they will attempt to Decouple in + // A::Unit::~Unit from already destroyed mUnitsList/Ambiguous + mUnitsAmbiguous.Reset(); for (auto& unit : mUnitsList) { - ENTITY_VERBOSE_SELF("Decoupling unit: ", unit); - unit->mOwners.Reset(); - ENTITY_VERBOSE_SELF("...", Reference(0), " uses remain"); + ENTITY_VERBOSE_SELF( + "Tearing off unit ", unit, " at ", unit->GetReferences(), " uses..."); + unit->mOwners.Remove(this); + + if (unit->mOwners.IsEmpty()) + unit->mOwners.Reset(); } - mUnitsAmbiguous.Reset(); - mUnitsList.Reset(); + // Propagate Teardown through the hierarchy of Things + for (auto& child : mChildren) + child->Teardown(); + + if (not mFlow.IsLocked()) + mFlow.Reset(); + + if (not mRuntime.IsLocked()) + mRuntime.Reset(); + + ENTITY_VERBOSE_SELF("Teardown complete: ", GetReferences(), " uses remain"); } /// Compare two entities @@ -215,24 +254,28 @@ namespace Langulus::Entity /// Dump the entity's hierarchy in log void Thing::DumpHierarchy() const { - const auto tab = Logger::VerboseTab("** ", *this); + const auto tab = Logger::Verbose( + Logger::White, Logger::Underline, *this, Logger::Tabs {}); if (mTraits) { - Logger::Verbose(".. contains ", mTraits.GetCount(), " traits:"); + const auto tab2 = Logger::Section(Logger::White, Logger::Underline, + "Traits (", mTraits.GetCount(), "):"); for (auto traitpair : mTraits) { for (auto& trait : traitpair.mValue) - Logger::Verbose(". ", trait); + Logger::Verbose(trait); } } if (mUnitsList) { - Logger::Verbose("++ contains ", mUnitsList.GetCount(), " units:"); + const auto tab2 = Logger::Section(Logger::White, Logger::Underline, + "Units (", mUnitsList.GetCount(), "):"); for (auto& unit : mUnitsList) - Logger::Verbose("+ ", *unit); + Logger::Verbose(*unit); } if (mChildren) { - Logger::Verbose("** contains ", mChildren.GetCount(), " child entities:"); + const auto tab2 = Logger::Section(Logger::White, Logger::Underline, + "Children (", mChildren.GetCount(), "):"); for (auto& child : mChildren) child->DumpHierarchy(); } @@ -312,7 +355,7 @@ namespace Langulus::Entity /// @param id - the type of the unit /// @param index - the unit index to seek /// @return the unit if found, or nullptr if not - A::Unit* Thing::GetUnitMeta(DMeta id, Index index) { + auto Thing::GetUnitMeta(DMeta id, Index index) -> A::Unit* { if (id) { // Search a typed trait const auto found = mUnitsAmbiguous.FindIt(id); @@ -323,7 +366,7 @@ namespace Langulus::Entity return mUnitsList[index]; } - const A::Unit* Thing::GetUnitMeta(DMeta type, Index offset) const { + auto Thing::GetUnitMeta(DMeta type, Index offset) const -> const A::Unit* { return const_cast(this)->GetUnitMeta(type, offset); } @@ -334,7 +377,7 @@ namespace Langulus::Entity /// @param what - the desired properties of the unit /// @param index - the unit index to seek /// @return the unit if found, or nullptr if not - A::Unit* Thing::GetUnitExt(DMeta meta, const Neat& what, Index index) { + auto Thing::GetUnitExt(DMeta meta, const Many& what, Index index) -> A::Unit* { if (meta) { // Search a typed unit const auto found = mUnitsAmbiguous.FindIt(meta); @@ -367,7 +410,7 @@ namespace Langulus::Entity return nullptr; } - const A::Unit* Thing::GetUnitExt(DMeta meta, const Neat& what, Index index) const { + auto Thing::GetUnitExt(DMeta meta, const Many& what, Index index) const -> const A::Unit* { return const_cast(this)->GetUnitExt(meta, what, index); } @@ -376,31 +419,31 @@ namespace Langulus::Entity /// @param token - the type name of the unit /// @param offset - the unit index /// @return the unit if found, or nullptr if not - A::Unit* Thing::GetUnitMeta(const Token& token, Index offset) { + auto Thing::GetUnitMeta(const Token& token, Index offset) -> A::Unit* { return GetUnitMeta(RTTI::DisambiguateMeta(token), offset); } #endif /// Get the owner /// @return the owner - const Ref& Thing::GetOwner() const noexcept { + auto Thing::GetOwner() const noexcept -> const Ref& { return mOwner; } /// Get children hierarchy /// @return the hierarchy - const Hierarchy& Thing::GetChildren() const noexcept { + auto Thing::GetChildren() const noexcept -> const Hierarchy& { return mChildren; } /// Get a child by index /// @param id - the index to pick /// @return the child entity, or nullptr of none was found - Thing* Thing::GetChild(Index offset) { + auto Thing::GetChild(Index offset) -> Thing* { return mChildren[offset]; } - const Thing* Thing::GetChild(Index offset) const { + auto Thing::GetChild(Index offset) const -> const Thing* { return const_cast(this)->GetChild(offset); } @@ -408,7 +451,7 @@ namespace Langulus::Entity /// @param name - name to seek /// @param offset - offset to seek /// @return the child entity, or nullptr of none was found - Thing* Thing::GetNamedChild(const Token& name, Index offset) { + auto Thing::GetNamedChild(const Token& name, Index offset) -> Thing* { Index matches = 0; for (auto& child : mChildren) { if (child->GetName() == name) { @@ -421,7 +464,7 @@ namespace Langulus::Entity return nullptr; } - const Thing* Thing::GetNamedChild(const Token& name, Index offset) const { + auto Thing::GetNamedChild(const Token& name, Index offset) const -> const Thing* { return const_cast(this)->GetNamedChild(name, offset); } @@ -452,7 +495,7 @@ namespace Langulus::Entity /// Count the number of matching units in this entity /// @param type - the type of units to search for /// @return the number of matching units - Count Thing::HasUnits(DMeta type) const { + auto Thing::HasUnits(DMeta type) const -> Count { const auto found = mUnitsAmbiguous.FindIt(type); return found ? found.GetValue().GetCount() : 0; } @@ -465,19 +508,19 @@ namespace Langulus::Entity /// Get the current runtime /// @return the pointer to the runtime - const Pin>& Thing::GetRuntime() const noexcept { + auto Thing::GetRuntime() const noexcept -> const Pin>& { return mRuntime; } /// Get the current temporal flow /// @return the pointer to the flow - const Pin>& Thing::GetFlow() const noexcept { + auto Thing::GetFlow() const noexcept -> const Pin>& { return mFlow; } /// Create a local runtime for this thing /// @return the new runtime instance, or the old one if already created - Runtime* Thing::CreateRuntime() { + auto Thing::CreateRuntime() -> Runtime* { if (mRuntime.IsLocked()) return &*mRuntime; @@ -494,7 +537,7 @@ namespace Langulus::Entity /// Create a local flow for this thing /// @return the new flow instance, or the old one, if already created - Temporal* Thing::CreateFlow() { + auto Thing::CreateFlow() -> Temporal* { if (mFlow.IsLocked()) return &*mFlow; @@ -515,7 +558,7 @@ namespace Langulus::Entity /// @param module - name of the module /// @param descriptor - instructions for module setup /// @return the instantiated module interface - A::Module* Thing::LoadMod(const Token& module, const Neat& descriptor) { + auto Thing::LoadMod(const Token& module, const Many& descriptor) -> A::Module* { const auto runtime = GetRuntime(); LANGULUS_ASSUME(UserAssumes, runtime, "No runtime available for loading a module"); diff --git a/source/Thing.hpp b/source/Thing.hpp index cb4c098..a176764 100644 --- a/source/Thing.hpp +++ b/source/Thing.hpp @@ -22,20 +22,10 @@ LANGULUS_DEFINE_TRAIT(Unit, namespace Langulus::Entity { - using UnitList = TMany;// Ref> ; - using UnitMap = TUnorderedMap>;// Ref> > ; + using UnitList = TMany; + using UnitMap = TUnorderedMap>; using TraitMap = TUnorderedMap; - /// A text specialization, dedicated for natural language text - /// It is a placeholder type, that can be extended by external modules - struct Lingua : Text { - LANGULUS(ABSTRACT) true; - LANGULUS_CONVERTS_FROM(); - - private: - using Text::SerializationRules; - }; - /// /// Thing @@ -51,27 +41,26 @@ namespace Langulus::Entity { LANGULUS(ABSTRACT) false; LANGULUS(PRODUCER) Thing; - LANGULUS(UNINSERTABLE) false; + LANGULUS(POOL_TACTIC) RTTI::PoolTactic::Type; LANGULUS_BASES(Resolvable); LANGULUS_VERBS(Verbs::Create, Verbs::Select); - LANGULUS(POOL_TACTIC) RTTI::PoolTactic::Type; protected: LANGULUS_API(ENTITY) void ResetRuntime(Runtime*); LANGULUS_API(ENTITY) void ResetFlow(Temporal*); + LANGULUS_API(ENTITY) void Teardown(); // The order of members is critical! - // Hierarchy should be destroyed last, hence it is the first - // member - Hierarchy mChildren; - // Runtime + // Runtime should be destroyed last, hence it is the first member Pin> mRuntime; // Temporal flow Pin> mFlow; - // Units indexed by all their relevant reflected bases - UnitMap mUnitsAmbiguous; + // Hierarchy + Hierarchy mChildren; // Units indexed by concrete type, in order of addition UnitList mUnitsList; + // Units indexed by all their relevant reflected bases + UnitMap mUnitsAmbiguous; // Traits TraitMap mTraits; // Hierarchy requires an update @@ -88,18 +77,15 @@ namespace Langulus::Entity public: LANGULUS_API(ENTITY) Thing(); LANGULUS_API(ENTITY) Thing(Describe&&); - LANGULUS_API(ENTITY) Thing(Thing*, const Neat& = {}); + LANGULUS_API(ENTITY) Thing(Thing*, const Many& = {}); LANGULUS_API(ENTITY) Thing(Thing&&) noexcept; LANGULUS_API(ENTITY) Thing(Cloned&&); LANGULUS_API(ENTITY) Thing(Abandoned&&); - - LANGULUS_API(ENTITY) ~Thing() IF_UNSAFE(noexcept); + LANGULUS_API(ENTITY)~Thing(); template NOD() static Thing Root(CT::String auto&&...); - void Detach(); - // Shallow copy is disabled, you should be able only to clone, // move, or abandon Thing(const Thing&) = delete; @@ -109,10 +95,10 @@ namespace Langulus::Entity bool RequiresRefresh() const noexcept; NOD() LANGULUS_API(ENTITY) - const Pin>& GetRuntime() const noexcept; + auto GetRuntime() const noexcept -> const Pin>&; NOD() LANGULUS_API(ENTITY) - const Pin>& GetFlow() const noexcept; + auto GetFlow() const noexcept -> const Pin>&; LANGULUS_API(ENTITY) void Do(Verb&); LANGULUS_API(ENTITY) void Select(Verb&); @@ -123,7 +109,7 @@ namespace Langulus::Entity template V& Run(V&); - LANGULUS_API(ENTITY) Many Run(const Lingua&); + LANGULUS_API(ENTITY) Many Say(const Text&); LANGULUS_API(ENTITY) Many Run(const Code&); LANGULUS_API(ENTITY) bool Update(Time); @@ -141,13 +127,13 @@ namespace Langulus::Entity /// Hierarchy management /// LANGULUS_API(ENTITY) - Runtime* CreateRuntime(); + auto CreateRuntime() -> Runtime*; LANGULUS_API(ENTITY) - Temporal* CreateFlow(); + auto CreateFlow() -> Temporal*; template - Ref CreateChild(T&&...); + auto CreateChild(T&&...) -> Ref; template Count AddChild(Thing*); @@ -155,25 +141,25 @@ namespace Langulus::Entity Count RemoveChild(Thing*); LANGULUS_API(ENTITY) - A::Module* LoadMod(const Token&, const Neat& = {}); + auto LoadMod(const Token&, const Many& = {}) -> A::Module*; NOD() LANGULUS_API(ENTITY) - const Ref& GetOwner() const noexcept; + auto GetOwner() const noexcept -> const Ref&; NOD() LANGULUS_API(ENTITY) - const Hierarchy& GetChildren() const noexcept; + auto GetChildren() const noexcept -> const Hierarchy&; NOD() LANGULUS_API(ENTITY) - Thing* GetChild(Index = 0); + auto GetChild(Index = 0) -> Thing*; NOD() LANGULUS_API(ENTITY) - const Thing* GetChild(Index = 0) const; + auto GetChild(Index = 0) const -> const Thing*; NOD() LANGULUS_API(ENTITY) - Thing* GetNamedChild(const Token&, Index = 0); + auto GetNamedChild(const Token&, Index = 0) -> Thing*; NOD() LANGULUS_API(ENTITY) - const Thing* GetNamedChild(const Token&, Index = 0) const; + auto GetNamedChild(const Token&, Index = 0) const -> const Thing*; LANGULUS_API(ENTITY) void DumpHierarchy() const; @@ -187,13 +173,13 @@ namespace Langulus::Entity template Count RemoveUnit(A::Unit*); - template + template Many CreateUnit(A&&...); - template + template Many CreateUnits(); #if LANGULUS_FEATURE(MANAGED_REFLECTION) - template + template Many CreateUnitToken(const Token&, A&&...); #endif @@ -201,40 +187,38 @@ namespace Langulus::Entity Count RemoveUnits(); NOD() LANGULUS_API(ENTITY) - Count HasUnits(DMeta) const; - - template - NOD() Count HasUnits() const; + auto HasUnits(DMeta) const -> Count; + template NOD() + auto HasUnits() const -> Count; NOD() LANGULUS_API(ENTITY) - const UnitList& GetUnits() const noexcept; + auto GetUnits() const noexcept -> const UnitList&; NOD() LANGULUS_API(ENTITY) - const UnitMap& GetUnitsMap() const noexcept; + auto GetUnitsMap() const noexcept -> const UnitMap&; NOD() LANGULUS_API(ENTITY) - A::Unit* GetUnitMeta(DMeta, Index = 0); + auto GetUnitMeta(DMeta, Index = 0) -> A::Unit*; NOD() LANGULUS_API(ENTITY) - const A::Unit* GetUnitMeta(DMeta, Index = 0) const; + auto GetUnitMeta(DMeta, Index = 0) const -> const A::Unit*; NOD() LANGULUS_API(ENTITY) - A::Unit* GetUnitExt(DMeta, const Neat&, Index = 0); + auto GetUnitExt(DMeta, const Many&, Index = 0) -> A::Unit*; NOD() LANGULUS_API(ENTITY) - const A::Unit* GetUnitExt(DMeta, const Neat&, Index = 0) const; + auto GetUnitExt(DMeta, const Many&, Index = 0) const -> const A::Unit*; - template - NOD() Decay* GetUnit(Index = 0); - template - NOD() const Decay* GetUnit(Index = 0) const; + template NOD() + auto GetUnit(Index = 0) -> Decay*; + template NOD() + auto GetUnit(Index = 0) const -> const Decay*; #if LANGULUS_FEATURE(MANAGED_REFLECTION) NOD() LANGULUS_API(ENTITY) - A::Unit const* GetUnitMeta(const Token&, Index = 0) const; - + auto GetUnitMeta(const Token&, Index = 0) const -> A::Unit const*; NOD() LANGULUS_API(ENTITY) - A::Unit* GetUnitMeta(const Token&, Index = 0); + auto GetUnitMeta(const Token&, Index = 0) -> A::Unit*; - template - NOD() Decay* GetUnitAs(const Token&, Index = 0); + template NOD() + auto GetUnitAs(const Token&, Index = 0) -> Decay*; #endif private: @@ -245,45 +229,37 @@ namespace Langulus::Entity /// /// Trait management /// - LANGULUS_API(ENTITY) Trait* AddTrait(Trait); + LANGULUS_API(ENTITY) auto AddTrait(Trait) -> Trait*; LANGULUS_API(ENTITY) Count RemoveTrait(TMeta); LANGULUS_API(ENTITY) Count RemoveTrait(Trait); NOD() LANGULUS_API(ENTITY) Count HasTraits(TMeta) const; - NOD() LANGULUS_API(ENTITY) Count HasTraits(const Trait&) const; NOD() LANGULUS_API(ENTITY) - const TraitMap& GetTraits() const noexcept; - + auto GetTraits() const noexcept -> const TraitMap&; NOD() LANGULUS_API(ENTITY) - Trait GetTrait(TMeta, Index = 0) const; - + auto GetTrait(TMeta, Index = 0) const -> Trait; NOD() LANGULUS_API(ENTITY) - Trait GetTrait(TMeta, Index = 0); - + auto GetTrait(TMeta, Index = 0) -> Trait; NOD() LANGULUS_API(ENTITY) - Trait GetTrait(const Trait&, Index = 0) const; - + auto GetTrait(const Trait&, Index = 0) const -> Trait; NOD() LANGULUS_API(ENTITY) - Trait GetTrait(const Trait&, Index = 0); - - template - NOD() Trait GetTrait(Index = 0); + auto GetTrait(const Trait&, Index = 0) -> Trait; + template NOD() + auto GetTrait(Index = 0) -> Trait; NOD() LANGULUS_API(ENTITY) - const Trait* GetLocalTrait(TMeta, Index = 0) const; - + auto GetLocalTrait(TMeta, Index = 0) const -> const Trait*; NOD() LANGULUS_API(ENTITY) - Trait* GetLocalTrait(TMeta, Index = 0); - - template - NOD() Trait* GetLocalTrait(Index = 0); - template - NOD() Trait const* GetLocalTrait(Index = 0) const; + auto GetLocalTrait(TMeta, Index = 0) -> Trait*; + template NOD() + auto GetLocalTrait(Index = 0) -> Trait*; + template NOD() + auto GetLocalTrait(Index = 0) const -> Trait const*; LANGULUS_API(ENTITY) void SetName(const Text&); @@ -303,24 +279,24 @@ namespace Langulus::Entity using SeekInterface::SeekValue; using SeekInterface::SeekValueAux; - template - NOD() A::Unit* SeekUnit(DMeta, Index = 0); - template - NOD() A::Unit* SeekUnitAux(const Neat&, DMeta, Index = 0); - template - NOD() A::Unit* SeekUnitExt(DMeta, const Neat&, Index = 0); - template - NOD() A::Unit* SeekUnitAuxExt(DMeta, const Neat&, const Neat&, Index = 0); + template NOD() + auto SeekUnit(DMeta, Index = 0) -> A::Unit*; + template NOD() + auto SeekUnitAux(const Many&, DMeta, Index = 0) -> A::Unit*; + template NOD() + auto SeekUnitExt(DMeta, const Many&, Index = 0) -> A::Unit*; + template NOD() + auto SeekUnitAuxExt(DMeta, const Many&, const Many&, Index = 0) -> A::Unit*; - template - NOD() Trait SeekTrait(TMeta, Index = 0); - template - NOD() Trait SeekTraitAux(const Neat&, TMeta, Index = 0); + template NOD() + auto SeekTrait(TMeta, Index = 0) -> Trait; + template NOD() + auto SeekTraitAux(const Many&, TMeta, Index = 0) -> Trait; template bool SeekValue(TMeta, CT::Data auto&, Index = 0) const; template - bool SeekValueAux(TMeta, const Neat&, CT::Data auto&, Index = 0) const; + bool SeekValueAux(TMeta, const Many&, CT::Data auto&, Index = 0) const; /// /// Gather @@ -330,15 +306,15 @@ namespace Langulus::Entity using SeekInterface::GatherTraits; template - NOD() TMany GatherUnits(DMeta); + auto GatherUnits(DMeta) -> TMany; template - NOD() TMany GatherUnitsExt(DMeta, const Neat&); + auto GatherUnitsExt(DMeta, const Many&) -> TMany; template - NOD() TraitList GatherTraits(TMeta); + auto GatherTraits(TMeta) -> TraitList; template - NOD() TMany GatherValues() const; + auto GatherValues() const -> TMany; }; } // namespace Langulus::Entity \ No newline at end of file diff --git a/source/Thing.inl b/source/Thing.inl index 373f26e..871bbab 100644 --- a/source/Thing.inl +++ b/source/Thing.inl @@ -10,22 +10,6 @@ #include "Thing-Gather.inl" #include "Thing-Seek.inl" -#if 0 - #define ENTITY_VERBOSE_ENABLED() 1 - #define ENTITY_VERBOSE_SELF(...) Logger::Verbose(this, ": ", __VA_ARGS__) - #define ENTITY_VERBOSE_SELF_TAB(...) const auto scoped = Logger::VerboseTab(this, ": ", __VA_ARGS__) - #define ENTITY_VERBOSE(...) Logger::Append(__VA_ARGS__) - #define ENTITY_CREATION_VERBOSE_SELF(...) Logger::Verbose(Self(), __VA_ARGS__) - #define ENTITY_SELECTION_VERBOSE_SELF(...) Logger::Verbose(Self(), __VA_ARGS__) -#else - #define ENTITY_VERBOSE_ENABLED() 0 - #define ENTITY_VERBOSE_SELF(...) LANGULUS(NOOP) - #define ENTITY_VERBOSE_SELF_TAB(...) LANGULUS(NOOP) - #define ENTITY_VERBOSE(...) LANGULUS(NOOP) - #define ENTITY_CREATION_VERBOSE_SELF(...) LANGULUS(NOOP) - #define ENTITY_SELECTION_VERBOSE_SELF(...) LANGULUS(NOOP) -#endif - namespace Langulus::Entity { @@ -51,9 +35,9 @@ namespace Langulus::Entity template Ref Thing::CreateChild(T&&...arguments) { ENTITY_VERBOSE_SELF_TAB( - "Producing child (at ", Reference(0), " references): "); + "Producing child (at ", GetReferences(), " references): "); Ref newThing; - newThing.New(this, Neat {Forward(arguments)...}); + newThing.New(this, Many {Forward(arguments)...}); return Abandon(newThing); } @@ -138,7 +122,7 @@ namespace Langulus::Entity } } } - else LANGULUS_ERROR("Unsupported descriptor"); + else static_assert(false, "Unsupported descriptor"); } /// Add a child @@ -341,7 +325,7 @@ namespace Langulus::Entity mRefreshRequired = true; ENTITY_VERBOSE( - unit, " added as unit (now at ", Reference(0), " references)"); + unit, " added as unit (now at ", GetReferences(), " references)"); return 1; } @@ -428,14 +412,14 @@ namespace Langulus::Entity /// Get the list of units, in order of addition /// @return a reference to the list of units LANGULUS(INLINED) - const UnitList& Thing::GetUnits() const noexcept { + auto Thing::GetUnits() const noexcept -> const UnitList& { return mUnitsList; } /// Get the ambiguous map of units /// @return a reference to the map of units LANGULUS(INLINED) - const UnitMap& Thing::GetUnitsMap() const noexcept { + auto Thing::GetUnitsMap() const noexcept -> const UnitMap& { return mUnitsAmbiguous; } @@ -572,22 +556,28 @@ namespace Langulus::Entity const auto type = construct.GetType(); const auto producer = type and type->mProducerRetriever ? type->mProducerRetriever() : nullptr; + Construct descriptor = construct; + ENTITY_VERBOSE_SELF( "Acting as producer context for making `", - type, "` (at ", Reference(0), " references)" + type, "` (at ", GetReferences(), " references)" ); // Implicitly add a parent trait to descriptor, if one isn't // already added - it will be stripped later, when normalizing // the descriptor when producing the item from a factory - Construct descriptor {construct}; - if (not descriptor.GetDescriptor().Get()) { - descriptor << Traits::Parent {this}; + Traits::Parent parent; + if (not descriptor->ExtractTrait(parent)) { + parent = this; + parent.MakeMissing(); + descriptor << parent; ENTITY_VERBOSE_SELF( - "Referenced as Traits::Parent (now at ", Reference(0), - " references)" + "Referenced as Traits::Parent (now at ", + GetReferences(), " references)" ); } + else if (parent.IsMissing()) + parent << this; if (producer) { // Data has a specific producer, we can narrow the required @@ -602,7 +592,7 @@ namespace Langulus::Entity // Potential unit producers found, attempt creation producers.MakeOr(); - Verbs::Create creator {&descriptor}; + Verbs::Create creator {descriptor}; if (Flow::DispatchFlat(producers, creator)) return Abandon(creator.GetOutput()); @@ -622,7 +612,7 @@ namespace Langulus::Entity // Potential module producers found, attempt creation producers.MakeOr(); - Verbs::Create creator {&descriptor}; + Verbs::Create creator {descriptor}; if (Flow::DispatchFlat(producers, creator)) return Abandon(creator.GetOutput()); @@ -645,7 +635,7 @@ namespace Langulus::Entity if (producers) { // Potential unit producers found, attempt creation there producers.MakeOr(); - Verbs::Create creator {&descriptor}; + Verbs::Create creator {descriptor}; if (Flow::DispatchFlat(producers, creator)) return Abandon(creator.GetOutput()); @@ -665,14 +655,9 @@ namespace Langulus::Entity // such constructor is reflected. If it's a unit, its // descriptor is resposible for registering it with the parent // via the Traits::Parent trait - Verbs::Create creator {&descriptor}; + Verbs::Create creator {descriptor}; if (Verbs::Create::ExecuteStateless(creator)) return Abandon(creator.GetOutput()); - - /*Logger::Error( - "Failed to create `", Logger::PushDarkYellow, - type, Logger::Pop, "` statelessly: ", descriptor - );*/ } LANGULUS_THROW(Construct, "Unable to create data"); @@ -706,11 +691,4 @@ namespace Langulus::A return verb; } -} // namespace Langulus::A - -#undef ENTITY_VERBOSE_ENABLED -#undef ENTITY_VERBOSE_SELF -#undef ENTITY_VERBOSE_SELF_TAB -#undef ENTITY_VERBOSE -#undef ENTITY_CREATION_VERBOSE_SELF -#undef ENTITY_SELECTION_VERBOSE_SELF +} // namespace Langulus::A \ No newline at end of file diff --git a/source/Unit-Seek.inl b/source/Unit-Seek.inl index 8383394..56d421a 100644 --- a/source/Unit-Seek.inl +++ b/source/Unit-Seek.inl @@ -19,7 +19,7 @@ namespace Langulus::A /// @param offset - which of the matches to return /// @return the found unit, or nullptr if no such unit was found template LANGULUS(INLINED) - Unit* Unit::SeekUnit(DMeta meta, Index offset) { + auto Unit::SeekUnit(DMeta meta, Index offset) -> Unit* { return mOwners.template SeekUnit(meta, offset); } @@ -30,7 +30,7 @@ namespace Langulus::A /// @param offset - the index of the unit to return /// @return the unit if found, or nullptr otherwise template LANGULUS(INLINED) - Unit* Unit::SeekUnitAux(const Neat& aux, DMeta meta, Index offset) { + auto Unit::SeekUnitAux(const Many& aux, DMeta meta, Index offset) -> Unit* { return mOwners.template SeekUnitAux(aux, meta, offset); } @@ -41,7 +41,7 @@ namespace Langulus::A /// @param offset - the index of the unit to return /// @return the unit if found, or nullptr otherwise template LANGULUS(INLINED) - Unit* Unit::SeekUnitExt(DMeta type, const Neat& ext, Index offset) { + auto Unit::SeekUnitExt(DMeta type, const Many& ext, Index offset) -> Unit* { return mOwners.template SeekUnitExt(type, ext, offset); } @@ -54,7 +54,7 @@ namespace Langulus::A /// @param offset - the index of the unit to return /// @return a pointer to the found unit, or nullptr if not found template LANGULUS(INLINED) - Unit* Unit::SeekUnitAuxExt(DMeta type, const Neat& aux, const Neat& ext, Index offset) { + auto Unit::SeekUnitAuxExt(DMeta type, const Many& aux, const Many& ext, Index offset) -> Unit* { return mOwners.template SeekUnitAuxExt(type, aux, ext, offset); } @@ -64,7 +64,7 @@ namespace Langulus::A /// @param offset - the offset to apply /// @return the trait, which is not empty, if trait was found template LANGULUS(INLINED) - Langulus::Trait Unit::SeekTrait(TMeta meta, Index offset) { + auto Unit::SeekTrait(TMeta meta, Index offset) -> Langulus::Trait { return mOwners.template SeekTrait(meta, offset); } @@ -75,7 +75,7 @@ namespace Langulus::A /// @param offset - the number of the matching trait to use /// @return the trait, which is not empty, if trait was found template LANGULUS(INLINED) - Langulus::Trait Unit::SeekTraitAux(const Neat& aux, TMeta meta, Index offset) { + auto Unit::SeekTraitAux(const Many& aux, TMeta meta, Index offset) -> Langulus::Trait { return mOwners.template SeekTraitAux(aux, meta, offset); } @@ -103,7 +103,7 @@ namespace Langulus::A /// @param offset - the number of the matching trait to use /// @return the trait, which is not empty, if trait was found template LANGULUS(INLINED) - bool Unit::SeekValueAux(TMeta meta, const Neat& aux, CT::Data auto& output, Index offset) const { + bool Unit::SeekValueAux(TMeta meta, const Many& aux, CT::Data auto& output, Index offset) const { return mOwners.template SeekValueAux(meta, aux, output, offset); } diff --git a/source/Unit.cpp b/source/Unit.cpp index 6a7ab7c..42bb3d7 100644 --- a/source/Unit.cpp +++ b/source/Unit.cpp @@ -12,6 +12,8 @@ using namespace Langulus::A; + +/// Unit destructor decouples unit from all owners Unit::~Unit() { for (auto entity : mOwners) Decouple(entity); @@ -27,11 +29,11 @@ void Unit::Select(Flow::Verb& verb) { /// Check if this unit has a given set of properties /// @param descriptor - descriptor with required properties /// @return true if the unit has the given properties -bool Unit::CompareDescriptor(const Neat& descriptor) const { +bool Unit::CompareDescriptor(const Many& descriptor) const { // First we compare traits only, all of them must be present bool mismatch = false; Offset memberOffset = 0; - descriptor.ForEach([&](const Anyness::Trait& trait) { + descriptor.ForEachDeep([&](const Anyness::Trait& trait) { if (not GetMember(trait.GetTrait(), memberOffset) .Compare(static_cast(trait))) { mismatch = true; @@ -42,10 +44,10 @@ bool Unit::CompareDescriptor(const Neat& descriptor) const { return Loop::Continue; }); - // Then we run another check, based on data types, again, all - // of them must be present, either in trait, or in other form + // Then we run another check based on data types, again - all + // of them must be present, either as trait or in other form memberOffset = 0; - descriptor.ForEachTail([&](const Many& anythingElse) { + descriptor.ForEachDeep([&](const Many& anythingElse) { if (not GetMember(TMeta {}, memberOffset).Compare(anythingElse)) { mismatch = true; return Loop::Break; @@ -60,7 +62,7 @@ bool Unit::CompareDescriptor(const Neat& descriptor) const { /// Get the list of unit owners /// @return the owners -const Hierarchy& Unit::GetOwners() const noexcept { +auto Unit::GetOwners() const noexcept -> const Hierarchy& { return mOwners; } @@ -71,7 +73,7 @@ void Unit::Refresh() {} /// @attention assumes units are correctly coupled and coupling to /// different runtimes should be explicitly disallowed /// @return a pointer to the runtime, if available -Runtime* Unit::GetRuntime() const noexcept { +auto Unit::GetRuntime() const noexcept -> Runtime* { if (not mOwners) return nullptr; return &*mOwners[0]->GetRuntime(); @@ -81,14 +83,19 @@ Runtime* Unit::GetRuntime() const noexcept { /// Traits::Parent, if any was defined (always two-sided) /// This will call refresh to all units in that entity on next tick /// @param desc - the descriptor to scan for parents -void Unit::Couple(const Neat& desc) { - // Couple any Thing provided in the descriptor +/// @param fallback - a fallback Thing to couple to (optional) +/// This usually comes from the producer's context. For example, if you +/// don't provide a parent for the renderer, it will be instantiated as +/// a child to the graphics module owner (i.e. the runtime owner) +void Unit::Couple(const Many& desc, const Thing* fallback) { const Thing* owner = nullptr; if (not desc.ExtractTrait(owner)) desc.ExtractData(owner); if (owner and mOwners.Merge(IndexBack, const_cast(owner))) const_cast(owner)->AddUnit(this); + else if (fallback) + const_cast(fallback)->AddUnit(this); } /// Decouple the component from an entity (always two-sided) diff --git a/source/Unit.hpp b/source/Unit.hpp index 2b33dde..5b200ed 100644 --- a/source/Unit.hpp +++ b/source/Unit.hpp @@ -35,7 +35,6 @@ namespace Langulus::A #endif , Entity::SeekInterface { - LANGULUS(UNINSERTABLE) false; LANGULUS_BASES(Resolvable); protected: @@ -55,7 +54,7 @@ namespace Langulus::A Unit() noexcept : Resolvable {this} {} Unit(const Unit&) = delete; Unit(Unit&&) noexcept = delete; - ~Unit(); + virtual ~Unit(); Unit& operator = (const Unit&) = delete; Unit& operator = (Unit&&) noexcept = delete; @@ -64,9 +63,9 @@ namespace Langulus::A virtual void Refresh(); - Runtime* GetRuntime() const noexcept; - const Hierarchy& GetOwners() const noexcept; - bool CompareDescriptor(const Neat&) const; + auto GetRuntime() const noexcept -> Runtime*; + auto GetOwners() const noexcept -> const Hierarchy&; + bool CompareDescriptor(const Many&) const; /// /// Flow @@ -86,24 +85,24 @@ namespace Langulus::A using SeekInterface::SeekValue; using SeekInterface::SeekValueAux; - template - NOD() Unit* SeekUnit(DMeta, Index = 0); - template - NOD() Unit* SeekUnitAux(const Neat&, DMeta, Index = 0); - template - NOD() Unit* SeekUnitExt(DMeta, const Neat&, Index = 0); - template - NOD() Unit* SeekUnitAuxExt(DMeta, const Neat&, const Neat&, Index = 0); + template NOD() + auto SeekUnit(DMeta, Index = 0) -> Unit*; + template NOD() + auto SeekUnitAux(const Many&, DMeta, Index = 0) -> Unit*; + template NOD() + auto SeekUnitExt(DMeta, const Many&, Index = 0) -> Unit*; + template NOD() + auto SeekUnitAuxExt(DMeta, const Many&, const Many&, Index = 0) -> Unit*; - template - NOD() Langulus::Trait SeekTrait(TMeta, Index = 0); - template - NOD() Langulus::Trait SeekTraitAux(const Neat&, TMeta, Index = 0); + template NOD() + auto SeekTrait(TMeta, Index = 0) -> Langulus::Trait; + template NOD() + auto SeekTraitAux(const Many&, TMeta, Index = 0) -> Langulus::Trait; template bool SeekValue(TMeta, CT::Data auto&, Index = 0) const; template - bool SeekValueAux(TMeta, const Neat&, CT::Data auto&, Index = 0) const; + bool SeekValueAux(TMeta, const Many&, CT::Data auto&, Index = 0) const; /// /// Gather @@ -112,19 +111,19 @@ namespace Langulus::A using SeekInterface::GatherUnitsExt; using SeekInterface::GatherTraits; - template - NOD() TMany GatherUnits(DMeta); - template - NOD() TMany GatherUnitsExt(DMeta, const Neat&); + template NOD() + auto GatherUnits(DMeta) -> TMany; + template NOD() + auto GatherUnitsExt(DMeta, const Many&) -> TMany; - template - NOD() TraitList GatherTraits(TMeta); + template NOD() + auto GatherTraits(TMeta) -> TraitList; - template - NOD() TMany GatherValues() const; + template NOD() + auto GatherValues() const -> TMany; protected: - void Couple(const Neat&); + void Couple(const Many&, const Thing* = nullptr); void Decouple(const Thing*); void ReplaceOwner(const Thing*, const Thing*); }; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b1a926e..f32821f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -4,14 +4,7 @@ file(GLOB_RECURSE *.cpp ) -add_executable(LangulusEntityTest ${LANGULUS_ENTITY_TEST_SOURCES}) - -target_link_libraries(LangulusEntityTest - PRIVATE LangulusEntity - Catch2 -) - -add_test( - NAME LangulusEntityTest - COMMAND LangulusEntityTest +add_langulus_test(LangulusEntityTest + SOURCES ${LANGULUS_ENTITY_TEST_SOURCES} + LIBRARIES LangulusEntity ) \ No newline at end of file diff --git a/test/TestThing.cpp b/test/TestThing.cpp index 5711a93..ed9e185 100644 --- a/test/TestThing.cpp +++ b/test/TestThing.cpp @@ -8,7 +8,10 @@ #include "Common.hpp" -SCENARIO("Testing Thing", "[thing]") { +TEMPLATE_TEST_CASE("Testing Thing with different kidns of descriptors", + "[thing]", + Many, Neat +) { static Allocator::State memoryState; static_assert(CT::Deep, "Hierarchy must be reflected as deep"); @@ -26,7 +29,7 @@ SCENARIO("Testing Thing", "[thing]") { REQUIRE(not root.GetUnits()); REQUIRE(not root.GetUnitsMap()); REQUIRE(not root.GetTraits()); - REQUIRE(root.Reference(0) == 1); + REQUIRE(root.GetReferences() == 1); } WHEN("Creating a Thing with a parent") { @@ -44,7 +47,7 @@ SCENARIO("Testing Thing", "[thing]") { REQUIRE(not root.GetUnits()); REQUIRE(not root.GetUnitsMap()); REQUIRE(not root.GetTraits()); - REQUIRE(root.Reference(0) == 1); + REQUIRE(root.GetReferences() == 1); REQUIRE(child.GetOwner() == &root); REQUIRE(child.GetRuntime() == nullptr); @@ -56,7 +59,7 @@ SCENARIO("Testing Thing", "[thing]") { REQUIRE(not child.GetUnits()); REQUIRE(not child.GetUnitsMap()); REQUIRE(not child.GetTraits()); - REQUIRE(child.Reference(0) == 1); + REQUIRE(child.GetReferences() == 1); } GIVEN("A root Thing") { @@ -88,7 +91,7 @@ SCENARIO("Testing Thing", "[thing]") { REQUIRE(root.GetChildren().GetCount() == 1); REQUIRE(not root.GetUnits()); REQUIRE(not root.GetTraits()); - REQUIRE(root.Reference(0) == 1); + REQUIRE(root.GetReferences() == 1); auto child1 = root.GetChildren()[0]; REQUIRE(child1 == child); @@ -101,66 +104,62 @@ SCENARIO("Testing Thing", "[thing]") { REQUIRE(not child1->GetChildren()); REQUIRE(not child1->GetUnits()); REQUIRE(not child1->GetTraits()); - REQUIRE(child1->Reference(0) == 2); + REQUIRE(child1->GetReferences() == 2); } WHEN("Adding an existing unit") { TestUnit1 testUnit; auto added = root.AddUnit(&testUnit); - THEN("Properties should match") { - REQUIRE(added == 1); - REQUIRE(root.GetOwner() == nullptr); - REQUIRE(root.GetRuntime() == nullptr); - REQUIRE(root.GetRuntime().IsLocked() == false); - REQUIRE(root.GetFlow() == nullptr); - REQUIRE(root.GetFlow().IsLocked() == false); - REQUIRE(root.RequiresRefresh() == true); - REQUIRE(root.GetChildren().IsEmpty()); - REQUIRE(root.GetUnits().GetCount() == 1); - REQUIRE(root.GetTraits().IsEmpty()); - REQUIRE(root.Reference(0) == 1); - - auto it = root.GetUnits().begin(); - REQUIRE(it->GetType() == MetaOf()); - REQUIRE(*it == &testUnit); - REQUIRE(it->GetOwners().GetCount() == 1); - REQUIRE(it->GetOwners()[0] == &root); - REQUIRE(it->Reference(0) == 1); - } + REQUIRE(added == 1); + REQUIRE(root.GetOwner() == nullptr); + REQUIRE(root.GetRuntime() == nullptr); + REQUIRE(root.GetRuntime().IsLocked() == false); + REQUIRE(root.GetFlow() == nullptr); + REQUIRE(root.GetFlow().IsLocked() == false); + REQUIRE(root.RequiresRefresh() == true); + REQUIRE(root.GetChildren().IsEmpty()); + REQUIRE(root.GetUnits().GetCount() == 1); + REQUIRE(root.GetTraits().IsEmpty()); + REQUIRE(root.GetReferences() == 1); + + auto it = root.GetUnits().begin(); + REQUIRE(it->GetType() == MetaOf()); + REQUIRE(*it == &testUnit); + REQUIRE(it->GetOwners().GetCount() == 1); + REQUIRE(it->GetOwners()[0] == &root); + REQUIRE(it->GetReferences() == 1); } WHEN("Creating a new unit") { auto unit = root.CreateUnit(); - THEN("Properties should match") { - REQUIRE(root.GetOwner() == nullptr); - REQUIRE(root.GetRuntime() == nullptr); - REQUIRE(root.GetRuntime().IsLocked() == false); - REQUIRE(root.GetFlow() == nullptr); - REQUIRE(root.GetFlow().IsLocked() == false); - REQUIRE(root.RequiresRefresh() == true); - REQUIRE(root.GetChildren().IsEmpty()); - REQUIRE(root.GetUnits().GetCount() == 1); - REQUIRE(root.GetTraits().IsEmpty()); - REQUIRE(root.Reference(0) == 1); - - auto it = root.GetUnits().begin(); - REQUIRE(it->GetType() == MetaOf()); - REQUIRE(*it == unit.As()); - - // Kept once in `unit` - // Kept once in root.mUnitsList - // Kept once in root.mUnitsAmbiguous - REQUIRE(unit.GetUses() == 3); - - REQUIRE(Fractalloc::Instance.Find({}, unit.As())->GetUses() == 3); - REQUIRE(unit.As()->Reference(0) == 3); - REQUIRE(Fractalloc::Instance.Find({}, unit.As())->GetUses() == 3); - REQUIRE(it->GetOwners().GetCount() == 1); - REQUIRE(it->GetOwners()[0] == &root); - REQUIRE(it->Reference(0) == 3); - } + REQUIRE(root.GetOwner() == nullptr); + REQUIRE(root.GetRuntime() == nullptr); + REQUIRE(root.GetRuntime().IsLocked() == false); + REQUIRE(root.GetFlow() == nullptr); + REQUIRE(root.GetFlow().IsLocked() == false); + REQUIRE(root.RequiresRefresh() == true); + REQUIRE(root.GetChildren().IsEmpty()); + REQUIRE(root.GetUnits().GetCount() == 1); + REQUIRE(root.GetTraits().IsEmpty()); + REQUIRE(root.GetReferences() == 1); + + auto it = root.GetUnits().begin(); + REQUIRE(it->GetType() == MetaOf()); + REQUIRE(*it == unit.As()); + + // Kept once in `unit` + // Kept once in root.mUnitsList + // Kept once in root.mUnitsAmbiguous + REQUIRE(unit.GetUses() == 3); + + REQUIRE(Fractalloc::Instance.Find({}, unit.As())->GetUses() == 3); + REQUIRE(unit.As()->GetReferences() == 3); + REQUIRE(Fractalloc::Instance.Find({}, unit.As())->GetUses() == 3); + REQUIRE(it->GetOwners().GetCount() == 1); + REQUIRE(it->GetOwners()[0] == &root); + REQUIRE(it->GetReferences() == 3); } WHEN("Adding a trait") { @@ -178,7 +177,7 @@ SCENARIO("Testing Thing", "[thing]") { REQUIRE(not root.GetUnits()); REQUIRE(not root.GetUnitsMap()); REQUIRE(root.GetTraits().GetCount() == 1); - REQUIRE(root.Reference(0) == 1); + REQUIRE(root.GetReferences() == 1); auto it = root.GetTraits().begin(); REQUIRE(it.GetKey() == MetaOf()); @@ -203,7 +202,7 @@ SCENARIO("Testing Thing", "[thing]") { REQUIRE(not root.GetUnitsMap()); REQUIRE(root.GetTraits().GetCount() == 1); REQUIRE(root.GetName() == "Dimo"); - REQUIRE(root.Reference(0) == 1); + REQUIRE(root.GetReferences() == 1); auto it = root.GetTraits().begin(); REQUIRE(it.GetKey() == MetaOf()); @@ -216,7 +215,7 @@ SCENARIO("Testing Thing", "[thing]") { for (int repeat = 0; repeat != 10; ++repeat) { WHEN(std::string("Creating a Thing by descriptor #") + std::to_string(repeat)) { Logger::Special("Start: Creating a Thing by descriptor"); - Neat descriptor { + TestType descriptor { Traits::Name {"Root"}, Construct::From(), Construct::From(), @@ -244,7 +243,7 @@ SCENARIO("Testing Thing", "[thing]") { REQUIRE(root.GetUnits().GetCount() == 2); REQUIRE(root.GetTraits().GetCount() == 1); REQUIRE(root.GetName() == "Root"); - REQUIRE(root.Reference(0) == 1); + REQUIRE(root.GetReferences() == 1); auto child1 = root.GetChildren()[0]; REQUIRE(child1->GetOwner() == &root); @@ -266,7 +265,7 @@ SCENARIO("Testing Thing", "[thing]") { // child1's GrandChild2 owner contains 1 reference //--------------------------------------------------- // total: 8 references confirmed - REQUIRE(child1->Reference(0) == 5); + REQUIRE(child1->GetReferences() == 5); auto child2 = root.GetChildren()[1]; REQUIRE(child2->GetOwner() == &root); @@ -279,7 +278,7 @@ SCENARIO("Testing Thing", "[thing]") { REQUIRE(not child2->GetUnits()); REQUIRE(child2->GetTraits().GetCount() == 1); REQUIRE(child2->GetName() == "Child2"); - REQUIRE(child2->Reference(0) == 1); + REQUIRE(child2->GetReferences() == 1); auto grandchild1 = child1->GetChildren()[0]; REQUIRE(grandchild1->GetOwner() == child1); @@ -292,7 +291,7 @@ SCENARIO("Testing Thing", "[thing]") { REQUIRE(not grandchild1->GetUnits()); REQUIRE(grandchild1->GetTraits().GetCount() == 1); REQUIRE(grandchild1->GetName() == "GrandChild1"); - REQUIRE(grandchild1->Reference(0) == 1); + REQUIRE(grandchild1->GetReferences() == 1); auto grandchild2 = child1->GetChildren()[1]; REQUIRE(grandchild2->GetOwner() == child1); @@ -305,14 +304,14 @@ SCENARIO("Testing Thing", "[thing]") { REQUIRE(not grandchild2->GetUnits()); REQUIRE(grandchild2->GetTraits().GetCount() == 1); REQUIRE(grandchild2->GetName() == "GrandChild2"); - REQUIRE(grandchild2->Reference(0) == 1); + REQUIRE(grandchild2->GetReferences() == 1); Logger::Special("End: Creating a Thing by descriptor"); } } GIVEN("A complex hierarchy with runtime, flow, units, and traits") { - Neat descriptor { + TestType descriptor { Traits::Name {"Root"}, Construct::From(), Construct::From(),