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 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] public PlushVector(bool deserializing) : base(deserializing) { } public PlushVector(PlushVector origin, Cloner cloner) : base(origin, cloner) { entries = new List(origin.entries); 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 (var i = currentIndex; i < entries.Count; i++) { var entry = entries[i]; var instructionType = entry.Instruction.GetType(); close += entry.Close; PushExpressionAttribute attribute; if (ExpressionTable.TypeToAttributeTable.TryGetValue(instructionType, out attribute)) { for (var blockIdx = 0u; blockIdx < attribute.ExecIn && currentIndex < entries.Count; blockIdx++) { if (close != 0) { close--; instructions.Add(PushProgram.Empty); } else { currentIndex++; var subProgram = FromPlush(ref currentIndex, ref close, depth + 1); var subExpression = subProgram.Count == 1 ? subProgram.Expressions[0] : subProgram; instructions.Add(subExpression); } } } instructions.Add(entry.Instruction); if (close > 0 && depth > 0) { close--; break; } if (depth == 0) { close = 0; } } 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]; } } } }