/// <summary> /// Search forward in Instructions array for an op that matches <c><paramref name="to_match"/></c> /// <para>Does <b>NOT</b> advance instruction pointer.</para> /// </summary> /// <param name="where">Variable to hold the match position. If not found, will be set to <c>-1</c></param> /// <param name="to_match">WantOp to search for</param> /// <param name="relative_pos">If <c>true</c> (default), outputs the offset compared to CurrentLocation. /// <para>If <c>false</c>, outputs the absolute position within the Instructions array.</para></param> /// <returns><c>this</c> for Fluent chaining</returns> public InstructionsWalker FindNextMatch(out int where, WantOp to_match, bool relative_pos = true, int?assert_where = null) { int?findloc = null; for (int i = CurrentLocation; i < Instructions.Length; i++) { if (to_match.Matches(Instructions[i])) { findloc = i; break; } } if (findloc is null) { where = -1; } else { where = relative_pos ? findloc.Value - CurrentLocation : findloc.Value; } if (!(assert_where is null)) { if (where != assert_where) { throw new AssertionFailure($"{to_match} found at {where} does not match assertion {assert_where}"); } } return(this); }
/// <summary> /// Fetch the instruction currently pointed at, and advance. /// </summary> /// <param name="fetchedOp">A <c>CodeInstruction</c> variable to store the fetched instruction</param> /// <param name="assert_op">Assert that instruction matches a <c>WantOp</c> criteria</param> /// <param name="move_pos">If <c>false</c>, don't advance pointer after fetching</param> /// <returns><c>this</c> for Fluent chaining</returns> public InstructionsWalker GoFetchOp(out CodeInstruction fetchedOp, WantOp assert_op = null, bool move_pos = true) { fetchedOp = CurrentOp(assert_op); if (move_pos) { CurrentLocation++; } return(this); }
/// <summary> /// Sets the pointer to a certain position /// </summary> /// <param name="pos">New position</param> /// <param name="assert_op">If given, then will assert that instruction at location 'pos' matches provided WantOp</param> /// <returns><c>this</c> to allow Fluent chaining.</returns> /// <remarks>Some code (especially within switch..case structure) can get shuffled around by the compiler during optimization. /// <para>This method allows returning to a certain point in the instruction chain, /// e.g., to the start of a switch structure.</para></remarks> public InstructionsWalker GoTo(int pos, WantOp assert_op = null) { if (!(assert_op is null)) { CodeInstruction op = Instructions[pos]; if (assert_op.NotMatches(Instructions[pos])) { throw new AssertionFailure($"Op at {pos} is <{op}> does not match assertion {assert_op}"); } } CurrentLocation = pos; return(this); }
public CodeInstruction CurrentOp(WantOp assert_op = null) { CodeInstruction op = Instructions[CurrentLocation]; if (!(assert_op is null)) { if (assert_op.NotMatches(op)) { throw new AssertionFailure($"CurrentOp <{op}> does not match assertion {assert_op}"); } } return(op); }
/// <summary> /// Advance pointer forward by N. If N is negative, move backwards instead. /// </summary> /// <param name="N">How many instructions to advance. Can be negative.</param> /// <param name="assert_op">If given, then will assert that instruction at destination matches provided WantOp</param> /// <returns><c>this</c> to allow Fluent chaining.</returns> public InstructionsWalker GoForward(int N, WantOp assert_op = null) { int newpos = CurrentLocation + N; if (!(assert_op is null)) { CodeInstruction op = Instructions[newpos]; if (assert_op.NotMatches(Instructions[newpos])) { throw new AssertionFailure($"Op at {newpos} is <{op}> does not match assertion {assert_op}"); } } CurrentLocation = newpos; return(this); }
/// <summary> /// Fetch the current location, but do NOT advance /// </summary> /// <param name="fetchedCurLoc">Variable to hold the fetched CurrentLocation</param> /// <param name="offset">Add this to the fetched location</param> /// <param name="assert_op">If given, asserts that instruction at location+offset matches a <c>WantOp</c> criteria</param> /// <returns><c>this</c> for Fluent chaining.</returns> public InstructionsWalker FetchLocation(out int fetchedCurLoc, int offset = 0, WantOp assert_op = null) { fetchedCurLoc = CurrentLocation + offset; if (!(assert_op is null)) { CodeInstruction op = Instructions[fetchedCurLoc]; if (assert_op.NotMatches(Instructions[fetchedCurLoc])) { throw new AssertionFailure($"Op at {fetchedCurLoc} is <{op}> does not match assertion {assert_op}"); } } return(this); }