1 | namespace HeuristicLab.Problems.ProgramSynthesis.Push.Expressions {
|
---|
2 |
|
---|
3 | using HeuristicLab.Problems.ProgramSynthesis.Push.Interpreter;
|
---|
4 | using HeuristicLab.Problems.ProgramSynthesis.Push.Stack;
|
---|
5 |
|
---|
6 | public struct LoopState {
|
---|
7 | //public LoopState() { }
|
---|
8 | public LoopState(Expression body, long currentIndex, long destinationIndex, long incrementor) {
|
---|
9 | this.Body = body;
|
---|
10 | this.CurrentIndex = currentIndex;
|
---|
11 | this.DestinationIndex = destinationIndex;
|
---|
12 | this.Incrementor = incrementor;
|
---|
13 | }
|
---|
14 |
|
---|
15 | public readonly Expression Body;
|
---|
16 | public readonly long CurrentIndex;
|
---|
17 | public readonly long DestinationIndex;
|
---|
18 | public readonly long Incrementor;
|
---|
19 |
|
---|
20 | public override int GetHashCode() {
|
---|
21 | var hash = 19;
|
---|
22 |
|
---|
23 | if (this.Body != null)
|
---|
24 | hash = hash * 31 + this.Body.GetHashCode();
|
---|
25 |
|
---|
26 | hash = hash * 31 + this.CurrentIndex.GetHashCode();
|
---|
27 | hash = hash * 31 + this.DestinationIndex.GetHashCode();
|
---|
28 | hash = hash * 31 + this.Incrementor.GetHashCode();
|
---|
29 |
|
---|
30 | return hash;
|
---|
31 | }
|
---|
32 | }
|
---|
33 |
|
---|
34 | public abstract class LoopExpression : StatefulExpression<LoopState> {
|
---|
35 | protected LoopExpression() : base(new LoopState()) { }
|
---|
36 | protected LoopExpression(LoopState state) : base(state) { }
|
---|
37 |
|
---|
38 | protected bool Eval(IPushInterpreter interpreter, IStack<Expression> sourceStack, bool pushCurrentIndex = false) {
|
---|
39 | // if not initialized
|
---|
40 | if (this.State.Body == null) {
|
---|
41 | if (this.HasInsufficientArguments(interpreter, sourceStack)) return false;
|
---|
42 |
|
---|
43 | var state = this.InitState(interpreter, sourceStack);
|
---|
44 | var initLoopExpression = Clone(state);
|
---|
45 |
|
---|
46 | interpreter.ExecStack.Push(initLoopExpression, state.Body);
|
---|
47 | return true;
|
---|
48 | }
|
---|
49 |
|
---|
50 | // if loop end reached
|
---|
51 | if (this.State.DestinationIndex == this.State.CurrentIndex) {
|
---|
52 | this.PushLastIteration(interpreter);
|
---|
53 | return true;
|
---|
54 | }
|
---|
55 |
|
---|
56 | this.PushIteration(interpreter);
|
---|
57 |
|
---|
58 | return true;
|
---|
59 | }
|
---|
60 |
|
---|
61 | protected virtual void PushIteration(IPushInterpreter interpreter) {
|
---|
62 | interpreter.IntegerStack.Push(this.State.CurrentIndex);
|
---|
63 |
|
---|
64 | var newState = new LoopState(State.Body, State.CurrentIndex + this.State.Incrementor, State.DestinationIndex, State.Incrementor);
|
---|
65 | var nextLoopExpression = Clone(newState);
|
---|
66 |
|
---|
67 | interpreter.ExecStack.Push(nextLoopExpression, this.State.Body);
|
---|
68 | }
|
---|
69 |
|
---|
70 | protected virtual void PushLastIteration(IPushInterpreter interpreter) {
|
---|
71 | interpreter.IntegerStack.Push(this.State.CurrentIndex);
|
---|
72 | interpreter.ExecStack.Push(this.State.Body);
|
---|
73 | }
|
---|
74 |
|
---|
75 | protected abstract LoopExpression Clone(LoopState state);
|
---|
76 | protected abstract bool HasInsufficientArguments(IPushInterpreter interpreter, IStack<Expression> sourceStack);
|
---|
77 | protected abstract LoopState InitState(IPushInterpreter interpreter, IStack<Expression> sourceStack);
|
---|
78 | }
|
---|
79 | } |
---|