10.12. AST pattern matching
AST pattern matching via reverse reification. Matches expressions and blocks against structural
patterns using the same tag system as qmacro but in reverse: $e clones a matched expression,
$v extracts a constant value, $i extracts an identifier name, $c extracts a call name,
$f extracts a field name, $b captures a statement range, $t captures a type,
and $a captures remaining arguments.
10.12.1. Enumerations
- QMatchError
- Values:
ok = 0 - Match succeeded.
rtti_mismatch = 1 - Expression RTTI type does not match the pattern.
field_mismatch = 2 - A named field (name, op, etc.) differs between pattern and expression.
const_type_mismatch = 3 - $v extraction failed — expression is not the expected constant type.
type_mismatch = 4 - TypeDecl comparison failed — types do not match.
list_length = 5 - Block statement count mismatch (after wildcard resolution).
wildcard_not_found = 6 - Wildcard could not find a matching statement.
null_expression = 7 - A null expression was passed where a non-null was expected.
10.12.2. Structures
- QMatchResult
- Fields:
matched : bool - True if the pattern matched the expression.
error : QMatchError - Error code describing why the match failed (ok when matched).
expr : Expression? - Pointer to the expression where matching failed (null on success).
10.12.3. Call macros
- qmatch_block
Function annotation qmatch_block
- qmatch
Function annotation qmatch
- qmatch_function
qmatch_function(func, block_pattern) — match function body against block pattern.
10.12.4. Match execution
- qm_run(expr: Expression?; blk: block<(var arg:Expression?):QMatchResult>): QMatchResult
Invoke a matching block on the expression.
Used internally by the qmatch macro.
- Arguments:
expr : Expression?
blk : block<(arg: Expression?): QMatchResult>
- qm_run_function(func: FunctionPtr; blk: block<(var body:Expression?;var func_ptr:Function?):QMatchResult>): QMatchResult
Run matching block on a function, passing both body and Function pointer.
- Arguments:
func : FunctionPtr
blk : block<(body: Expression?;func_ptr: Function?): QMatchResult>
10.12.5. Result builders
- qm_fail_const(expr: Expression?): QMatchResult
Return a failure — constant type does not match $v extraction target.
- Arguments:
expr : Expression?
- qm_fail_field(expr: Expression?): QMatchResult
Return a failure — a named field differs between pattern and expression.
- Arguments:
expr : Expression?
- qm_fail_list(expr: Expression?): QMatchResult
Return a failure — block statement count mismatch.
- Arguments:
expr : Expression?
- qm_fail_null(): QMatchResult
Return a failure — null expression encountered.
- qm_fail_rtti(expr: Expression?): QMatchResult
Return a failure — expression RTTI type does not match the pattern.
- Arguments:
expr : Expression?
- qm_fail_type(expr: Expression?): QMatchResult
Return a failure — TypeDecl comparison failed.
- Arguments:
expr : Expression?
- qm_fail_wildcard(expr: Expression?): QMatchResult
Return a failure — wildcard could not find a matching statement.
- Arguments:
expr : Expression?
- qm_ok(): QMatchResult
Return a successful match result.
10.12.6. Value extraction
qm_extract (var expr: Expression?; var val: float&) : QMatchResult
qm_extract (var expr: Expression?; var val: int&) : QMatchResult
qm_extract (var expr: Expression?; var val: string&) : QMatchResult
qm_extract (var expr: Expression?; var val: bool&) : QMatchResult
qm_extract (var expr: Expression?; var val: double&) : QMatchResult
qm_extract (var expr: Expression?; var val: uint&) : QMatchResult
qm_extract (var expr: Expression?; var val: int64&) : QMatchResult
10.12.6.1. qm_extract
- qm_extract(expr: Expression?; val: float&): QMatchResult
Extract float from ExprConstFloat. Fails if wrong type.
- Arguments:
expr : Expression?
val : float&
- qm_extract(expr: Expression?; val: int&): QMatchResult
- qm_extract(expr: Expression?; val: string&): QMatchResult
- qm_extract(expr: Expression?; val: bool&): QMatchResult
- qm_extract(expr: Expression?; val: double&): QMatchResult
- qm_extract(expr: Expression?; val: uint&): QMatchResult
- qm_extract(expr: Expression?; val: int64&): QMatchResult
10.12.7. Name and type extraction
- qm_call_name_matches(call: ExprCall?; expected_name: string): bool
Check if a call’s name matches, accounting for generic instantiation.
When a generic function is instantiated, the call name is mangled
(e.g. generic_add`123456). This checks the mangled name first,
then falls back to the fromGeneric original name.
- Arguments:
call : ExprCall?
expected_name : string
- qm_extract_call_name(expr: Expression?): string
Extract call name from ExprCall. If the call targets a generic instance, returns the original generic name (before mangling).
- Arguments:
expr : Expression?
- qm_extract_field_name(expr: Expression?): string
Extract field name from ExprField, ExprSafeField, or variant expressions.
- Arguments:
expr : Expression?
- qm_extract_name(expr: Expression?): string
Extract the “name” field from common expression types. Works for ExprVar, ExprCall, ExprField, ExprSafeField, ExprLet variables, etc.
- Arguments:
expr : Expression?
- qm_extract_type(expr: Expression?; out_type: TypeDeclPtr): QMatchResult
Extract TypeDeclPtr from ExprTypeDecl.
- Arguments:
expr : Expression?
out_type : TypeDeclPtr
- qm_rtti(expr: Expression const?): string
Return the RTTI type name of an expression.
- Arguments:
expr : Expression?
10.12.8. Argument filtering
- qm_count_real_args(args: dasvector`ptr`Variable): int
Count arguments excluding fakeContext and fakeLineInfo.
- Arguments:
args : vector<Variable*>
- qm_count_real_call_args(args: dasvector`ptr`Expression): int
Count call arguments excluding fakeContext and fakeLineInfo expressions.
- Arguments:
args : vector<Expression*>
- qm_extract_remaining_args(args: dasvector`ptr`Variable; from_logical: int; result: array<VariablePtr>)
Collect remaining real arguments (skipping fakeContext/fakeLineInfo) starting from logical index.
- Arguments:
args : vector<Variable*>
from_logical : int
result : array< VariablePtr>
- qm_is_fake_arg(arg: Expression?): bool
Returns true if the expression is a compiler-injected fakeContext or fakeLineInfo.
- Arguments:
arg : Expression?
- qm_real_arg_index(args: dasvector`ptr`Variable; logical_idx: int): int
Map logical argument index (skipping fakeContext/fakeLineInfo) to physical index.
- Arguments:
args : vector<Variable*>
logical_idx : int
- qm_real_call_arg_index(args: dasvector`ptr`Expression; logical_idx: int): int
Map logical call argument index (skipping fake args) to physical index.
- Arguments:
args : vector<Expression*>
logical_idx : int
10.12.9. Block scanning
- qm_extract_stmts(blk_expr: Expression?; from_pos: int; to_pos: int; result: array<Expression?>)
Extract statements [from_pos, to_pos) from a block into an array (cloned).
- Arguments:
blk_expr : Expression?
from_pos : int
to_pos : int
result : array< Expression?>
- qm_scan(blk_expr: Expression?&; pos: int&; len: int; matcher: block<(var elem:Expression?):QMatchResult>): QMatchResult
Scan block statements from pos to len, trying matcher at each position. On first success, update pos to the position after the match and return ok.
- Arguments:
blk_expr : Expression?&
pos : int&
len : int
matcher : block<(elem: Expression?): QMatchResult>
10.12.10. Constant construction
- qm_make_zero_const(call_name: string): Expression?
Create a zero-value ExprConst for the range first component. range → 0, urange → 0u, range64 → 0l, urange64 → 0ul.
- Arguments:
call_name : string
10.12.11. AST reconstruction
- qm_convert_comprehension(expr: Expression?): Expression?
Reverse generateComprehension: ExprInvoke(invoke, ExprMakeBlock(closure)) → ExprArrayComprehension. Detects the pattern by checking ExprReturn.fromComprehension flag. Returns null if the expression is not a generated comprehension.
- Arguments:
expr : Expression?
- qm_convert_local_function(expr: Expression?): Expression?
Reverse generateLocalFunction: ExprAddr → ExprMakeBlock(isLocalFunction=true). Returns null if the expression is not a generated local function.
- Arguments:
expr : Expression?
- qm_resolve_comprehension(expr: Expression?): Expression?
If expr is ExprArrayComprehension, shallow-clone it. If ExprInvoke (post-inference comprehension), reconstruct ExprArrayComprehension. Returns null if neither works.
- Arguments:
expr : Expression?
- qm_resolve_local_function(expr: Expression?): Expression?
If expr is ExprMakeBlock, clone it. If ExprAddr (post-inference local function), convert back to ExprMakeBlock. Returns null if neither works.
- Arguments:
expr : Expression?