namespace HeuristicLab.Problems.ProgramSynthesis.Push.Expressions { using System; using Attributes; using Interpreter; using Persistence.Default.CompositeSerializers.Storable; using Stack; /// /// 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] [StorableClass] [PushExpression(StackTypes.Code, "CODE.DO*TIMES", "Like CODE.DO*COUNT but does not push the loop counter", StackTypes.Integer)] public class CodeDoTimesExpression : StatelessExpression { public CodeDoTimesExpression() { } [StorableConstructor] protected CodeDoTimesExpression(bool deserializing) : base(deserializing) { } public override void Eval(IInternalPushInterpreter interpreter) { var destinationIndex = Math.Max(0, interpreter.IntegerStack.Top - 1); if (destinationIndex == 0) { interpreter.IntegerStack.Pop(); interpreter.ExecStack.Push((PushProgram)interpreter.CodeStack.Pop()); return; } interpreter.IntegerStack.Top = 0; interpreter.IntegerStack.Push(destinationIndex); var popExpressions = ExpressionTable.GetStatelessExpression(); PushProgram program; if (!interpreter.CodeStack.Top.IsProgram) { var expressions = interpreter.PoolContainer.ExpressionListPool.Get(); expressions.Add(interpreter.ExecStack.Top); expressions.Add(popExpressions); program = PushProgram.Create(interpreter.PoolContainer.PushProgramPool, expressions); } else { program = PushProgram.Merge( interpreter.PoolContainer.PushProgramPool, interpreter.PoolContainer.ExpressionListPool, (PushProgram)interpreter.CodeStack.Top, popExpressions); } interpreter.CodeStack.Top = program; interpreter.ExecStack.Push(ExpressionTable.GetStatelessExpression()); } public override bool IsNoop(IInternalPushInterpreter interpreter) { return interpreter.IntegerStack.IsEmpty || interpreter.IntegerStack.Top < 0 || interpreter.CodeStack.IsEmpty; } } /// /// 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] [StorableClass] [PushExpression(StackTypes.Exec, "EXEC.DO*TIMES", "Like EXEC.DO*COUNT but does not push the loop counter", StackTypes.Integer, requiredBlockCount: 1)] public class ExecDoTimesExpression : StatelessExpression { public ExecDoTimesExpression() { } [StorableConstructor] protected ExecDoTimesExpression(bool deserializing) : base(deserializing) { } public override void Eval(IInternalPushInterpreter interpreter) { var destinationIndex = Math.Max(0, interpreter.IntegerStack.Top - 1); if (destinationIndex == 0) { interpreter.IntegerStack.Pop(); return; } interpreter.IntegerStack.Top = 0; interpreter.IntegerStack.Push(destinationIndex); var popExpressions = ExpressionTable.GetStatelessExpression(); PushProgram program; if (!interpreter.ExecStack.Top.IsProgram) { var expressions = interpreter.PoolContainer.ExpressionListPool.Get(); expressions.Add(interpreter.ExecStack.Top); expressions.Add(popExpressions); program = PushProgram.Create(interpreter.PoolContainer.PushProgramPool, expressions); } else { program = PushProgram.Merge( interpreter.PoolContainer.PushProgramPool, interpreter.PoolContainer.ExpressionListPool, (PushProgram)interpreter.ExecStack.Top, popExpressions); } interpreter.ExecStack.Top = program; interpreter.ExecStack.Push(ExpressionTable.GetStatelessExpression()); } public override bool IsNoop(IInternalPushInterpreter interpreter) { return interpreter.IntegerStack.IsEmpty || interpreter.IntegerStack.Top < 0 || interpreter.ExecStack.IsEmpty; } } }