Changeset 15017 for branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/DoRangeExpressions.cs
- Timestamp:
- 06/01/17 09:28:34 (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/PushGP/HeuristicLab.PushGP/HeuristicLab.Problems.ProgramSynthesis/Push/Expressions/DoRangeExpressions.cs
r14952 r15017 1 1 namespace HeuristicLab.Problems.ProgramSynthesis.Push.Expressions { 2 2 using System; 3 4 3 using Attributes; 5 6 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;7 8 4 using Interpreter; 5 using Persistence.Default.CompositeSerializers.Storable; 9 6 using Stack; 10 7 11 [Serializable]12 [StorableClass]13 public abstract class DoRangeExpression : LoopExpression {14 protected DoRangeExpression() { }15 protected DoRangeExpression(LoopState state) : base(state) { }16 [StorableConstructor]17 protected DoRangeExpression(bool deserializing) : base(deserializing) { }18 19 protected override bool HasInsufficientArguments(IInternalPushInterpreter interpreter, IPushStack<Expression> sourceStack) {20 return interpreter.IntegerStack.Count < 2 ||21 sourceStack.Count == 0 ||22 interpreter.IntegerStack.Top == interpreter.IntegerStack[1];23 }24 25 protected override LoopState InitState(IInternalPushInterpreter interpreter, IPushStack<Expression> sourceStack) {26 var destinationIndex = interpreter.IntegerStack.Pop();27 var incrementor = destinationIndex < interpreter.IntegerStack.Top ? -1 : 1;28 29 return LoopState.Create(interpreter.PoolContainer.LoopStatePool,30 body: sourceStack.Pop(),31 currentIndex: interpreter.IntegerStack.Top + incrementor,32 destinationIndex: destinationIndex,33 incrementor: incrementor);34 }35 }36 37 8 /// <summary> 38 /// An iteration instruction that executes the top item on the CODE stack a number of times that depends on the 39 /// top two integers, while also pushing the loop counter onto the INTEGER stack for possible access during the 40 /// execution of 41 /// the body of the loop. The top integer is the "destination index" and the second integer is the "current index." 42 /// Last the code 43 /// and the integer arguments are saved locally and popped. Then the integers are compared. If the integers are equal 44 /// then the current 45 /// index is pushed onto the INTEGER stack and the code (which is the "body" of the loop) is pushed onto the EXEC stack 46 /// for subsequent 47 /// execution. If the integers are not equal then the current index will still be pushed onto the INTEGER stack but two 48 /// items will be 49 /// pushed onto the EXEC stack -- first a recursive call to CODE.DO*RANGE (with the same code and destination index, 50 /// but with a current 51 /// index that has been either incremented or decremented by 1 to be closer to the destination index) and then the body 52 /// code. Note that 53 /// the range is inclusive of both endpoints; a call with integer arguments 3 and 5 will cause its body to be executed 54 /// 3 times, with the 55 /// loop counter having the values 3, 4, and 5. Note also that one can specify a loop that "counts down" by providing a 56 /// destination index 57 /// that is less than the specified current index. 9 /// An iteration instruction that executes the top item on the CODE stack a number of times that depends on the 10 /// top two integers, while also pushing the loop counter onto the INTEGER stack for possible access during the 11 /// execution of the body of the loop. The top integer is the "destination index" and the second integer is the "current index." 12 /// Last the code and the integer arguments are saved locally and popped. Then the integers are compared. If the integers are equal 13 /// 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 14 /// for subsequent execution. If the integers are not equal then the current index will still be pushed onto the INTEGER stack but two 15 /// items will be pushed onto the EXEC stack -- first a recursive call to CODE.DO*RANGE (with the same code and destination index, 16 /// 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 17 /// 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 18 /// 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 19 /// destination index that is less than the specified current index. 58 20 /// </summary> 59 21 [Serializable] 60 22 [StorableClass] 61 23 [PushExpression(StackTypes.Code, "CODE.DO*RANGE", StackTypes.Integer)] 62 public class CodeDoRangeExpression : DoRangeExpression {24 public class CodeDoRangeExpression : StatelessExpression { 63 25 public CodeDoRangeExpression() { } 64 public CodeDoRangeExpression(LoopState state) : base(state) { }65 26 [StorableConstructor] 66 27 protected CodeDoRangeExpression(bool deserializing) : base(deserializing) { } 67 28 68 29 public override bool IsNoop(IInternalPushInterpreter interpreter) { 69 return State.Body == null && HasInsufficientArguments(interpreter, interpreter.CodeStack);30 return interpreter.IntegerStack.Count < 2 || interpreter.CodeStack.IsEmpty; 70 31 } 71 32 72 33 public override void Eval(IInternalPushInterpreter interpreter) { 73 Eval(interpreter, interpreter.CodeStack); 74 } 34 var toDo = interpreter.CodeStack.Pop(); 35 var currentIndex = interpreter.IntegerStack[1]; 36 var destinationIndex = interpreter.IntegerStack[0]; 75 37 76 protected override LoopExpression Clone(LoopState state, IInternalPushInterpreter interpreter) { 77 var expression = interpreter.PoolContainer.GetStatefulExpression<CodeDoRangeExpression>(); 78 expression.State = state; 38 interpreter.IntegerStack.Pop(); 79 39 80 return expression; 40 if (currentIndex != destinationIndex) { 41 42 var incrementor = currentIndex < destinationIndex ? 1 : -1; 43 var continuation = interpreter.PoolContainer.ExpressionListPool.Get(); 44 var pool = interpreter.PoolContainer.GetStatefulExpressionPool<IntegerPushExpression>(); 45 46 continuation.Add(this); 47 continuation.Add(toDo); 48 continuation.Add(ExpressionTable.GetStatelessExpression<CodeQuoteExpression>()); 49 continuation.Add(IntegerPushExpression.Create(pool, destinationIndex)); 50 continuation.Add(IntegerPushExpression.Create(pool, currentIndex + incrementor)); 51 52 var program = PushProgram.Create(interpreter.PoolContainer.PushProgramPool, continuation); 53 interpreter.ExecStack.Push(program); 54 } 55 56 interpreter.ExecStack.Push(toDo); 81 57 } 82 58 } … … 84 60 /// <summary> 85 61 /// An iteration instruction that executes the top item on the EXEC stack a number of times that depends on the top two 86 /// integers, 87 /// while also pushing the loop counter onto the INTEGER stack for possible access during the execution of the body of 88 /// the loop. 89 /// This is similar to CODE.DO*COUNT except that it takes its code argument from the EXEC stack. The top integer is the 62 /// integers, while also pushing the loop counter onto the INTEGER stack for possible access during the execution of the body of 63 /// 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 90 64 /// "destination index" and the second integer is the "current index." Last the code and the integer arguments are 91 /// saved locally 92 /// and popped. Then the integers are compared. If the integers are equal then the current index is pushed onto the 93 /// INTEGER stack 94 /// and the code (which is the "body" of the loop) is pushed onto the EXEC stack for subsequent execution. If the 95 /// integers are not 96 /// equal then the current index will still be pushed onto the INTEGER stack but two items will be pushed onto the EXEC 97 /// stack 98 /// -- first a recursive call to EXEC.DO*RANGE (with the same code and destination index, but with a current index that 99 /// has been 100 /// either incremented or decremented by 1 to be closer to the destination index) and then the body code. Note that the 101 /// range is 102 /// inclusive of both endpoints; a call with integer arguments 3 and 5 will cause its body to be executed 3 times, with 103 /// the loop 104 /// counter having the values 3, 4, and 5. Note also that one can specify a loop that "counts down" by providing a 105 /// destination 106 /// index that is less than the specified current index. 65 /// saved locally and popped. Then the integers are compared. If the integers are equal then the current index is pushed onto the 66 /// INTEGER stack and the code (which is the "body" of the loop) is pushed onto the EXEC stack for subsequent execution. If the 67 /// 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 68 /// stack -- first a recursive call to EXEC.DO*RANGE (with the same code and destination index, but with a current index that 69 /// has been either incremented or decremented by 1 to be closer to the destination index) and then the body code. Note that the 70 /// range is inclusive of both endpoints; a call with integer arguments 3 and 5 will cause its body to be executed 3 times, with 71 /// the loop counter having the values 3, 4, and 5. Note also that one can specify a loop that "counts down" by providing a 72 /// destination index that is less than the specified current index. 107 73 /// </summary> 108 74 [Serializable] 109 75 [StorableClass] 110 [PushExpression(StackTypes.Exec, "EXEC.DO*RANGE", StackTypes.Integer )]111 public class ExecDoRangeExpression : DoRangeExpression {76 [PushExpression(StackTypes.Exec, "EXEC.DO*RANGE", StackTypes.Integer, execIn: 1)] 77 public class ExecDoRangeExpression : StatelessExpression { 112 78 public ExecDoRangeExpression() { } 113 79 114 public ExecDoRangeExpression(LoopState state) : base(state) { }115 80 [StorableConstructor] 116 81 protected ExecDoRangeExpression(bool deserializing) : base(deserializing) { } 117 82 118 83 public override bool IsNoop(IInternalPushInterpreter interpreter) { 119 return State.Body == null && HasInsufficientArguments(interpreter, interpreter.ExecStack);84 return interpreter.IntegerStack.Count < 2 || interpreter.ExecStack.IsEmpty; 120 85 } 121 86 122 87 public override void Eval(IInternalPushInterpreter interpreter) { 123 Eval(interpreter, interpreter.ExecStack); 124 } 125 protected override LoopExpression Clone(LoopState state, IInternalPushInterpreter interpreter) { 126 var expression = interpreter.PoolContainer.GetStatefulExpression<ExecDoRangeExpression>(); 127 expression.State = state; 88 var currentIndex = interpreter.IntegerStack[1]; 89 var destinationIndex = interpreter.IntegerStack[0]; 128 90 129 return expression; 91 interpreter.IntegerStack.Pop(); 92 93 if (currentIndex == destinationIndex) 94 return; 95 96 var toDo = interpreter.ExecStack.Top; 97 var incrementor = currentIndex < destinationIndex ? 1 : -1; 98 var continuation = interpreter.PoolContainer.ExpressionListPool.Get(); 99 var pool = interpreter.PoolContainer.GetStatefulExpressionPool<IntegerPushExpression>(); 100 101 continuation.Add(toDo); 102 continuation.Add(this); 103 continuation.Add(IntegerPushExpression.Create(pool, destinationIndex)); 104 continuation.Add(IntegerPushExpression.Create(pool, currentIndex + incrementor)); 105 106 interpreter.ExecStack.Top = PushProgram.Create(interpreter.PoolContainer.PushProgramPool, continuation); 107 interpreter.ExecStack.Push(toDo); 130 108 } 131 109 }
Note: See TracChangeset
for help on using the changeset viewer.