public static OpcodeInstruction FromLine(string line) { OpcodeInstruction op = new OpcodeInstruction(); op.LineOrigin = line; string[] parts = line.Split(' '); op.Argument = Int32.Parse(parts[1]); switch (parts[0]) { case "nop": op.Action = op.NoOperation; op.FlipAction = op.Jump; op.Undo = op.UndoNoOperation; op.UndoFlip = op.UndoJump; break; case "acc": op.Action = op.Accumulate; op.Undo = op.UndoAccumulate; break; case "jmp": op.Action = op.Jump; op.FlipAction = op.NoOperation; op.Undo = op.UndoJump; op.UndoFlip = op.UndoNoOperation; break; } return(op); }
private void ExecuteOrThrow(OpcodeInstruction opcode) { if (opcode.AlreadyExecuted) { throw new OpcodeAlreadyExecutedException(Accumulator, InstructionPointer, Opcodes[InstructionPointer]); } Execute(opcode); }
private void ExecuteOrRewindAndBranch(OpcodeInstruction opcode) { if (opcode.AlreadyExecuted) { Console.WriteLine($"Blocked at IP {InstructionPointer}. Undoing..."); OpcodeInstruction previousOpcode; do { previousOpcode = OpcodeHistory.Pop(); previousOpcode.AlreadyExecuted = false; previousOpcode.Undo(this); Console.WriteLine("Undoing {" + InstructionPointer + "} " + previousOpcode); } while (!previousOpcode.IsJumpOrNop()); while (true) { Console.WriteLine("Flipping {" + InstructionPointer + "} " + previousOpcode); previousOpcode.AlreadyExecuted = true; previousOpcode.FlipAction(this); OpcodeHistory.Push(previousOpcode); try { RunUntilTheEnd(); Console.WriteLine("Run successful, accumulator is " + Accumulator); return; } catch (Exception) { OpcodeInstruction branchOpCode = OpcodeHistory.Pop(); while (branchOpCode != previousOpcode) { branchOpCode.AlreadyExecuted = false; branchOpCode.Undo(this); Console.WriteLine("Undoing {" + InstructionPointer + "} " + branchOpCode); branchOpCode = OpcodeHistory.Pop(); } branchOpCode.AlreadyExecuted = false; Console.WriteLine("Undoing flip {" + InstructionPointer + "} " + branchOpCode); branchOpCode.UndoFlip(this); do { previousOpcode = OpcodeHistory.Pop(); previousOpcode.AlreadyExecuted = false; previousOpcode.Undo(this); Console.WriteLine("Undoing {" + InstructionPointer + "} " + previousOpcode); } while (!previousOpcode.IsJumpOrNop()); } } } else { Console.WriteLine("Doing {" + InstructionPointer + "} " + opcode); Execute(opcode); } }
public OpcodeAlreadyExecutedException(int accumulator, int instructionPointer, OpcodeInstruction opcode) { Accumulator = accumulator; InstructionPointer = instructionPointer; Opcode = opcode; }
private void Execute(OpcodeInstruction opcode) { OpcodeHistory.Push(opcode); opcode.AlreadyExecuted = true; opcode.Action(this); }