[15771] | 1 | using System;
|
---|
| 2 | using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; |
---|
| 3 | |
---|
| 4 | namespace HeuristicLab.Problems.ProgramSynthesis { |
---|
[14777] | 5 |
|
---|
[14727] | 6 | /// <summary>
|
---|
| 7 | /// Like CODE.DO*COUNT but does not push the loop counter.
|
---|
| 8 | /// This should be implemented as a macro that expands into CODE.DO*RANGE, similarly to the implementation
|
---|
| 9 | /// of CODE.DO*COUNT, except that a call to INTEGER.POP should be tacked on to the front of the loop body code
|
---|
| 10 | /// in the call to CODE.DO*RANGE.
|
---|
| 11 | /// </summary>
|
---|
[14777] | 12 | [Serializable]
|
---|
[14952] | 13 | [StorableClass]
|
---|
[15032] | 14 | [PushExpression(StackTypes.Code, "CODE.DO*TIMES", "Like CODE.DO*COUNT but does not push the loop counter", StackTypes.Integer)]
|
---|
[15017] | 15 | public class CodeDoTimesExpression : StatelessExpression {
|
---|
[14727] | 16 | public CodeDoTimesExpression() { }
|
---|
[14952] | 17 | [StorableConstructor]
|
---|
| 18 | protected CodeDoTimesExpression(bool deserializing) : base(deserializing) { }
|
---|
[14727] | 19 |
|
---|
[14952] | 20 | public override void Eval(IInternalPushInterpreter interpreter) {
|
---|
[15017] | 21 | var destinationIndex = Math.Max(0, interpreter.IntegerStack.Top - 1);
|
---|
| 22 |
|
---|
| 23 | if (destinationIndex == 0) {
|
---|
| 24 | interpreter.IntegerStack.Pop();
|
---|
| 25 | interpreter.ExecStack.Push((PushProgram)interpreter.CodeStack.Pop());
|
---|
| 26 | return;
|
---|
| 27 | }
|
---|
| 28 |
|
---|
| 29 | interpreter.IntegerStack.Top = 0;
|
---|
| 30 | interpreter.IntegerStack.Push(destinationIndex);
|
---|
| 31 |
|
---|
| 32 | var popExpressions = ExpressionTable.GetStatelessExpression<IntegerPopExpression>();
|
---|
| 33 | PushProgram program;
|
---|
| 34 |
|
---|
| 35 | if (!interpreter.CodeStack.Top.IsProgram) {
|
---|
| 36 | var expressions = interpreter.PoolContainer.ExpressionListPool.Get();
|
---|
| 37 | expressions.Add(interpreter.ExecStack.Top);
|
---|
| 38 | expressions.Add(popExpressions);
|
---|
| 39 |
|
---|
| 40 | program = PushProgram.Create(interpreter.PoolContainer.PushProgramPool, expressions);
|
---|
| 41 | } else {
|
---|
| 42 | program = PushProgram.Merge(
|
---|
| 43 | interpreter.PoolContainer.PushProgramPool,
|
---|
| 44 | interpreter.PoolContainer.ExpressionListPool,
|
---|
| 45 | (PushProgram)interpreter.CodeStack.Top,
|
---|
| 46 | popExpressions);
|
---|
| 47 | }
|
---|
| 48 |
|
---|
| 49 | interpreter.CodeStack.Top = program;
|
---|
| 50 | interpreter.ExecStack.Push(ExpressionTable.GetStatelessExpression<CodeDoRangeExpression>());
|
---|
[14727] | 51 | }
|
---|
[15017] | 52 |
|
---|
[14952] | 53 | public override bool IsNoop(IInternalPushInterpreter interpreter) {
|
---|
[15017] | 54 | return interpreter.IntegerStack.IsEmpty ||
|
---|
| 55 | interpreter.IntegerStack.Top < 0 ||
|
---|
| 56 | interpreter.CodeStack.IsEmpty;
|
---|
[14952] | 57 | }
|
---|
[14727] | 58 | }
|
---|
| 59 |
|
---|
| 60 | /// <summary>
|
---|
[15032] | 61 | /// Like EXEC.DO*COUNT but does not push the loop counter. This should be implemented as a macro that expands into
|
---|
| 62 | /// EXEC.DO*RANGE, similarly to the implementation of EXEC.DO*COUNT, except that a call to INTEGER.POP should be tacked on to the
|
---|
| 63 | /// front of the loop body code in the call to EXEC.DO*RANGE. This call to INTEGER.POP will remove the loop counter, which will have
|
---|
| 64 | /// been pushed by EXEC.DO*RANGE, prior to the execution of the loop body.
|
---|
[14727] | 65 | /// </summary>
|
---|
[14777] | 66 | [Serializable]
|
---|
[14952] | 67 | [StorableClass]
|
---|
[15334] | 68 | [PushExpression(StackTypes.Exec, "EXEC.DO*TIMES", "Like EXEC.DO*COUNT but does not push the loop counter", StackTypes.Integer, requiredBlockCount: 1)]
|
---|
[15017] | 69 | public class ExecDoTimesExpression : StatelessExpression {
|
---|
[14727] | 70 | public ExecDoTimesExpression() { }
|
---|
[14952] | 71 | [StorableConstructor]
|
---|
| 72 | protected ExecDoTimesExpression(bool deserializing) : base(deserializing) { }
|
---|
[14727] | 73 |
|
---|
[14952] | 74 | public override void Eval(IInternalPushInterpreter interpreter) {
|
---|
[15017] | 75 | var destinationIndex = Math.Max(0, interpreter.IntegerStack.Top - 1);
|
---|
| 76 |
|
---|
| 77 | if (destinationIndex == 0) {
|
---|
| 78 | interpreter.IntegerStack.Pop();
|
---|
| 79 | return;
|
---|
| 80 | }
|
---|
| 81 |
|
---|
| 82 | interpreter.IntegerStack.Top = 0;
|
---|
| 83 | interpreter.IntegerStack.Push(destinationIndex);
|
---|
| 84 |
|
---|
| 85 | var popExpressions = ExpressionTable.GetStatelessExpression<IntegerPopExpression>();
|
---|
| 86 | PushProgram program;
|
---|
| 87 |
|
---|
| 88 | if (!interpreter.ExecStack.Top.IsProgram) {
|
---|
| 89 | var expressions = interpreter.PoolContainer.ExpressionListPool.Get();
|
---|
| 90 | expressions.Add(interpreter.ExecStack.Top);
|
---|
| 91 | expressions.Add(popExpressions);
|
---|
| 92 |
|
---|
| 93 | program = PushProgram.Create(interpreter.PoolContainer.PushProgramPool, expressions);
|
---|
| 94 | } else {
|
---|
| 95 | program = PushProgram.Merge(
|
---|
| 96 | interpreter.PoolContainer.PushProgramPool,
|
---|
| 97 | interpreter.PoolContainer.ExpressionListPool,
|
---|
| 98 | (PushProgram)interpreter.ExecStack.Top,
|
---|
| 99 | popExpressions);
|
---|
| 100 | }
|
---|
| 101 |
|
---|
| 102 | interpreter.ExecStack.Top = program;
|
---|
| 103 | interpreter.ExecStack.Push(ExpressionTable.GetStatelessExpression<ExecDoRangeExpression>());
|
---|
[14727] | 104 | }
|
---|
| 105 |
|
---|
[14952] | 106 | public override bool IsNoop(IInternalPushInterpreter interpreter) {
|
---|
[15017] | 107 | return interpreter.IntegerStack.IsEmpty ||
|
---|
| 108 | interpreter.IntegerStack.Top < 0 ||
|
---|
| 109 | interpreter.ExecStack.IsEmpty;
|
---|
[14952] | 110 | }
|
---|
[14727] | 111 | }
|
---|
| 112 | } |
---|