public void ExecuteDrawingInstruction()
    {
        var repositoryMock = new Mock <IDrawingInstructionRepository>();
        var instruction    = new ClearInstruction();

        instruction.ExecuteDrawingInstruction(repositoryMock.Object);

        repositoryMock.Verify(mock => mock.Clear(), Times.Once);
    }
Esempio n. 2
0
        // Replaces copy and multiplication loops with Mul (clear loop [-] will also be replaced with Clear)
        // [->++>>>+++++>++<+<<<<<] becomes Mul(1,2) Mul(4,5) Mul(5,2) Mul(6,1) Clear(0)
        public List <InstructionBase> OptimizeCopyMultiplyLoop(List <InstructionBase> instructions)
        {
            List <InstructionBase> optimized = new List <InstructionBase>();

            int i = 0;

            while (true)
            {
                int previousI = i;

                // Find next leaf loop (loop without inner loop)
                bool found = false;
                while (i < instructions.Count)
                {
                    if (instructions[i] is OpenInstruction)
                    {
                        found = true;
                        break;
                    }
                    i++;
                }
                if (!found)                                           // no Open found
                {
                    optimized.AddRange(instructions.Skip(previousI)); // copy remaining instructions
                    break;
                }
                int j = i + 1;
                found = false;
                while (j < instructions.Count)
                {
                    if (instructions[j] is CloseInstruction)
                    {
                        found = true;
                        break;
                    }
                    if (instructions[j] is OpenInstruction)
                    {
                        i = j;
                    }
                    j++;
                }
                if (!found)                                           // no leaf loop found
                {
                    optimized.AddRange(instructions.Skip(previousI)); // copy remaining instructions
                    break;
                }
                // copy instructions before loop
                optimized.AddRange(instructions.Skip(previousI).Take(i - previousI));
                // check it contains only Add, Sub, Left, Right
                List <InstructionBase> loopInstructions = instructions.Skip(i + 1).Take(j - i - 1).ToList();
                bool ok = loopInstructions.All(x => x is ArithmeticInstructionBase || x is PositionInstructionBase);
                if (!ok)
                {
                    optimized.AddRange(instructions.Skip(i).Take(j - i + 1)); // copy loop instructions
                    i = j + 1;
                    continue;                                                 // search another loop
                }
                // interpret loop and track pointer position and what arithmetic operations it carries out
                Dictionary <int, int> mem = new Dictionary <int, int>();
                int p = 0;
                foreach (InstructionBase instruction in loopInstructions) // contains only Add/Sub/Left/Right
                {
                    switch (instruction)
                    {
                    // Add
                    case AddInstruction add:
                        mem[p + add.Offset] = mem.Get(p + add.Offset, 0) + add.X;
                        break;

                    // Sub
                    case SubInstruction sub:
                        mem[p + sub.Offset] = mem.Get(p + sub.Offset, 0) - sub.X;
                        break;

                    // Left
                    case LeftInstruction left:
                        p -= left.X;
                        break;

                    // Right
                    case RightInstruction right:
                        p += right.X;
                        break;
                    }
                }
                // if pointed ended where it started and we subtracted exactly 1 from cell 0, then loop can be replaced with copy/mul instruction
                if (p != 0 || mem.Get(0, 0) != -1)                            // not a copy/mul instruction
                {
                    optimized.AddRange(instructions.Skip(i).Take(j - i + 1)); // copy loop instructions
                    i = j + 1;
                    continue;
                }
                mem.Remove(0);
                Debug.Write($"Replacing loop {string.Join(" ", loopInstructions.Select(x => x.ToIntermediateRepresentation()))} with ");
                // add Mul operations
                foreach (KeyValuePair <int, int> kv in mem)
                {
                    MulInstruction mulInstruction = new MulInstruction
                    {
                        Factor = (short)kv.Value,
                        Offset = kv.Key,
                    };
                    optimized.Add(mulInstruction);
                    Debug.Write($"{mulInstruction.ToIntermediateRepresentation()}, ");
                }
                // add Clear operation
                ClearInstruction clearInstruction = new ClearInstruction();
                optimized.Add(clearInstruction);
                Debug.WriteLine(clearInstruction.ToIntermediateRepresentation());
                //
                i = j + 1;
            }

            return(optimized);
        }
    public void ExecuteDrawingInstructionPassNull()
    {
        var instruction = new ClearInstruction();

        Assert.Throws <ArgumentNullException>(() => instruction.ExecuteDrawingInstruction(null));
    }