namespace HeuristicLab.Problems.ProgramSynthesis.Push.Expressions { using HeuristicLab.Problems.ProgramSynthesis.Push.Interpreter; using HeuristicLab.Problems.ProgramSynthesis.Push.Stack; public class LoopState { public LoopState() { } public LoopState(Expression body, long currentIndex, long destinationIndex, long incrementor) { this.Body = body; this.CurrentIndex = currentIndex; this.DestinationIndex = destinationIndex; this.Incrementor = incrementor; } public readonly Expression Body; public readonly long CurrentIndex; public readonly long DestinationIndex; public readonly long Incrementor; public override int GetHashCode() { var hash = 19; if (this.Body != null) hash = hash * 31 + this.Body.GetHashCode(); hash = hash * 31 + this.CurrentIndex.GetHashCode(); hash = hash * 31 + this.DestinationIndex.GetHashCode(); hash = hash * 31 + this.Incrementor.GetHashCode(); return hash; } } public abstract class LoopExpression : StatefullExpression { protected LoopExpression() : base(new LoopState()) { } protected LoopExpression(LoopState state) : base(state) { } protected void Eval(IPushGpInterpreter interpreter, IStack sourceStack, bool pushCurrentIndex = false) { // if not initialized if (this.State.Body == null) { if (this.HasInsufficientArguments(interpreter, sourceStack)) return; var state = this.InitState(interpreter, sourceStack); var initLoopExpression = Clone(state); interpreter.ExecStack.Push(initLoopExpression, state.Body); return; } // if loop end reached if (this.State.DestinationIndex == this.State.CurrentIndex) { this.PushLastIteration(interpreter); return; } this.PushIteration(interpreter); } protected abstract LoopExpression Clone(LoopState state); protected virtual void PushIteration(IPushGpInterpreter interpreter) { interpreter.IntegerStack.Push(this.State.CurrentIndex); var newState = new LoopState(State.Body, State.CurrentIndex + this.State.Incrementor, State.DestinationIndex, State.Incrementor); var nextLoopExpression = Clone(newState); interpreter.ExecStack.Push(nextLoopExpression, this.State.Body); } protected virtual void PushLastIteration(IPushGpInterpreter interpreter) { interpreter.IntegerStack.Push(this.State.CurrentIndex); interpreter.ExecStack.Push(this.State.Body); } //public override bool Equals(object obj) { // if (this == obj) // return true; // if (obj == null || obj.GetType() != this.GetType()) // return false; // var other = obj as LoopExpression; // if (this.State.CurrentIndex != other.State.CurrentIndex || // this.State.DestinationIndex != other.State.DestinationIndex || // this.State.Incrementor != other.State.Incrementor) // return false; // var isBodyEqual = this.State.Body == other.State.Body || // (this.State.Body != null && // other.State.Body != null && // this.State.Body.Equals(other.State.Body)); // return isBodyEqual; //} protected abstract bool HasInsufficientArguments(IPushGpInterpreter interpreter, IStack sourceStack); protected abstract LoopState InitState(IPushGpInterpreter interpreter, IStack sourceStack); } }