namespace HeuristicLab.Problems.ProgramSynthesis.Push.Expressions { using System; using Attributes; using Interpreter; using Stack; [Serializable] public abstract class DoRangeExpression : LoopExpression { protected DoRangeExpression() { } protected DoRangeExpression(LoopState state) : base(state) { } protected override bool HasInsufficientArguments(IPushInterpreter interpreter, IStack sourceStack) { return interpreter.IntegerStack.Count < 2 || sourceStack.Count == 0 || interpreter.IntegerStack.Top == interpreter.IntegerStack.ReverseElementAt(1); } protected override LoopState InitState(IPushInterpreter interpreter, IStack sourceStack) { var destinationIndex = interpreter.IntegerStack.Pop(); var incrementor = destinationIndex < interpreter.IntegerStack.Top ? -1 : 1; return LoopState.Create(interpreter.PoolContainer.LoopStatePool, body: sourceStack.Pop(), currentIndex: interpreter.IntegerStack.Top + incrementor, destinationIndex: destinationIndex, incrementor: incrementor); } } /// /// An iteration instruction that executes the top item on the CODE stack a number of times that depends on the /// top two integers, while also pushing the loop counter onto the INTEGER stack for possible access during the /// execution of /// the body of the loop. The top integer is the "destination index" and the second integer is the "current index." /// First the code /// and the integer arguments are saved locally and popped. Then the integers are compared. If the integers are equal /// then the current /// index is pushed onto the INTEGER stack and the code (which is the "body" of the loop) is pushed onto the EXEC stack /// for subsequent /// execution. If the integers are not equal then the current index will still be pushed onto the INTEGER stack but two /// items will be /// pushed onto the EXEC stack -- first a recursive call to CODE.DO*RANGE (with the same code and destination index, /// but with a current /// index that has been either incremented or decremented by 1 to be closer to the destination index) and then the body /// code. Note that /// the range is inclusive of both endpoints; a call with integer arguments 3 and 5 will cause its body to be executed /// 3 times, with the /// loop counter having the values 3, 4, and 5. Note also that one can specify a loop that "counts down" by providing a /// destination index /// that is less than the specified current index. /// [Serializable] [PushExpression(StackTypes.Code, "CODE.DO*RANGE", StackTypes.Integer)] public class CodeDoRangeExpression : DoRangeExpression { public CodeDoRangeExpression() { } public CodeDoRangeExpression(LoopState state) : base(state) { } public override bool Eval(IPushInterpreter interpreter) { return this.Eval(interpreter, interpreter.CodeStack); } protected override LoopExpression Clone(LoopState state, IPushInterpreter interpreter) { var expression = interpreter.PoolContainer.GetStatefulExpression(); expression.State = state; return expression; } } /// /// An iteration instruction that executes the top item on the EXEC stack a number of times that depends on the top two /// integers, /// while also pushing the loop counter onto the INTEGER stack for possible access during the execution of the body of /// the loop. /// This is similar to CODE.DO*COUNT except that it takes its code argument from the EXEC stack. The top integer is the /// "destination index" and the second integer is the "current index." First the code and the integer arguments are /// saved locally /// and popped. Then the integers are compared. If the integers are equal then the current index is pushed onto the /// INTEGER stack /// and the code (which is the "body" of the loop) is pushed onto the EXEC stack for subsequent execution. If the /// integers are not /// equal then the current index will still be pushed onto the INTEGER stack but two items will be pushed onto the EXEC /// stack /// -- first a recursive call to EXEC.DO*RANGE (with the same code and destination index, but with a current index that /// has been /// either incremented or decremented by 1 to be closer to the destination index) and then the body code. Note that the /// range is /// inclusive of both endpoints; a call with integer arguments 3 and 5 will cause its body to be executed 3 times, with /// the loop /// counter having the values 3, 4, and 5. Note also that one can specify a loop that "counts down" by providing a /// destination /// index that is less than the specified current index. /// [Serializable] [PushExpression(StackTypes.Exec, "EXEC.DO*RANGE", StackTypes.Integer)] public class ExecDoRangeExpression : DoRangeExpression { public ExecDoRangeExpression() { } public ExecDoRangeExpression(LoopState state) : base(state) { } public override bool Eval(IPushInterpreter interpreter) { return this.Eval(interpreter, interpreter.ExecStack); } protected override LoopExpression Clone(LoopState state, IPushInterpreter interpreter) { var expression = interpreter.PoolContainer.GetStatefulExpression(); expression.State = state; return expression; } } }