feat: add possibility to only include structs in zcg for certain variants

This commit is contained in:
Jan Laupetin committed 2026-10-22 20:01:07 +02:00
1 parent 3cd0a80666
commit 70f0564af8
12 files changed
+124 -4

No files matched your search

@@ -1,7 +1,8 @@
#include "GameVariant.h"
GameVariant::GameVariant(std::string name, const WordSize wordSize, const std::endian endianness)
: m_name(std::move(name)),
GameVariant::GameVariant(const unsigned index, std::string name, const WordSize wordSize, const std::endian endianness)
: m_index(index),
m_name(std::move(name)),
m_word_size(wordSize),
m_endianness(endianness)
{
@@ -8,8 +8,9 @@
class GameVariant
{
public:
GameVariant(std::string name, WordSize wordSize, std::endian endianness);
GameVariant(unsigned index, std::string name, WordSize wordSize, std::endian endianness);
unsigned m_index;
std::string m_name;
WordSize m_word_size;
std::endian m_endianness;
@@ -16,3 +16,8 @@ StructureInformation::StructureInformation(DefinitionWithMembers* definition, Ty
m_block(nullptr)
{
}
bool StructureInformation::IsIncludedForVariant(const unsigned variantIndex) const
{
return m_variants.empty() || m_variants.contains(variantIndex);
}
@@ -8,6 +8,7 @@
#include "TypeInformation.h"
#include <memory>
#include <unordered_set>
#include <vector>
class MemberInformation;
@@ -17,10 +18,17 @@ class StructureInformation
public:
StructureInformation(DefinitionWithMembers* definition, TypeInformation* typeInfo);
[[nodiscard]] bool IsIncludedForVariant(unsigned variantIndex) const;
DefinitionWithMembers* m_definition;
TypeInformation* m_type_info;
std::string m_asset_name;
/**
* All variants this structure should be included in. If empty, it should be included in all variants.
*/
std::unordered_set<unsigned> m_variants;
std::unique_ptr<IEvaluation> m_alloc_alignment;
std::vector<StructureInformation*> m_usages;
std::vector<std::unique_ptr<MemberInformation>> m_ordered_members;
@@ -12,6 +12,7 @@
#include <filesystem>
#include <format>
#include <fstream>
#include <variant>
namespace fs = std::filesystem;
@@ -195,6 +196,9 @@ bool CodeGenerator::GenerateCode(const IDataRepository* repository)
{
for (auto* asset : assets)
{
if (!asset->IsIncludedForVariant(variant->m_index))
continue;
auto context = std::make_unique<PerAssetRenderingContext>(repository, asset, variant);
const auto result = GenerateCodeOncePerAsset(*context, foundTemplate->second.get());
LogDirtyCheckResult(
@@ -33,6 +33,9 @@ namespace
for (const auto* asset : m_env.m_all_assets)
{
if (!asset->IsIncludedForVariant(m_env.m_variant->m_index))
continue;
LINEF("#include \"Game/{0}/XAssets/{1}/{1}_{2}_{3}_load_db.h\"",
m_env.m_game,
Lower(asset->m_definition->m_name),
@@ -33,6 +33,9 @@ namespace
for (const auto* asset : m_env.m_all_assets)
{
if (!asset->IsIncludedForVariant(m_env.m_variant->m_index))
continue;
LINEF("#include \"Game/{0}/XAssets/{1}/{1}_{2}_{3}_mark_db.h\"",
m_env.m_game,
Lower(asset->m_definition->m_name),
@@ -33,6 +33,9 @@ namespace
for (const auto* asset : m_env.m_all_assets)
{
if (!asset->IsIncludedForVariant(m_env.m_variant->m_index))
continue;
LINEF("#include \"Game/{0}/XAssets/{1}/{1}_{2}_{3}_write_db.h\"",
m_env.m_game,
Lower(asset->m_definition->m_name),
@@ -14,6 +14,7 @@
#include "Parsing/Commands/Sequence/SequenceReusable.h"
#include "Parsing/Commands/Sequence/SequenceScriptString.h"
#include "Parsing/Commands/Sequence/SequenceSetBlock.h"
#include "Parsing/Commands/Sequence/SequenceSetVariant.h"
#include "Parsing/Commands/Sequence/SequenceString.h"
#include "Parsing/Commands/Sequence/SequenceUse.h"
#include "Parsing/Commands/Sequence/SequenceVariant.h"
@@ -41,6 +42,7 @@ const std::vector<CommandsParser::sequence_t*>& CommandsParser::GetTestsForState
new SequenceReusable(),
new SequenceScriptString(),
new SequenceSetBlock(),
new SequenceSetVariant(),
new SequenceString(),
new SequenceUse(),
new SequenceVariant(),
@@ -76,7 +76,8 @@ void CommandsParserState::AddBlock(std::unique_ptr<FastFileBlock> block) const
void CommandsParserState::AddGameVariant(std::string variantName, const WordSize wordSize, const std::endian endianness) const
{
m_repository->AddGameVariant(std::make_unique<GameVariant>(std::move(variantName), wordSize, endianness));
m_repository->AddGameVariant(
std::make_unique<GameVariant>(static_cast<unsigned>(m_repository->GetGameVariants().size()), std::move(variantName), wordSize, endianness));
}
void CommandsParserState::SetGame(std::string gameName) const
@@ -0,0 +1,77 @@
#include "SequenceSetVariant.h"
#include "Parsing/Commands/Matcher/CommandsCommonMatchers.h"
#include "Parsing/Commands/Matcher/CommandsMatcherFactory.h"
namespace
{
constexpr auto CAPTURE_START = 1;
constexpr auto CAPTURE_TYPE_OR_VARIANT = 2;
constexpr auto CAPTURE_VARIANT = 3;
std::optional<unsigned> GetVariantIndexForName(const IDataRepository& repository, const std::string& name)
{
for (const auto* variant : repository.GetGameVariants())
{
if (utils::StringEqualsIgnoreCase(variant->m_name, name))
return variant->m_index;
}
return std::nullopt;
}
} // namespace
SequenceSetVariant::SequenceSetVariant()
{
const CommandsMatcherFactory create(this);
AddLabeledMatchers(CommandsCommonMatchers::Typename(this), CommandsCommonMatchers::LABEL_TYPENAME);
AddMatchers({
create.Keyword("set").Capture(CAPTURE_START),
create.Keyword("variant"),
create.Label(CommandsCommonMatchers::LABEL_TYPENAME).Capture(CAPTURE_TYPE_OR_VARIANT),
create.OptionalLoop(create.Identifier().Capture(CAPTURE_VARIANT)),
create.Char(';'),
});
}
void SequenceSetVariant::ProcessMatch(CommandsParserState* state, SequenceResult<CommandsParserValue>& result) const
{
const auto& typeOrVariantToken = result.NextCapture(CAPTURE_TYPE_OR_VARIANT);
const auto& typeOrVariantValue = typeOrVariantToken.TypeNameValue();
const auto maybeTypeOrVariantAsVariantIndex = GetVariantIndexForName(*state->GetRepository(), typeOrVariantValue);
StructureInformation* information;
std::vector<MemberInformation*> memberChain;
if (state->GetTypenameAndMembersFromTypename(typeOrVariantValue, information, memberChain))
{
if (maybeTypeOrVariantAsVariantIndex)
throw ParsingException(typeOrVariantToken.GetPos(), "Expression is ambiguous, could both be a variant name or a type.");
if (!memberChain.empty())
{
information = memberChain.back()->m_type;
if (information == nullptr)
throw ParsingException(typeOrVariantToken.GetPos(), "Specified type must be a structure.");
}
}
else
{
information = state->GetInUse();
if (information == nullptr)
throw ParsingException(result.NextCapture(CAPTURE_START).GetPos(), "No type is used. Therefore one needs to be specified directly.");
}
if (maybeTypeOrVariantAsVariantIndex.has_value())
information->m_variants.emplace(*maybeTypeOrVariantAsVariantIndex);
while (result.HasNextCapture(CAPTURE_VARIANT))
{
const auto& variantToken = result.NextCapture(CAPTURE_VARIANT);
const auto maybeVariant = GetVariantIndexForName(*state->GetRepository(), variantToken.TypeNameValue());
if (!maybeVariant)
throw ParsingException(variantToken.GetPos(), "No variant with this name.");
information->m_variants.emplace(*maybeVariant);
}
}
@@ -0,0 +1,12 @@
#pragma once
#include "Parsing/Commands/Impl/CommandsParser.h"
class SequenceSetVariant final : public CommandsParser::sequence_t
{
public:
SequenceSetVariant();
protected:
void ProcessMatch(CommandsParserState* state, SequenceResult<CommandsParserValue>& result) const override;
};