public void ProcessorExecutePerformsNoOpOnHaltState()
        {
            ITape mockTape = Substitute.For<ITape>();
            mockTape.Read().Returns(' ');
            IInstructionTable mockTable = Substitute.For<IInstructionTable>();
            Processor processor = new Processor(mockTape, mockTable);

            Instruction testInstruction = new Instruction();
            testInstruction.State = "START";
            testInstruction.NextStates[' '] = "HALT";
            testInstruction.WriteSymbols[' '] = ' ';
            testInstruction.MoveDirections[' '] = MoveDirection.None;

            mockTable.GetInstruction(Arg.Any<String>()).Returns(testInstruction);

            processor.Execute();

            mockTape.ClearReceivedCalls();
            mockTable.ClearReceivedCalls();

            processor.Execute();

            mockTable.Received(0).GetInstruction(Arg.Any<String>());
            mockTape.Received(0).Read();
            mockTape.Received(0).Write(Arg.Any<char>());
            mockTape.Received(0).MoveLeft();
            mockTape.Received(0).MoveRight();
        }
        public static Instruction Parse(String instruction)
        {
            if(string.IsNullOrEmpty(instruction))
            {
                throw new ArgumentNullException("Instruction string must not be null");
            }

            string [] elements = instruction.Split(',');

            if(elements.Length != 5)
            {
                throw new ArgumentException("Incorrect number of parameters specified for instruction");
            }

            Instruction parsedInstruction = new Instruction();
            parsedInstruction.State = elements[0];

            char readSymbol = ParseSymbol(elements[1]);

            parsedInstruction.WriteSymbols[readSymbol] = ParseSymbol(elements[2]);
            parsedInstruction.MoveDirections[readSymbol] = (MoveDirection) Enum.Parse(typeof(MoveDirection), elements[3]);
            parsedInstruction.NextStates[readSymbol] = elements[4];

            return parsedInstruction;
        }
        public void ProcessorDoesNotMoveTapeOnNoMoveInstruction()
        {
            ITape mockTape = Substitute.For<ITape>();
            IInstructionTable mockTable = Substitute.For<IInstructionTable>();
            Processor processor = new Processor(mockTape, mockTable);

            char symbol = 'a';

            Instruction noMoveInstruction = new Instruction();
            noMoveInstruction.State = "START";
            noMoveInstruction.WriteSymbols[symbol] = symbol;
            noMoveInstruction.MoveDirections[symbol] = MoveDirection.None;
            noMoveInstruction.NextStates[symbol] = "HALT";

            mockTape.Read().Returns(symbol);
            mockTable.GetInstruction(Arg.Any<String>()).Returns(noMoveInstruction);

            processor.Execute();

            mockTable.Received(1).GetInstruction("START");
            mockTape.Received(1).Read();
            mockTape.Received(1).Write(symbol);
            mockTape.Received(0).MoveRight();
            mockTape.Received(0).MoveLeft();
        }
        public void AddInstruction(Instruction instruction)
        {
            if(null == instruction)
            {
                throw new ArgumentNullException("Instruction must not be null");
            }

            if(mInstruction.ContainsKey(instruction.State))
            {
                foreach(char readSymbol in instruction.WriteSymbols.Keys)
                {
                    mInstruction[instruction.State].WriteSymbols[readSymbol] = instruction.WriteSymbols[readSymbol];
                }

                foreach (char readSymbol in instruction.MoveDirections.Keys)
                {
                    mInstruction[instruction.State].MoveDirections[readSymbol] = instruction.MoveDirections[readSymbol];
                }

                foreach (char readSymbol in instruction.NextStates.Keys)
                {
                    mInstruction[instruction.State].NextStates[readSymbol] = instruction.NextStates[readSymbol];
                }
            }
            else
            {
                mInstruction.Add(instruction.State, instruction);
            }
        }
 public void InstructionIsConstructedWithDefaultValues()
 {
     Instruction instruction = new Instruction();
     Assert.AreEqual(null, instruction.State);
     Assert.AreEqual(0, instruction.NextStates.Keys.Count);
     Assert.AreEqual(0, instruction.MoveDirections.Keys.Count);
     Assert.AreEqual(0, instruction.WriteSymbols.Keys.Count);
 }
        public void InstructionTableStoresAddedInstructions()
        {
            InstructionTable table = new InstructionTable();

            Instruction instructionA = new Instruction();
            instructionA.State = "A";

            table.AddInstruction(instructionA);

            Assert.AreEqual(instructionA, table.GetInstruction(instructionA.State));
        }
        public void ProcessorExecuteReturnsFalseOnHaltState()
        {
            ITape mockTape = Substitute.For<ITape>();
            mockTape.Read().Returns(' ');
            IInstructionTable mockTable = Substitute.For<IInstructionTable>();
            Processor processor = new Processor(mockTape, mockTable);

            Instruction testInstruction = new Instruction();
            testInstruction.State = "START";
            testInstruction.NextStates[' '] = "HALT";
            testInstruction.WriteSymbols[' '] = ' ';
            testInstruction.MoveDirections[' '] = MoveDirection.None;

            mockTable.GetInstruction(Arg.Any<String>()).Returns(testInstruction);

            Assert.IsTrue(processor.Execute());
            Assert.IsFalse(processor.Execute());
        }
        public void InstructionTableAddsToWriteSymbolsIf2InstructionsHaveTheSameState()
        {
            InstructionTable table = new InstructionTable();

            Instruction instructionA1 = new Instruction();
            instructionA1.State = "A";
            instructionA1.WriteSymbols['0'] = '1';

            Instruction instructionA2 = new Instruction();
            instructionA2.State = "A";
            instructionA2.WriteSymbols['1'] = '0';

            table.AddInstruction(instructionA1);
            table.AddInstruction(instructionA2);

            Instruction storedInstruction = table.GetInstruction("A");
            Assert.AreEqual(2, storedInstruction.WriteSymbols.Keys.Count);
            Assert.AreEqual('1', storedInstruction.WriteSymbols['0']);
            Assert.AreEqual('0', storedInstruction.WriteSymbols['1']);
        }
        public void InstructionTableAddsToNextStatesIf2InstructionsHaveTheSameState()
        {
            InstructionTable table = new InstructionTable();

            Instruction instructionA1 = new Instruction();
            instructionA1.State = "A";
            instructionA1.NextStates['0'] = "B";

            Instruction instructionA2 = new Instruction();
            instructionA2.State = "A";
            instructionA2.NextStates['1'] = "C";

            table.AddInstruction(instructionA1);
            table.AddInstruction(instructionA2);

            Instruction storedInstruction = table.GetInstruction("A");
            Assert.AreEqual(2, storedInstruction.NextStates.Keys.Count);
            Assert.AreEqual("B", storedInstruction.NextStates['0']);
            Assert.AreEqual("C", storedInstruction.NextStates['1']);
        }
        public void InstructionTableAddsToMoveDirectionsIf2InstructionsHaveTheSameState()
        {
            InstructionTable table = new InstructionTable();

            Instruction instructionA1 = new Instruction();
            instructionA1.State = "A";
            instructionA1.MoveDirections['0'] = MoveDirection.Left;

            Instruction instructionA2 = new Instruction();
            instructionA2.State = "A";
            instructionA2.MoveDirections['1'] = MoveDirection.Right;

            table.AddInstruction(instructionA1);
            table.AddInstruction(instructionA2);

            Instruction storedInstruction = table.GetInstruction("A");
            Assert.AreEqual(2, storedInstruction.MoveDirections.Keys.Count);
            Assert.AreEqual(MoveDirection.Left, storedInstruction.MoveDirections['0']);
            Assert.AreEqual(MoveDirection.Right, storedInstruction.MoveDirections['1']);
        }
        public void ProcessorExecutesStartStateFollowedByNextState()
        {
            ITape mockTape = Substitute.For<ITape>();
            mockTape.Read().Returns(' ');
            IInstructionTable mockTable = Substitute.For<IInstructionTable>();
            Processor processor = new Processor(mockTape, mockTable);

            Instruction testInstruction = new Instruction();
            testInstruction.State = "START";
            testInstruction.NextStates[' '] = "A";
            testInstruction.WriteSymbols[' '] = ' ';
            testInstruction.MoveDirections[' '] = MoveDirection.None;

            mockTable.GetInstruction(Arg.Any<String>()).Returns(testInstruction);

            processor.Execute();

            mockTable.Received(1).GetInstruction("START");
            mockTape.Received(1).Read();
            mockTape.Received(1).Write(' ');
            mockTape.Received(0).MoveRight();
            mockTape.Received(0).MoveLeft();

            processor.Execute();

            mockTable.Received(1).GetInstruction(testInstruction.NextStates[' ']);
        }