public static IEnumerable <CodeInstruction> AddRegionBefore(this IEnumerable <CodeInstruction> code, Func <CodeInstruction, bool>[] before, Func <CodeInstruction[], IEnumerable <CodeInstruction> > region) { if (code is null) { throw new ArgumentNullException(nameof(code)); } if (before is null) { throw new ArgumentNullException(nameof(before)); } if (region is null) { throw new ArgumentNullException(nameof(region)); } if (before.Length is 0) { throw new ArgumentException($"{nameof(before)} cannot be empty.", nameof(before)); } if (Array.Exists(before, b => b is null)) { throw new ArgumentException($"Delegates in {nameof(before)} cannot be null.", nameof(before)); } return(AddRegionBefore2()); IEnumerable <CodeInstruction> AddRegionBefore2() { SearchState state = SearchState.Searching; int current = 0; CodeInstruction[] matches = new CodeInstruction[before.Length]; foreach (CodeInstruction instr in code) { if (state == SearchState.Passed) { yield return(instr); } else if (state == SearchState.Searching) { if (before[current](instr)) { matches[current] = instr; if (++current == before.Length) { state = SearchState.Passed; CodeInstruction[] arr = new CodeInstruction[matches.Length]; matches.CopyTo(arr, 0); IEnumerable <CodeInstruction> added = region(arr); if (added is null) { throw new ArgumentException($"{nameof(region)} cannot return null."); } foreach (CodeInstruction instr2 in added) { if (instr2 is null) { throw new ArgumentException($"Collection returned by {nameof(region)} cannot contain null.", nameof(region)); } yield return(new CodeInstruction(instr2)); } for (int i = 0; i < current; i++) { yield return(matches[i]); } } } else { if (current > 0) { for (int i = 0; i < current; i++) { yield return(matches[i]); } current = 0; } yield return(instr); } } } } }
public static IEnumerable <CodeInstruction> AddRegionAfter(this IEnumerable <CodeInstruction> code, Func <CodeInstruction, bool>[] after, Func <CodeInstruction[], IEnumerable <CodeInstruction> > region) { if (code is null) { throw new ArgumentNullException(nameof(code)); } if (after is null) { throw new ArgumentNullException(nameof(after)); } if (region is null) { throw new ArgumentNullException(nameof(region)); } if (after.Length is 0) { throw new ArgumentException($"{nameof(after)} cannot be empty.", nameof(after)); } if (Array.Exists(after, a => a is null)) { throw new ArgumentException($"Delegates in {nameof(after)} cannot be null.", nameof(after)); } return(AddRegionAfter2()); IEnumerable <CodeInstruction> AddRegionAfter2() { SearchState state = SearchState.Searching; int current = 0; CodeInstruction[] matches = new CodeInstruction[after.Length]; foreach (CodeInstruction instr in code) { if (state == SearchState.Passed) { yield return(instr); } else if (state == SearchState.Searching) { yield return(instr); if (after[current](instr)) { matches[current] = instr; if (++current == after.Length) { state = SearchState.Passed; CodeInstruction[] arr = new CodeInstruction[matches.Length]; matches.CopyTo(arr, 0); IEnumerable <CodeInstruction> added = region(arr); if (added is null) { throw new ArgumentException($"{nameof(region)} cannot return null."); } foreach (CodeInstruction instr2 in added) { if (instr2 is null) { throw new ArgumentException($"Collection returned by {nameof(region)} cannot contain null.", nameof(region)); } yield return(new CodeInstruction(instr2)); } } } else { current = 0; } } } if (state == SearchState.Searching) { throw new InvalidOperationException("Could not match the after region."); } } }