namespace HeuristicLab.Problems.ProgramSynthesis.Push.Expressions { using System; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Problems.ProgramSynthesis.Push.Attributes; using HeuristicLab.Problems.ProgramSynthesis.Push.Stack; using Interpreter; /// /// If the top item of the BOOLEAN stack is TRUE then this removes the second item on the EXEC stack, leaving the first /// item to be executed. If it is false then it removes the first item, leaving the second to be executed. This is similar to /// CODE.IF except that it operates on the EXEC stack. This acts as a NOOP unless there are at least two items on the EXEC stack and /// one item on the BOOLEAN stack. /// [StorableClass] [PushExpression( StackTypes.Exec, "EXEC.IF", "If the top item of the BOOLEAN stack is TRUE then this removes the second item on the EXEC stack, leaving the first item to be executed. If it is false then it removes the first item, leaving the second to be executed.", StackTypes.Boolean, requiredBlockCount: 2)] public class ExecIfExpression : StatelessExpression { public ExecIfExpression() { } [StorableConstructor] protected ExecIfExpression(bool deserializing) : base(deserializing) { } public override bool IsNoop(IInternalPushInterpreter interpreter) { return (interpreter.BooleanStack.Count == 0) || (interpreter.ExecStack.Count < 2); } public override void Eval(IInternalPushInterpreter interpreter) { var condition = interpreter.BooleanStack.Pop(); if (condition) interpreter.ExecStack.RemoveAt(interpreter.ExecStack.Count - 2); else interpreter.ExecStack.RemoveTop(); } } /// /// Inserts beneath the top item of the EXEC stack a new item of the form "( EXEC.Y )". /// [PushExpression( StackTypes.Exec, "EXEC.Y", "Inserts beneath the top item of the EXEC stack a new item of the form \"( EXEC.Y )\"", requiredBlockCount: 1)] [StorableClass] public class ExecYExpression : StatelessExpression { public ExecYExpression() { } [StorableConstructor] protected ExecYExpression(bool deserializing) : base(deserializing) { } public override bool IsNoop(IInternalPushInterpreter interpreter) { return interpreter.ExecStack.Count == 0 || interpreter.Configuration.MaxProgramLength < 2 || (interpreter.ExecStack.Top.IsProgram && ((PushProgram)interpreter.ExecStack.Top).Depth == interpreter.Configuration.MaxDepth); } public override void Eval(IInternalPushInterpreter interpreter) { var top = interpreter.ExecStack.Top; var execYExpression = ExpressionTable.GetStatelessExpression(); var expressions = interpreter.PoolContainer.ExpressionListPool.Get(); expressions.Add(top); expressions.Add(execYExpression); var result = PushProgram.Create(interpreter.PoolContainer.PushProgramPool, expressions); interpreter.ExecStack.Top = result; interpreter.ExecStack.Add(top); } } /// /// Removes the second item on the EXEC stack. /// [PushExpression( StackTypes.Exec, "EXEC.K", "Removes the second item on the EXEC stack.", requiredBlockCount: 2)] [StorableClass] public class ExecKExpression : StatelessExpression { public ExecKExpression() { } [StorableConstructor] protected ExecKExpression(bool deserializing) : base(deserializing) { } public override bool IsNoop(IInternalPushInterpreter interpreter) { return interpreter.ExecStack.Count < 2; } public override void Eval(IInternalPushInterpreter interpreter) { var top = interpreter.ExecStack.Pop(); interpreter.ExecStack.Top = top; } } /// /// Pops 3 items from the EXEC stack, which we will call A, B, and C /// (with A being the first one popped). Then pushes a list containing B and C back onto the EXEC stack, followed by /// another instance of C, followed by another instance of A. /// [PushExpression( StackTypes.Exec, "EXEC.S", "Pops 3 items from the EXEC stack called A, B, and C. Then pushes a list containing B and C back onto the EXEC stack, followed by another instance of C, followed by another instance of A.", requiredBlockCount: 3)] [StorableClass] public class ExecSExpression : StatelessExpression { public ExecSExpression() { } [StorableConstructor] protected ExecSExpression(bool deserializing) : base(deserializing) { } public override bool IsNoop(IInternalPushInterpreter interpreter) { return interpreter.ExecStack.Count < 3 || (interpreter.ExecStack.Top is PushProgram && ((PushProgram)interpreter.ExecStack.Top).Depth == interpreter.Configuration.MaxDepth) || (interpreter.ExecStack[1] is PushProgram && ((PushProgram)interpreter.ExecStack[1]).Depth == interpreter.Configuration.MaxDepth); } public override void Eval(IInternalPushInterpreter interpreter) { var a = interpreter.ExecStack.Top; var b = interpreter.ExecStack[1]; var c = interpreter.ExecStack[2]; interpreter.ExecStack.Remove(2); var expressions = interpreter.PoolContainer.ExpressionListPool.Get(); expressions.Add(c); expressions.Add(b); var newTop = PushProgram.Create(interpreter.PoolContainer.PushProgramPool, expressions); interpreter.ExecStack.Top = newTop; interpreter.ExecStack.Push(c, a); } } /// /// Does nothing. /// /// [StorableClass] [Serializable] [PushExpression( StackTypes.Exec, "EXEC.NOOP", "Does nothing.")] public class ExecNoopExpression : StatelessExpression { public ExecNoopExpression() { } [StorableConstructor] protected ExecNoopExpression(bool deserializing) : base(deserializing) { } public override bool IsNoop(IInternalPushInterpreter interpreter) { return true; } public override void Eval(IInternalPushInterpreter interpreter) { // do nothing } } /// /// Executes top EXEC item recursively as long top BOOLEAN is TRUE. /// [PushExpression( StackTypes.Exec, "EXEC.WHILE", "Executes top EXEC item recursively as long top BOOLEAN is TRUE.", StackTypes.Boolean, requiredBlockCount: 1)] [StorableClass] public class ExecWhileExpression : StatelessExpression { public ExecWhileExpression() { } [StorableConstructor] protected ExecWhileExpression(bool deserializing) : base(deserializing) { } public override bool IsNoop(IInternalPushInterpreter interpreter) { return interpreter.ExecStack.IsEmpty; } public override void Eval(IInternalPushInterpreter interpreter) { if (interpreter.BooleanStack.IsEmpty || !interpreter.BooleanStack.Pop()) { interpreter.ExecStack.Pop(); return; } interpreter.ExecStack.Push(this, interpreter.ExecStack.Top); } } /// /// Executes top EXEC item recursively until max. amount of eval. expressions is reached or top EXEC item removes the the recursive call. /// [PushExpression( StackTypes.Exec, "EXEC.DO*WHILE", "Executes top EXEC item recursively until max. amount of eval. expressions is reached or top EXEC item removes the the recursive call.", requiredBlockCount: 1)] [StorableClass] public class ExecDoWhileExpression : StatelessExpression { public ExecDoWhileExpression() { } [StorableConstructor] protected ExecDoWhileExpression(bool deserializing) : base(deserializing) { } public override bool IsNoop(IInternalPushInterpreter interpreter) { return interpreter.ExecStack.IsEmpty; } public override void Eval(IInternalPushInterpreter interpreter) { interpreter.ExecStack.Push(this, interpreter.ExecStack.Top); } } /// /// Top EXEC item is only executed, if top BOOLEAN is TRUE. /// [PushExpression( StackTypes.Exec, "EXEC.WHEN", "Top EXEC item is only executed, if top BOOLEAN is TRUE.", StackTypes.Boolean, requiredBlockCount: 1)] [StorableClass] public class ExecWhenExpression : StatelessExpression { public ExecWhenExpression() { } [StorableConstructor] protected ExecWhenExpression(bool deserializing) : base(deserializing) { } public override bool IsNoop(IInternalPushInterpreter interpreter) { return interpreter.ExecStack.IsEmpty || interpreter.BooleanStack.IsEmpty; } public override void Eval(IInternalPushInterpreter interpreter) { var when = interpreter.BooleanStack.Pop(); if (!when) { interpreter.ExecStack.Pop(); } } } }