ZoneCodeGenerator: Add possibility to specify a custom array count to signalize how many entries of a static array should be loaded

This commit is contained in:
Jan 2019-12-24 12:41:27 +01:00
parent 9e10cffdce
commit 33ec343460
8 changed files with 118 additions and 14 deletions

View File

@ -1345,8 +1345,10 @@ set string localization;
use XGlobals; use XGlobals;
set string name; set string name;
set name name; set name name;
//set count gumps gumpsCount; set arraycount gumps gumpsCount;
//set count overlays overlayCount; set condition gumps gumpsCount >= 0 && gumpsCount <= 32;
set arraycount overlays overlayCount;
set condition overlays overlayCount >= 0 && overlayCount <= 32;
// gump_info_t // gump_info_t
set string gump_info_t::name; set string gump_info_t::name;

View File

@ -7,11 +7,13 @@ namespace ZoneCodeGenerator.Domain
public int ArraySize { get; } public int ArraySize { get; }
public IEvaluation DynamicSize { get; set; } public IEvaluation DynamicSize { get; set; }
public IEvaluation DynamicCount { get; set; }
public ReferenceTypeArray(int arraySize) public ReferenceTypeArray(int arraySize)
{ {
ArraySize = arraySize; ArraySize = arraySize;
DynamicSize = null; DynamicSize = null;
DynamicCount = null;
} }
} }
} }

View File

@ -29,6 +29,11 @@ namespace ZoneCodeGenerator.Generating.Computations
public bool IsArray => Reference is ReferenceTypeArray; public bool IsArray => Reference is ReferenceTypeArray;
public int ArraySize => Reference is ReferenceTypeArray array ? array.ArraySize : 0; public int ArraySize => Reference is ReferenceTypeArray array ? array.ArraySize : 0;
public bool HasDynamicArrayCount => Reference is ReferenceTypeArray array && array.DynamicCount != null;
public IEvaluation DynamicArrayCountEvaluation =>
Reference is ReferenceTypeArray array ? array.DynamicCount : null;
public IEnumerable<MemberReferenceComputations> ArrayEntries => Enumerable.Range(0, ArraySize) public IEnumerable<MemberReferenceComputations> ArrayEntries => Enumerable.Range(0, ArraySize)
.Select(i => new MemberReferenceComputations(information, referenceIndices.Concat(new[] {i}))); .Select(i => new MemberReferenceComputations(information, referenceIndices.Concat(new[] {i})));
@ -64,7 +69,7 @@ namespace ZoneCodeGenerator.Generating.Computations
public bool IsDynamicArray => public bool IsDynamicArray =>
Reference is ReferenceTypeArray referenceTypeArray && referenceTypeArray.DynamicSize != null; Reference is ReferenceTypeArray referenceTypeArray && referenceTypeArray.DynamicSize != null;
public IEvaluation DynamicArrayCountEvaluation => Reference is ReferenceTypeArray referenceTypeArray public IEvaluation DynamicArraySizeEvaluation => Reference is ReferenceTypeArray referenceTypeArray
? referenceTypeArray.DynamicSize ? referenceTypeArray.DynamicSize
: null; : null;

View File

@ -6,11 +6,11 @@ LoadDynamicArray_Load(context, structure, member, reference) ::= <%
$if(member.StructureType && !member.StructureType.IsLeaf)$ $if(member.StructureType && !member.StructureType.IsLeaf)$
$TypeVarName(member.Member.VariableType.Type)$ = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$ $TypeVarName(member.Member.VariableType.Type)$ = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$
LoadArray_$member.Member.VariableType.Type.Name$(true, $PrintEvaluation(reference.DynamicArrayCountEvaluation)$); LoadArray_$member.Member.VariableType.Type.Name$(true, $PrintEvaluation(reference.DynamicArraySizeEvaluation)$);
$else$ $else$
m_stream->Load<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$, $PrintEvaluation(reference.DynamicArrayCountEvaluation)$); m_stream->Load<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$, $PrintEvaluation(reference.DynamicArraySizeEvaluation)$);
$endif$ $endif$
%> %>

View File

@ -2,6 +2,14 @@ delimiters "$", "$"
// Everything related to loading an embedded reference // Everything related to loading an embedded reference
ArrayCount(reference) ::= <%
$if(reference.HasDynamicArrayCount)$
$PrintEvaluation(reference.DynamicArrayCountEvaluation)$
$else$
$reference.ArraySize$
$endif$
%>
LoadEmbedded_Load(context, structure, member, reference) ::= << LoadEmbedded_Load(context, structure, member, reference) ::= <<
$if(!member.IsLeaf)$ $if(!member.IsLeaf)$
$TypeVarName(member.Member.VariableType.Type)$ = &$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$; $TypeVarName(member.Member.VariableType.Type)$ = &$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;
@ -38,16 +46,16 @@ $LoadEmbedded_Block(context, structure, member, reference)$
LoadEmbeddedArray_Load(context, structure, member, reference) ::= << LoadEmbeddedArray_Load(context, structure, member, reference) ::= <<
$if(!member.IsLeaf)$ $if(!member.IsLeaf)$
$TypeVarName(member.Member.VariableType.Type)$ = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$; $TypeVarName(member.Member.VariableType.Type)$ = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;
LoadArray_$member.Member.VariableType.Type.Name$($if(member.Computations.IsAfterPartialLoad)$true$else$false$endif$, $reference.ArraySize$);$\\$ LoadArray_$member.Member.VariableType.Type.Name$($if(member.Computations.IsAfterPartialLoad)$true$else$false$endif$, $ArrayCount(reference)$);$\\$
$elseif(member.Computations.IsAfterPartialLoad)$ $elseif(member.Computations.IsAfterPartialLoad)$
m_stream->Load<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$, $reference.ArraySize$);$\\$ m_stream->Load<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$, $ArrayCount(reference)$);$\\$
$endif$ $endif$
>> >>
LoadEmbeddedArray_TypeCheck(context, structure, member, reference) ::= <% LoadEmbeddedArray_TypeCheck(context, structure, member, reference) ::= <%
$if(member.IsScriptString)$ $if(member.IsScriptString)$
varScriptString = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$ varScriptString = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$
LoadScriptStringArray(false, $reference.ArraySize$); LoadScriptStringArray(false, $ArrayCount(reference)$);
$else$ $else$
$LoadEmbeddedArray_Load(context, structure, member, reference)$ $LoadEmbeddedArray_Load(context, structure, member, reference)$
$endif$ $endif$

View File

@ -13,7 +13,9 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Impl
{ {
class CommandParserState : ICommandParserState class CommandParserState : ICommandParserState
{ {
private static readonly ITokenTest<ICommandParserState>[] tests = { private static readonly ITokenTest<ICommandParserState>[] tests =
{
new TestArrayCount(),
new TestArraySize(), new TestArraySize(),
new TestAsset(), new TestAsset(),
new TestBlock(), new TestBlock(),
@ -58,7 +60,8 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Impl
return true; return true;
} }
private bool FindTypenameParts(string[] parts, out DataTypeWithMembers dataTypeWithMembers, out int typeNamePartCount) private bool FindTypenameParts(string[] parts, out DataTypeWithMembers dataTypeWithMembers,
out int typeNamePartCount)
{ {
typeNamePartCount = 1; typeNamePartCount = 1;
while (typeNamePartCount <= parts.Length) while (typeNamePartCount <= parts.Length)
@ -70,7 +73,8 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Impl
{ {
if (!(foundDataType is DataTypeWithMembers foundDataTypeWithMembers)) if (!(foundDataType is DataTypeWithMembers foundDataTypeWithMembers))
{ {
throw new TestFailedException($"Referenced type '{currentTypeName}' needs to be a data type with members to be used in an evaluation."); throw new TestFailedException(
$"Referenced type '{currentTypeName}' needs to be a data type with members to be used in an evaluation.");
} }
dataTypeWithMembers = foundDataTypeWithMembers; dataTypeWithMembers = foundDataTypeWithMembers;
@ -84,7 +88,8 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Impl
return false; return false;
} }
public bool GetMembersFromParts(string[] parts, StructureInformation baseType, out List<MemberInformation> members) public bool GetMembersFromParts(string[] parts, StructureInformation baseType,
out List<MemberInformation> members)
{ {
members = new List<MemberInformation>(); members = new List<MemberInformation>();
var currentStructure = baseType; var currentStructure = baseType;

View File

@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Domain.Information;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
{
class TestArrayCount : TestWithEvaluation
{
private StructureInformation referencedType;
private const string TypeNameToken = "typeName";
// set count <typename> <calculationStatement>;
private static readonly TokenMatcher[] matchers =
{
new MatcherLiteral("set"),
new MatcherLiteral("arraycount"),
new MatcherTypename().WithName(TypeNameToken),
new MatcherWithTag(TagEvaluation),
new MatcherLiteral(";")
};
public TestArrayCount() : base(matchers)
{
}
protected override void ProcessMatch(ICommandParserState state)
{
var typeName = NextMatch(TypeNameToken);
var typeNameParts = typeName.Split(new[] { "::" }, StringSplitOptions.None);
if (state.DataTypeInUse != null
&& state.GetMembersFromParts(typeNameParts, state.DataTypeInUse, out var typeMembers))
{
referencedType = state.DataTypeInUse;
}
else if (state.GetTypenameAndMembersFromParts(typeNameParts, out referencedType, out typeMembers))
{
// Do nothing
}
else
{
throw new TestFailedException($"Could not find type/members '{typeName}'");
}
if (typeMembers == null
|| !typeMembers.Any())
{
throw new TestFailedException("Can only set array size for members and not for types.");
}
if (!NextTag().Equals(TagEvaluation))
throw new Exception("Expected first array size tag to be a calculation statement");
var evaluation = ProcessEvaluation(state);
var referencedMember = typeMembers.Last();
var reference = referencedMember.Member.VariableType.References.OfType<ReferenceTypeArray>()
.FirstOrDefault();
if (reference != null)
reference.DynamicCount = evaluation;
else
throw new TestFailedException(
$"Member '{referencedMember.Member.Name}' of type '{referencedMember.Member.VariableType.Type.FullName}' cannot have its array count set due to it not having an array reference");
}
protected override IEnumerable<StructureInformation> GetUsedTypes(ICommandParserState state)
{
if (state.DataTypeInUse != null
&& state.DataTypeInUse != referencedType)
{
return new[] { state.DataTypeInUse, referencedType };
}
return new[] { referencedType };
}
}
}

View File

@ -145,7 +145,7 @@ void ContentLoaderT6::LoadXAsset(const bool atStreamStart)
LOAD_ASSET(ASSET_TYPE_RAWFILE, RawFile, rawfile); LOAD_ASSET(ASSET_TYPE_RAWFILE, RawFile, rawfile);
LOAD_ASSET(ASSET_TYPE_STRINGTABLE, StringTable, stringTable); LOAD_ASSET(ASSET_TYPE_STRINGTABLE, StringTable, stringTable);
LOAD_ASSET(ASSET_TYPE_LEADERBOARD, LeaderboardDef, leaderboardDef); LOAD_ASSET(ASSET_TYPE_LEADERBOARD, LeaderboardDef, leaderboardDef);
// LOAD_ASSET(ASSET_TYPE_XGLOBALS, XGlobals, xGlobals); LOAD_ASSET(ASSET_TYPE_XGLOBALS, XGlobals, xGlobals);
LOAD_ASSET(ASSET_TYPE_DDL, ddlRoot_t, ddlRoot); LOAD_ASSET(ASSET_TYPE_DDL, ddlRoot_t, ddlRoot);
LOAD_ASSET(ASSET_TYPE_GLASSES, Glasses, glasses); LOAD_ASSET(ASSET_TYPE_GLASSES, Glasses, glasses);
LOAD_ASSET(ASSET_TYPE_EMBLEMSET, EmblemSet, emblemSet); LOAD_ASSET(ASSET_TYPE_EMBLEMSET, EmblemSet, emblemSet);