namespace HeuristicLab.Problems.ProgramSynthesis.Push.Encoding { using System.Collections.Generic; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Problems.ProgramSynthesis.Push.Attributes; using HeuristicLab.Problems.ProgramSynthesis.Push.Expressions; [StorableClass] public sealed class PlushVector : Item { [Storable] private readonly List entries; public IReadOnlyList Entries { get { return entries; } } public PlushVector() : this(0) { } public PlushVector(int length) { entries = new List(length); } [StorableConstructor] private PlushVector(bool deserializing) : base(deserializing) { } public PlushVector(PlushVector origin, Cloner cloner) : base(origin, cloner) { entries = new List(origin.entries.Count); for (var i = 0; i < origin.entries.Count; i++) { entries.Add(cloner.Clone(origin.entries[i])); } pushProgram = origin.pushProgram; } public override IDeepCloneable Clone(Cloner cloner) { return new PlushVector(this, cloner); } private PushProgram pushProgram; public PushProgram PushProgram { get { if (pushProgram == null) CreatePushProgram(); return pushProgram; } } private void CreatePushProgram() { var close = 0; var currentIndex = 0; pushProgram = FromPlush(ref currentIndex, ref close, 0); } private PushProgram FromPlush( ref int currentIndex, ref int close, int depth) { if (currentIndex >= entries.Count) return PushProgram.Empty; var instructions = new List(); for (; currentIndex < entries.Count; currentIndex++) { var entry = entries[currentIndex]; if (entry.Silent) continue; close += entry.Close; instructions.Add(entry.Instruction); PushExpressionAttribute attribute; var instructionType = entry.Instruction.GetType(); if (ExpressionTable.TypeToAttributeTable.TryGetValue(instructionType, out attribute)) { for (var blockIdx = 0u; blockIdx < attribute.RequiredBlockCount; blockIdx++) { if (close == 0 && currentIndex < entries.Count) { currentIndex++; var subProgram = FromPlush(ref currentIndex, ref close, depth + 1); instructions.Add(subProgram); } else { close--; instructions.Add(PushProgram.Empty); } } } if (close > 0 && depth > 0) { close--; break; } if (depth == 0) { close = 0; } } instructions.Reverse(); return new PushProgram(instructions); } public void UpdatePushProgram() { pushProgram = null; } public void Add(PlushEntry entry) { entries.Add(entry); } public PlushEntry this[int key] { get { return entries[key]; } } } }