namespace HeuristicLab.Problems.ProgramSynthesis.Push.Expressions { using System; using HeuristicLab.Problems.ProgramSynthesis.Push.Attributes; using HeuristicLab.Problems.ProgramSynthesis.Push.Interpreter; using HeuristicLab.Problems.ProgramSynthesis.Push.Stack; [Serializable] public abstract class DoTimesExpression : LoopExpression { protected DoTimesExpression() { } protected DoTimesExpression(LoopState state) : base(state) { } protected override bool HasInsufficientArguments(IInternalPushInterpreter interpreter, IPushStack sourceStack) { return (interpreter.IntegerStack.Count < 1) || (sourceStack.Count == 0) || (interpreter.IntegerStack.Top <= 0); } protected override LoopState InitState(IInternalPushInterpreter interpreter, IPushStack sourceStack) { return LoopState.Create(interpreter.PoolContainer.LoopStatePool, body: sourceStack.Pop(), currentIndex: 1, destinationIndex: interpreter.IntegerStack.Pop(), incrementor: 1); } protected override void PushIteration(IInternalPushInterpreter interpreter) { var newState = LoopState.Create(interpreter.PoolContainer.LoopStatePool, State.Body, State.CurrentIndex + this.State.Incrementor, State.DestinationIndex, State.Incrementor); var nextLoopExpression = Clone(newState, interpreter); interpreter.ExecStack.Push(nextLoopExpression, State.Body); } protected override void PushLastIteration(IInternalPushInterpreter interpreter) { interpreter.ExecStack.Push(this.State.Body); } } /// /// Like CODE.DO*COUNT but does not push the loop counter. /// This should be implemented as a macro that expands into CODE.DO*RANGE, similarly to the implementation /// of CODE.DO*COUNT, except that a call to INTEGER.POP should be tacked on to the front of the loop body code /// in the call to CODE.DO*RANGE. /// [Serializable] [PushExpression(StackTypes.Code, "CODE.DO*TIMES", StackTypes.Integer)] public class CodeDoTimesExpression : DoTimesExpression { public CodeDoTimesExpression() { } public CodeDoTimesExpression(LoopState state) : base(state) { } public override bool Eval(IInternalPushInterpreter interpreter) { return this.Eval(interpreter, interpreter.CodeStack); } protected override LoopExpression Clone(LoopState state, IInternalPushInterpreter interpreter) { var expression = interpreter.PoolContainer.GetStatefulExpression(); expression.State = state; return expression; } } /// /// Like EXEC.DO*COUNT but does not push the loop counter. This should be implemented as a macro that expands into /// EXEC.DO*RANGE, /// similarly to the implementation of EXEC.DO*COUNT, except that a call to INTEGER.POP should be tacked on to the /// 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 /// been /// pushed by EXEC.DO*RANGE, prior to the execution of the loop body. /// [Serializable] [PushExpression(StackTypes.Exec, "EXEC.DO*TIMES", StackTypes.Integer)] public class ExecDoTimesExpression : DoTimesExpression { public ExecDoTimesExpression() { } public ExecDoTimesExpression(LoopState state) : base(state) { } public override bool Eval(IInternalPushInterpreter interpreter) { return this.Eval(interpreter, interpreter.ExecStack); } protected override LoopExpression Clone(LoopState state, IInternalPushInterpreter interpreter) { var expression = interpreter.PoolContainer.GetStatefulExpression(); expression.State = state; return expression; } } }