/// <summary> /// Constructs a Loop given a set of instructions and /// an offset of the position of where the loop starts /// </summary> /// <param name="instructions"></param> /// <param name="offset">The index of the StartLoop instruction</param> /// <returns></returns> public static Loop Construct(LanguageInstruction[] instructions, int offset) { var loopInstructions = GetLoopInstructions(instructions, offset); var nestedLoops = GetNestedLoops(loopInstructions); return new Loop(offset, loopInstructions, nestedLoops); }
/// <summary> /// Returns null if the number of StartLoop operations match the number of EndLoop operations /// /// Otherwise, it returns the operation with the excess total. /// </summary> private LanguageInstruction? AreLoopOperationsBalanced(LanguageInstruction[] instructions) { int totalStartLoopOperations = instructions.Where(instruction => instruction == LanguageInstruction.StartLoop).Count(), totalEndLoopOperations = instructions.Where(instruction => instruction == LanguageInstruction.EndLoop).Count(); if (totalStartLoopOperations == totalEndLoopOperations) { return null; } if (totalStartLoopOperations > totalEndLoopOperations) { return LanguageInstruction.StartLoop; } return LanguageInstruction.EndLoop; }
/// <summary> /// Given a set of instructions, this method returns a collection of /// nested loops contained in the set. /// </summary> /// <returns></returns> private static List<Loop> GetNestedLoops(LanguageInstruction[] instructions) { var nestedLoops = new List<Loop>(); var loopInstructions = instructions; var containsNestedLoops = loopInstructions.Any(li => li == LanguageInstruction.StartLoop); if (!containsNestedLoops) { return nestedLoops; } for (int i = 0; i < instructions.Length; i++) { var ins = instructions[i]; if (!(ins == LanguageInstruction.StartLoop || ins == LanguageInstruction.EndLoop)) { continue; } if (ins == LanguageInstruction.StartLoop) { var lInstructions = GetLoopInstructions(instructions, i); var loop = new Loop(i, lInstructions, GetNestedLoops(lInstructions)); nestedLoops.Add(loop); i = GetNextClosingLoopIndex(instructions, i).Value; } } return nestedLoops; }
private static int? GetNextClosingLoopIndex(LanguageInstruction[] instructions, int index) { int stack = 0; for (int i = index + 1; i < instructions.Length; i++) { if (instructions[i] == LanguageInstruction.StartLoop) { stack += 1; } if (instructions[i] == LanguageInstruction.EndLoop) { if (stack > 0) { stack--; continue; } return i; } } return null; }
/// <summary> /// Given a set of instructions and an offset of where the loop starts, /// this method returns the operations that the loop contains /// </summary> /// <param name="instructions"></param> /// <param name="offset">The index of the StartLoop instruction</param> /// <returns></returns> private static LanguageInstruction[] GetLoopInstructions(LanguageInstruction[] instructions, int offset) { var closingEndLoopIndex = GetNextClosingLoopIndex(instructions, offset).Value; return instructions.Skip(offset + 1).Take(closingEndLoopIndex - offset - 1).ToArray(); }