public void ExecuteDrawingInstruction() { var repositoryMock = new Mock <IDrawingInstructionRepository>(); var instruction = new ClearInstruction(); instruction.ExecuteDrawingInstruction(repositoryMock.Object); repositoryMock.Verify(mock => mock.Clear(), Times.Once); }
// 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)); }