From 5d3c13e833626ae779c0d20e515532ca28f072bb Mon Sep 17 00:00:00 2001 From: Jan Date: Sun, 24 Nov 2019 01:58:01 +0100 Subject: [PATCH] ZoneCodeGenerator: Add computations for single references to be able to correctly handle arrays --- .../Computations/MemberComputations.cs | 53 ++++-- .../MemberReferenceComputations.cs | 67 ++++++++ .../Generating/RenderingContext.cs | 73 +++++--- .../Generating/Templates/Common.stg | 20 ++- .../Templates/Loading/ArrayPointer.stg | 67 ++++---- .../Generating/Templates/Loading/Common.stg | 2 + .../Generating/Templates/Loading/Embedded.stg | 32 ++-- .../Templates/Loading/PointerArray.stg | 45 +++++ .../Templates/Loading/SinglePointer.stg | 76 ++++---- .../Generating/Templates/Loading/String.stg | 30 ---- .../Generating/Templates/ZoneLoad.stg | 162 +++++++++++------- .../PostProcessor/PostProcessorUsages.cs | 8 +- .../Parsing/CommandFile/Tests/TestName.cs | 2 +- .../Parsing/CommandFile/Tests/TestReusable.cs | 2 +- .../Parsing/CommandFile/Tests/TestString.cs | 2 +- 15 files changed, 418 insertions(+), 223 deletions(-) create mode 100644 src/ZoneCodeGenerator/Generating/Computations/MemberReferenceComputations.cs create mode 100644 src/ZoneCodeGenerator/Generating/Templates/Loading/PointerArray.stg delete mode 100644 src/ZoneCodeGenerator/Generating/Templates/Loading/String.stg diff --git a/src/ZoneCodeGenerator/Generating/Computations/MemberComputations.cs b/src/ZoneCodeGenerator/Generating/Computations/MemberComputations.cs index 9bc1e790..cf13b026 100644 --- a/src/ZoneCodeGenerator/Generating/Computations/MemberComputations.cs +++ b/src/ZoneCodeGenerator/Generating/Computations/MemberComputations.cs @@ -10,40 +10,59 @@ namespace ZoneCodeGenerator.Generating.Computations { private readonly MemberInformation information; - public bool ShouldIgnore => information.Condition != null - && information.Condition.IsStatic + public bool ShouldIgnore => information.Condition != null + && information.Condition.IsStatic && information.Condition.EvaluateNumeric() == 0; - public bool IsEmbeddedReference => !information.Member.VariableType.References.OfType().Any(); + public bool ContainsNonEmbeddedReference => + information.Member.VariableType.References.OfType().Any(); - public bool IsNonEmbeddedReference => !IsEmbeddedReference; + public bool ContainsSinglePointerReference => information.Member.VariableType.References.Any() + && information.Member.VariableType.References.Last() is + ReferenceTypePointer pointerReference + && !pointerReference.IsArray; - public bool IsSinglePointerReference => information.Member.VariableType.References.Any() - && information.Member.VariableType.References.Last() is ReferenceTypePointer - pointerReference - && !pointerReference.IsArray; + public bool ContainsArrayPointerReference => information.Member.VariableType.References.Any() + && information.Member.VariableType.References.Last() is + ReferenceTypePointer pointerReference + && pointerReference.IsArray; + + public bool ContainsPointerArrayReference => ContainsSinglePointerReference + && (IsArray && PointerDepthIsOne || !IsArray && PointerDepthIsTwo); + + public bool ContainsArrayReference => information.Member.VariableType.References.Any() + && information.Member.VariableType.References + .Last() is ReferenceTypeArray; - public bool IsArrayPointerReference => information.Member.VariableType.References.Any() - && information.Member.VariableType.References.Last() is ReferenceTypePointer - pointerReference - && pointerReference.IsArray; public IEvaluation ArrayPointerCountEvaluation => information.Member.VariableType.References.Last() is ReferenceTypePointer pointerReference ? pointerReference.Count : null; - public bool IsArrayReference => information.Member.VariableType.References.Any() - && information.Member.VariableType.References.Last() is ReferenceTypeArray; - public bool IsArray => information.Member.VariableType.References - .OfType() + .TakeWhile(type => type is ReferenceTypeArray) .Any(); public IEnumerable ArraySizes => information.Member.VariableType.References + .TakeWhile(type => type is ReferenceTypeArray) .OfType() .Select(array => array.ArraySize); + public int ArrayDimension => information.Member.VariableType.References + .TakeWhile(type => type is ReferenceTypeArray) + .Count(); + + public bool IsPointerToArray => information.Member.VariableType.References.OfType().Any() + && information.Member.VariableType.References.Last() is ReferenceTypeArray; + + public IEnumerable PointerToArraySizes => information.Member.VariableType.References + .Reverse() + .TakeWhile(type => type is ReferenceTypeArray) + .OfType() + .Reverse() + .Select(array => array.ArraySize); + public int PointerDepth => information.Member.VariableType.References .OfType() .Count(); @@ -51,6 +70,8 @@ namespace ZoneCodeGenerator.Generating.Computations public bool PointerDepthIsOne => PointerDepth == 1; public bool PointerDepthIsTwo => PointerDepth == 2; + public MemberReferenceComputations References => new MemberReferenceComputations(information); + public MemberComputations(MemberInformation information) { this.information = information; diff --git a/src/ZoneCodeGenerator/Generating/Computations/MemberReferenceComputations.cs b/src/ZoneCodeGenerator/Generating/Computations/MemberReferenceComputations.cs new file mode 100644 index 00000000..3f0a28c6 --- /dev/null +++ b/src/ZoneCodeGenerator/Generating/Computations/MemberReferenceComputations.cs @@ -0,0 +1,67 @@ +using System.Collections.Generic; +using System.Linq; +using ZoneCodeGenerator.Domain; +using ZoneCodeGenerator.Domain.Evaluation; +using ZoneCodeGenerator.Domain.Information; + +namespace ZoneCodeGenerator.Generating.Computations +{ + class MemberReferenceComputations + { + private readonly MemberInformation information; + private readonly List referenceIndices; + + public ReferenceType Reference => referenceIndices.Count < information.Member.VariableType.References.Count + ? information.Member.VariableType.References[referenceIndices.Count] + : null; + + public ReferenceType NextReference => + referenceIndices.Count + 1 < information.Member.VariableType.References.Count + ? information.Member.VariableType.References[referenceIndices.Count + 1] + : null; + + public IEnumerable FollowingReferences => + information.Member.VariableType.References.Skip(referenceIndices.Count + 1); + + public IEnumerable ArrayIndices => referenceIndices; + + public bool IsArray => Reference is ReferenceTypeArray; + public int ArraySize => Reference is ReferenceTypeArray array ? array.ArraySize : 0; + + public IEnumerable ArrayEntries => Enumerable.Range(0, ArraySize) + .Select(i => new MemberReferenceComputations(information, referenceIndices.Concat(new[] {i}))); + + public bool IsSinglePointer => Reference is ReferenceTypePointer referenceTypePointer + && !referenceTypePointer.IsArray + && !FollowingReferences.OfType().Any(); + + public bool IsArrayPointer => Reference is ReferenceTypePointer referenceTypePointer + && referenceTypePointer.IsArray + && !FollowingReferences.OfType().Any(); + + public IEvaluation ArrayPointerCountEvaluation => Reference is ReferenceTypePointer referenceTypePointer + ? referenceTypePointer.Count + : null; + + public bool IsPointerArray => + (Reference is ReferenceTypePointer referenceTypePointer && referenceTypePointer.IsArray || + Reference is ReferenceTypeArray) + && NextReference is ReferenceTypePointer nextReferencePointer && !nextReferencePointer.IsArray; + + public IEvaluation PointerArrayCountEvaluation => NextReference is ReferenceTypePointer referenceTypePointer + ? referenceTypePointer.Count + : null; + + public MemberReferenceComputations(MemberInformation information) + { + this.information = information; + referenceIndices = new List(); + } + + private MemberReferenceComputations(MemberInformation information, IEnumerable referenceIndices) + { + this.information = information; + this.referenceIndices = new List(referenceIndices); + } + } +} \ No newline at end of file diff --git a/src/ZoneCodeGenerator/Generating/RenderingContext.cs b/src/ZoneCodeGenerator/Generating/RenderingContext.cs index 8b19998f..afd8ad54 100644 --- a/src/ZoneCodeGenerator/Generating/RenderingContext.cs +++ b/src/ZoneCodeGenerator/Generating/RenderingContext.cs @@ -1,24 +1,42 @@ using System.Collections.Generic; -using System.IO; using System.Linq; using ZoneCodeGenerator.Domain; using ZoneCodeGenerator.Domain.FastFileStructure; using ZoneCodeGenerator.Domain.Information; using ZoneCodeGenerator.Interface; -using ZoneCodeGenerator.Persistence; namespace ZoneCodeGenerator.Generating { class RenderingContext { + public class UsedType + { + public DataType Type { get; } + public StructureInformation Information { get; } + public bool IsContextAsset { get; set; } + + public bool NonEmbeddedReferenceExists { get; set; } + public bool ArrayReferenceExists { get; set; } + public bool PointerArrayReferenceExists { get; set; } + + public UsedType(DataType type, StructureInformation information) + { + Type = type; + Information = information; + IsContextAsset = false; + NonEmbeddedReferenceExists = false; + ArrayReferenceExists = false; + PointerArrayReferenceExists = false; + } + } + public string Game { get; set; } public StructureInformation Asset { get; set; } - public ISet Structures { get; } - public ISet MemberTypes { get; } + private readonly IDictionary usedTypes; + public IEnumerable UsedTypes => usedTypes.Values; - public IEnumerable ReferencedAssets => - Structures.Where(inf => inf.IsAsset && inf != Asset); + public IEnumerable ReferencedAssets => UsedTypes.Where(type => type.Information != null && type.Information.IsAsset && type.Information != Asset); public IList Blocks { get; private set; } @@ -27,22 +45,45 @@ namespace ZoneCodeGenerator.Generating private RenderingContext() { - Structures = new HashSet(); - MemberTypes = new HashSet(); + usedTypes = new Dictionary(); } private void AddToContext(StructureInformation structureInformation) { - if (!Structures.Add(structureInformation)) + if (usedTypes.ContainsKey(structureInformation.Type)) return; + var newUsage = new UsedType(structureInformation.Type, structureInformation); + usedTypes.Add(newUsage.Type, newUsage); + if (structureInformation.IsAsset && structureInformation != Asset) return; foreach (var member in structureInformation.OrderedMembers - .Where(member => member.StructureType != null && !member.Computations.ShouldIgnore)) + .Where(member => !member.Computations.ShouldIgnore)) { - AddToContext(member.StructureType); + if(member.StructureType != null) + AddToContext(member.StructureType); + + UsedType usedType; + if (!usedTypes.ContainsKey(member.Member.VariableType.Type)) + { + usedType = new UsedType(member.Member.VariableType.Type, member.StructureType); + usedTypes.Add(usedType.Type, usedType); + } + else + { + usedType = usedTypes[member.Member.VariableType.Type]; + } + + if (member.Computations.ContainsNonEmbeddedReference) + usedType.NonEmbeddedReferenceExists = true; + + if (member.Computations.ContainsArrayPointerReference || member.Computations.ContainsArrayReference) + usedType.ArrayReferenceExists = true; + + if (member.Computations.ContainsPointerArrayReference) + usedType.PointerArrayReferenceExists = true; } } @@ -56,15 +97,7 @@ namespace ZoneCodeGenerator.Generating }; context.AddToContext(asset); - context.MemberTypes.UnionWith(context.Structures - .Where(structureInformation => !structureInformation.IsAsset || structureInformation == asset) - .Where(structureInformation => - structureInformation.Computations.IsUsed || structureInformation == asset) - .SelectMany(information => information.OrderedMembers) - .Where(information => !information.Computations.ShouldIgnore) - .Select(information => information.Member.VariableType.Type) - .Where(type => !(type is DataTypeBaseType) && type != asset.Type) - .Distinct()); + context.usedTypes[asset.Type].IsContextAsset = true; return context; } diff --git a/src/ZoneCodeGenerator/Generating/Templates/Common.stg b/src/ZoneCodeGenerator/Generating/Templates/Common.stg index 52a83d44..da2f92d5 100644 --- a/src/ZoneCodeGenerator/Generating/Templates/Common.stg +++ b/src/ZoneCodeGenerator/Generating/Templates/Common.stg @@ -5,8 +5,24 @@ Lower(name) ::= "$name; format=\"lower\"$" TypeDeclaration(typeDecl) ::= "$if(typeDecl.IsConst)$const $endif$$typeDecl.Type.FullName$" -TypeVarName(structure) ::= "var$structure.Type.Name$" -TypePtrVarName(structure) ::= "var$structure.Type.Name$Ptr" +TypeVarName(structure) ::= "var$SafeTypeName(structure.Type)$" +TypePtrVarName(structure) ::= "var$SafeTypeName(structure.Type)$Ptr" + +SafeTypeName(type) ::= "$type; format=\"safe_name\"$" + +PrintFollowingReferences(references) ::= <% +$references:{ reference | + +$if(reference.ArraySize)$ +[$reference.ArraySize$] +$else$ +* +$endif$ + +}$ +%> + +PrintArrayIndices(reference) ::= "$reference.ArrayIndices:{ index | [$index$] }$" PrintOperandStatic(op) ::= <% $if(op.EnumMemberValue)$ diff --git a/src/ZoneCodeGenerator/Generating/Templates/Loading/ArrayPointer.stg b/src/ZoneCodeGenerator/Generating/Templates/Loading/ArrayPointer.stg index ce7715ee..45ed2c9a 100644 --- a/src/ZoneCodeGenerator/Generating/Templates/Loading/ArrayPointer.stg +++ b/src/ZoneCodeGenerator/Generating/Templates/Loading/ArrayPointer.stg @@ -1,68 +1,59 @@ +delimiters "$", "$" + // Everything related to loading a pointer with a count that can be larger than 1 -LoadArrayPointer_Loading(context, structure, member) ::= <% -$TypeVarName(structure)$->$member.Member.Name$ = m_stream->Alloc<$TypeDeclaration(member.Member.VariableType)$>(alignof($TypeDeclaration(member.Member.VariableType)$));$\n$ +LoadArrayPointer_Loading(context, structure, member, reference) ::= <% +$TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$ = m_stream->Alloc<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>(alignof($TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$));$\n$ $if(member.StructureType && !member.StructureType.IsLeaf)$ -$TypeVarName(member.StructureType)$ = $TypeVarName(structure)$->$member.Member.Name$;$\n$ -LoadArray_$member.Member.VariableType.Type.Name$(true, $PrintEvaluation(member.Computations.ArrayPointerCountEvaluation)$); +$TypeVarName(member.StructureType)$ = $TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$ +LoadArray_$member.Member.VariableType.Type.Name$(true, $PrintEvaluation(reference.ArrayPointerCountEvaluation)$); $else$ -m_stream->Load<$TypeDeclaration(member.Member.VariableType)$>($TypeVarName(structure)$->$member.Member.Name$, $PrintEvaluation(member.Computations.ArrayPointerCountEvaluation)$); +m_stream->Load<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>($TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$, $PrintEvaluation(reference.ArrayPointerCountEvaluation)$); $endif$ %> -LoadArrayPointer_PointerCheck(context, structure, member) ::= << -if ($TypeVarName(structure)$->$member.Member.Name$) +LoadArrayPointer_PointerCheck(context, structure, member, reference) ::= << +if ($TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$) { $if(member.IsReusable)$ - if($TypeVarName(structure)$->$member.Member.Name$ == PTR_FOLLOWING) + if($TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$ == PTR_FOLLOWING) { - $LoadArrayPointer_Loading(context, structure, member)$ + $LoadArrayPointer_Loading(context, structure, member, reference)$ } else { - $TypeVarName(structure)$->$member.Member.Name$ = m_stream->ConvertOffsetToPointer($TypeVarName(structure)$->$member.Member.Name$); + $TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$ = m_stream->ConvertOffsetToPointer($TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$); } $else$ - $LoadArrayPointer_Loading(context, structure, member)$ + $LoadArrayPointer_Loading(context, structure, member, reference)$ $endif$ } >> -LoadArrayPointer_Condition(context, structure, member) ::= <% -$if(member.Condition)$ -$if(structure.IsUnion)$ - -if($PrintEvaluation(member.Condition)$)$\n$ -{$\n$ - $LoadArrayPointer_PointerCheck(context, structure, member)$$\n$ -}$\n$ -$\n$ - +LoadArrayPointer_TypeCheck(context, structure, member, reference) ::= <% +$if(member.IsScriptString)$ +// ScriptString $member.Member.Name$ $else$ - -if($PrintEvaluation(member.Condition)$)$\n$ -{$\n$ - $LoadArrayPointer_PointerCheck(context, structure, member)$$\n$ -}$\n$ -$\n$ - -$endif$ - -$else$ - -$LoadArrayPointer_PointerCheck(context, structure, member)$$\n$ -$\n$ - +$LoadArrayPointer_PointerCheck(context, structure, member, reference)$ $endif$ %> -LoadArrayPointer(context, structure, member) ::= <% -$if(!member.Computations.ShouldIgnore)$ -$LoadArrayPointer_Condition(context, structure, member)$ +LoadArrayPointer_Condition(context, structure, member, reference) ::= << +$if(member.Condition)$$\\$ +if($PrintEvaluation(member.Condition)$) +{ + $LoadArrayPointer_TypeCheck(context, structure, member, reference)$ +} +$else$$\\$ +$LoadArrayPointer_TypeCheck(context, structure, member, reference)$$\\$ $endif$ +>> + +LoadArrayPointer(context, structure, member, reference) ::= <% +$LoadArrayPointer_Condition(context, structure, member, reference)$ %> \ No newline at end of file diff --git a/src/ZoneCodeGenerator/Generating/Templates/Loading/Common.stg b/src/ZoneCodeGenerator/Generating/Templates/Loading/Common.stg index f01f1280..1a3cc6ea 100644 --- a/src/ZoneCodeGenerator/Generating/Templates/Loading/Common.stg +++ b/src/ZoneCodeGenerator/Generating/Templates/Loading/Common.stg @@ -1,2 +1,4 @@ +delimiters "$", "$" + // Loading common LoaderClassName(asset) ::= "Loader_$asset.Type.Name$" \ No newline at end of file diff --git a/src/ZoneCodeGenerator/Generating/Templates/Loading/Embedded.stg b/src/ZoneCodeGenerator/Generating/Templates/Loading/Embedded.stg index f3e2f4b0..50700370 100644 --- a/src/ZoneCodeGenerator/Generating/Templates/Loading/Embedded.stg +++ b/src/ZoneCodeGenerator/Generating/Templates/Loading/Embedded.stg @@ -1,21 +1,25 @@ +delimiters "$", "$" + // Everything related to loading an embedded reference -LoadEmbedded_Load(context, structure, member) ::= << -$TypeVarName(member.StructureType)$ = &$TypeVarName(structure)$->$member.Member.Name$; +LoadEmbedded_Load(context, structure, member, reference) ::= << +$TypeVarName(member.StructureType)$ = &$TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$; Load_$member.Member.VariableType.Type.Name$(false); - >> -LoadEmbedded_Array(context, structure, member) ::= << - ->> - -LoadEmbedded(context, structure, member) ::= <% -$if(!member.Computations.ShouldIgnore)$ -$if(member.Computations.IsArray)$ -$LoadEmbedded_Array(context, structure, member)$ +LoadEmbedded_TypeCheck(context, structure, member, reference) ::= <% +$if(member.IsScriptString)$ +$TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$ = UseScriptString($TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$); $else$ -$LoadEmbedded_Load(context, structure, member)$ +$LoadEmbedded_Load(context, structure, member, reference)$ $endif$ -$endif$ -%> \ No newline at end of file +%> + +LoadEmbedded(context, structure, member, reference) ::= <% +$LoadEmbedded_TypeCheck(context, structure, member, reference)$ +%> + +LoadEmbeddedArray(context, structure, member, reference) ::= << +$TypeVarName(member.StructureType)$ = $TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$; +LoadArray_$member.Member.VariableType.Type.Name$(false, $reference.ArraySize$); // ASDF +>> \ No newline at end of file diff --git a/src/ZoneCodeGenerator/Generating/Templates/Loading/PointerArray.stg b/src/ZoneCodeGenerator/Generating/Templates/Loading/PointerArray.stg new file mode 100644 index 00000000..167c55f7 --- /dev/null +++ b/src/ZoneCodeGenerator/Generating/Templates/Loading/PointerArray.stg @@ -0,0 +1,45 @@ +delimiters "$", "$" + +LoadPointerArray_Loading(context, structure, member, reference) ::= <% +$if(member.Computations.IsArray)$ +$TypePtrVarName(member.Member.VariableType)$ = $TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$ +LoadPtrArray_$SafeTypeName(member.Member.VariableType.Type)$(false, $reference.ArraySize$); +$else$ +$TypePtrVarName(member.Member.VariableType)$ = $TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$ +LoadPtrArray_$SafeTypeName(member.Member.VariableType.Type)$(true, $PrintEvaluation(reference.ArrayPointerCountEvaluation)$); +$endif$ +%> + +LoadPointerArray_String(context, structure, member, reference) ::= <% +$if(reference.IsArray)$ +varXString = $TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$ +LoadXStringArray(false, $reference.ArraySize$); +$else$ +$TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$ = m_stream->Alloc<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>(alignof($TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$));$\n$ +varXString = $TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$ +LoadXStringArray(true, $PrintEvaluation(reference.ArrayPointerCountEvaluation)$); +$endif$ +%> + +LoadPointerArray_TypeCheck(context, structure, member, reference) ::= <% +$if(member.IsString)$ +$LoadPointerArray_String(context, structure, member, reference)$ +$else$ +$LoadPointerArray_Loading(context, structure, member, reference)$ +$endif$ +%> + +LoadPointerArray_Condition(context, structure, member, reference) ::= << +$if(member.Condition)$$\\$ +if($PrintEvaluation(member.Condition)$) +{ + $LoadPointerArray_TypeCheck(context, structure, member, reference)$ +} +$else$$\\$ +$LoadPointerArray_TypeCheck(context, structure, member, reference)$$\\$ +$endif$ +>> + +LoadPointerArray(context, structure, member, reference) ::= <% +$LoadPointerArray_Condition(context, structure, member, reference)$ +%> \ No newline at end of file diff --git a/src/ZoneCodeGenerator/Generating/Templates/Loading/SinglePointer.stg b/src/ZoneCodeGenerator/Generating/Templates/Loading/SinglePointer.stg index 4cbd9bd7..a072d429 100644 --- a/src/ZoneCodeGenerator/Generating/Templates/Loading/SinglePointer.stg +++ b/src/ZoneCodeGenerator/Generating/Templates/Loading/SinglePointer.stg @@ -1,62 +1,78 @@ +delimiters "$", "$" + // Everything related to loading a pointer with a count that is statically 1 -LoadSinglePointerInner(context, structure, member) ::= << -$TypeVarName(structure)$->$member.Member.Name$ = m_stream->Alloc<$TypeDeclaration(member.Member.VariableType)$>(alignof($TypeDeclaration(member.Member.VariableType)$)); +LoadSinglePointerInner(context, structure, member, reference) ::= <% +$TypeVarName(structure)$->$member.Member.Name$ = m_stream->Alloc<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>(alignof($TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$));$\n$ + $if(member.StructureType && !member.StructureType.IsLeaf)$ -$TypeVarName(member.StructureType)$ = $TypeVarName(structure)$->$member.Member.Name$; + +$TypeVarName(member.StructureType)$ = $TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$ Load_$member.Member.VariableType.Type.Name$(true); + $else$ -m_stream->Load<$TypeDeclaration(member.Member.VariableType)$>($TypeVarName(structure)$->$member.Member.Name$);$endif$ ->> -LoadSinglePointerAsset(context, structure, member) ::= << +m_stream->Load<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>($TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$); + +$endif$ +%> + +LoadSinglePointerAsset(context, structure, member, reference) ::= << $LoaderClassName(member.StructureType)$ loader(m_script_string_provider, m_zone, m_stream); -loader.Load(&$TypeVarName(structure)$->$member.Member.Name$); +loader.Load(&$TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$); >> -LoadSinglePointer_PointerCheck(context, structure, member) ::= << -if ($TypeVarName(structure)$->$member.Member.Name$) +LoadSinglePointer_PointerCheck(context, structure, member, reference) ::= << +if ($TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$) { $if(member.StructureType && member.StructureType.IsAsset)$ - $LoadSinglePointerAsset(context, structure, member)$ + $LoadSinglePointerAsset(context, structure, member, reference)$ $else$ $if(member.IsReusable)$ - if($TypeVarName(structure)$->$member.Member.Name$ == PTR_FOLLOWING) + if($TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$ == PTR_FOLLOWING) { - $LoadSinglePointerInner(context, structure, member)$ + $LoadSinglePointerInner(context, structure, member, reference)$ } else { - $TypeVarName(structure)$->$member.Member.Name$ = m_stream->ConvertOffsetToPointer($TypeVarName(structure)$->$member.Member.Name$); + $TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$ = m_stream->ConvertOffsetToPointer($TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$); } $else$ - $LoadSinglePointerInner(context, structure, member)$ + $LoadSinglePointerInner(context, structure, member, reference)$ $endif$ $endif$ } >> -LoadSinglePointer_Condition(context, structure, member) ::= <% -$if(member.Condition)$ - -if($PrintEvaluation(member.Condition)$)$\n$ -{$\n$ - $LoadSinglePointer_PointerCheck(context, structure, member)$$\n$ -}$\n$ -$\n$ +LoadSinglePointer_String(context, structure, member, reference) ::= <% +varXString = &$TypeVarName(structure)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$ +LoadXString(false); +%> +LoadSinglePointer_TypeCheck(context, structure, member, reference) ::= <% +$if(member.IsString)$ +$LoadSinglePointer_String(context, structure, member, reference)$ +$elseif(member.IsScriptString)$ +// ScriptString $member.Member.Name$ $else$ - -$LoadSinglePointer_PointerCheck(context, structure, member)$$\n$ -$\n$ - +$LoadSinglePointer_PointerCheck(context, structure, member, reference)$ $endif$ %> -LoadSinglePointer(context, structure, member) ::= <% -$if(!member.Computations.ShouldIgnore)$ -$if(!member.Computations.IsArray && member.Computations.PointerDepthIsOne)$$! TODO: FIX ARRAYS !$ -$LoadSinglePointer_Condition(context, structure, member)$ +LoadSinglePointer_Condition(context, structure, member, reference) ::= << +$if(member.Condition)$ +if($PrintEvaluation(member.Condition)$) +{ + $LoadSinglePointer_TypeCheck(context, structure, member, reference)$ +} +$if(structure.IsUnion)$ +return; $endif$ +$else$$\\$ +$LoadSinglePointer_TypeCheck(context, structure, member, reference)$$\\$ $endif$ +>> + +LoadSinglePointer(context, structure, member, reference) ::= <% +$LoadSinglePointer_Condition(context, structure, member, reference)$ %> \ No newline at end of file diff --git a/src/ZoneCodeGenerator/Generating/Templates/Loading/String.stg b/src/ZoneCodeGenerator/Generating/Templates/Loading/String.stg deleted file mode 100644 index 4906678b..00000000 --- a/src/ZoneCodeGenerator/Generating/Templates/Loading/String.stg +++ /dev/null @@ -1,30 +0,0 @@ -// String - -LoadStringSingleDepth(context, structure, member) ::= <% -$if(!member.Computations.IsArray)$ -varXString = &$TypeVarName(structure)$->$member.Member.Name$;$\n$ -LoadXString(false);$\n$ -$else$ -varXString = $TypeVarName(structure)$->$member.Member.Name$;$\n$ -LoadXStringArray(false, $first(member.Computations.ArraySizes)$);$\n$ -$endif$ -%> - -LoadString_PointerCheck(context, structure, member) ::= << -if ($TypeVarName(structure)$->$member.Member.Name$) -{ - $TypeVarName(structure)$->$member.Member.Name$ = m_stream->Alloc<$TypeDeclaration(member.Member.VariableType)$*>(alignof($TypeDeclaration(member.Member.VariableType)$*)); - varXString = $TypeVarName(structure)$->$member.Member.Name$; - LoadXStringArray(true, $PrintEvaluation(member.Computations.ArrayPointerCountEvaluation)$); -} ->> - -LoadString(context, structure, member) ::= <% -$if(member.Computations.PointerDepthIsOne)$ -$LoadStringSingleDepth(context, structure, member)$ -$elseif(member.Computations.PointerDepthIsTwo && member.Computations.ArrayPointerCountEvaluation)$ -$LoadString_PointerCheck(context, structure, member)$ -$else$ -#error Cannot load string $member.Member.Name$ -$endif$ -%> \ No newline at end of file diff --git a/src/ZoneCodeGenerator/Generating/Templates/ZoneLoad.stg b/src/ZoneCodeGenerator/Generating/Templates/ZoneLoad.stg index 32baff89..040e2287 100644 --- a/src/ZoneCodeGenerator/Generating/Templates/ZoneLoad.stg +++ b/src/ZoneCodeGenerator/Generating/Templates/ZoneLoad.stg @@ -3,10 +3,10 @@ delimiters "$", "$" import "Common.stg" import "Loading/Common.stg" -import "Loading/String.stg" import "Loading/ArrayPointer.stg" import "Loading/Embedded.stg" import "Loading/SinglePointer.stg" +import "Loading/PointerArray.stg" // Loading common LoaderClassName(asset) ::= "Loader_$asset.Type.Name$" @@ -14,7 +14,8 @@ LoaderClassName(asset) ::= "Loader_$asset.Type.Name$" HeaderConstructor(context) ::= "$LoaderClassName(context.Asset)$(IZoneScriptStringProvider* scriptStringProvider, Zone* zone, IZoneInputStream* stream);" HeaderSinglePtrLoadMethodDeclaration(structure) ::= "void LoadPtr_$structure.Type.Name$(bool atStreamStart);" -HeaderArrayPtrLoadMethodDeclaration(structure) ::= "void LoadArray_$structure.Type.Name$(bool atStreamStart, size_t count);" +HeaderArrayLoadMethodDeclaration(structure) ::= "void LoadArray_$structure.Type.Name$(bool atStreamStart, size_t count);" +HeaderPtrArrayLoadMethodDeclaration(type) ::= "void LoadPtrArray_$SafeTypeName(type)$(bool atStreamStart, size_t count);" HeaderLoadMethodDeclaration(structure) ::= "void Load_$structure.Type.Name$(bool atStreamStart);" HeaderGetNameMethodDeclaration(asset) ::= "static std::string GetAssetName($asset.Type.FullName$* pAsset);" @@ -22,26 +23,24 @@ HeaderAssetLoadMethodDeclaration(asset) ::= "void LoadAsset_$asset.Type.Name$($a HeaderMainLoadMethodDeclaration(asset) ::= "void Load($asset.Type.FullName$** pAsset);" VariableDeclaration(type) ::= << -$type.FullName$* var$type.Name$; +$type.FullName$* var$SafeTypeName(type)$; >> PointerVariableDeclaration(type) ::= << -$type.FullName$** var$type.Name$Ptr; +$type.FullName$** var$SafeTypeName(type)$Ptr; >> -HeaderDeclaration(structure) ::= <% -$if(structure.SinglePointerReferenceExists)$ -$HeaderSinglePtrLoadMethodDeclaration(structure)$ +HeaderMethodDeclarations(usedType) ::= <% +$if(usedType.PointerArrayReferenceExists)$ +$HeaderPtrArrayLoadMethodDeclaration(usedType.Type)$ $\n$ $endif$ - -$if(structure.ArrayPointerReferenceExists && !structure.IsLeaf)$ -$HeaderArrayPtrLoadMethodDeclaration(structure)$ +$if(usedType.ArrayReferenceExists && usedType.Information && !usedType.Information.IsLeaf)$ +$HeaderArrayLoadMethodDeclaration(usedType.Information)$ $\n$ $endif$ - -$if(!structure.IsLeaf && structure.Computations.IsUsed)$ -$HeaderLoadMethodDeclaration(structure)$ +$if(usedType.Information && !usedType.Information.IsLeaf && !usedType.Information.IsAsset)$ +$HeaderLoadMethodDeclaration(usedType.Information)$ $\n$ $endif$ %> @@ -68,11 +67,13 @@ namespace $context.Game$ { $VariableDeclaration(context.Asset.Type)$ $PointerVariableDeclaration(context.Asset.Type)$ - $context.MemberTypes:{type | $if(!type.IsAnonymous)$$VariableDeclaration(type)$ + + $context.UsedTypes:{type | $if(type.Information && !type.Information.Type.IsAnonymous && !type.Information.IsLeaf && !type.Information.IsAsset)$$VariableDeclaration(type.Type)$ $endif$}$ - $context.Structures:{structure | $if(!structure.IsAsset && structure.SinglePointerReferenceExists)$$PointerVariableDeclaration(structure.Type)$ - $endif$}$ - $context.Structures:{structure | $if(!structure.IsAsset)$$HeaderDeclaration(structure)$$endif$}$ + $context.UsedTypes:{type | $if(type.PointerArrayReferenceExists && !type.IsContextAsset)$$PointerVariableDeclaration(type.Type)$ + $endif$}$$\\$ + + $context.UsedTypes:{usedType | $HeaderMethodDeclarations(usedType)$}$ $HeaderLoadMethodDeclaration(context.Asset)$ $HeaderSinglePtrLoadMethodDeclaration(context.Asset)$ $HeaderAssetLoadMethodDeclaration(context.Asset)$ @@ -89,41 +90,43 @@ LoadMember(context, member) ::= << Loading member $member.Member.Name$ >> - -LoadMemberIfNeedsTreatment(context, structure, member) ::= <% -$if(member.IsString)$ -$LoadString(context, structure, member)$ -$elseif(member.IsScriptString)$ -// Load scriptstring for $member.Member.Name$ -$elseif(member.Computations.IsArrayPointerReference && member.Computations.PointerDepthIsOne)$ -$LoadArrayPointer(context, structure, member)$ -$elseif(member.Computations.IsSinglePointerReference)$ -$LoadSinglePointer(context, structure, member)$ -$elseif(member.Computations.IsEmbeddedReference && member.StructureType && !member.StructureType.IsLeaf)$ -$LoadEmbedded(context, structure, member)$ +LoadMemberReference(context, structure, member, reference) ::= <% +$if(reference.IsSinglePointer)$ +$\n$$\n$ +$LoadSinglePointer(context, structure, member, reference)$ +$elseif(reference.IsArrayPointer)$ +$\n$$\n$ +$LoadArrayPointer(context, structure, member, reference)$ +$elseif(reference.IsPointerArray)$ +$\n$$\n$ +$LoadPointerArray(context, structure, member, reference)$ +$elseif(reference.IsArray && !reference.NextReference)$ +$\n$$\n$ +$LoadEmbeddedArray(context, structure, member, reference)$ +$elseif(!reference.Reference)$ +$\n$$\n$ +$LoadEmbedded(context, structure, member, reference)$ +$else$ +$\n$$\n$ +// $member.Member.Name$ $endif$ %> -LoadMethod(structure, context) ::= << -void $LoaderClassName(context.Asset)$::Load_$structure.Type.Name$(const bool atStreamStart) -{ - assert($TypeVarName(structure)$ != nullptr); +LoadMemberIfNeedsTreatment(context, structure, member) ::= <% +$if(!member.Computations.ShouldIgnore)$ - if(atStreamStart) - m_stream->Load<$structure.Type.FullName$>($TypeVarName(structure)$); - $if(structure.Block.IsTemp)$ +$if(member.IsString || member.IsScriptString)$ +$LoadMemberReference(context, structure, member, member.Computations.References)$ +$elseif(member.Computations.ContainsNonEmbeddedReference)$ +$LoadMemberReference(context, structure, member, member.Computations.References)$ +$elseif(member.StructureType && !member.StructureType.IsLeaf)$ +$LoadMemberReference(context, structure, member, member.Computations.References)$ +$endif$ - m_stream->PushBlock($context.DefaultNormalBlock.Name$); - $endif$ - - $structure.OrderedMembers:{member | $LoadMemberIfNeedsTreatment(context, structure, member)$}$ - $if(structure.Block.IsTemp)$ - m_stream->PopBlock(); - $endif$ -} ->> +$endif$ +%> -LoadSinglePtrMethod(structure, context) ::= << +LoadSinglePtrMethod(context, structure) ::= << void $LoaderClassName(context.Asset)$::LoadPtr_$structure.Type.Name$(const bool atStreamStart) { assert($TypePtrVarName(structure)$ != nullptr); @@ -177,7 +180,14 @@ void $LoaderClassName(context.Asset)$::LoadPtr_$structure.Type.Name$(const bool } >> -LoadArrayPtrMethod(structure, context) ::= << +LoadPointerArrayMethod(context, type, structure) ::= << +void $LoaderClassName(context.Asset)$::LoadPtrArray_$SafeTypeName(type)$(const bool atStreamStart, const size_t count) +{ + +} +>> + +LoadArrayMethod(context, structure) ::= << void $LoaderClassName(context.Asset)$::LoadArray_$structure.Type.Name$(const bool atStreamStart, const size_t count) { assert($TypeVarName(structure)$ != nullptr); @@ -193,21 +203,40 @@ void $LoaderClassName(context.Asset)$::LoadArray_$structure.Type.Name$(const boo } >> -SourceDefinition(structure, context) ::= << -$if(structure.SinglePointerReferenceExists)$ -$LoadSinglePtrMethod(structure, context)$ +LoadMethod(context, structure) ::= << +void $LoaderClassName(context.Asset)$::Load_$structure.Type.Name$(const bool atStreamStart) +{ + assert($TypeVarName(structure)$ != nullptr); -$endif$ -$if(structure.ArrayPointerReferenceExists && !structure.IsLeaf)$ -$LoadArrayPtrMethod(structure, context)$ + if(atStreamStart) + m_stream->Load<$structure.Type.FullName$>($TypeVarName(structure)$);$\\$ + $if(structure.Block.IsTemp)$ -$endif$ -$if(!structure.IsLeaf && structure.Computations.IsUsed)$ -$LoadMethod(structure, context)$ + m_stream->PushBlock($context.DefaultNormalBlock.Name$);$\\$ + $endif$ + $structure.OrderedMembers:{member | $LoadMemberIfNeedsTreatment(context, structure, member)$}$ + $if(structure.Block.IsTemp)$ -$endif$ + m_stream->PopBlock(); + $endif$ +} >> +SourceDefinition(context, usedType) ::= <% +$if(usedType.PointerArrayReferenceExists)$ +$LoadPointerArrayMethod(context, usedType.Type, usedType.Information)$ +$\n$$\n$ +$endif$ +$if(usedType.ArrayReferenceExists && usedType.Information && !usedType.Information.IsLeaf)$ +$LoadArrayMethod(context, usedType.Information)$ +$\n$$\n$ +$endif$ +$if(usedType.Information && !usedType.Information.IsLeaf && !usedType.Information.IsAsset)$ +$LoadMethod(context, usedType.Information)$ +$\n$$\n$ +$endif$ +%> + VariableInitialization(type) ::= << var$type.Name$ = nullptr; >> @@ -222,14 +251,15 @@ $LoaderClassName(context.Asset)$::$LoaderClassName(context.Asset)$(IZoneScriptSt { $VariableInitialization(context.Asset.Type)$ $PointerVariableInitialization(context.Asset.Type)$ - $context.MemberTypes:{type | $if(!type.IsAnonymous)$$VariableInitialization(type)$ - $endif$}$ - $context.Structures:{structure | $if(!structure.IsAsset && structure.SinglePointerReferenceExists)$$PointerVariableInitialization(structure.Type)$ - $endif$}$ + + $context.UsedTypes:{type | $if(type.Information && !type.Information.Type.IsAnonymous && !type.Information.IsLeaf && !type.Information.IsAsset)$$VariableInitialization(type.Type)$ + $endif$}$ + $context.UsedTypes:{type | $if(type.Information && type.PointerArrayReferenceExists && !type.IsContextAsset)$$PointerVariableInitialization(type.Type)$ + $endif$}$$\\$ } >> -LoadAssetMethod(structure, context) ::= << +LoadAssetMethod(context, structure) ::= << void $LoaderClassName(context.Asset)$::LoadAsset_$structure.Type.Name$($structure.Type.FullName$** pAsset) { assert(pAsset != nullptr); @@ -283,12 +313,12 @@ using namespace $context.Game$; $ConstructorMethod(context)$ -$context.Structures:{structure | $if(!structure.IsAsset)$$SourceDefinition(structure, context)$$endif$}$ -$LoadMethod(context.Asset, context)$ +$context.UsedTypes:{usedType | $SourceDefinition(context, usedType)$}$ +$LoadMethod(context, context.Asset)$ -$LoadAssetMethod(context.Asset, context)$ +$LoadSinglePtrMethod(context, context.Asset)$ -$LoadSinglePtrMethod(context.Asset, context)$ +$LoadAssetMethod(context, context.Asset)$ $MainLoadMethod(context)$ diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/PostProcessor/PostProcessorUsages.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/PostProcessor/PostProcessorUsages.cs index b731146a..084fb13f 100644 --- a/src/ZoneCodeGenerator/Parsing/CommandFile/PostProcessor/PostProcessorUsages.cs +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/PostProcessor/PostProcessorUsages.cs @@ -27,16 +27,16 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.PostProcessor .Where(member => member.StructureType != null) .Where(member => !member.Computations.ShouldIgnore)) { - if (member.Computations.IsNonEmbeddedReference) + if (member.Computations.ContainsNonEmbeddedReference) member.StructureType.NonEmbeddedReferenceExists = true; - if (member.Computations.IsSinglePointerReference) + if (member.Computations.ContainsSinglePointerReference) member.StructureType.SinglePointerReferenceExists = true; - if (member.Computations.IsArrayPointerReference) + if (member.Computations.ContainsArrayPointerReference) member.StructureType.ArrayPointerReferenceExists = true; - if (member.Computations.IsArrayReference) + if (member.Computations.ContainsArrayReference) member.StructureType.ArrayReferenceExists = true; member.StructureType.Usages.Add(currentStructure); diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestName.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestName.cs index 54700aed..ec541347 100644 --- a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestName.cs +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestName.cs @@ -50,7 +50,7 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests for (var i = 0; i < memberList.Count - 1; i++) { - if (!memberList[i].Computations.IsEmbeddedReference) + if (memberList[i].Computations.ContainsNonEmbeddedReference) { throw new TestFailedException("Can only add embedded members to name chain."); } diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestReusable.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestReusable.cs index 9cb0534b..bdb6872e 100644 --- a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestReusable.cs +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestReusable.cs @@ -52,7 +52,7 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests var lastMember = memberList.Last(); - if (!lastMember.Computations.IsNonEmbeddedReference) + if (!lastMember.Computations.ContainsNonEmbeddedReference) { throw new TestFailedException($"Specified member '{lastMember.Member.Name}' is not a pointer reference and therefore cannot be reusable."); } diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestString.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestString.cs index 5bd68340..1bd4bb76 100644 --- a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestString.cs +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestString.cs @@ -56,7 +56,7 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests throw new TestFailedException($"Specified member '{lastMember.Member.Name}' is not char type and therefore cannot be a string."); } - if (!lastMember.Computations.IsSinglePointerReference) + if (!lastMember.Computations.ContainsSinglePointerReference) { throw new TestFailedException($"Specified member '{lastMember.Member.Name}' is a single pointer reference and therefore cannot be a string."); }