Class CodeMatcher
- Namespace
- Concord
- Assembly
- Concord.Emit.dll
A fluent positional cursor over a transpiler's IL stream. Locate a sequence with MatchStartForward(params CodeMatch[]) or MatchStartBackwards(params CodeMatch[]), then read or edit at the cursor and chain onward.
public sealed class CodeMatcher
- Inheritance
-
CodeMatcher
- Inherited Members
Remarks
A failed match leaves Pos at -1. Every editing method (the two
Set*AndAdvance methods, SetInstruction(CodeInstruction), Insert(params CodeInstruction[]),
InsertAndAdvance(params CodeInstruction[]), RemoveInstruction(), and
RemoveInstructions(int)) is a no-op while IsInvalid, so a fluent
chain never throws before it reaches ThrowIfInvalid(string). Insert(params CodeInstruction[]) and
InsertAndAdvance(params CodeInstruction[]) both need a valid Pos to insert before, so
there is no way to append after the working list's last instruction through the cursor;
append directly to InstructionEnumeration()'s returned list instead.
Constructors
CodeMatcher(IEnumerable<CodeInstruction>)
Wraps a fresh working copy of instructions, positioned before the first instruction.
public CodeMatcher(IEnumerable<CodeInstruction> instructions)
Parameters
instructionsIEnumerable<CodeInstruction>The instructions to search and edit.
CodeMatcher(IEnumerable<CodeInstruction>, ITranspilerContext)
Wraps a fresh working copy of instructions, positioned before the first instruction.
public CodeMatcher(IEnumerable<CodeInstruction> instructions, ITranspilerContext context)
Parameters
instructionsIEnumerable<CodeInstruction>The instructions to search and edit.
contextITranspilerContextThe transpiler context this matcher's edits belong to. Not read by any member in this version.
Properties
Instruction
The instruction at Pos.
public CodeInstruction Instruction { get; }
Property Value
Exceptions
- ConcordEmitException
Thrown with code
CONC120when IsInvalid.
IsInvalid
The negation of IsValid.
public bool IsInvalid { get; }
Property Value
IsValid
Whether Pos refers to an instruction in the working list.
public bool IsValid { get; }
Property Value
Pos
The zero-based index of the current instruction, or -1 when invalid.
public int Pos { get; }
Property Value
Methods
Advance(int)
Moves the cursor by offset instructions. A no-op while invalid.
public CodeMatcher Advance(int offset)
Parameters
offsetintThe number of instructions to move forward, or backward when negative.
Returns
- CodeMatcher
This matcher, at the new position, or invalid when the move landed outside the list.
End()
Moves the cursor to the last instruction.
public CodeMatcher End()
Returns
- CodeMatcher
This matcher, positioned at the last index, or invalid when the working list is empty.
Insert(params CodeInstruction[])
Inserts instructions before the cursor without moving it, so
Instruction now returns the first inserted instruction. A no-op while invalid.
public CodeMatcher Insert(params CodeInstruction[] instructions)
Parameters
instructionsCodeInstruction[]The instructions to insert.
Returns
- CodeMatcher
This matcher, still at the same numeric position.
InsertAndAdvance(params CodeInstruction[])
Inserts instructions before the cursor and advances past all of them, so the
cursor lands back on the instruction that was current before the call. A no-op while invalid.
public CodeMatcher InsertAndAdvance(params CodeInstruction[] instructions)
Parameters
instructionsCodeInstruction[]The instructions to insert.
Returns
- CodeMatcher
This matcher, positioned just after the inserted instructions.
InstructionEnumeration()
The working list of instructions, including every edit made so far.
public List<CodeInstruction> InstructionEnumeration()
Returns
- List<CodeInstruction>
The working list, returned by reference rather than a copy: mutating it (including appending past the last instruction, the cursor's own editing methods cannot do this) mutates this matcher directly. A transpiler returns this to hand its rewritten body back to Concord.
MatchStartBackwards(params CodeMatch[])
Searches backward for the first run of instructions matching matches in order,
starting just before Pos (or at the end of the list when invalid).
public CodeMatcher MatchStartBackwards(params CodeMatch[] matches)
Parameters
matchesCodeMatch[]The consecutive sequence to find. Pos lands on its first instruction. An empty array is treated as an immediate non-match rather than a match at the current search origin.
Returns
- CodeMatcher
This matcher, positioned on the match, or invalid when none was found.
MatchStartForward(params CodeMatch[])
Searches forward for the first run of instructions matching matches in order,
starting just after Pos (or at the start of the list when invalid).
public CodeMatcher MatchStartForward(params CodeMatch[] matches)
Parameters
matchesCodeMatch[]The consecutive sequence to find. Pos lands on its first instruction. An empty array is treated as an immediate non-match rather than a match at the current search origin.
Returns
- CodeMatcher
This matcher, positioned on the match, or invalid when none was found.
RemoveInstruction()
Removes the current instruction. Any labels it carried are moved onto the following instruction
(or the preceding one, if the removal reached the end of the list) so branch targets stay
resolvable. Exception-block boundaries only move onto a following instruction; removing the
boundary at the very end of the list with nothing left to carry it forward drops it, which
surfaces as CONC118 (unbalanced exception blocks) when the rewritten body is composed,
rather than silently producing a malformed region. A no-op while invalid.
public CodeMatcher RemoveInstruction()
Returns
- CodeMatcher
This matcher, at the same numeric position, or invalid when the removed instruction was last.
RemoveInstructions(int)
Removes up to count instructions starting at the cursor, clamped to the
instructions actually remaining. Labels carried by the removed range are moved onto the following
instruction (or the preceding one, if the removal reached the end of the list). Exception-block
boundaries only move onto a following instruction; a boundary stranded at the very end of the
list is dropped, which surfaces as CONC118 when the rewritten body is composed rather than
silently producing a malformed region. A no-op while invalid.
public CodeMatcher RemoveInstructions(int count)
Parameters
countintThe number of instructions to remove.
Returns
- CodeMatcher
This matcher, at the same numeric position, or invalid when the removal reached the end.
SetInstruction(CodeInstruction)
Replaces the current instruction outright. A no-op while invalid.
public CodeMatcher SetInstruction(CodeInstruction instruction)
Parameters
instructionCodeInstructionThe replacement instruction.
Returns
- CodeMatcher
This matcher, still positioned at the replaced index.
SetOpcodeAndAdvance(OpCode)
Sets the opcode of the current instruction, then advances by one. A no-op while invalid.
public CodeMatcher SetOpcodeAndAdvance(OpCode opcode)
Parameters
opcodeOpCodeThe opcode to assign.
Returns
- CodeMatcher
This matcher, past the edited instruction.
SetOperandAndAdvance(object?)
Sets the operand of the current instruction, then advances by one. A no-op while invalid.
public CodeMatcher SetOperandAndAdvance(object? operand)
Parameters
Returns
- CodeMatcher
This matcher, past the edited instruction.
Start()
Moves the cursor to the first instruction.
public CodeMatcher Start()
Returns
- CodeMatcher
This matcher, positioned at index 0, or invalid when the working list is empty.
ThrowIfInvalid(string)
Throws when the cursor is invalid.
public CodeMatcher ThrowIfInvalid(string message)
Parameters
messagestringThe failure detail included in the thrown exception.
Returns
- CodeMatcher
This matcher, unchanged, when valid.
Exceptions
- ConcordEmitException
Thrown with code
CONC120when IsInvalid.