Skip to content
Concord

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

instructions IEnumerable<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

instructions IEnumerable<CodeInstruction>

The instructions to search and edit.

context ITranspilerContext

The 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

CodeInstruction

Exceptions

ConcordEmitException

Thrown with code CONC120 when IsInvalid.

IsInvalid

The negation of IsValid.

public bool IsInvalid { get; }

Property Value

bool

IsValid

Whether Pos refers to an instruction in the working list.

public bool IsValid { get; }

Property Value

bool

Pos

The zero-based index of the current instruction, or -1 when invalid.

public int Pos { get; }

Property Value

int

Methods

Advance(int)

Moves the cursor by offset instructions. A no-op while invalid.

public CodeMatcher Advance(int offset)

Parameters

offset int

The 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

instructions CodeInstruction[]

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

instructions CodeInstruction[]

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

matches CodeMatch[]

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

matches CodeMatch[]

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

count int

The 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

instruction CodeInstruction

The 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

opcode OpCode

The 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

operand object

The operand to assign, or null to clear it.

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

message string

The failure detail included in the thrown exception.

Returns

CodeMatcher

This matcher, unchanged, when valid.

Exceptions

ConcordEmitException

Thrown with code CONC120 when IsInvalid.