add post processors for leafs, memberleafs, unions and usages

This commit is contained in:
Jan 2021-02-20 00:32:26 +01:00
parent 42851bcaf8
commit a6f547f1df
9 changed files with 284 additions and 0 deletions

View File

@ -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<CalculateSizeAndAlignPostProcessor>());
m_post_processors.emplace_back(std::make_unique<UsagesPostProcessor>());
m_post_processors.emplace_back(std::make_unique<LeafsPostProcessor>());
m_post_processors.emplace_back(std::make_unique<MemberLeafsPostProcessor>());
m_post_processors.emplace_back(std::make_unique<UnionsPostProcessor>());
}
bool CommandsFileReader::ReadCommandsFile(IDataRepository* repository)

View File

@ -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<PointerDeclarationModifier*>(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;
}

View File

@ -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;
};

View File

@ -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<PointerDeclarationModifier*>(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;
}

View File

@ -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;
};

View File

@ -0,0 +1,50 @@
#include "UnionsPostProcessor.h"
#include <algorithm>
#include <iostream>
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);
});
}

View File

@ -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;
};

View File

@ -0,0 +1,68 @@
#include "UsagesPostProcessor.h"
#include <algorithm>
#include <queue>
#include <set>
#include "Domain/Computations/MemberComputations.h"
#include "Domain/Computations/StructureComputations.h"
bool UsagesPostProcessor::ProcessAsset(StructureInformation* info)
{
std::set<StructureInformation*> processedInfos;
std::queue<StructureInformation*> 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);
});
}

View File

@ -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;
};