From a6f547f1df438723f51b04e5c29448750c49b029 Mon Sep 17 00:00:00 2001 From: Jan Date: Sat, 20 Feb 2021 00:32:26 +0100 Subject: [PATCH] add post processors for leafs, memberleafs, unions and usages --- .../Parsing/Commands/CommandsFileReader.cpp | 9 +++ .../PostProcessing/LeafsPostProcessor.cpp | 59 ++++++++++++++++ .../PostProcessing/LeafsPostProcessor.h | 11 +++ .../MemberLeafsPostProcessor.cpp | 53 +++++++++++++++ .../PostProcessing/MemberLeafsPostProcessor.h | 12 ++++ .../PostProcessing/UnionsPostProcessor.cpp | 50 ++++++++++++++ .../PostProcessing/UnionsPostProcessor.h | 11 +++ .../PostProcessing/UsagesPostProcessor.cpp | 68 +++++++++++++++++++ .../PostProcessing/UsagesPostProcessor.h | 11 +++ 9 files changed, 284 insertions(+) create mode 100644 src/ZoneCodeGeneratorLib/Parsing/PostProcessing/LeafsPostProcessor.cpp create mode 100644 src/ZoneCodeGeneratorLib/Parsing/PostProcessing/LeafsPostProcessor.h create mode 100644 src/ZoneCodeGeneratorLib/Parsing/PostProcessing/MemberLeafsPostProcessor.cpp create mode 100644 src/ZoneCodeGeneratorLib/Parsing/PostProcessing/MemberLeafsPostProcessor.h create mode 100644 src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UnionsPostProcessor.cpp create mode 100644 src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UnionsPostProcessor.h create mode 100644 src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UsagesPostProcessor.cpp create mode 100644 src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UsagesPostProcessor.h diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/CommandsFileReader.cpp b/src/ZoneCodeGeneratorLib/Parsing/Commands/CommandsFileReader.cpp index 8e717faa..8c3d0528 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/CommandsFileReader.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/CommandsFileReader.cpp @@ -11,6 +11,10 @@ #include "Parsing/Impl/IncludingStreamProxy.h" #include "Parsing/Impl/ParserFilesystemStream.h" #include "Parsing/PostProcessing/CalculateSizeAndAlignPostProcessor.h" +#include "Parsing/PostProcessing/LeafsPostProcessor.h" +#include "Parsing/PostProcessing/MemberLeafsPostProcessor.h" +#include "Parsing/PostProcessing/UnionsPostProcessor.h" +#include "Parsing/PostProcessing/UsagesPostProcessor.h" CommandsFileReader::CommandsFileReader(const ZoneCodeGeneratorArguments* args, std::string filename) : m_args(args), @@ -50,7 +54,12 @@ void CommandsFileReader::SetupStreamProxies() void CommandsFileReader::SetupPostProcessors() { + // Order is important m_post_processors.emplace_back(std::make_unique()); + m_post_processors.emplace_back(std::make_unique()); + m_post_processors.emplace_back(std::make_unique()); + m_post_processors.emplace_back(std::make_unique()); + m_post_processors.emplace_back(std::make_unique()); } bool CommandsFileReader::ReadCommandsFile(IDataRepository* repository) diff --git a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/LeafsPostProcessor.cpp b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/LeafsPostProcessor.cpp new file mode 100644 index 00000000..fa692323 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/LeafsPostProcessor.cpp @@ -0,0 +1,59 @@ +#include "LeafsPostProcessor.h" + +#include "Domain/Computations/MemberComputations.h" +#include "Domain/Computations/StructureComputations.h" +#include "Domain/Definition/PointerDeclarationModifier.h" + +bool LeafsPostProcessor::IsLeaf(StructureInformation* info) +{ + for (const auto& member : info->m_ordered_members) + { + // If there is a condition to this member and it always evaluates to false: Skip this member + if (member->m_condition && member->m_condition->IsStatic() && member->m_condition->EvaluateNumeric() == 0) + continue; + + // Any ScriptStrings or Strings need to be processed. + if (member->m_is_script_string || member->m_is_string) + return false; + + // If there are any Pointer members that are not always count 0 it needs to be processed. + for (const auto& modifier : member->m_member->m_type_declaration->m_declaration_modifiers) + { + if (modifier->GetType() == DeclarationModifierType::POINTER) + { + auto* pointer = dynamic_cast(modifier.get()); + const auto* countEvaluation = pointer->GetCountEvaluation(); + + if (!countEvaluation->IsStatic() || countEvaluation->EvaluateNumeric() != 0) + return false; + } + } + + MemberComputations computations(member.get()); + + // If the member has an embedded type with dynamic size + if (computations.HasDynamicArraySize()) + return false; + + if (member->m_type != nullptr + && member->m_type != info + && !IsLeaf(member->m_type)) + { + return false; + } + } + + return true; +} + +bool LeafsPostProcessor::PostProcess(IDataRepository* repository) +{ + const auto& allInfos = repository->GetAllStructureInformation(); + + for (const auto& info : allInfos) + { + info->m_is_leaf = IsLeaf(info); + } + + return true; +} diff --git a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/LeafsPostProcessor.h b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/LeafsPostProcessor.h new file mode 100644 index 00000000..b19848b4 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/LeafsPostProcessor.h @@ -0,0 +1,11 @@ +#pragma once + +#include "IPostProcessor.h" + +class LeafsPostProcessor final : public IPostProcessor +{ + static bool IsLeaf(StructureInformation* info); + +public: + bool PostProcess(IDataRepository* repository) override; +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/MemberLeafsPostProcessor.cpp b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/MemberLeafsPostProcessor.cpp new file mode 100644 index 00000000..4c8d2a2d --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/MemberLeafsPostProcessor.cpp @@ -0,0 +1,53 @@ +#include "MemberLeafsPostProcessor.h" + +#include "Domain/Computations/MemberComputations.h" +#include "Domain/Definition/PointerDeclarationModifier.h" + +bool MemberLeafsPostProcessor::MemberIsLeaf(MemberInformation* member) +{ + if (member->m_is_string || member->m_is_script_string) + return false; + + if (member->m_type != nullptr && !member->m_type->m_is_leaf) + return false; + + // If there are any Pointer members that are not always count 0 it needs to be processed. + for (const auto& modifier : member->m_member->m_type_declaration->m_declaration_modifiers) + { + if (modifier->GetType() == DeclarationModifierType::POINTER) + { + auto* pointer = dynamic_cast(modifier.get()); + const auto* countEvaluation = pointer->GetCountEvaluation(); + + if (!countEvaluation->IsStatic() || countEvaluation->EvaluateNumeric() != 0) + return false; + } + } + + const MemberComputations computations(member); + + if (computations.HasDynamicArraySize()) + return false; + + return true; +} + +void MemberLeafsPostProcessor::ProcessInfo(StructureInformation* info) +{ + for(const auto& member : info->m_ordered_members) + { + member->m_is_leaf = MemberIsLeaf(member.get()); + } +} + +bool MemberLeafsPostProcessor::PostProcess(IDataRepository* repository) +{ + const auto& allInfos = repository->GetAllStructureInformation(); + + for (const auto& info : allInfos) + { + ProcessInfo(info); + } + + return true; +} diff --git a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/MemberLeafsPostProcessor.h b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/MemberLeafsPostProcessor.h new file mode 100644 index 00000000..763e9a79 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/MemberLeafsPostProcessor.h @@ -0,0 +1,12 @@ +#pragma once + +#include "IPostProcessor.h" + +class MemberLeafsPostProcessor final : public IPostProcessor +{ + static bool MemberIsLeaf(MemberInformation* member); + static void ProcessInfo(StructureInformation* info); + +public: + bool PostProcess(IDataRepository* repository) override; +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UnionsPostProcessor.cpp b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UnionsPostProcessor.cpp new file mode 100644 index 00000000..f843092a --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UnionsPostProcessor.cpp @@ -0,0 +1,50 @@ +#include "UnionsPostProcessor.h" + +#include +#include + +bool UnionsPostProcessor::ProcessUnion(StructureInformation* info) +{ + auto index = 0u; + auto lastEntryWithoutCondition = 0u; + auto entriesWithoutConditionCount = 0u; + + for(const auto& member : info->m_ordered_members) + { + if(!member->m_condition && !member->m_is_leaf) + { + entriesWithoutConditionCount++; + lastEntryWithoutCondition = index; + } + index++; + } + + if (entriesWithoutConditionCount > 1 && !info->m_usages.empty() && !info->m_is_leaf) + { + std::cout << "Union '" << info->m_definition->GetFullName() << "' has more than one entry without a condition!" << std::endl; + return false; + } + + if (entriesWithoutConditionCount == 1) + { + // If there is only one entry without condition make it the last of the ordered members + auto entryWithoutCondition = std::move(info->m_ordered_members.at(lastEntryWithoutCondition)); + info->m_ordered_members.erase(info->m_ordered_members.begin() + lastEntryWithoutCondition); + info->m_ordered_members.emplace_back(std::move(entryWithoutCondition)); + } + + return true; +} + +bool UnionsPostProcessor::PostProcess(IDataRepository* repository) +{ + const auto& allInfos = repository->GetAllStructureInformation(); + + return std::all_of(allInfos.begin(), allInfos.end(), [](StructureInformation* info) + { + if (info->m_definition->GetType() != DataDefinitionType::UNION) + return true; + + return ProcessUnion(info); + }); +} diff --git a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UnionsPostProcessor.h b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UnionsPostProcessor.h new file mode 100644 index 00000000..85b9d53c --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UnionsPostProcessor.h @@ -0,0 +1,11 @@ +#pragma once + +#include "IPostProcessor.h" + +class UnionsPostProcessor final : public IPostProcessor +{ + static bool ProcessUnion(StructureInformation* info); + +public: + bool PostProcess(IDataRepository* repository) override; +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UsagesPostProcessor.cpp b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UsagesPostProcessor.cpp new file mode 100644 index 00000000..da9366a2 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UsagesPostProcessor.cpp @@ -0,0 +1,68 @@ +#include "UsagesPostProcessor.h" + +#include +#include +#include + +#include "Domain/Computations/MemberComputations.h" +#include "Domain/Computations/StructureComputations.h" + +bool UsagesPostProcessor::ProcessAsset(StructureInformation* info) +{ + std::set processedInfos; + std::queue processingQueue; + + processingQueue.push(info); + + while(!processingQueue.empty()) + { + auto* currentStructure = processingQueue.front(); + processingQueue.pop(); + + if(processedInfos.find(currentStructure) != processedInfos.end()) + continue; + processedInfos.emplace(currentStructure); + + for (const auto& member : currentStructure->m_ordered_members) + { + if(member->m_type == nullptr) + continue; + + const MemberComputations computations(member.get()); + + if(computations.ShouldIgnore()) + continue; + + if (computations.ContainsNonEmbeddedReference()) + member->m_type->m_non_embedded_reference_exists = true; + + if (computations.ContainsSinglePointerReference()) + member->m_type->m_single_pointer_reference_exists = true; + + if (computations.ContainsArrayPointerReference()) + member->m_type->m_array_pointer_reference_exists = true; + + if (computations.ContainsArrayReference()) + member->m_type->m_array_reference_exists = true; + + if (computations.IsNotInDefaultNormalBlock()) + member->m_type->m_reference_from_non_default_normal_block_exists = true; + + member->m_type->m_usages.push_back(currentStructure); + processingQueue.push(member->m_type); + } + } + + return true; +} + +bool UsagesPostProcessor::PostProcess(IDataRepository* repository) +{ + const auto& allInfos = repository->GetAllStructureInformation(); + + return std::all_of(allInfos.begin(), allInfos.end(), [](StructureInformation* info) + { + const StructureComputations computations(info); + return !computations.IsAsset() || ProcessAsset(info); + }); +} diff --git a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UsagesPostProcessor.h b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UsagesPostProcessor.h new file mode 100644 index 00000000..e5b1f778 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/UsagesPostProcessor.h @@ -0,0 +1,11 @@ +#pragma once + +#include "IPostProcessor.h" + +class UsagesPostProcessor final : public IPostProcessor +{ + static bool ProcessAsset(StructureInformation* info); + +public: + bool PostProcess(IDataRepository* repository) override; +};