diff --git a/src/ZoneCode/Game/IW4/IW4_Commands.txt b/src/ZoneCode/Game/IW4/IW4_Commands.txt index 12bc9ba8..52eacd84 100644 --- a/src/ZoneCode/Game/IW4/IW4_Commands.txt +++ b/src/ZoneCode/Game/IW4/IW4_Commands.txt @@ -1,5 +1,6 @@ // Game: Modern Warfare 2 (IW4) game IW4; +architecture x86; // Game Assets asset PhysPreset ASSET_TYPE_PHYSPRESET; diff --git a/src/ZoneCode/Game/T6/T6_Commands.txt b/src/ZoneCode/Game/T6/T6_Commands.txt index 9d450680..208d020f 100644 --- a/src/ZoneCode/Game/T6/T6_Commands.txt +++ b/src/ZoneCode/Game/T6/T6_Commands.txt @@ -1,5 +1,6 @@ // Game: Black Ops 2 (T6) game T6; +architecture x86; // Game Assets asset PhysPreset ASSET_TYPE_PHYSPRESET; diff --git a/src/ZoneCodeGeneratorLib/Domain/Definition/DefinitionWithMembers.cpp b/src/ZoneCodeGeneratorLib/Domain/Definition/DefinitionWithMembers.cpp index bd076fa2..dade3c98 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Definition/DefinitionWithMembers.cpp +++ b/src/ZoneCodeGeneratorLib/Domain/Definition/DefinitionWithMembers.cpp @@ -36,27 +36,21 @@ DefinitionWithMembers::DefinitionWithMembers(std::string _namespace, std::string unsigned DefinitionWithMembers::GetAlignment() const { - assert(m_flags & FLAG_ALIGNMENT_CALCULATED); - /*if ((m_flags & FLAG_ALIGNMENT_CALCULATED) == 0) - CalculateAlignment();*/ + assert(m_flags & FLAG_FIELDS_CALCULATED); return m_alignment; } bool DefinitionWithMembers::GetForceAlignment() const { - assert(m_flags & FLAG_ALIGNMENT_CALCULATED); - /*if ((m_flags & FLAG_ALIGNMENT_CALCULATED) == 0) - CalculateAlignment();*/ + assert(m_flags & FLAG_FIELDS_CALCULATED); return m_flags & FLAG_ALIGNMENT_FORCED; } unsigned DefinitionWithMembers::GetSize() const { - assert(m_flags & FLAG_SIZE_CALCULATED); - /*if ((m_flags & FLAG_SIZE_CALCULATED) == 0) - CalculateSize();*/ + assert(m_flags & FLAG_FIELDS_CALCULATED); return m_size; } diff --git a/src/ZoneCodeGeneratorLib/Domain/Definition/DefinitionWithMembers.h b/src/ZoneCodeGeneratorLib/Domain/Definition/DefinitionWithMembers.h index 0791f5e3..658a25a7 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Definition/DefinitionWithMembers.h +++ b/src/ZoneCodeGeneratorLib/Domain/Definition/DefinitionWithMembers.h @@ -9,17 +9,14 @@ class DefinitionWithMembers : public DataDefinition { public: - static constexpr int FLAG_SIZE_CALCULATED = 1 << 0; - static constexpr int FLAG_ALIGNMENT_CALCULATED = 1 << 1; + static constexpr int FLAG_FIELDS_CALCULATED = 1 << 0; + static constexpr int FLAG_FIELDS_CALCULATING = 1 << 1; static constexpr int FLAG_ALIGNMENT_FORCED = 1 << 2; unsigned m_flags; unsigned m_size; unsigned m_alignment; - /*virtual void CalculateSize() = 0; - void CalculateAlignment();*/ - bool m_has_alignment_override; bool m_anonymous; diff --git a/src/ZoneCodeGeneratorLib/Domain/Definition/StructDefinition.cpp b/src/ZoneCodeGeneratorLib/Domain/Definition/StructDefinition.cpp index 43691118..51a1557b 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Definition/StructDefinition.cpp +++ b/src/ZoneCodeGeneratorLib/Domain/Definition/StructDefinition.cpp @@ -1,43 +1,5 @@ #include "StructDefinition.h" -#include "Utils/AlignmentUtils.h" - -//void StructDefinition::CalculateSize() -//{ -// m_size = 0; -// auto currentBitOffset = 0u; -// -// for(const auto& member : m_members) -// { -// if(member->m_type_declaration->m_has_custom_bit_size) -// { -// currentBitOffset += member->m_type_declaration->m_custom_bit_size; -// } -// else -// { -// if (currentBitOffset > 0) -// { -// currentBitOffset = AlignmentUtils::Align(currentBitOffset, 8u); -// m_size += currentBitOffset / 8; -// currentBitOffset = 0; -// } -// -// m_size = AlignmentUtils::Align(m_size, member->GetForceAlignment() ? member->GetAlignment() : std::min(member->GetAlignment(), m_pack)); -// m_size += member->m_type_declaration->GetSize(); -// } -// } -// -// if (currentBitOffset > 0) -// { -// currentBitOffset = AlignmentUtils::Align(currentBitOffset, 8u); -// m_size += currentBitOffset / 8; -// } -// -// m_size = AlignmentUtils::Align(m_size, GetAlignment()); -// -// m_flags |= FLAG_SIZE_CALCULATED; -//} - StructDefinition::StructDefinition(std::string _namespace, std::string name, const int pack) : DefinitionWithMembers(std::move(_namespace), std::move(name), pack) { diff --git a/src/ZoneCodeGeneratorLib/Domain/Definition/StructDefinition.h b/src/ZoneCodeGeneratorLib/Domain/Definition/StructDefinition.h index 45f00807..41d89c61 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Definition/StructDefinition.h +++ b/src/ZoneCodeGeneratorLib/Domain/Definition/StructDefinition.h @@ -4,9 +4,6 @@ class StructDefinition final : public DefinitionWithMembers { -//protected: -// void CalculateSize() override; - public: StructDefinition(std::string _namespace, std::string name, int pack); diff --git a/src/ZoneCodeGeneratorLib/Domain/Definition/TypeDeclaration.cpp b/src/ZoneCodeGeneratorLib/Domain/Definition/TypeDeclaration.cpp index 542f955e..20243f16 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Definition/TypeDeclaration.cpp +++ b/src/ZoneCodeGeneratorLib/Domain/Definition/TypeDeclaration.cpp @@ -16,75 +16,20 @@ TypeDeclaration::TypeDeclaration(const DataDefinition* type) assert(m_type != nullptr); } -void TypeDeclaration::CalculateSize() +unsigned TypeDeclaration::GetSize() const { - auto currentSize = m_type->GetSize(); - - for (auto i = m_declaration_modifiers.size(); i > 0; i--) - { - const auto& declarationModifier = m_declaration_modifiers[i - 1]; - - switch (declarationModifier->GetType()) - { - case DeclarationModifierType::POINTER: - currentSize = POINTER_SIZE; - break; - - case DeclarationModifierType::ARRAY: - currentSize *= dynamic_cast(declarationModifier.get())->m_size; - break; - } - } - - m_flags |= FLAG_SIZE_CALCULATED; -} - -void TypeDeclaration::CalculateAlignment() -{ - auto hasPointerModifier = false; - for (const auto& declarationModifier : m_declaration_modifiers) - { - if (declarationModifier->GetType() == DeclarationModifierType::POINTER) - { - hasPointerModifier = true; - break; - } - } - - if (hasPointerModifier) - { - m_alignment = POINTER_SIZE; - } - else - { - m_alignment = m_type->GetAlignment(); - if (m_type->GetForceAlignment()) - m_flags |= FLAG_ALIGNMENT_FORCED; - } - - m_flags |= FLAG_ALIGNMENT_CALCULATED; -} - -unsigned TypeDeclaration::GetSize() -{ - if ((m_flags & FLAG_SIZE_CALCULATED) == 0) - CalculateSize(); - + assert(m_flags & FLAG_FIELDS_CALCULATED); return m_size; } -unsigned TypeDeclaration::GetAlignment() +unsigned TypeDeclaration::GetAlignment() const { - if ((m_flags & FLAG_ALIGNMENT_CALCULATED) == 0) - CalculateAlignment(); - + assert(m_flags & FLAG_FIELDS_CALCULATED); return m_alignment; } -bool TypeDeclaration::GetForceAlignment() +bool TypeDeclaration::GetForceAlignment() const { - if ((m_flags & FLAG_ALIGNMENT_CALCULATED) == 0) - CalculateAlignment(); - + assert(m_flags & FLAG_FIELDS_CALCULATED); return m_flags & FLAG_ALIGNMENT_FORCED; } diff --git a/src/ZoneCodeGeneratorLib/Domain/Definition/TypeDeclaration.h b/src/ZoneCodeGeneratorLib/Domain/Definition/TypeDeclaration.h index e7cf3f77..1d2b541f 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Definition/TypeDeclaration.h +++ b/src/ZoneCodeGeneratorLib/Domain/Definition/TypeDeclaration.h @@ -1,26 +1,22 @@ #pragma once + #include #include -#include +#include "Utils/ClassUtils.h" #include "DataDefinition.h" #include "DeclarationModifier.h" class TypeDeclaration { - static constexpr unsigned POINTER_SIZE = sizeof(uint32_t); // TODO: Change this to support 64bit - static constexpr int FLAG_SIZE_CALCULATED = 1 << 0; - static constexpr int FLAG_ALIGNMENT_CALCULATED = 1 << 1; - static constexpr int FLAG_ALIGNMENT_FORCED = 1 << 2; +public: + static constexpr int FLAG_FIELDS_CALCULATED = 1 << 0; + static constexpr int FLAG_ALIGNMENT_FORCED = 1 << 1; unsigned m_flags; unsigned m_size; unsigned m_alignment; - void CalculateSize(); - void CalculateAlignment(); - -public: explicit TypeDeclaration(const DataDefinition* type); bool m_is_const; @@ -31,7 +27,7 @@ public: std::vector> m_declaration_modifiers; - unsigned GetSize(); - unsigned GetAlignment(); - bool GetForceAlignment(); + _NODISCARD unsigned GetSize() const; + _NODISCARD unsigned GetAlignment() const; + _NODISCARD bool GetForceAlignment() const; }; diff --git a/src/ZoneCodeGeneratorLib/Domain/Definition/UnionDefinition.cpp b/src/ZoneCodeGeneratorLib/Domain/Definition/UnionDefinition.cpp index ecd039f9..ce7a10cb 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Definition/UnionDefinition.cpp +++ b/src/ZoneCodeGeneratorLib/Domain/Definition/UnionDefinition.cpp @@ -1,23 +1,5 @@ #include "UnionDefinition.h" -#include "Utils/AlignmentUtils.h" - -//void UnionDefinition::CalculateSize() -//{ -// m_size = 0; -// -// for(const auto& member : m_members) -// { -// const auto memberSize = member->m_type_declaration->GetSize(); -// if (memberSize > m_size) -// m_size = memberSize; -// } -// -// m_size = AlignmentUtils::Align(m_size, GetAlignment()); -// -// m_flags |= FLAG_SIZE_CALCULATED; -//} - UnionDefinition::UnionDefinition(std::string _namespace, std::string name, const int pack) : DefinitionWithMembers(std::move(_namespace), std::move(name), pack) { diff --git a/src/ZoneCodeGeneratorLib/Domain/Definition/Variable.cpp b/src/ZoneCodeGeneratorLib/Domain/Definition/Variable.cpp index b8e78244..7798142b 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Definition/Variable.cpp +++ b/src/ZoneCodeGeneratorLib/Domain/Definition/Variable.cpp @@ -8,7 +8,7 @@ Variable::Variable(std::string name, std::unique_ptr typeDeclar { } -unsigned Variable::GetAlignment() +unsigned Variable::GetAlignment() const { if (m_has_alignment_override) return m_alignment_override; @@ -16,7 +16,7 @@ unsigned Variable::GetAlignment() return m_type_declaration->GetAlignment(); } -bool Variable::GetForceAlignment() +bool Variable::GetForceAlignment() const { return m_has_alignment_override || m_type_declaration->GetForceAlignment(); } diff --git a/src/ZoneCodeGeneratorLib/Domain/Definition/Variable.h b/src/ZoneCodeGeneratorLib/Domain/Definition/Variable.h index 4e8016c5..f36e6aa8 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Definition/Variable.h +++ b/src/ZoneCodeGeneratorLib/Domain/Definition/Variable.h @@ -15,6 +15,6 @@ public: Variable(std::string name, std::unique_ptr typeDeclaration); - unsigned GetAlignment(); - bool GetForceAlignment(); + unsigned GetAlignment() const; + bool GetForceAlignment() const; }; diff --git a/src/ZoneCodeGeneratorLib/Domain/Environment/Architecture.h b/src/ZoneCodeGeneratorLib/Domain/Environment/Architecture.h new file mode 100644 index 00000000..0748fbfb --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Domain/Environment/Architecture.h @@ -0,0 +1,8 @@ +#pragma once + +enum class Architecture +{ + UNKNOWN, + X86, + X64 +}; \ No newline at end of file diff --git a/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandDynamic.cpp b/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandDynamic.cpp index d2dafad3..0a281735 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandDynamic.cpp +++ b/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandDynamic.cpp @@ -7,6 +7,13 @@ OperandDynamic::OperandDynamic(StructureInformation* structure) { } +OperandDynamic::OperandDynamic(StructureInformation* structure, std::vector referencedMemberChain, std::vector> arrayIndices) + : m_structure(structure), + m_referenced_member_chain(std::move(referencedMemberChain)), + m_array_indices(std::move(arrayIndices)) +{ +} + EvaluationType OperandDynamic::GetType() const { return EvaluationType::OPERAND_DYNAMIC; diff --git a/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandDynamic.h b/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandDynamic.h index 958fa4ea..0ebf3b0d 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandDynamic.h +++ b/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandDynamic.h @@ -14,6 +14,7 @@ public: std::vector> m_array_indices; explicit OperandDynamic(StructureInformation* structure); + OperandDynamic(StructureInformation* structure, std::vector referencedMemberChain, std::vector> arrayIndices); _NODISCARD EvaluationType GetType() const override; _NODISCARD bool IsStatic() const override; diff --git a/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandStatic.cpp b/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandStatic.cpp index 6c2aa019..7d2de18c 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandStatic.cpp +++ b/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandStatic.cpp @@ -6,8 +6,8 @@ OperandStatic::OperandStatic(const int value) { } -OperandStatic::OperandStatic(const int value, EnumMember* enumMember) - : m_value(value), +OperandStatic::OperandStatic(EnumMember* enumMember) + : m_value(enumMember->m_value), m_enum_member(enumMember) { } diff --git a/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandStatic.h b/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandStatic.h index 7ab0a721..7ea1150f 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandStatic.h +++ b/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperandStatic.h @@ -10,7 +10,7 @@ public: EnumMember* const m_enum_member; explicit OperandStatic(int value); - OperandStatic(int value, EnumMember* enumMember); + explicit OperandStatic(EnumMember* enumMember); _NODISCARD EvaluationType GetType() const override; _NODISCARD bool IsStatic() const override; diff --git a/src/ZoneCodeGeneratorLib/Domain/Evaluation/Operation.cpp b/src/ZoneCodeGeneratorLib/Domain/Evaluation/Operation.cpp index c2e2320b..d095bda4 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Evaluation/Operation.cpp +++ b/src/ZoneCodeGeneratorLib/Domain/Evaluation/Operation.cpp @@ -5,6 +5,13 @@ Operation::Operation(const OperationType* type) { } +Operation::Operation(const OperationType* type, std::unique_ptr operand1, std::unique_ptr operand2) + : m_operation_type(type), + m_operand1(std::move(operand1)), + m_operand2(std::move(operand2)) +{ +} + EvaluationType Operation::GetType() const { return EvaluationType::OPERATION; diff --git a/src/ZoneCodeGeneratorLib/Domain/Evaluation/Operation.h b/src/ZoneCodeGeneratorLib/Domain/Evaluation/Operation.h index fbb907f7..6ff78d2a 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Evaluation/Operation.h +++ b/src/ZoneCodeGeneratorLib/Domain/Evaluation/Operation.h @@ -14,6 +14,7 @@ public: std::unique_ptr m_operand2; explicit Operation(const OperationType* type); + Operation(const OperationType* type, std::unique_ptr operand1, std::unique_ptr operand2); _NODISCARD EvaluationType GetType() const override; _NODISCARD bool IsStatic() const override; diff --git a/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperationType.cpp b/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperationType.cpp index 1f6844ac..3615f0d1 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperationType.cpp +++ b/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperationType.cpp @@ -73,7 +73,7 @@ const OperationType* const OperationType::OPERATION_GREATER_THAN return op1 > op2 ? 1 : 0; }); -const OperationType* const OperationType::OPERATION_GREATER_EQUALS_THAN +const OperationType* const OperationType::OPERATION_GREATER_EQUAL_THAN = new OperationType(">=", OperationPrecedence::RELATIONAL_GREATER_LESS_THAN, [](auto op1, auto op2) { return op1 >= op2 ? 1 : 0; @@ -85,7 +85,7 @@ const OperationType* const OperationType::OPERATION_LESS_THAN return op1 < op2 ? 1 : 0; }); -const OperationType* const OperationType::OPERATION_LESS_EQUALS_THAN +const OperationType* const OperationType::OPERATION_LESS_EQUAL_THAN = new OperationType("<=", OperationPrecedence::RELATIONAL_GREATER_LESS_THAN, [](auto op1, auto op2) { return op1 <= op2 ? 1 : 0; @@ -97,7 +97,7 @@ const OperationType* const OperationType::OPERATION_EQUALS return op1 == op2 ? 1 : 0; }); -const OperationType* const OperationType::OPERATION_NOT_EQUALS +const OperationType* const OperationType::OPERATION_NOT_EQUAL = new OperationType("!=", OperationPrecedence::RELATIONAL_EQUALS, [](auto op1, auto op2) { return op1 != op2 ? 1 : 0; @@ -129,11 +129,11 @@ const OperationType* const OperationType::ALL_OPERATION_TYPES[] OPERATION_SHIFT_LEFT, OPERATION_SHIFT_RIGHT, OPERATION_GREATER_THAN, - OPERATION_GREATER_EQUALS_THAN, + OPERATION_GREATER_EQUAL_THAN, OPERATION_LESS_THAN, - OPERATION_LESS_EQUALS_THAN, + OPERATION_LESS_EQUAL_THAN, OPERATION_EQUALS, - OPERATION_NOT_EQUALS, + OPERATION_NOT_EQUAL, OPERATION_AND, OPERATION_OR }; diff --git a/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperationType.h b/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperationType.h index d4f9b5df..f33cf3cc 100644 --- a/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperationType.h +++ b/src/ZoneCodeGeneratorLib/Domain/Evaluation/OperationType.h @@ -40,11 +40,11 @@ public: static const OperationType* const OPERATION_SHIFT_LEFT; static const OperationType* const OPERATION_SHIFT_RIGHT; static const OperationType* const OPERATION_GREATER_THAN; - static const OperationType* const OPERATION_GREATER_EQUALS_THAN; + static const OperationType* const OPERATION_GREATER_EQUAL_THAN; static const OperationType* const OPERATION_LESS_THAN; - static const OperationType* const OPERATION_LESS_EQUALS_THAN; + static const OperationType* const OPERATION_LESS_EQUAL_THAN; static const OperationType* const OPERATION_EQUALS; - static const OperationType* const OPERATION_NOT_EQUALS; + static const OperationType* const OPERATION_NOT_EQUAL; static const OperationType* const OPERATION_AND; static const OperationType* const OPERATION_OR; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/CommandsFileReader.cpp b/src/ZoneCodeGeneratorLib/Parsing/Commands/CommandsFileReader.cpp index e706fae5..8e717faa 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/CommandsFileReader.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/CommandsFileReader.cpp @@ -1,5 +1,6 @@ #include "CommandsFileReader.h" +#include #include #include @@ -9,12 +10,14 @@ #include "Parsing/Impl/DefinesStreamProxy.h" #include "Parsing/Impl/IncludingStreamProxy.h" #include "Parsing/Impl/ParserFilesystemStream.h" +#include "Parsing/PostProcessing/CalculateSizeAndAlignPostProcessor.h" CommandsFileReader::CommandsFileReader(const ZoneCodeGeneratorArguments* args, std::string filename) : m_args(args), m_filename(std::move(filename)), m_stream(nullptr) { + SetupPostProcessors(); } bool CommandsFileReader::OpenBaseStream() @@ -45,6 +48,11 @@ void CommandsFileReader::SetupStreamProxies() m_open_streams.emplace_back(std::move(definesProxy)); } +void CommandsFileReader::SetupPostProcessors() +{ + m_post_processors.emplace_back(std::make_unique()); +} + bool CommandsFileReader::ReadCommandsFile(IDataRepository* repository) { std::cout << "Reading commands file: " << m_filename << std::endl; @@ -62,5 +70,11 @@ bool CommandsFileReader::ReadCommandsFile(IDataRepository* repository) const auto end = std::chrono::steady_clock::now(); std::cout << "Processing commands took " << std::chrono::duration_cast(end - start).count() << "ms" << std::endl; - return result; + if (!result) + return false; + + return std::all_of(m_post_processors.begin(), m_post_processors.end(), [repository](const std::unique_ptr& postProcessor) + { + return postProcessor->PostProcess(repository); + }); } diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/CommandsFileReader.h b/src/ZoneCodeGeneratorLib/Parsing/Commands/CommandsFileReader.h index 5eb8be11..bfe77f60 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/CommandsFileReader.h +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/CommandsFileReader.h @@ -4,6 +4,7 @@ #include "ZoneCodeGeneratorArguments.h" #include "Parsing/IParserLineStream.h" +#include "Parsing/PostProcessing/IPostProcessor.h" #include "Persistence/IDataRepository.h" class CommandsFileReader @@ -17,8 +18,11 @@ class CommandsFileReader std::vector> m_open_streams; IParserLineStream* m_stream; + std::vector> m_post_processors; + bool OpenBaseStream(); void SetupStreamProxies(); + void SetupPostProcessors(); public: explicit CommandsFileReader(const ZoneCodeGeneratorArguments* args, std::string filename); diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParser.cpp b/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParser.cpp index 012a4000..d7c0a67f 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParser.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParser.cpp @@ -1,6 +1,7 @@ #include "CommandsParser.h" #include "Parsing/Commands/Sequence/SequenceAction.h" +#include "Parsing/Commands/Sequence/SequenceArchitecture.h" #include "Parsing/Commands/Sequence/SequenceArrayCount.h" #include "Parsing/Commands/Sequence/SequenceArraySize.h" #include "Parsing/Commands/Sequence/SequenceAsset.h" @@ -26,6 +27,7 @@ const std::vector& CommandsParser::GetTestsForState { static std::vector tests({ new SequenceAction(), + new SequenceArchitecture(), new SequenceArrayCount(), new SequenceArraySize(), new SequenceAsset(), diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserState.cpp b/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserState.cpp index 004bd887..e7ba6ebd 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserState.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserState.cpp @@ -16,6 +16,11 @@ void CommandsParserState::AddBlock(std::unique_ptr block) const m_repository->Add(std::move(block)); } +void CommandsParserState::SetArchitecture(const Architecture architecture) const +{ + m_repository->SetArchitecture(architecture); +} + void CommandsParserState::SetGame(std::string gameName) const { m_repository->SetGame(std::move(gameName)); @@ -31,12 +36,105 @@ void CommandsParserState::SetInUse(StructureInformation* structure) m_in_use = structure; } -bool CommandsParserState::GetMembersFromParts(const std::string& typeNameValue, StructureInformation* baseType, std::vector& members) +MemberInformation* CommandsParserState::GetMemberWithName(const std::string& memberName, StructureInformation* type) { + for (const auto& member : type->m_ordered_members) + { + if (member->m_member->m_name == memberName) + { + return member.get(); + } + } + + return nullptr; +} + +bool CommandsParserState::GetNextTypenameSeparatorPos(const std::string& typeNameValue, const unsigned startPos, unsigned& separatorPos) +{ + const auto typeNameValueSize = typeNameValue.size(); + for (auto currentHead = startPos + 1; currentHead < typeNameValueSize; currentHead++) + { + if (typeNameValue[currentHead] == ':' + && typeNameValue[currentHead - 1] == ':') + { + separatorPos = currentHead - 1; + return true; + } + } + return false; } -bool CommandsParserState::GetTypenameAndMembersFromParts(const std::string& typeNameValue, StructureInformation*& structure, std::vector& members) +bool CommandsParserState::ExtractMembersFromTypenameInternal(const std::string& typeNameValue, unsigned typeNameOffset, StructureInformation* type, std::vector& members) { - return false; + auto startOffset = typeNameOffset; + while (GetNextTypenameSeparatorPos(typeNameValue, typeNameOffset, typeNameOffset)) + { + auto* foundMember = GetMemberWithName(std::string(typeNameValue, startOffset, typeNameOffset - startOffset), type); + + if (foundMember == nullptr) + return false; + + members.push_back(foundMember); + type = foundMember->m_type; + typeNameOffset += 2; + startOffset = typeNameOffset; + } + + auto* foundMember = GetMemberWithName(std::string(typeNameValue, startOffset, typeNameValue.size() - startOffset), type); + if (foundMember == nullptr) + return false; + + members.push_back(foundMember); + return true; +} + +bool CommandsParserState::GetMembersFromTypename(const std::string& typeNameValue, StructureInformation* baseType, std::vector& members) const +{ + return m_in_use != nullptr && ExtractMembersFromTypenameInternal(typeNameValue, 0, m_in_use, members) + || ExtractMembersFromTypenameInternal(typeNameValue, 0, baseType, members); +} + +bool CommandsParserState::GetTypenameAndMembersFromTypename(const std::string& typeNameValue, StructureInformation*& structure, std::vector& members) const +{ + if (m_in_use != nullptr) + { + if (ExtractMembersFromTypenameInternal(typeNameValue, 0, m_in_use, members)) + { + structure = m_in_use; + return true; + } + members.clear(); + } + + DataDefinition* foundDefinition = nullptr; + unsigned currentSeparatorPos = 0; + while (GetNextTypenameSeparatorPos(typeNameValue, currentSeparatorPos, currentSeparatorPos)) + { + std::string currentTypename(typeNameValue, 0, currentSeparatorPos); + currentSeparatorPos += 2; + + foundDefinition = m_repository->GetDataDefinitionByName(currentTypename); + if (foundDefinition != nullptr) + break; + } + + if (foundDefinition == nullptr) + { + currentSeparatorPos = typeNameValue.size(); + foundDefinition = m_repository->GetDataDefinitionByName(typeNameValue); + } + + if (foundDefinition == nullptr) + return false; + + auto* definitionWithMembers = dynamic_cast(foundDefinition); + if (definitionWithMembers == nullptr) + return false; + + structure = m_repository->GetInformationFor(definitionWithMembers); + if (currentSeparatorPos >= typeNameValue.size()) + return true; + + return ExtractMembersFromTypenameInternal(typeNameValue, currentSeparatorPos, structure, members); } diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserState.h b/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserState.h index a7803676..c23b3c80 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserState.h +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserState.h @@ -11,17 +11,22 @@ class CommandsParserState IDataRepository* m_repository; StructureInformation* m_in_use; + static MemberInformation* GetMemberWithName(const std::string& memberName, StructureInformation* type); + static bool GetNextTypenameSeparatorPos(const std::string& typeNameValue, unsigned startPos, unsigned& separatorPos); + static bool ExtractMembersFromTypenameInternal(const std::string& typeNameValue, unsigned typeNameOffset, StructureInformation* type, std::vector& members); + public: explicit CommandsParserState(IDataRepository* repository); _NODISCARD const IDataRepository* GetRepository() const; void AddBlock(std::unique_ptr block) const; + void SetArchitecture(Architecture architecture) const; void SetGame(std::string gameName) const; _NODISCARD StructureInformation* GetInUse() const; void SetInUse(StructureInformation* structure); - bool GetMembersFromParts(const std::string& typeNameValue, StructureInformation* baseType, std::vector& members); - bool GetTypenameAndMembersFromParts(const std::string& typeNameValue, StructureInformation*& structure, std::vector& members); + bool GetMembersFromTypename(const std::string& typeNameValue, StructureInformation* baseType, std::vector& members) const; + bool GetTypenameAndMembersFromTypename(const std::string& typeNameValue, StructureInformation*& structure, std::vector& members) const; }; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserValue.cpp b/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserValue.cpp index a0b4493b..4ce677a9 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserValue.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserValue.cpp @@ -105,6 +105,13 @@ CommandsParserValue CommandsParserValue::TypeName(const TokenPos pos, std::strin return pv; } +CommandsParserValue CommandsParserValue::OpType(const TokenPos pos, const OperationType* operationType) +{ + CommandsParserValue pv(pos, CommandsParserValueType::OPERATION_TYPE); + pv.m_value.op_type_value = operationType; + return pv; +} + CommandsParserValue::CommandsParserValue(const TokenPos pos, const CommandsParserValueType type) : m_pos(pos), m_type(type), @@ -201,3 +208,9 @@ std::string& CommandsParserValue::TypeNameValue() const assert(m_type == CommandsParserValueType::TYPE_NAME); return *m_value.string_value; } + +const OperationType* CommandsParserValue::OpTypeValue() const +{ + assert(m_type == CommandsParserValueType::OPERATION_TYPE); + return m_value.op_type_value; +} diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserValue.h b/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserValue.h index 44dd5089..2a26c9bd 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserValue.h +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Impl/CommandsParserValue.h @@ -3,6 +3,8 @@ #include + +#include "Domain/Evaluation/OperationType.h" #include "Parsing/IParserValue.h" #include "Utils/ClassUtils.h" #include "Parsing/TokenPos.h" @@ -43,6 +45,7 @@ enum class CommandsParserValueType // Parser created TYPE_NAME, + OPERATION_TYPE, // End MAX @@ -60,6 +63,7 @@ public: int int_value; double double_value; std::string* string_value; + const OperationType* op_type_value; } m_value; static CommandsParserValue Invalid(TokenPos pos); @@ -78,6 +82,7 @@ public: static CommandsParserValue String(TokenPos pos, std::string* stringValue); static CommandsParserValue Identifier(TokenPos pos, std::string* identifier); static CommandsParserValue TypeName(TokenPos pos, std::string* typeName); + static CommandsParserValue OpType(TokenPos pos, const OperationType* operationType); private: CommandsParserValue(TokenPos pos, CommandsParserValueType type); @@ -99,4 +104,5 @@ public: _NODISCARD std::string& IdentifierValue() const; _NODISCARD size_t IdentifierHash() const; _NODISCARD std::string& TypeNameValue() const; + _NODISCARD const OperationType* OpTypeValue() const; }; \ No newline at end of file diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Matcher/CommandsCommonMatchers.cpp b/src/ZoneCodeGeneratorLib/Parsing/Commands/Matcher/CommandsCommonMatchers.cpp index 9a560f80..d6360a5e 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/Matcher/CommandsCommonMatchers.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Matcher/CommandsCommonMatchers.cpp @@ -1,8 +1,13 @@ #include "CommandsCommonMatchers.h" +#include #include +#include #include "CommandsMatcherFactory.h" +#include "Domain/Evaluation/OperandDynamic.h" +#include "Domain/Evaluation/OperandStatic.h" +#include "Domain/Evaluation/Operation.h" std::unique_ptr CommandsCommonMatchers::Typename(const supplier_t* labelSupplier) { @@ -86,43 +91,23 @@ std::unique_ptr CommandsCommonMatchers::Array }); } -static constexpr int TAG_OPERATION_TYPE = std::numeric_limits::max() - 1; -static constexpr int TAG_ADD = std::numeric_limits::max() - 2; -static constexpr int TAG_MINUS = std::numeric_limits::max() - 3; -static constexpr int TAG_MULTIPLY = std::numeric_limits::max() - 4; -static constexpr int TAG_DIVIDE = std::numeric_limits::max() - 5; -static constexpr int TAG_REMAINDER = std::numeric_limits::max() - 6; -static constexpr int TAG_BITWISE_AND = std::numeric_limits::max() - 7; -static constexpr int TAG_BITWISE_XOR = std::numeric_limits::max() - 8; -static constexpr int TAG_BITWISE_OR = std::numeric_limits::max() - 9; -static constexpr int TAG_SHIFT_LEFT = std::numeric_limits::max() - 10; -static constexpr int TAG_SHIFT_RIGHT = std::numeric_limits::max() - 11; -static constexpr int TAG_GREATER_THAN = std::numeric_limits::max() - 12; -static constexpr int TAG_GREATER_EQUAL = std::numeric_limits::max() - 13; -static constexpr int TAG_LESS_THAN = std::numeric_limits::max() - 14; -static constexpr int TAG_LESS_EQUAL = std::numeric_limits::max() - 15; -static constexpr int TAG_EQUALS = std::numeric_limits::max() - 16; -static constexpr int TAG_NOT_EQUAL = std::numeric_limits::max() - 17; -static constexpr int TAG_LOGICAL_AND = std::numeric_limits::max() - 18; -static constexpr int TAG_LOGICAL_OR = std::numeric_limits::max() - 19; -static constexpr int TAG_OPERAND = std::numeric_limits::max() - 20; -static constexpr int TAG_OPERAND_TYPENAME = std::numeric_limits::max() - 21; -static constexpr int TAG_OPERAND_ARRAY = std::numeric_limits::max() - 22; -static constexpr int TAG_OPERAND_ARRAY_END = std::numeric_limits::max() - 23; -static constexpr int TAG_OPERAND_INTEGER = std::numeric_limits::max() - 24; -static constexpr int TAG_OPERAND_FLOATING_POINT = std::numeric_limits::max() - 25; -static constexpr int TAG_EVALUATION_NOT = std::numeric_limits::max() - 26; -static constexpr int TAG_EVALUATION_PARENTHESIS = std::numeric_limits::max() - 27; -static constexpr int TAG_EVALUATION_PARENTHESIS_END = std::numeric_limits::max() - 28; -static constexpr int TAG_EVALUATION = std::numeric_limits::max() - 29; -static constexpr int TAG_EVALUATION_OPERATION = std::numeric_limits::max() - 30; +static constexpr int TAG_OPERAND = std::numeric_limits::max() - 1; +static constexpr int TAG_OPERAND_TYPENAME = std::numeric_limits::max() - 2; +static constexpr int TAG_OPERAND_ARRAY = std::numeric_limits::max() - 3; +static constexpr int TAG_OPERAND_ARRAY_END = std::numeric_limits::max() - 4; +static constexpr int TAG_OPERAND_INTEGER = std::numeric_limits::max() - 5; +static constexpr int TAG_EVALUATION_NOT = std::numeric_limits::max() - 6; +static constexpr int TAG_EVALUATION_PARENTHESIS = std::numeric_limits::max() - 7; +static constexpr int TAG_EVALUATION_PARENTHESIS_END = std::numeric_limits::max() - 8; +static constexpr int TAG_EVALUATION = std::numeric_limits::max() - 9; +static constexpr int TAG_EVALUATION_OPERATION = std::numeric_limits::max() - 10; static constexpr int CAPTURE_OPERAND_TYPENAME = std::numeric_limits::max() - 1; static constexpr int CAPTURE_OPERAND_ARRAY = std::numeric_limits::max() - 1; static constexpr int CAPTURE_OPERAND_INTEGER = std::numeric_limits::max() - 2; -static constexpr int CAPTURE_OPERAND_FLOATING_POINT = std::numeric_limits::max() - 3; +static constexpr int CAPTURE_OPERATION_TYPE = std::numeric_limits::max() - 3; -std::unique_ptr CommandsCommonMatchers::OperandArray(const supplier_t* labelSupplier) +std::unique_ptr CommandsCommonMatchers::ParseOperandArray(const supplier_t* labelSupplier) { const CommandsMatcherFactory create(labelSupplier); @@ -133,44 +118,97 @@ std::unique_ptr CommandsCommonMatchers::Opera }).Tag(TAG_OPERAND_ARRAY); } -std::unique_ptr CommandsCommonMatchers::Operand(const supplier_t* labelSupplier) +std::unique_ptr CommandsCommonMatchers::ParseOperand(const supplier_t* labelSupplier) { const CommandsMatcherFactory create(labelSupplier); return create.Or({ create.And({ create.Label(LABEL_TYPENAME).Capture(CAPTURE_OPERAND_TYPENAME), - create.OptionalLoop(MatcherFactoryWrapper(OperandArray(labelSupplier)).Capture(CAPTURE_OPERAND_ARRAY)) + create.OptionalLoop(MatcherFactoryWrapper(ParseOperandArray(labelSupplier)).Capture(CAPTURE_OPERAND_ARRAY)) }).Tag(TAG_OPERAND_TYPENAME), - create.Integer().Tag(TAG_OPERAND_INTEGER).Capture(CAPTURE_OPERAND_INTEGER), - create.FloatingPoint().Tag(TAG_OPERAND_FLOATING_POINT).Capture(CAPTURE_OPERAND_FLOATING_POINT) + create.Integer().Tag(TAG_OPERAND_INTEGER).Capture(CAPTURE_OPERAND_INTEGER) }).Tag(TAG_OPERAND); } -std::unique_ptr CommandsCommonMatchers::OperationType(const supplier_t* labelSupplier) +std::unique_ptr CommandsCommonMatchers::ParseOperationType(const supplier_t* labelSupplier) { const CommandsMatcherFactory create(labelSupplier); return create.Or({ - create.Char('+').Tag(TAG_ADD), - create.Char('-').Tag(TAG_MINUS), - create.Char('*').Tag(TAG_MULTIPLY), - create.Char('/').Tag(TAG_DIVIDE), - create.Char('%').Tag(TAG_REMAINDER), - create.Char('&').Tag(TAG_BITWISE_AND), - create.Char('^').Tag(TAG_BITWISE_XOR), - create.Char('|').Tag(TAG_BITWISE_OR), - create.Type(CommandsParserValueType::SHIFT_LEFT).Tag(TAG_SHIFT_LEFT), - create.Type(CommandsParserValueType::SHIFT_RIGHT).Tag(TAG_SHIFT_RIGHT), - create.Char('>').Tag(TAG_GREATER_THAN), - create.Type(CommandsParserValueType::GREATER_EQUAL).Tag(TAG_GREATER_EQUAL), - create.Char('<').Tag(TAG_LESS_THAN), - create.Type(CommandsParserValueType::LESS_EQUAL).Tag(TAG_LESS_EQUAL), - create.Type(CommandsParserValueType::EQUALS).Tag(TAG_EQUALS), - create.Type(CommandsParserValueType::NOT_EQUAL).Tag(TAG_NOT_EQUAL), - create.Type(CommandsParserValueType::LOGICAL_AND).Tag(TAG_LOGICAL_AND), - create.Type(CommandsParserValueType::LOGICAL_OR).Tag(TAG_LOGICAL_OR) - }).Tag(TAG_OPERATION_TYPE); + create.Char('+').Transform([](CommandsMatcherFactory::token_list_t& values) + { + return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_ADD); + }), + create.Char('-').Transform([](CommandsMatcherFactory::token_list_t& values) + { + return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_SUBTRACT); + }), + create.Char('*').Transform([](CommandsMatcherFactory::token_list_t& values) + { + return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_MULTIPLY); + }), + create.Char('/').Transform([](CommandsMatcherFactory::token_list_t& values) + { + return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_DIVIDE); + }), + create.Char('%').Transform([](CommandsMatcherFactory::token_list_t& values) + { + return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_REMAINDER); + }), + create.Char('&').Transform([](CommandsMatcherFactory::token_list_t& values) + { + return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_BITWISE_AND); + }), + create.Char('^').Transform([](CommandsMatcherFactory::token_list_t& values) + { + return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_BITWISE_XOR); + }), + create.Char('|').Transform([](CommandsMatcherFactory::token_list_t& values) + { + return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_BITWISE_OR); + }), + create.Type(CommandsParserValueType::SHIFT_LEFT).Transform([](CommandsMatcherFactory::token_list_t& values) + { + return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_SHIFT_LEFT); + }), + create.Type(CommandsParserValueType::SHIFT_RIGHT).Transform([](CommandsMatcherFactory::token_list_t& values) + { + return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_SHIFT_RIGHT); + }), + create.Char('>').Transform([](CommandsMatcherFactory::token_list_t& values) + { + return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_GREATER_THAN); + }), + create.Type(CommandsParserValueType::GREATER_EQUAL).Transform([](CommandsMatcherFactory::token_list_t& values) + { + return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_GREATER_EQUAL_THAN); + }), + create.Char('<').Transform([](CommandsMatcherFactory::token_list_t& values) + { + return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_LESS_THAN); + }), + create.Type(CommandsParserValueType::LESS_EQUAL).Transform([](CommandsMatcherFactory::token_list_t& values) + { + return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_LESS_EQUAL_THAN); + }), + create.Type(CommandsParserValueType::EQUALS).Transform([](CommandsMatcherFactory::token_list_t& values) + { + return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_EQUALS); + }), + create.Type(CommandsParserValueType::NOT_EQUAL).Transform([](CommandsMatcherFactory::token_list_t& values) + { + return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_NOT_EQUAL); + }), + create.Type(CommandsParserValueType::LOGICAL_AND).Transform([](CommandsMatcherFactory::token_list_t& values) + { + return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_AND); + }), + create.Type(CommandsParserValueType::LOGICAL_OR).Transform([](CommandsMatcherFactory::token_list_t& values) + { + return CommandsParserValue::OpType(values[0].get().GetPos(), OperationType::OPERATION_OR); + }) + }).Capture(CAPTURE_OPERATION_TYPE); } std::unique_ptr CommandsCommonMatchers::Evaluation(const supplier_t* labelSupplier) @@ -185,21 +223,123 @@ std::unique_ptr CommandsCommonMatchers::Evalu create.Label(LABEL_EVALUATION), create.Char(')').Tag(TAG_EVALUATION_PARENTHESIS_END) }).Tag(TAG_EVALUATION_PARENTHESIS), - Operand(labelSupplier) + ParseOperand(labelSupplier) }), create.Optional(create.And({ - OperationType(labelSupplier), + ParseOperationType(labelSupplier), create.Label(LABEL_EVALUATION) - })).Tag(TAG_EVALUATION_OPERATION) + }).Tag(TAG_EVALUATION_OPERATION)) }).Tag(TAG_EVALUATION); } -std::unique_ptr CommandsCommonMatchers::ParseEvaluation(CommandsParserState* state, SequenceResult& result) +std::unique_ptr CommandsCommonMatchers::ProcessEvaluationInParenthesis(CommandsParserState* state, SequenceResult& result) +{ + const auto isNegated = result.PeekAndRemoveIfTag(TAG_EVALUATION_NOT) == TAG_EVALUATION_NOT; + + auto processedEvaluation = ProcessEvaluation(state, result); + + if (result.PeekAndRemoveIfTag(TAG_EVALUATION_PARENTHESIS_END) != TAG_EVALUATION_PARENTHESIS_END) + throw ParsingException(TokenPos(), "Expected parenthesis end tag @ EvaluationInParenthesis"); + + if (isNegated) + processedEvaluation = std::make_unique(OperationType::OPERATION_EQUALS, std::move(processedEvaluation), std::make_unique(0)); + + return processedEvaluation; +} + +std::unique_ptr CommandsCommonMatchers::ProcessOperand(CommandsParserState* state, SequenceResult& result, StructureInformation* currentType) +{ + const auto nextTag = result.NextTag(); + + if (nextTag == TAG_OPERAND_INTEGER) + { + return std::make_unique(result.NextCapture(CAPTURE_OPERAND_INTEGER).IntegerValue()); + } + + if (nextTag == TAG_OPERAND_TYPENAME) + { + const auto& typeNameToken = result.NextCapture(CAPTURE_OPERAND_TYPENAME); + std::vector> arrayIndexEvaluations; + + while (result.PeekAndRemoveIfTag(TAG_OPERAND_ARRAY) == TAG_OPERAND_ARRAY) + { + arrayIndexEvaluations.emplace_back(ProcessEvaluation(state, result, currentType)); + + if (result.PeekAndRemoveIfTag(TAG_OPERAND_ARRAY_END) != TAG_OPERAND_ARRAY_END) + throw ParsingException(TokenPos(), "Expected operand array end tag @ Operand"); + } + + auto* foundEnumMember = state->GetRepository()->GetEnumMemberByName(typeNameToken.TypeNameValue()); + if (foundEnumMember != nullptr) + return std::make_unique(foundEnumMember); + + StructureInformation* structure; + std::vector memberChain; + if (state->GetTypenameAndMembersFromTypename(typeNameToken.TypeNameValue(), structure, memberChain)) + return std::make_unique(structure, std::move(memberChain), std::move(arrayIndexEvaluations)); + + if (currentType != nullptr && state->GetMembersFromTypename(typeNameToken.TypeNameValue(), currentType, memberChain)) + return std::make_unique(currentType, std::move(memberChain), std::move(arrayIndexEvaluations)); + + throw ParsingException(typeNameToken.GetPos(), "Unknown type"); + } + + throw ParsingException(TokenPos(), "Unknown operand type @ Operand"); +} + +std::unique_ptr CommandsCommonMatchers::ProcessEvaluation(CommandsParserState* state, SequenceResult& result) +{ + return ProcessEvaluation(state, result, nullptr); +} + +std::unique_ptr CommandsCommonMatchers::ProcessEvaluation(CommandsParserState* state, SequenceResult& result, StructureInformation* currentType) { if (result.PeekAndRemoveIfTag(TAG_EVALUATION) != TAG_EVALUATION) return nullptr; + if (currentType == state->GetInUse()) + currentType = nullptr; + std::list> operands; + std::list> operators; + + while (true) + { + std::unique_ptr firstStatementPart; + const auto nextTag = result.NextTag(); + switch (nextTag) + { + case TAG_EVALUATION_PARENTHESIS: + firstStatementPart = ProcessEvaluationInParenthesis(state, result); + break; + + case TAG_OPERAND: + firstStatementPart = ProcessOperand(state, result, currentType); + break; + + default: + throw ParsingException(TokenPos(), "Invalid followup tag @ Evaluation"); + } + operands.emplace_back(std::move(firstStatementPart)); + + if (result.PeekAndRemoveIfTag(TAG_EVALUATION_OPERATION) == TAG_EVALUATION_OPERATION) + operators.emplace_back(operators.size(), result.NextCapture(CAPTURE_OPERATION_TYPE).OpTypeValue()); + else + break; + + if (result.PeekAndRemoveIfTag(TAG_EVALUATION) != TAG_EVALUATION) + throw ParsingException(TokenPos(), "Expected EvaluationTag @ Evaluation"); + } + + operators.sort([](const std::pair& p1, const std::pair& p2) + { + return p1.second->m_precedence > p2.second->m_precedence; + }); + + while (!operators.empty()) + { + operators.pop_back(); + } return nullptr; } diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Matcher/CommandsCommonMatchers.h b/src/ZoneCodeGeneratorLib/Parsing/Commands/Matcher/CommandsCommonMatchers.h index 28ab35ee..7514257f 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/Matcher/CommandsCommonMatchers.h +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Matcher/CommandsCommonMatchers.h @@ -4,6 +4,7 @@ #include #include "Domain/Evaluation/IEvaluation.h" +#include "Domain/Evaluation/OperationType.h" #include "Parsing/Commands/Impl/CommandsParserState.h" #include "Parsing/Commands/Impl/CommandsParserValue.h" #include "Parsing/Matcher/AbstractMatcher.h" @@ -24,11 +25,15 @@ public: static std::unique_ptr ArrayDef(const supplier_t* labelSupplier); private: - static std::unique_ptr OperandArray(const supplier_t* labelSupplier); - static std::unique_ptr Operand(const supplier_t* labelSupplier); - static std::unique_ptr OperationType(const supplier_t* labelSupplier); + static std::unique_ptr ParseOperandArray(const supplier_t* labelSupplier); + static std::unique_ptr ParseOperand(const supplier_t* labelSupplier); + static std::unique_ptr ParseOperationType(const supplier_t* labelSupplier); + + static std::unique_ptr ProcessEvaluationInParenthesis(CommandsParserState* state, SequenceResult& result); + static std::unique_ptr ProcessOperand(CommandsParserState* state, SequenceResult& result, StructureInformation* currentType); public: static std::unique_ptr Evaluation(const supplier_t* labelSupplier); - static std::unique_ptr ParseEvaluation(CommandsParserState* state, SequenceResult& result); + static std::unique_ptr ProcessEvaluation(CommandsParserState* state, SequenceResult& result); + static std::unique_ptr ProcessEvaluation(CommandsParserState* state, SequenceResult& result, StructureInformation* currentType); }; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceArchitecture.cpp b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceArchitecture.cpp new file mode 100644 index 00000000..842c4922 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceArchitecture.cpp @@ -0,0 +1,35 @@ +#include "SequenceArchitecture.h" + +#include "Parsing/Commands/Matcher/CommandsMatcherFactory.h" +#include "Parsing/Commands/Matcher/CommandsCommonMatchers.h" + +SequenceArchitecture::SequenceArchitecture() +{ + const CommandsMatcherFactory create(this); + + AddMatchers({ + create.Keyword("architecture"), + create.Or({ + create.Keyword("x86").Tag(TAG_X86), + create.Keyword("x64").Tag(TAG_X64) + }), + create.Char(';') + }); +} + +void SequenceArchitecture::ProcessMatch(CommandsParserState* state, SequenceResult& result) const +{ + switch (result.NextTag()) + { + case TAG_X86: + state->SetArchitecture(Architecture::X86); + break; + + case TAG_X64: + state->SetArchitecture(Architecture::X64); + break; + + default: + throw ParsingException(TokenPos(), "Unknown architecture!"); + } +} diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceArchitecture.h b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceArchitecture.h new file mode 100644 index 00000000..a9f19f92 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceArchitecture.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Parsing/Commands/Impl/CommandsParser.h" + +class SequenceArchitecture final : public CommandsParser::sequence_t +{ + static constexpr auto TAG_X86 = 1; + static constexpr auto TAG_X64 = 2; + +protected: + void ProcessMatch(CommandsParserState* state, SequenceResult& result) const override; + +public: + SequenceArchitecture(); +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceArrayCount.cpp b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceArrayCount.cpp index adb769d8..48a1284e 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceArrayCount.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceArrayCount.cpp @@ -1,5 +1,7 @@ #include "SequenceArrayCount.h" + +#include "Domain/Definition/ArrayDeclarationModifier.h" #include "Parsing/Commands/Matcher/CommandsMatcherFactory.h" #include "Parsing/Commands/Matcher/CommandsCommonMatchers.h" @@ -13,11 +15,38 @@ SequenceArrayCount::SequenceArrayCount() create.Keyword("set"), create.Keyword("arraycount"), create.Label(CommandsCommonMatchers::LABEL_TYPENAME).Capture(CAPTURE_TYPE), - create.Label(CommandsCommonMatchers::LABEL_EVALUATION).Capture(CAPTURE_EVALUATION), + create.Label(CommandsCommonMatchers::LABEL_EVALUATION), create.Char(';') }); } void SequenceArrayCount::ProcessMatch(CommandsParserState* state, SequenceResult& result) const { + const auto& typeNameToken = result.NextCapture(CAPTURE_TYPE); + + StructureInformation* structure; + std::vector memberChain; + if (!state->GetTypenameAndMembersFromTypename(typeNameToken.TypeNameValue(), structure, memberChain)) + throw ParsingException(typeNameToken.GetPos(), "Unknown type"); + + if(memberChain.empty()) + throw ParsingException(typeNameToken.GetPos(), "Must specify type with member"); + + const auto& memberDeclarationModifiers = memberChain.back()->m_member->m_type_declaration->m_declaration_modifiers; + ArrayDeclarationModifier* arrayModifier = nullptr; + for (const auto& modifier : memberDeclarationModifiers) + { + if (modifier->GetType() == DeclarationModifierType::ARRAY) + { + arrayModifier = dynamic_cast(modifier.get()); + break; + } + } + + if (arrayModifier == nullptr) + throw ParsingException(typeNameToken.GetPos(), "Specified member is not an array"); + + auto evaluation = CommandsCommonMatchers::ProcessEvaluation(state, result, structure); + + arrayModifier->m_dynamic_count_evaluation = std::move(evaluation); } diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceArrayCount.h b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceArrayCount.h index 136e8dcf..d134304f 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceArrayCount.h +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceArrayCount.h @@ -5,7 +5,6 @@ class SequenceArrayCount final : public CommandsParser::sequence_t { static constexpr auto CAPTURE_TYPE = 1; - static constexpr auto CAPTURE_EVALUATION = 2; protected: void ProcessMatch(CommandsParserState* state, SequenceResult& result) const override; diff --git a/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceUse.cpp b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceUse.cpp index 0defd8aa..5a82381d 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceUse.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Commands/Sequence/SequenceUse.cpp @@ -17,4 +17,14 @@ SequenceUse::SequenceUse() void SequenceUse::ProcessMatch(CommandsParserState* state, SequenceResult& result) const { + const auto& typeNameToken = result.NextCapture(CAPTURE_TYPE); + auto* definition = state->GetRepository()->GetDataDefinitionByName(typeNameToken.TypeNameValue()); + if (definition == nullptr) + throw ParsingException(typeNameToken.GetPos(), "Unknown type"); + + auto* definitionWithMembers = dynamic_cast(definition); + if (definitionWithMembers == nullptr) + throw ParsingException(typeNameToken.GetPos(), "Type must be able to have members"); + + state->SetInUse(state->GetRepository()->GetInformationFor(definitionWithMembers)); } diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Block/HeaderBlockStruct.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/Block/HeaderBlockStruct.cpp index a322bcfe..1b2634c0 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Header/Block/HeaderBlockStruct.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Block/HeaderBlockStruct.cpp @@ -102,7 +102,7 @@ void HeaderBlockStruct::SetBlockName(const TokenPos& nameTokenPos, std::string n bool HeaderBlockStruct::IsDefiningVariable() { - return !m_is_typedef && !m_variable_name.empty(); + return true; } DataDefinition* HeaderBlockStruct::GetVariableType() diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/Block/HeaderBlockUnion.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/Block/HeaderBlockUnion.cpp index c93c69f2..a23fcd91 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Header/Block/HeaderBlockUnion.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/Block/HeaderBlockUnion.cpp @@ -102,7 +102,7 @@ void HeaderBlockUnion::SetBlockName(const TokenPos& nameTokenPos, std::string na bool HeaderBlockUnion::IsDefiningVariable() { - return !m_is_typedef && !m_variable_name.empty(); + return true; } DataDefinition* HeaderBlockUnion::GetVariableType() diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.cpp b/src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.cpp index a4ca4e21..a3036f6e 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.cpp +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.cpp @@ -1,6 +1,6 @@ #include "HeaderFileReader.h" - +#include #include #include @@ -11,6 +11,9 @@ #include "Parsing/Impl/IncludingStreamProxy.h" #include "Parsing/Impl/PackDefinitionStreamProxy.h" #include "Parsing/Impl/ParserFilesystemStream.h" +#include "Parsing/PostProcessing/CreateMemberInformationPostProcessor.h" +#include "Parsing/PostProcessing/CreateStructureInformationPostProcessor.h" +#include "Parsing/PostProcessing/IPostProcessor.h" HeaderFileReader::HeaderFileReader(const ZoneCodeGeneratorArguments* args, std::string filename) : m_args(args), @@ -18,6 +21,7 @@ HeaderFileReader::HeaderFileReader(const ZoneCodeGeneratorArguments* args, std:: m_pack_value_supplier(nullptr), m_stream(nullptr) { + SetupPostProcessors(); } bool HeaderFileReader::OpenBaseStream() @@ -51,6 +55,13 @@ void HeaderFileReader::SetupStreamProxies() m_open_streams.emplace_back(std::move(definesProxy)); } +void HeaderFileReader::SetupPostProcessors() +{ + // Order is important + m_post_processors.emplace_back(std::make_unique()); + m_post_processors.emplace_back(std::make_unique()); +} + bool HeaderFileReader::ReadHeaderFile(IDataRepository* repository) { std::cout << "Reading header file: " << m_filename << std::endl; @@ -64,11 +75,17 @@ bool HeaderFileReader::ReadHeaderFile(IDataRepository* repository) const auto parser = std::make_unique(lexer.get(), m_pack_value_supplier); const auto start = std::chrono::steady_clock::now(); - const auto result = parser->Parse(); + auto result = parser->Parse(); if (result) - parser->SaveToRepository(repository); + result = parser->SaveToRepository(repository); const auto end = std::chrono::steady_clock::now(); std::cout << "Processing header took " << std::chrono::duration_cast(end - start).count() << "ms" << std::endl; - return result; + if (!result) + return false; + + return std::all_of(m_post_processors.begin(), m_post_processors.end(), [repository](const std::unique_ptr& postProcessor) + { + return postProcessor->PostProcess(repository); + }); } diff --git a/src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.h b/src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.h index 2dded170..6b9ed259 100644 --- a/src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.h +++ b/src/ZoneCodeGeneratorLib/Parsing/Header/HeaderFileReader.h @@ -5,6 +5,7 @@ #include "ZoneCodeGeneratorArguments.h" #include "Parsing/IPackValueSupplier.h" #include "Parsing/IParserLineStream.h" +#include "Parsing/PostProcessing/IPostProcessor.h" #include "Persistence/IDataRepository.h" class HeaderFileReader @@ -19,8 +20,11 @@ class HeaderFileReader const IPackValueSupplier* m_pack_value_supplier; IParserLineStream* m_stream; + std::vector> m_post_processors; + bool OpenBaseStream(); void SetupStreamProxies(); + void SetupPostProcessors(); public: HeaderFileReader(const ZoneCodeGeneratorArguments* args, std::string filename); diff --git a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CalculateSizeAndAlignPostProcessor.cpp b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CalculateSizeAndAlignPostProcessor.cpp new file mode 100644 index 00000000..af0e984b --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CalculateSizeAndAlignPostProcessor.cpp @@ -0,0 +1,300 @@ +#include "CalculateSizeAndAlignPostProcessor.h" + +#include +#include +#include + +#include "Domain/Definition/ArrayDeclarationModifier.h" +#include "Utils/AlignmentUtils.h" + +unsigned CalculateSizeAndAlignPostProcessor::GetPointerSizeForArchitecture(const Architecture architecture) +{ + switch (architecture) + { + case Architecture::X86: + return sizeof(uint32_t); + + case Architecture::X64: + return sizeof(uint64_t); + + default: + assert(false); + return sizeof(uint32_t); + } +} + +bool CalculateSizeAndAlignPostProcessor::CalculateAlign(IDataRepository* repository, TypeDeclaration* declaration) +{ + auto hasPointerModifier = false; + for (const auto& declarationModifier : declaration->m_declaration_modifiers) + { + if (declarationModifier->GetType() == DeclarationModifierType::POINTER) + { + hasPointerModifier = true; + break; + } + } + + if (hasPointerModifier) + { + declaration->m_alignment = GetPointerSizeForArchitecture(repository->GetArchitecture()); + } + else + { + if (!CalculateFieldsIfNecessary(repository, declaration->m_type)) + return false; + declaration->m_alignment = declaration->m_type->GetAlignment(); + if (declaration->m_type->GetForceAlignment()) + declaration->m_flags |= TypeDeclaration::FLAG_ALIGNMENT_FORCED; + } + + return true; +} + +bool CalculateSizeAndAlignPostProcessor::CalculateAlign(IDataRepository* repository, DefinitionWithMembers* definition) +{ + if (definition->m_has_alignment_override) + { + definition->m_flags |= DefinitionWithMembers::FLAG_ALIGNMENT_FORCED; + definition->m_alignment = definition->m_alignment_override; + } + else + { + definition->m_alignment = 0; + for (const auto& member : definition->m_members) + { + if (!CalculateFields(repository, member->m_type_declaration.get())) + return false; + + const auto memberAlignment = member->GetAlignment(); + if (memberAlignment > definition->m_alignment) + definition->m_alignment = memberAlignment; + } + } + + return true; +} + +bool CalculateSizeAndAlignPostProcessor::CalculateSize(IDataRepository* repository, TypeDeclaration* declaration) +{ + if (declaration->m_declaration_modifiers.empty()) + { + if (!CalculateFieldsIfNecessary(repository, declaration->m_type)) + return false; + declaration->m_size = declaration->m_type->GetSize(); + } + else + { + auto currentSize = 0u; + + // If the first modifier is a pointer we do not need the actual type size + if (declaration->m_declaration_modifiers.back()->GetType() != DeclarationModifierType::POINTER) + { + if (!CalculateFieldsIfNecessary(repository, declaration->m_type)) + return false; + currentSize = declaration->m_type->GetSize(); + } + + for (auto i = declaration->m_declaration_modifiers.size(); i > 0; i--) + { + const auto& declarationModifier = declaration->m_declaration_modifiers[i - 1]; + + switch (declarationModifier->GetType()) + { + case DeclarationModifierType::POINTER: + currentSize = GetPointerSizeForArchitecture(repository->GetArchitecture()); + break; + + case DeclarationModifierType::ARRAY: + currentSize *= dynamic_cast(declarationModifier.get())->m_size; + break; + } + } + + declaration->m_size = currentSize; + } + + return true; +} + +bool CalculateSizeAndAlignPostProcessor::CalculateSize(IDataRepository* repository, StructDefinition* definition) +{ + definition->m_size = 0; + auto currentBitOffset = 0u; + + for (const auto& member : definition->m_members) + { + if (!CalculateFields(repository, member->m_type_declaration.get())) + return false; + + if (member->m_type_declaration->m_has_custom_bit_size) + { + currentBitOffset += member->m_type_declaration->m_custom_bit_size; + } + else + { + if (currentBitOffset > 0) + { + currentBitOffset = AlignmentUtils::Align(currentBitOffset, 8u); + definition->m_size += currentBitOffset / 8; + currentBitOffset = 0; + } + + definition->m_size = AlignmentUtils::Align(definition->m_size, member->GetForceAlignment() ? member->GetAlignment() : std::min(member->GetAlignment(), definition->m_pack)); + definition->m_size += member->m_type_declaration->GetSize(); + } + } + + if (currentBitOffset > 0) + { + currentBitOffset = AlignmentUtils::Align(currentBitOffset, 8u); + definition->m_size += currentBitOffset / 8; + } + + definition->m_size = AlignmentUtils::Align(definition->m_size, definition->m_alignment); + + return true; +} + +bool CalculateSizeAndAlignPostProcessor::CalculateSize(IDataRepository* repository, UnionDefinition* definition) +{ + definition->m_size = 0; + + for (const auto& member : definition->m_members) + { + if (!CalculateFields(repository, member->m_type_declaration.get())) + return false; + + const auto memberSize = member->m_type_declaration->GetSize(); + if (memberSize > definition->m_size) + definition->m_size = memberSize; + } + + definition->m_size = AlignmentUtils::Align(definition->m_size, definition->m_alignment); + + return true; +} + +bool CalculateSizeAndAlignPostProcessor::CalculateFields(IDataRepository* repository, TypeDeclaration* declaration) +{ + if (declaration->m_flags & TypeDeclaration::FLAG_FIELDS_CALCULATED) + return true; + + if(!CalculateAlign(repository, declaration) + || !CalculateSize(repository, declaration)) + { + return false; + } + + declaration->m_flags |= TypeDeclaration::FLAG_FIELDS_CALCULATED; + return true; +} + +bool CalculateSizeAndAlignPostProcessor::CalculateFields(IDataRepository* repository, StructDefinition* structDefinition) +{ + if (structDefinition->m_flags & DefinitionWithMembers::FLAG_FIELDS_CALCULATED) + return true; + if (structDefinition->m_flags & DefinitionWithMembers::FLAG_FIELDS_CALCULATING) + { + std::cout << "Detected circular dependency:\n"; + return false; + } + + structDefinition->m_flags |= DefinitionWithMembers::FLAG_FIELDS_CALCULATING; + + if (!CalculateAlign(repository, structDefinition) + || !CalculateSize(repository, structDefinition)) + { + return false; + } + + structDefinition->m_flags &= ~DefinitionWithMembers::FLAG_FIELDS_CALCULATING; + structDefinition->m_flags |= DefinitionWithMembers::FLAG_FIELDS_CALCULATED; + + return true; +} + +bool CalculateSizeAndAlignPostProcessor::CalculateFields(IDataRepository* repository, UnionDefinition* unionDefinition) +{ + if (unionDefinition->m_flags & DefinitionWithMembers::FLAG_FIELDS_CALCULATED) + return true; + if (unionDefinition->m_flags & DefinitionWithMembers::FLAG_FIELDS_CALCULATING) + { + std::cout << "Detected circular dependency:\n"; + return false; + } + + unionDefinition->m_flags |= DefinitionWithMembers::FLAG_FIELDS_CALCULATING; + + if (!CalculateAlign(repository, unionDefinition) + || !CalculateSize(repository, unionDefinition)) + { + return false; + } + + unionDefinition->m_flags &= ~DefinitionWithMembers::FLAG_FIELDS_CALCULATING; + unionDefinition->m_flags |= DefinitionWithMembers::FLAG_FIELDS_CALCULATED; + + return true; +} + +bool CalculateSizeAndAlignPostProcessor::CalculateFieldsIfNecessary(IDataRepository* repository, const DataDefinition* definition) +{ + if(definition->GetType() == DataDefinitionType::STRUCT) + { + // We can do a const cast here because the only reason that field is const anyway is because it could be a base type + return CalculateFields(repository, dynamic_cast(const_cast(definition))); + } + + if(definition->GetType() == DataDefinitionType::UNION) + { + // We can do a const cast here because the only reason that field is const anyway is because it could be a base type + return CalculateFields(repository, dynamic_cast(const_cast(definition))); + } + + if(definition->GetType() == DataDefinitionType::TYPEDEF) + { + // We can do a const cast here because the only reason that field is const anyway is because it could be a base type + return CalculateFields(repository, dynamic_cast(const_cast(definition))->m_type_declaration.get()); + } + + return true; +} + +bool CalculateSizeAndAlignPostProcessor::PostProcess(IDataRepository* repository) +{ + if (repository->GetArchitecture() == Architecture::UNKNOWN) + { + std::cout << "You must set an architecture!" << std::endl; + return false; + } + + for (auto* structDefinition : repository->GetAllStructs()) + { + if (!CalculateFields(repository, structDefinition)) + { + std::cout << std::endl; + return false; + } + } + + for (auto* unionDefinition : repository->GetAllUnions()) + { + if (!CalculateFields(repository, unionDefinition)) + { + std::cout << std::endl; + return false; + } + } + + for (auto* typedefDeclaration : repository->GetAllTypedefs()) + { + if (!CalculateFields(repository, typedefDeclaration->m_type_declaration.get())) + { + std::cout << std::endl; + return false; + } + } + + return true; +} diff --git a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CalculateSizeAndAlignPostProcessor.h b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CalculateSizeAndAlignPostProcessor.h new file mode 100644 index 00000000..ec5adc59 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CalculateSizeAndAlignPostProcessor.h @@ -0,0 +1,20 @@ +#pragma once + +#include "IPostProcessor.h" + +class CalculateSizeAndAlignPostProcessor final : public IPostProcessor +{ + static unsigned GetPointerSizeForArchitecture(Architecture architecture); + static bool CalculateAlign(IDataRepository* repository, TypeDeclaration* declaration); + static bool CalculateAlign(IDataRepository* repository, DefinitionWithMembers* definition); + static bool CalculateSize(IDataRepository* repository, TypeDeclaration* declaration); + static bool CalculateSize(IDataRepository* repository, StructDefinition* definition); + static bool CalculateSize(IDataRepository* repository, UnionDefinition* definition); + static bool CalculateFields(IDataRepository* repository, TypeDeclaration* declaration); + static bool CalculateFields(IDataRepository* repository, StructDefinition* structDefinition); + static bool CalculateFields(IDataRepository* repository, UnionDefinition* unionDefinition); + static bool CalculateFieldsIfNecessary(IDataRepository* repository, const DataDefinition* definition); + +public: + bool PostProcess(IDataRepository* repository) override; +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CreateMemberInformationPostProcessor.cpp b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CreateMemberInformationPostProcessor.cpp new file mode 100644 index 00000000..c07052f4 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CreateMemberInformationPostProcessor.cpp @@ -0,0 +1,29 @@ +#include "CreateMemberInformationPostProcessor.h" + +#include + +bool CreateMemberInformationPostProcessor::CreateMemberInformationForStructure(IDataRepository* repository, StructureInformation* structure) const +{ + for(const auto& member : structure->m_definition->m_members) + { + StructureInformation* typeInfo = nullptr; + const auto* memberDefinition = dynamic_cast(member->m_type_declaration->m_type); + + if(memberDefinition != nullptr) + typeInfo = repository->GetInformationFor(memberDefinition); + + structure->m_ordered_members.emplace_back(std::make_unique(structure, typeInfo, member.get())); + } + + return true; +} + +bool CreateMemberInformationPostProcessor::PostProcess(IDataRepository* repository) +{ + const auto& allStructureInformation = repository->GetAllStructureInformation(); + + return std::all_of(allStructureInformation.begin(), allStructureInformation.end(), [this, repository](StructureInformation* structure) + { + return CreateMemberInformationForStructure(repository, structure); + }); +} diff --git a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CreateMemberInformationPostProcessor.h b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CreateMemberInformationPostProcessor.h new file mode 100644 index 00000000..31c83c15 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CreateMemberInformationPostProcessor.h @@ -0,0 +1,11 @@ +#pragma once + +#include "IPostProcessor.h" + +class CreateMemberInformationPostProcessor final : public IPostProcessor +{ + bool CreateMemberInformationForStructure(IDataRepository* repository, StructureInformation* structure) const; + +public: + bool PostProcess(IDataRepository* repository) override; +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CreateStructureInformationPostProcessor.cpp b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CreateStructureInformationPostProcessor.cpp new file mode 100644 index 00000000..3d95f041 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CreateStructureInformationPostProcessor.cpp @@ -0,0 +1,20 @@ +#include "CreateStructureInformationPostProcessor.h" + +bool CreateStructureInformationPostProcessor::PostProcess(IDataRepository* repository) +{ + for(auto* structDefinition : repository->GetAllStructs()) + { + auto* information = repository->GetInformationFor(structDefinition); + if(information == nullptr) + repository->Add(std::make_unique(structDefinition)); + } + + for(auto* unionDefinition : repository->GetAllUnions()) + { + auto* information = repository->GetInformationFor(unionDefinition); + if(information == nullptr) + repository->Add(std::make_unique(unionDefinition)); + } + + return true; +} diff --git a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CreateStructureInformationPostProcessor.h b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CreateStructureInformationPostProcessor.h new file mode 100644 index 00000000..040a011c --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/CreateStructureInformationPostProcessor.h @@ -0,0 +1,9 @@ +#pragma once + +#include "IPostProcessor.h" + +class CreateStructureInformationPostProcessor final : public IPostProcessor +{ +public: + bool PostProcess(IDataRepository* repository) override; +}; diff --git a/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/IPostProcessor.h b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/IPostProcessor.h new file mode 100644 index 00000000..2fc9fb45 --- /dev/null +++ b/src/ZoneCodeGeneratorLib/Parsing/PostProcessing/IPostProcessor.h @@ -0,0 +1,15 @@ +#pragma once +#include "Persistence/IDataRepository.h" + +class IPostProcessor +{ +public: + IPostProcessor() = default; + virtual ~IPostProcessor() = default; + IPostProcessor(const IPostProcessor& other) = default; + IPostProcessor(IPostProcessor&& other) noexcept = default; + IPostProcessor& operator=(const IPostProcessor& other) = default; + IPostProcessor& operator=(IPostProcessor&& other) noexcept = default; + + virtual bool PostProcess(IDataRepository* repository) = 0; +}; diff --git a/src/ZoneCodeGeneratorLib/Persistence/IDataRepository.h b/src/ZoneCodeGeneratorLib/Persistence/IDataRepository.h index cdea1534..796af7bd 100644 --- a/src/ZoneCodeGeneratorLib/Persistence/IDataRepository.h +++ b/src/ZoneCodeGeneratorLib/Persistence/IDataRepository.h @@ -7,6 +7,7 @@ #include "Domain/Definition/StructDefinition.h" #include "Domain/Definition/TypedefDefinition.h" #include "Domain/Definition/UnionDefinition.h" +#include "Domain/Environment/Architecture.h" #include "Domain/Information/StructureInformation.h" #include "Domain/FastFile/FastFileBlock.h" @@ -29,6 +30,8 @@ public: _NODISCARD virtual const std::string& GetGameName() const = 0; virtual void SetGame(std::string gameName) = 0; + _NODISCARD virtual Architecture GetArchitecture() const = 0; + virtual void SetArchitecture(Architecture architecture) = 0; _NODISCARD virtual const std::vector& GetAllEnums() const = 0; _NODISCARD virtual const std::vector& GetAllStructs() const = 0; @@ -38,6 +41,6 @@ public: _NODISCARD virtual const std::vector& GetAllFastFileBlocks() const = 0; _NODISCARD virtual DataDefinition* GetDataDefinitionByName(const std::string& name) const = 0; - _NODISCARD virtual StructureInformation* GetInformationFor(DefinitionWithMembers* definitionWithMembers) const = 0; + _NODISCARD virtual StructureInformation* GetInformationFor(const DefinitionWithMembers* definitionWithMembers) const = 0; _NODISCARD virtual EnumMember* GetEnumMemberByName(const std::string& name) const = 0; }; diff --git a/src/ZoneCodeGeneratorLib/Persistence/InMemory/InMemoryRepository.cpp b/src/ZoneCodeGeneratorLib/Persistence/InMemory/InMemoryRepository.cpp index 94fcfc22..f0c242b5 100644 --- a/src/ZoneCodeGeneratorLib/Persistence/InMemory/InMemoryRepository.cpp +++ b/src/ZoneCodeGeneratorLib/Persistence/InMemory/InMemoryRepository.cpp @@ -1,5 +1,10 @@ #include "InMemoryRepository.h" +InMemoryRepository::InMemoryRepository() + : m_architecture(Architecture::UNKNOWN) +{ +} + InMemoryRepository::~InMemoryRepository() { for (auto* enumDefinition : m_enums) @@ -22,7 +27,7 @@ void InMemoryRepository::Add(std::unique_ptr enumsDefinition) m_enums.push_back(raw); m_data_definitions_by_name[raw->m_name] = raw; - for(const auto& enumMember : raw->m_members) + for (const auto& enumMember : raw->m_members) m_enum_members_by_name[enumMember->m_name] = enumMember.get(); } @@ -69,6 +74,16 @@ void InMemoryRepository::SetGame(std::string gameName) m_game_name = std::move(gameName); } +Architecture InMemoryRepository::GetArchitecture() const +{ + return m_architecture; +} + +void InMemoryRepository::SetArchitecture(const Architecture architecture) +{ + m_architecture = architecture; +} + const std::vector& InMemoryRepository::GetAllEnums() const { return m_enums; @@ -109,7 +124,7 @@ DataDefinition* InMemoryRepository::GetDataDefinitionByName(const std::string& n return nullptr; } -StructureInformation* InMemoryRepository::GetInformationFor(DefinitionWithMembers* definitionWithMembers) const +StructureInformation* InMemoryRepository::GetInformationFor(const DefinitionWithMembers* definitionWithMembers) const { const auto foundEntry = m_structure_information_by_definition.find(definitionWithMembers); diff --git a/src/ZoneCodeGeneratorLib/Persistence/InMemory/InMemoryRepository.h b/src/ZoneCodeGeneratorLib/Persistence/InMemory/InMemoryRepository.h index 0fe965a7..be76f93b 100644 --- a/src/ZoneCodeGeneratorLib/Persistence/InMemory/InMemoryRepository.h +++ b/src/ZoneCodeGeneratorLib/Persistence/InMemory/InMemoryRepository.h @@ -14,11 +14,12 @@ class InMemoryRepository final : public IDataRepository std::vector m_fast_file_blocks; std::map m_data_definitions_by_name; std::map m_enum_members_by_name; - std::map m_structure_information_by_definition; + std::map m_structure_information_by_definition; std::string m_game_name; + Architecture m_architecture; public: - InMemoryRepository() = default; + InMemoryRepository(); ~InMemoryRepository() override; InMemoryRepository(const InMemoryRepository& other) = delete; InMemoryRepository(InMemoryRepository&& other) noexcept = default; @@ -34,6 +35,8 @@ public: _NODISCARD const std::string& GetGameName() const override; void SetGame(std::string gameName) override; + Architecture GetArchitecture() const override; + void SetArchitecture(Architecture architecture) override; _NODISCARD const std::vector& GetAllEnums() const override; _NODISCARD const std::vector& GetAllStructs() const override; @@ -43,6 +46,6 @@ public: _NODISCARD const std::vector& GetAllFastFileBlocks() const override; _NODISCARD DataDefinition* GetDataDefinitionByName(const std::string& name) const override; - _NODISCARD StructureInformation* GetInformationFor(DefinitionWithMembers* definitionWithMembers) const override; + _NODISCARD StructureInformation* GetInformationFor(const DefinitionWithMembers* definitionWithMembers) const override; _NODISCARD EnumMember* GetEnumMemberByName(const std::string& name) const override; };