public IList <long> Run() { if (_memory == null) { throw new Exception($"You must load a program first using {nameof(Computer)}.{nameof(Load)}"); } Running = true; while (Running && _instructionPointer < _memory.Count) { var instruction = new Instruction(_memory[(int)_instructionPointer]); var parameterValues = GetParameterValues(instruction); long index; var jmp = false; switch (instruction.Op) { case OpCode.Add: index = GetIndex(parameterValues[2]); ExtendMemoryIfRequired(index); _memory[(int)index] = GetValue(parameterValues[0]) + GetValue(parameterValues[1]); break; case OpCode.Multiply: index = GetIndex(parameterValues[2]); ExtendMemoryIfRequired(index); _memory[(int)index] = GetValue(parameterValues[0]) * GetValue(parameterValues[1]); break; case OpCode.Save: index = GetIndex(parameterValues[0]); ExtendMemoryIfRequired(index); var input = InputModule.InputCallback(); _memory[(int)index] = input; break; case OpCode.Output: var outputValue = GetValue(parameterValues[0]); OutputModule.OutputCallback(outputValue); break; case OpCode.JmpT: jmp = GetValue(parameterValues[0]) > 0; if (jmp) { _instructionPointer = GetValue(parameterValues[1]); } break; case OpCode.JmpF: jmp = GetValue(parameterValues[0]) == 0; if (jmp) { _instructionPointer = GetValue(parameterValues[1]); } break; case OpCode.LessThan: var lt = GetValue(parameterValues[0]) < GetValue(parameterValues[1]); index = GetIndex(parameterValues[2]); ExtendMemoryIfRequired(index); _memory[(int)index] = lt ? 1 : 0;; break; case OpCode.Eql: var eql = GetValue(parameterValues[0]) == GetValue(parameterValues[1]); index = GetIndex(parameterValues[2]); ExtendMemoryIfRequired(index); var toStore = eql ? 1 : 0; _memory[(int)index] = toStore; break; case OpCode.Halt: Halted = true; return(_memory); case OpCode.SetRbo: _rbo += GetValue(parameterValues[0]); break; default: throw new ArgumentOutOfRangeException(); } if (!jmp) { _instructionPointer += instruction.ParameterModes.Count + 1; } } return(_memory); }