namespace HeuristicLab.Problems.ProgramSynthesis.Push.Expressions { using HeuristicLab.Problems.ProgramSynthesis.Push.Attributes; using HeuristicLab.Problems.ProgramSynthesis.Push.Interpreter; using HeuristicLab.Problems.ProgramSynthesis.Push.Stack; public abstract class DoCountExpression : LoopExpression { protected DoCountExpression() { } protected DoCountExpression(LoopState state) : base(state) { } protected override bool HasInsufficientArguments(IPushInterpreter interpreter, IStack sourceStack) { return interpreter.IntegerStack.Count < 1 || sourceStack.Count == 0 || interpreter.IntegerStack.Top <= 0; } protected override LoopState InitState(IPushInterpreter interpreter, IStack sourceStack) { var state = new LoopState( body: sourceStack.Pop(), currentIndex: 1, destinationIndex: interpreter.IntegerStack.Top, incrementor: 1); interpreter.IntegerStack.SetTop(0); return state; } } /// /// An iteration instruction that performs a loop (the body of which is taken from the CODE stack) the number of times /// indicated by /// the INTEGER argument, pushing an index (which runs from zero to one less than the number of iterations) onto the /// INTEGER stack /// prior to each execution of the loop body. This should be implemented as a macro that expands into a call to /// CODE.DO*RANGE. /// CODE.DO*COUNT takes a single INTEGER argument (the number of times that the loop will be executed) and a single /// CODE argument /// (the body of the loop). If the provided INTEGER argument is negative or zero then this becomes a NOOP. Otherwise it /// expands into: /// ( 0 '1 - IntegerArg>' CODE.QUOTE 'CodeArg' CODE.DO*RANGE ) /// [PushExpression(StackType.Code, "CODE.DO*COUNT")] public class CodeDoCountExpression : DoCountExpression { public CodeDoCountExpression() { } public CodeDoCountExpression(LoopState state) : base(state) { } public override bool Eval(IPushInterpreter interpreter) { return this.Eval(interpreter, interpreter.CodeStack); } protected override LoopExpression Clone(LoopState state) { return new CodeDoCountExpression(state); } } /// /// An iteration instruction that performs a loop (the body of which is taken from the EXEC stack) the number of times /// indicated /// by the INTEGER argument, pushing an index (which runs from zero to one less than the number of iterations) onto the /// INTEGER /// stack prior to each execution of the loop body. This is similar to CODE.DO*COUNT except that it takes its code /// argument from /// the EXEC stack. This should be implemented as a macro that expands into a call to EXEC.DO*RANGE. EXEC.DO*COUNT /// takes a single /// INTEGER argument (the number of times that the loop will be executed) and a single EXEC argument (the body of the /// loop). If /// the provided INTEGER argument is negative or zero then this becomes a NOOP. Otherwise it expands into: /// ( 0 '1 - IntegerArg' EXEC.DO* RANGE'ExecArg' ) /// [PushExpression(StackType.Exec, "EXEC.DO*COUNT")] public class ExecDoCountExpression : DoCountExpression { public ExecDoCountExpression() { } public ExecDoCountExpression(LoopState state) : base(state) { } public override bool Eval(IPushInterpreter interpreter) { return this.Eval(interpreter, interpreter.ExecStack); } protected override LoopExpression Clone(LoopState state) { return new ExecDoCountExpression(state); } } }