mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 16:15:43 +00:00
ZoneCodeGenerator: Make pointer counts be able to differ by array index
This commit is contained in:
parent
a7936c9eaa
commit
be17ae6a48
@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using ZoneCodeGenerator.Domain.Evaluation;
|
using ZoneCodeGenerator.Domain.Evaluation;
|
||||||
|
|
||||||
namespace ZoneCodeGenerator.Domain
|
namespace ZoneCodeGenerator.Domain
|
||||||
@ -8,7 +10,20 @@ namespace ZoneCodeGenerator.Domain
|
|||||||
public static IEvaluation DefaultCount = new OperandStatic(1);
|
public static IEvaluation DefaultCount = new OperandStatic(1);
|
||||||
|
|
||||||
public IEvaluation Count { get; set; } = DefaultCount;
|
public IEvaluation Count { get; set; } = DefaultCount;
|
||||||
|
public IEvaluation[] CountByArrayIndex { get; set; }
|
||||||
|
public bool HasCountByArrayIndex => CountByArrayIndex != null;
|
||||||
|
|
||||||
public bool IsArray => !Count.IsStatic || Count.EvaluateNumeric() > 1;
|
private static bool EvaluationIsArray(IEvaluation eval)
|
||||||
|
{
|
||||||
|
return !eval.IsStatic || eval.EvaluateNumeric() > 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsArray(int index)
|
||||||
|
{
|
||||||
|
return EvaluationIsArray(HasCountByArrayIndex ? CountByArrayIndex[index] : Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AnyIsArray =>
|
||||||
|
HasCountByArrayIndex ? CountByArrayIndex.Any(EvaluationIsArray) : EvaluationIsArray(Count);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,12 +20,12 @@ namespace ZoneCodeGenerator.Generating.Computations
|
|||||||
public bool ContainsSinglePointerReference => information.Member.VariableType.References.Any()
|
public bool ContainsSinglePointerReference => information.Member.VariableType.References.Any()
|
||||||
&& information.Member.VariableType.References.Last() is
|
&& information.Member.VariableType.References.Last() is
|
||||||
ReferenceTypePointer pointerReference
|
ReferenceTypePointer pointerReference
|
||||||
&& !pointerReference.IsArray;
|
&& !pointerReference.AnyIsArray;
|
||||||
|
|
||||||
public bool ContainsArrayPointerReference => information.Member.VariableType.References.Any()
|
public bool ContainsArrayPointerReference => information.Member.VariableType.References.Any()
|
||||||
&& information.Member.VariableType.References.Last() is
|
&& information.Member.VariableType.References.Last() is
|
||||||
ReferenceTypePointer pointerReference
|
ReferenceTypePointer pointerReference
|
||||||
&& pointerReference.IsArray;
|
&& pointerReference.AnyIsArray;
|
||||||
|
|
||||||
public bool ContainsPointerArrayReference => ContainsSinglePointerReference
|
public bool ContainsPointerArrayReference => ContainsSinglePointerReference
|
||||||
&& (IsArray && PointerDepthIsOne || !IsArray && PointerDepthIsTwo);
|
&& (IsArray && PointerDepthIsOne || !IsArray && PointerDepthIsTwo);
|
||||||
@ -73,11 +73,16 @@ namespace ZoneCodeGenerator.Generating.Computations
|
|||||||
public bool IsNotDefaultNormalBlock =>
|
public bool IsNotDefaultNormalBlock =>
|
||||||
information.Block != null && !(information.Block.IsNormal && information.Block.IsDefault);
|
information.Block != null && !(information.Block.IsNormal && information.Block.IsDefault);
|
||||||
|
|
||||||
|
public bool IsTempBlock => information.Block != null && information.Block.IsTemp;
|
||||||
|
public bool IsRuntimeBlock => information.Block != null && information.Block.IsRuntime;
|
||||||
|
|
||||||
public bool IsFirstMember =>
|
public bool IsFirstMember =>
|
||||||
information.Parent.OrderedMembers.FirstOrDefault(member => !member.IsLeaf && !member.Computations.ShouldIgnore) == information;
|
information.Parent.OrderedMembers.FirstOrDefault(member =>
|
||||||
|
!member.IsLeaf && !member.Computations.ShouldIgnore) == information;
|
||||||
|
|
||||||
public bool IsLastMember =>
|
public bool IsLastMember =>
|
||||||
information.Parent.OrderedMembers.LastOrDefault(member => !member.IsLeaf && !member.Computations.ShouldIgnore) == information;
|
information.Parent.OrderedMembers.LastOrDefault(member =>
|
||||||
|
!member.IsLeaf && !member.Computations.ShouldIgnore) == information;
|
||||||
|
|
||||||
public MemberReferenceComputations References => new MemberReferenceComputations(information);
|
public MemberReferenceComputations References => new MemberReferenceComputations(information);
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ namespace ZoneCodeGenerator.Generating.Computations
|
|||||||
{
|
{
|
||||||
private readonly MemberInformation information;
|
private readonly MemberInformation information;
|
||||||
private readonly List<int> referenceIndices;
|
private readonly List<int> referenceIndices;
|
||||||
|
private readonly int combinedIndex;
|
||||||
|
|
||||||
public ReferenceType Reference => referenceIndices.Count < information.Member.VariableType.References.Count
|
public ReferenceType Reference => referenceIndices.Count < information.Member.VariableType.References.Count
|
||||||
? information.Member.VariableType.References[referenceIndices.Count]
|
? information.Member.VariableType.References[referenceIndices.Count]
|
||||||
@ -32,21 +33,29 @@ namespace ZoneCodeGenerator.Generating.Computations
|
|||||||
.Select(i => new MemberReferenceComputations(information, referenceIndices.Concat(new[] {i})));
|
.Select(i => new MemberReferenceComputations(information, referenceIndices.Concat(new[] {i})));
|
||||||
|
|
||||||
public bool IsSinglePointer => Reference is ReferenceTypePointer referenceTypePointer
|
public bool IsSinglePointer => Reference is ReferenceTypePointer referenceTypePointer
|
||||||
&& !referenceTypePointer.IsArray
|
&& !referenceTypePointer.IsArray(combinedIndex)
|
||||||
&& !FollowingReferences.OfType<ReferenceTypePointer>().Any();
|
&& !FollowingReferences.OfType<ReferenceTypePointer>().Any();
|
||||||
|
|
||||||
public bool IsArrayPointer => Reference is ReferenceTypePointer referenceTypePointer
|
public bool IsArrayPointer => Reference is ReferenceTypePointer referenceTypePointer
|
||||||
&& referenceTypePointer.IsArray
|
&& referenceTypePointer.IsArray(combinedIndex)
|
||||||
&& !FollowingReferences.OfType<ReferenceTypePointer>().Any();
|
&& !FollowingReferences.OfType<ReferenceTypePointer>().Any();
|
||||||
|
|
||||||
public IEvaluation ArrayPointerCountEvaluation => Reference is ReferenceTypePointer referenceTypePointer
|
public IEvaluation ArrayPointerCountEvaluation
|
||||||
? referenceTypePointer.Count
|
{
|
||||||
: null;
|
get
|
||||||
|
{
|
||||||
|
if (!(Reference is ReferenceTypePointer pointer))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return pointer.HasCountByArrayIndex ? pointer.CountByArrayIndex[combinedIndex] : pointer.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsPointerArray =>
|
public bool IsPointerArray =>
|
||||||
(Reference is ReferenceTypePointer referenceTypePointer && referenceTypePointer.IsArray ||
|
(Reference is ReferenceTypePointer referenceTypePointer && referenceTypePointer.IsArray(combinedIndex) ||
|
||||||
Reference is ReferenceTypeArray)
|
Reference is ReferenceTypeArray)
|
||||||
&& NextReference is ReferenceTypePointer nextReferencePointer && !nextReferencePointer.IsArray;
|
&& NextReference is ReferenceTypePointer nextReferencePointer &&
|
||||||
|
!nextReferencePointer.IsArray(combinedIndex);
|
||||||
|
|
||||||
public IEvaluation PointerArrayCountEvaluation => NextReference is ReferenceTypePointer referenceTypePointer
|
public IEvaluation PointerArrayCountEvaluation => NextReference is ReferenceTypePointer referenceTypePointer
|
||||||
? referenceTypePointer.Count
|
? referenceTypePointer.Count
|
||||||
@ -56,12 +65,29 @@ namespace ZoneCodeGenerator.Generating.Computations
|
|||||||
{
|
{
|
||||||
this.information = information;
|
this.information = information;
|
||||||
referenceIndices = new List<int>();
|
referenceIndices = new List<int>();
|
||||||
|
combinedIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MemberReferenceComputations(MemberInformation information, IEnumerable<int> referenceIndices)
|
private MemberReferenceComputations(MemberInformation information, IEnumerable<int> referenceIndices)
|
||||||
{
|
{
|
||||||
this.information = information;
|
this.information = information;
|
||||||
this.referenceIndices = new List<int>(referenceIndices);
|
this.referenceIndices = new List<int>(referenceIndices);
|
||||||
|
|
||||||
|
var arraySizes = information.Member.VariableType.References
|
||||||
|
.OfType<ReferenceTypeArray>()
|
||||||
|
.Select(array => array.ArraySize)
|
||||||
|
.ToList();
|
||||||
|
var indexDepth = 0;
|
||||||
|
combinedIndex = 0;
|
||||||
|
foreach (var referenceIndex in this.referenceIndices)
|
||||||
|
{
|
||||||
|
var sizePerIndexInCurrentDepth = arraySizes.Count <= indexDepth + 1
|
||||||
|
? 1
|
||||||
|
: arraySizes.Skip(indexDepth + 1).Aggregate((i1, i2) => i1 * i2);
|
||||||
|
|
||||||
|
combinedIndex += referenceIndex * sizePerIndexInCurrentDepth;
|
||||||
|
indexDepth++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,7 +7,7 @@ $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)
|
|||||||
// $member.Member.VariableType.Type.Alignment$
|
// $member.Member.VariableType.Type.Alignment$
|
||||||
$\n$
|
$\n$
|
||||||
|
|
||||||
$if(member.StructureType && !member.StructureType.IsLeaf)$
|
$if(member.StructureType && !member.StructureType.IsLeaf && !member.Computations.IsRuntimeBlock)$
|
||||||
|
|
||||||
$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.ArrayPointerCountEvaluation)$);
|
LoadArray_$member.Member.VariableType.Type.Name$(true, $PrintEvaluation(reference.ArrayPointerCountEvaluation)$);
|
||||||
|
@ -73,8 +73,11 @@ namespace $context.Game$
|
|||||||
}
|
}
|
||||||
>>
|
>>
|
||||||
|
|
||||||
LoadMember(context, member) ::= <<
|
LoadMemberReference_Array(context, structure, member, reference) ::= <<
|
||||||
Loading member $member.Member.Name$
|
$first(reference.ArrayEntries):{entry | $LoadMemberReference(context, structure, member, entry)$}$
|
||||||
|
$rest(reference.ArrayEntries):{entry |
|
||||||
|
|
||||||
|
$LoadMemberReference(context, structure, member, entry)$}$
|
||||||
>>
|
>>
|
||||||
|
|
||||||
LoadMemberReference(context, structure, member, reference) ::= <%
|
LoadMemberReference(context, structure, member, reference) ::= <%
|
||||||
@ -88,8 +91,10 @@ $elseif(reference.IsArray && !reference.NextReference)$
|
|||||||
$LoadEmbeddedArray(context, structure, member, reference)$
|
$LoadEmbeddedArray(context, structure, member, reference)$
|
||||||
$elseif(!reference.Reference)$
|
$elseif(!reference.Reference)$
|
||||||
$LoadEmbedded(context, structure, member, reference)$
|
$LoadEmbedded(context, structure, member, reference)$
|
||||||
|
$elseif(reference.IsArray)$
|
||||||
|
$LoadMemberReference_Array(context, structure, member, reference)$
|
||||||
$else$
|
$else$
|
||||||
// $member.Member.Name$
|
// LoadMemberReference failed @ $member.Member.Name$
|
||||||
$endif$
|
$endif$
|
||||||
%>
|
%>
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using ZoneCodeGenerator.Domain;
|
using ZoneCodeGenerator.Domain;
|
||||||
|
using ZoneCodeGenerator.Domain.Evaluation;
|
||||||
using ZoneCodeGenerator.Domain.Information;
|
using ZoneCodeGenerator.Domain.Information;
|
||||||
using ZoneCodeGenerator.Parsing.Matching;
|
using ZoneCodeGenerator.Parsing.Matching;
|
||||||
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
using ZoneCodeGenerator.Parsing.Matching.Matchers;
|
||||||
@ -14,27 +15,65 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
|
|||||||
private StructureInformation referencedType;
|
private StructureInformation referencedType;
|
||||||
private const string TokenTypeName = "typeName";
|
private const string TokenTypeName = "typeName";
|
||||||
private const string TokenPointerResolve = "pointerResolve";
|
private const string TokenPointerResolve = "pointerResolve";
|
||||||
|
private const string TokenArrayIndex = "arrayIndex";
|
||||||
|
|
||||||
// set count <typename> <calculationStatement>;
|
// set count <typename> <calculationStatement>;
|
||||||
private static readonly TokenMatcher[] matchers =
|
private static readonly TokenMatcher[] matchers =
|
||||||
{
|
{
|
||||||
new MatcherLiteral("set"),
|
new MatcherLiteral("set"),
|
||||||
new MatcherLiteral("count"),
|
new MatcherLiteral("count"),
|
||||||
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherLiteral("*").WithName(TokenPointerResolve)),
|
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple,
|
||||||
|
new MatcherLiteral("*").WithName(TokenPointerResolve)),
|
||||||
new MatcherTypename().WithName(TokenTypeName),
|
new MatcherTypename().WithName(TokenTypeName),
|
||||||
|
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple,
|
||||||
|
new MatcherArray().WithName(TokenArrayIndex)),
|
||||||
new MatcherWithTag(TagEvaluation),
|
new MatcherWithTag(TagEvaluation),
|
||||||
new MatcherLiteral(";")
|
new MatcherLiteral(";")
|
||||||
};
|
};
|
||||||
|
|
||||||
public TestCount() : base(matchers)
|
public TestCount() : base(matchers)
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetCountByArrayIndex(MemberInformation referencedMember, ReferenceTypePointer pointer,
|
||||||
|
IEvaluation evaluation)
|
||||||
|
{
|
||||||
|
if (pointer.CountByArrayIndex == null)
|
||||||
|
{
|
||||||
|
pointer.CountByArrayIndex = new IEvaluation[referencedMember.Member.VariableType.References
|
||||||
|
.OfType<ReferenceTypeArray>().Select(array => array.ArraySize).Aggregate((i1, i2) => i1 * i2)];
|
||||||
|
}
|
||||||
|
|
||||||
|
var arraySizes = referencedMember.Member.VariableType.References
|
||||||
|
.OfType<ReferenceTypeArray>()
|
||||||
|
.Select(array => array.ArraySize)
|
||||||
|
.ToList();
|
||||||
|
var index = 0;
|
||||||
|
var indexDepth = 0;
|
||||||
|
string s;
|
||||||
|
while ((s = NextMatch(TokenArrayIndex)) != null)
|
||||||
|
{
|
||||||
|
var specifiedIndex = int.Parse(s);
|
||||||
|
|
||||||
|
if (specifiedIndex >= arraySizes[indexDepth])
|
||||||
|
{
|
||||||
|
throw new TestFailedException($"Specified index '{specifiedIndex}' is out of bounds at type '{referencedMember.Parent.Type.FullName}::{referencedMember.Member.Name}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
var sizePerIndexInCurrentDepth = arraySizes.Count <= indexDepth + 1 ?
|
||||||
|
1 : arraySizes.Skip(indexDepth + 1).Aggregate((i1, i2) => i1 * i2);
|
||||||
|
|
||||||
|
index += specifiedIndex * sizePerIndexInCurrentDepth;
|
||||||
|
indexDepth++;
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer.CountByArrayIndex[index] = evaluation;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ProcessMatch(ICommandParserState state)
|
protected override void ProcessMatch(ICommandParserState state)
|
||||||
{
|
{
|
||||||
var typeName = NextMatch(TokenTypeName);
|
var typeName = NextMatch(TokenTypeName);
|
||||||
var typeNameParts = typeName.Split(new[] { "::" }, StringSplitOptions.None);
|
var typeNameParts = typeName.Split(new[] {"::"}, StringSplitOptions.None);
|
||||||
if (state.DataTypeInUse != null
|
if (state.DataTypeInUse != null
|
||||||
&& state.GetMembersFromParts(typeNameParts, state.DataTypeInUse, out var typeMembers))
|
&& state.GetMembersFromParts(typeNameParts, state.DataTypeInUse, out var typeMembers))
|
||||||
{
|
{
|
||||||
@ -67,10 +106,21 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
|
|||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
|
|
||||||
if (reference != null)
|
if (reference != null)
|
||||||
reference.Count = evaluation;
|
{
|
||||||
|
if (HasMatcherTokens(TokenArrayIndex))
|
||||||
|
{
|
||||||
|
SetCountByArrayIndex(referencedMember, reference, evaluation);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reference.Count = evaluation;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
throw new TestFailedException(
|
throw new TestFailedException(
|
||||||
$"Member '{referencedMember.Member.Name}' of type '{referencedMember.Member.VariableType.Type.FullName}' cannot have its count set due to it not having a pointer reference");
|
$"Member '{referencedMember.Member.Name}' of type '{referencedMember.Member.VariableType.Type.FullName}' cannot have its count set due to it not having a pointer reference");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IEnumerable<StructureInformation> GetUsedTypes(ICommandParserState state)
|
protected override IEnumerable<StructureInformation> GetUsedTypes(ICommandParserState state)
|
||||||
@ -78,10 +128,10 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
|
|||||||
if (state.DataTypeInUse != null
|
if (state.DataTypeInUse != null
|
||||||
&& state.DataTypeInUse != referencedType)
|
&& state.DataTypeInUse != referencedType)
|
||||||
{
|
{
|
||||||
return new[] { state.DataTypeInUse, referencedType };
|
return new[] {state.DataTypeInUse, referencedType};
|
||||||
}
|
}
|
||||||
|
|
||||||
return new[] { referencedType };
|
return new[] {referencedType};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user