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; private readonly int combinedIndex; 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 bool HasDynamicArrayCount => Reference is ReferenceTypeArray array && array.DynamicCount != null; public IEvaluation DynamicArrayCountEvaluation => Reference is ReferenceTypeArray array ? array.DynamicCount : null; 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(combinedIndex) && !FollowingReferences.OfType().Any(); public bool IsArrayPointer => Reference is ReferenceTypePointer referenceTypePointer && referenceTypePointer.IsArray(combinedIndex) && !FollowingReferences.OfType().Any(); public IEvaluation ArrayPointerCountEvaluation { get { if (!(Reference is ReferenceTypePointer pointer)) return null; return pointer.HasCountByArrayIndex ? pointer.CountByArrayIndex[combinedIndex] : pointer.Count; } } public bool IsPointerArray => (Reference is ReferenceTypePointer referenceTypePointer && referenceTypePointer.IsArray(combinedIndex) || Reference is ReferenceTypeArray) && NextReference is ReferenceTypePointer nextReferencePointer && !nextReferencePointer.IsArray(combinedIndex); public IEvaluation PointerArrayCountEvaluation => NextReference is ReferenceTypePointer referenceTypePointer ? referenceTypePointer.Count : null; public bool IsDynamicArray => Reference is ReferenceTypeArray referenceTypeArray && referenceTypeArray.DynamicSize != null; public IEvaluation DynamicArraySizeEvaluation => Reference is ReferenceTypeArray referenceTypeArray ? referenceTypeArray.DynamicSize : null; public MemberReferenceComputations(MemberInformation information) { this.information = information; referenceIndices = new List(); combinedIndex = 0; } private MemberReferenceComputations(MemberInformation information, IEnumerable referenceIndices) { this.information = information; this.referenceIndices = new List(referenceIndices); var arraySizes = information.Member.VariableType.References .OfType() .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++; } } } }