Skip to main content

miden_assembly_syntax/ast/
visit.rs

1//! This module provides an implementation of the visitor pattern for the AST of Miden Assembly.
2//!
3//! The pattern is implemented in terms of two traits, `Visit` and `VisitMut`, corresponding to
4//! whether or not the visitor has mutable access to each AST node.
5//!
6//! In addition to the visitor traits, there are a number of free functions that correspond to the
7//! methods of those traits. For example, the visit methods for a [Procedure] are
8//! [Visit::visit_procedure] and [VisitMut::visit_mut_procedure]. There are two free functions that
9//! are used in conjunction with these methods: [visit_procedure], and [visit_mut_procedure], which
10//! are typically not imported directly, but are referenced through the `visit` module, e.g.
11//! `visit::visit_procedure`. These free functions implement the default visitor for the AST node
12//! they correspond to. By default, all methods of the `Visit` and `VisitMut` traits delegate to
13//! these functions. As a result, `impl Visit for MyVisitor {}` is technically a valid visitor, and
14//! will traverse the entire AST if invoked.
15//!
16//! Obviously, that visitor wouldn't be very useful, but in practice, the free functions are called
17//! to resume traversal of the AST either before or after executing the desired behavior for a given
18//! AST node. Doing so essentially corresponds to either a post- or preorder traversal of the AST
19//! respectively.
20//!
21//! How do you choose between performing a postorder vs preorder visit? It depends on the semantics
22//! of the visitor, but here are some examples:
23//!
24//! 1. When implementing a visitor that performs constant folding/propagation, you need to visit the
25//!    operands of an expression before the operator, in order to determine whether it is possible
26//!    to fold, and if so, what the actual values of the operands are. As a result, this is
27//!    implemented as a postorder visitor, so that the AST node corresponding to the expression is
28//!    rewritten after all of it's children.
29//!
30//! 2. When implementing an analysis based on lexical scope, it is necessary to "push down" context
31//!    from the root to the leaves of the AST - the context being the contents of each AST nodes
32//!    inherited scope. As a result, this is implemented as a preorder traversal, so that the
33//!    context at each node can be computed before visiting the children of that node.
34//!
35//! In both cases, the implementor must call the free function corresponding to the _current_ AST
36//! node at the appropriate point (i.e. before/after executing the logic for the node), so that the
37//! visitor will resume its traversal of the tree correctly. Put another way, failing to do so will
38//! cause the traversal to stop at that node (it will continue visiting sibling nodes, if
39//! applicable, but it will go no deeper in the tree).
40//!
41//! # FAQs
42//!
43//! * Why are the free `visit` functions needed?
44//!
45//! Technically they aren't - you could reimplement the visit pattern for every AST node, in each
46//! visitor, independently. However, this is a lot of boilerplate (as you can see below), and would
47//! represent a major maintenance burden if the AST changes shape at all. By implementing the
48//! default pattern in those free functions, they can be reused everywhere, and a visitor need only
49//! override the methods of those nodes it cares about. Changes to the AST only require modifying
50//! the code in this module, with the exception of visitors whose logic must be updated to reflect
51//! modifications to specific nodes they care about.
52use alloc::sync::Arc;
53use core::ops::ControlFlow;
54
55use miden_debug_types::Span;
56
57use super::immediate::ErrorMsg;
58use crate::{
59    Felt,
60    ast::*,
61    parser::{PushValue, WordValue},
62};
63
64/// Represents an immutable AST visitor, whose "early return" type is `T` (by default `()`).
65///
66/// Immutable visitors are primarily used for analysis, or to search the AST for something specific.
67///
68/// Unless explicitly overridden, all methods of this trait will perform a default depth-first
69/// traversal of the AST. When a node is overridden, you must ensure that the corresponding free
70/// function in this module is called at an appropriate point if you wish to visit all of the
71/// children of that node. For example, if visiting procedures, you must call
72/// `visit::visit_procedure` either before you do your analysis for that procedure, or after,
73/// corresponding to whether you are pushing information up the tree, or down. If you do not do
74/// this, none of the children of the [Procedure] node will be visited. This is perfectly valid!
75/// Sometimes you don't want/need to waste time on the children of a node if you can obtain all the
76/// information you need at the parent. It is just important to be aware that this is one of the
77/// elements placed in the hands of the visitor implementation.
78///
79/// The methods of this trait all return [core::ops::ControlFlow], which can be used to break out
80/// of the traversal early via `ControlFlow::Break`. The `T` type parameter of this trait controls
81/// what the value associated with an early return will be. In most cases, the default of `()` is
82/// all you need - but in some cases it can be useful to return an error or other value, that
83/// indicates why the traversal ended early.
84pub trait Visit<T = ()> {
85    fn visit_module(&mut self, module: &Module) -> ControlFlow<T> {
86        visit_module(self, module)
87    }
88    fn visit_import(&mut self, import: &Import) -> ControlFlow<T> {
89        visit_import(self, import)
90    }
91    fn visit_export(&mut self, export: &Item) -> ControlFlow<T> {
92        visit_export(self, export)
93    }
94    fn visit_procedure(&mut self, procedure: &Procedure) -> ControlFlow<T> {
95        visit_procedure(self, procedure)
96    }
97    fn visit_constant(&mut self, constant: &Constant) -> ControlFlow<T> {
98        visit_constant(self, constant)
99    }
100    fn visit_constant_expr(&mut self, expr: &ConstantExpr) -> ControlFlow<T> {
101        visit_constant_expr(self, expr)
102    }
103    fn visit_constant_ref(&mut self, path: &Span<Arc<Path>>) -> ControlFlow<T> {
104        visit_constant_ref(self, path)
105    }
106    fn visit_type_decl(&mut self, ty: &TypeDecl) -> ControlFlow<T> {
107        visit_type_decl(self, ty)
108    }
109    fn visit_type_alias(&mut self, ty: &TypeAlias) -> ControlFlow<T> {
110        visit_type_alias(self, ty)
111    }
112    fn visit_type_expr(&mut self, ty: &TypeExpr) -> ControlFlow<T> {
113        visit_type_expr(self, ty)
114    }
115    fn visit_type_ref(&mut self, path: &Span<Arc<Path>>) -> ControlFlow<T> {
116        visit_type_ref(self, path)
117    }
118    fn visit_enum(&mut self, ty: &EnumType) -> ControlFlow<T> {
119        visit_enum(self, ty)
120    }
121    fn visit_enum_variant(&mut self, variant: &Variant) -> ControlFlow<T> {
122        visit_enum_variant(self, variant)
123    }
124    fn visit_block(&mut self, block: &Block) -> ControlFlow<T> {
125        visit_block(self, block)
126    }
127    fn visit_op(&mut self, op: &Op) -> ControlFlow<T> {
128        visit_op(self, op)
129    }
130    fn visit_inst(&mut self, inst: &Span<Instruction>) -> ControlFlow<T> {
131        visit_inst(self, inst)
132    }
133    fn visit_system_event(&mut self, sys_event: Span<&SystemEventNode>) -> ControlFlow<T> {
134        visit_system_event(self, sys_event)
135    }
136
137    fn visit_exec(&mut self, target: &InvocationTarget) -> ControlFlow<T> {
138        visit_exec(self, target)
139    }
140    fn visit_call(&mut self, target: &InvocationTarget) -> ControlFlow<T> {
141        visit_call(self, target)
142    }
143    fn visit_syscall(&mut self, target: &InvocationTarget) -> ControlFlow<T> {
144        visit_syscall(self, target)
145    }
146    fn visit_procref(&mut self, target: &InvocationTarget) -> ControlFlow<T> {
147        visit_procref(self, target)
148    }
149    fn visit_invoke_target(&mut self, target: &InvocationTarget) -> ControlFlow<T> {
150        visit_invoke_target(self, target)
151    }
152    fn visit_immediate_u8(&mut self, imm: &Immediate<u8>) -> ControlFlow<T> {
153        visit_immediate_u8(self, imm)
154    }
155    fn visit_immediate_u16(&mut self, imm: &Immediate<u16>) -> ControlFlow<T> {
156        visit_immediate_u16(self, imm)
157    }
158    fn visit_immediate_u32(&mut self, imm: &Immediate<u32>) -> ControlFlow<T> {
159        visit_immediate_u32(self, imm)
160    }
161    fn visit_immediate_felt(&mut self, imm: &Immediate<Felt>) -> ControlFlow<T> {
162        visit_immediate_felt(self, imm)
163    }
164    fn visit_immediate_word_value(&mut self, code: &Immediate<WordValue>) -> ControlFlow<T> {
165        visit_immediate_word_value(self, code)
166    }
167    fn visit_immediate_push_value(&mut self, code: &Immediate<PushValue>) -> ControlFlow<T> {
168        visit_immediate_push_value(self, code)
169    }
170    fn visit_immediate_error_message(&mut self, code: &ErrorMsg) -> ControlFlow<T> {
171        visit_immediate_error_message(self, code)
172    }
173}
174
175impl<V, T> Visit<T> for &mut V
176where
177    V: ?Sized + Visit<T>,
178{
179    fn visit_module(&mut self, module: &Module) -> ControlFlow<T> {
180        (**self).visit_module(module)
181    }
182    fn visit_import(&mut self, import: &Import) -> ControlFlow<T> {
183        (**self).visit_import(import)
184    }
185    fn visit_export(&mut self, export: &Item) -> ControlFlow<T> {
186        (**self).visit_export(export)
187    }
188    fn visit_procedure(&mut self, procedure: &Procedure) -> ControlFlow<T> {
189        (**self).visit_procedure(procedure)
190    }
191    fn visit_constant(&mut self, constant: &Constant) -> ControlFlow<T> {
192        (**self).visit_constant(constant)
193    }
194    fn visit_constant_expr(&mut self, expr: &ConstantExpr) -> ControlFlow<T> {
195        (**self).visit_constant_expr(expr)
196    }
197    fn visit_constant_ref(&mut self, path: &Span<Arc<Path>>) -> ControlFlow<T> {
198        (**self).visit_constant_ref(path)
199    }
200    fn visit_type_decl(&mut self, ty: &TypeDecl) -> ControlFlow<T> {
201        (**self).visit_type_decl(ty)
202    }
203    fn visit_type_alias(&mut self, ty: &TypeAlias) -> ControlFlow<T> {
204        (**self).visit_type_alias(ty)
205    }
206    fn visit_type_expr(&mut self, ty: &TypeExpr) -> ControlFlow<T> {
207        (**self).visit_type_expr(ty)
208    }
209    fn visit_type_ref(&mut self, path: &Span<Arc<Path>>) -> ControlFlow<T> {
210        (**self).visit_type_ref(path)
211    }
212    fn visit_enum(&mut self, ty: &EnumType) -> ControlFlow<T> {
213        (**self).visit_enum(ty)
214    }
215    fn visit_enum_variant(&mut self, variant: &Variant) -> ControlFlow<T> {
216        (**self).visit_enum_variant(variant)
217    }
218    fn visit_block(&mut self, block: &Block) -> ControlFlow<T> {
219        (**self).visit_block(block)
220    }
221    fn visit_op(&mut self, op: &Op) -> ControlFlow<T> {
222        (**self).visit_op(op)
223    }
224    fn visit_inst(&mut self, inst: &Span<Instruction>) -> ControlFlow<T> {
225        (**self).visit_inst(inst)
226    }
227    fn visit_system_event(&mut self, sys_event: Span<&SystemEventNode>) -> ControlFlow<T> {
228        (**self).visit_system_event(sys_event)
229    }
230
231    fn visit_exec(&mut self, target: &InvocationTarget) -> ControlFlow<T> {
232        (**self).visit_exec(target)
233    }
234    fn visit_call(&mut self, target: &InvocationTarget) -> ControlFlow<T> {
235        (**self).visit_call(target)
236    }
237    fn visit_syscall(&mut self, target: &InvocationTarget) -> ControlFlow<T> {
238        (**self).visit_syscall(target)
239    }
240    fn visit_procref(&mut self, target: &InvocationTarget) -> ControlFlow<T> {
241        (**self).visit_procref(target)
242    }
243    fn visit_invoke_target(&mut self, target: &InvocationTarget) -> ControlFlow<T> {
244        (**self).visit_invoke_target(target)
245    }
246    fn visit_immediate_u8(&mut self, imm: &Immediate<u8>) -> ControlFlow<T> {
247        (**self).visit_immediate_u8(imm)
248    }
249    fn visit_immediate_u16(&mut self, imm: &Immediate<u16>) -> ControlFlow<T> {
250        (**self).visit_immediate_u16(imm)
251    }
252    fn visit_immediate_u32(&mut self, imm: &Immediate<u32>) -> ControlFlow<T> {
253        (**self).visit_immediate_u32(imm)
254    }
255    fn visit_immediate_felt(&mut self, imm: &Immediate<Felt>) -> ControlFlow<T> {
256        (**self).visit_immediate_felt(imm)
257    }
258    fn visit_immediate_word_value(&mut self, imm: &Immediate<WordValue>) -> ControlFlow<T> {
259        (**self).visit_immediate_word_value(imm)
260    }
261    fn visit_immediate_push_value(&mut self, imm: &Immediate<PushValue>) -> ControlFlow<T> {
262        (**self).visit_immediate_push_value(imm)
263    }
264    fn visit_immediate_error_message(&mut self, code: &ErrorMsg) -> ControlFlow<T> {
265        (**self).visit_immediate_error_message(code)
266    }
267}
268
269pub fn visit_module<V, T>(visitor: &mut V, module: &Module) -> ControlFlow<T>
270where
271    V: ?Sized + Visit<T>,
272{
273    for export in module.items() {
274        visitor.visit_export(export)?;
275    }
276
277    ControlFlow::Continue(())
278}
279
280#[inline(always)]
281pub fn visit_import<V, T>(_visitor: &mut V, _import: &Import) -> ControlFlow<T>
282where
283    V: ?Sized + Visit<T>,
284{
285    ControlFlow::Continue(())
286}
287
288pub fn visit_export<V, T>(visitor: &mut V, export: &Item) -> ControlFlow<T>
289where
290    V: ?Sized + Visit<T>,
291{
292    match export {
293        Item::Procedure(item) => visitor.visit_procedure(item),
294        Item::Constant(item) => visitor.visit_constant(item),
295        Item::Type(item) => visitor.visit_type_decl(item),
296    }
297}
298
299pub fn visit_procedure<V, T>(visitor: &mut V, procedure: &Procedure) -> ControlFlow<T>
300where
301    V: ?Sized + Visit<T>,
302{
303    if let Some(signature) = procedure.signature() {
304        for ty in signature.args.iter().chain(signature.results.iter()) {
305            visitor.visit_type_expr(ty)?;
306        }
307    }
308    visitor.visit_block(procedure.body())
309}
310
311#[inline(always)]
312pub fn visit_constant<V, T>(visitor: &mut V, constant: &Constant) -> ControlFlow<T>
313where
314    V: ?Sized + Visit<T>,
315{
316    visitor.visit_constant_expr(&constant.value)
317}
318
319pub fn visit_constant_expr<V, T>(visitor: &mut V, expr: &ConstantExpr) -> ControlFlow<T>
320where
321    V: ?Sized + Visit<T>,
322{
323    match expr {
324        ConstantExpr::Var(path) => visitor.visit_constant_ref(path),
325        ConstantExpr::BinaryOp { lhs, rhs, .. } => {
326            visitor.visit_constant_expr(lhs)?;
327            visitor.visit_constant_expr(rhs)
328        },
329        ConstantExpr::Hash(..)
330        | ConstantExpr::Int(_)
331        | ConstantExpr::String(_)
332        | ConstantExpr::Word(_) => ControlFlow::Continue(()),
333    }
334}
335
336#[inline(always)]
337pub fn visit_constant_ref<V, T>(_visitor: &mut V, _path: &Span<Arc<Path>>) -> ControlFlow<T>
338where
339    V: ?Sized + Visit<T>,
340{
341    ControlFlow::Continue(())
342}
343
344pub fn visit_type_decl<V, T>(visitor: &mut V, ty: &TypeDecl) -> ControlFlow<T>
345where
346    V: ?Sized + Visit<T>,
347{
348    match ty {
349        TypeDecl::Alias(ty) => visitor.visit_type_alias(ty),
350        TypeDecl::Enum(ty) => visitor.visit_enum(ty),
351    }
352}
353
354pub fn visit_type_alias<V, T>(visitor: &mut V, ty: &TypeAlias) -> ControlFlow<T>
355where
356    V: ?Sized + Visit<T>,
357{
358    visitor.visit_type_expr(&ty.ty)
359}
360
361pub fn visit_type_expr<V, T>(visitor: &mut V, ty: &TypeExpr) -> ControlFlow<T>
362where
363    V: ?Sized + Visit<T>,
364{
365    match ty {
366        TypeExpr::Ref(path) => visitor.visit_type_ref(path),
367        TypeExpr::Primitive(_) => ControlFlow::Continue(()),
368        TypeExpr::Array(ty) => visitor.visit_type_expr(&ty.elem),
369        TypeExpr::Ptr(ty) => visitor.visit_type_expr(&ty.pointee),
370        TypeExpr::Struct(ty) => {
371            for field in ty.fields.iter() {
372                visitor.visit_type_expr(&field.ty)?;
373            }
374            ControlFlow::Continue(())
375        },
376    }
377}
378
379#[inline(always)]
380pub fn visit_type_ref<V, T>(_visitor: &mut V, _path: &Span<Arc<Path>>) -> ControlFlow<T>
381where
382    V: ?Sized + Visit<T>,
383{
384    ControlFlow::Continue(())
385}
386
387pub fn visit_enum<V, T>(visitor: &mut V, ty: &EnumType) -> ControlFlow<T>
388where
389    V: ?Sized + Visit<T>,
390{
391    for variant in ty.variants() {
392        visitor.visit_enum_variant(variant)?;
393    }
394    ControlFlow::Continue(())
395}
396
397pub fn visit_enum_variant<V, T>(visitor: &mut V, variant: &Variant) -> ControlFlow<T>
398where
399    V: ?Sized + Visit<T>,
400{
401    visitor.visit_constant_expr(&variant.discriminant)?;
402    if let Some(value_ty) = variant.value_ty.as_ref() {
403        visitor.visit_type_expr(value_ty)
404    } else {
405        ControlFlow::Continue(())
406    }
407}
408
409pub fn visit_block<V, T>(visitor: &mut V, block: &Block) -> ControlFlow<T>
410where
411    V: ?Sized + Visit<T>,
412{
413    for op in block.iter() {
414        visitor.visit_op(op)?;
415    }
416    ControlFlow::Continue(())
417}
418
419pub fn visit_op<V, T>(visitor: &mut V, op: &Op) -> ControlFlow<T>
420where
421    V: ?Sized + Visit<T>,
422{
423    match op {
424        Op::If { then_blk, else_blk, .. } => {
425            visitor.visit_block(then_blk)?;
426            visitor.visit_block(else_blk)
427        },
428        Op::While { body, .. } | Op::Repeat { body, .. } => visitor.visit_block(body),
429        Op::DoWhile { body, condition, .. } => {
430            visitor.visit_block(body)?;
431            visitor.visit_block(condition)
432        },
433        Op::Inst(inst) => visitor.visit_inst(inst),
434    }
435}
436
437pub fn visit_inst<V, T>(visitor: &mut V, inst: &Span<Instruction>) -> ControlFlow<T>
438where
439    V: ?Sized + Visit<T>,
440{
441    use Instruction::*;
442    let span = inst.span();
443    match &**inst {
444        U32ShrImm(imm) | U32ShlImm(imm) | U32RotrImm(imm) | U32RotlImm(imm) => {
445            visitor.visit_immediate_u8(imm)
446        },
447        Locaddr(imm) | LocLoad(imm) | LocLoadWBe(imm) | LocLoadWLe(imm) | LocStore(imm)
448        | LocStoreWBe(imm) | LocStoreWLe(imm) => visitor.visit_immediate_u16(imm),
449        AssertWithError(code)
450        | AssertEqWithError(code)
451        | AssertEqwWithError(code)
452        | AssertzWithError(code)
453        | U32AssertWithError(code)
454        | U32Assert2WithError(code)
455        | U32AssertWWithError(code)
456        | MTreeVerifyWithError(code) => visitor.visit_immediate_error_message(code),
457        AddImm(imm) | SubImm(imm) | MulImm(imm) | DivImm(imm) | ExpImm(imm) | EqImm(imm)
458        | NeqImm(imm) | LtImm(imm) | LteImm(imm) | GtImm(imm) | GteImm(imm) => {
459            visitor.visit_immediate_felt(imm)
460        },
461        Push(imm) => visitor.visit_immediate_push_value(imm),
462        PushSlice(imm, _) => visitor.visit_immediate_word_value(imm),
463        U32WrappingAddImm(imm)
464        | U32OverflowingAddImm(imm)
465        | U32WideningAddImm(imm)
466        | U32WrappingSubImm(imm)
467        | U32OverflowingSubImm(imm)
468        | U32WrappingMulImm(imm)
469        | U32WideningMulImm(imm)
470        | U32DivImm(imm)
471        | U32ModImm(imm)
472        | U32DivModImm(imm)
473        | MemLoadImm(imm)
474        | MemLoadWBeImm(imm)
475        | MemLoadWLeImm(imm)
476        | MemStoreImm(imm)
477        | MemStoreWBeImm(imm)
478        | MemStoreWLeImm(imm) => visitor.visit_immediate_u32(imm),
479        EmitImm(EventImmediate::Immediate(imm)) | TraceImm(EventImmediate::Immediate(imm)) => {
480            visitor.visit_immediate_felt(imm)
481        },
482        EmitImm(EventImmediate::Name(_)) | TraceImm(EventImmediate::Name(_)) => {
483            ControlFlow::Continue(())
484        },
485        SysEvent(sys_event) => visitor.visit_system_event(Span::new(span, sys_event)),
486        Exec(target) => visitor.visit_exec(target),
487        Call(target) => visitor.visit_call(target),
488        SysCall(target) => visitor.visit_syscall(target),
489        ProcRef(target) => visitor.visit_procref(target),
490
491        Nop | Assert | AssertEq | AssertEqw | Assertz | Add | Sub | Mul | Div | Neg | ILog2
492        | Inv | Incr | Pow2 | Exp | ExpBitLength(_) | Not | And | Or | Xor | Eq | Neq | Eqw
493        | Lt | Lte | Gt | Gte | IsOdd | Ext2Add | Ext2Sub | Ext2Mul | Ext2Div | Ext2Neg
494        | Ext2Inv | U32Test | U32TestW | U32Assert | U32Assert2 | U32AssertW | U32Split
495        | U32Cast | U32WrappingAdd | U32OverflowingAdd | U32WideningAdd | U32OverflowingAdd3
496        | U32WideningAdd3 | U32WrappingAdd3 | U32WrappingSub | U32OverflowingSub
497        | U32WrappingMul | U32WideningMul | U32WideningMadd | U32WrappingMadd | U32Div | U32Mod
498        | U32DivMod | U32And | U32Or | U32Xor | U32Not | U32Shr | U32Shl | U32Rotr | U32Rotl
499        | U32Popcnt | U32Clz | U32Ctz | U32Clo | U32Cto | U32Lt | U32Lte | U32Gt | U32Gte
500        | U32Min | U32Max | Drop | DropW | PadW | Dup0 | Dup1 | Dup2 | Dup3 | Dup4 | Dup5
501        | Dup6 | Dup7 | Dup8 | Dup9 | Dup10 | Dup11 | Dup12 | Dup13 | Dup14 | Dup15 | DupW0
502        | DupW1 | DupW2 | DupW3 | Swap1 | Swap2 | Swap3 | Swap4 | Swap5 | Swap6 | Swap7 | Swap8
503        | Swap9 | Swap10 | Swap11 | Swap12 | Swap13 | Swap14 | Swap15 | SwapW1 | SwapW2
504        | SwapW3 | SwapDw | MovUp2 | MovUp3 | MovUp4 | MovUp5 | MovUp6 | MovUp7 | MovUp8
505        | MovUp9 | MovUp10 | MovUp11 | MovUp12 | MovUp13 | MovUp14 | MovUp15 | MovUpW2
506        | MovUpW3 | MovDn2 | MovDn3 | MovDn4 | MovDn5 | MovDn6 | MovDn7 | MovDn8 | MovDn9
507        | MovDn10 | MovDn11 | MovDn12 | MovDn13 | MovDn14 | MovDn15 | MovDnW2 | MovDnW3
508        | Reversew | Reversedw | CSwap | CSwapW | CDrop | CDropW | PushFeltList(_) | Sdepth
509        | Caller | Clk | MemLoad | MemLoadWBe | MemLoadWLe | MemStore | MemStoreWBe
510        | MemStoreWLe | MemStream | AdvPipe | AdvPush | AdvPushW | AdvLoadW | Hash | HMerge
511        | HPerm | MTreeGet | MTreeSet | MTreeMerge | MTreeVerify | FriExt2Fold4 | DynExec
512        | DynCall | DebugVar(_) | DebugInlineCall(_) | DebugInlineCallClear | HornerBase
513        | HornerExt | CryptoStream | EvalCircuit | LogDeferred | Emit | Trace => {
514            ControlFlow::Continue(())
515        },
516    }
517}
518
519pub fn visit_system_event<V, T>(_visitor: &mut V, _node: Span<&SystemEventNode>) -> ControlFlow<T>
520where
521    V: ?Sized + Visit<T>,
522{
523    ControlFlow::Continue(())
524}
525
526#[inline]
527pub fn visit_exec<V, T>(visitor: &mut V, target: &InvocationTarget) -> ControlFlow<T>
528where
529    V: ?Sized + Visit<T>,
530{
531    visitor.visit_invoke_target(target)
532}
533
534#[inline]
535pub fn visit_call<V, T>(visitor: &mut V, target: &InvocationTarget) -> ControlFlow<T>
536where
537    V: ?Sized + Visit<T>,
538{
539    visitor.visit_invoke_target(target)
540}
541
542#[inline]
543pub fn visit_syscall<V, T>(visitor: &mut V, target: &InvocationTarget) -> ControlFlow<T>
544where
545    V: ?Sized + Visit<T>,
546{
547    visitor.visit_invoke_target(target)
548}
549
550#[inline]
551pub fn visit_procref<V, T>(visitor: &mut V, target: &InvocationTarget) -> ControlFlow<T>
552where
553    V: ?Sized + Visit<T>,
554{
555    visitor.visit_invoke_target(target)
556}
557
558#[inline(always)]
559pub fn visit_invoke_target<V, T>(_visitor: &mut V, _target: &InvocationTarget) -> ControlFlow<T>
560where
561    V: ?Sized + Visit<T>,
562{
563    ControlFlow::Continue(())
564}
565
566#[inline(always)]
567pub fn visit_immediate_u8<V, T>(_visitor: &mut V, _imm: &Immediate<u8>) -> ControlFlow<T>
568where
569    V: ?Sized + Visit<T>,
570{
571    ControlFlow::Continue(())
572}
573
574#[inline(always)]
575pub fn visit_immediate_u16<V, T>(_visitor: &mut V, _imm: &Immediate<u16>) -> ControlFlow<T>
576where
577    V: ?Sized + Visit<T>,
578{
579    ControlFlow::Continue(())
580}
581
582#[inline(always)]
583pub fn visit_immediate_u32<V, T>(_visitor: &mut V, _imm: &Immediate<u32>) -> ControlFlow<T>
584where
585    V: ?Sized + Visit<T>,
586{
587    ControlFlow::Continue(())
588}
589
590#[inline(always)]
591pub fn visit_immediate_felt<V, T>(_visitor: &mut V, _imm: &Immediate<Felt>) -> ControlFlow<T>
592where
593    V: ?Sized + Visit<T>,
594{
595    ControlFlow::Continue(())
596}
597
598#[inline(always)]
599pub fn visit_immediate_word_value<V, T>(
600    _visitor: &mut V,
601    _imm: &Immediate<WordValue>,
602) -> ControlFlow<T>
603where
604    V: ?Sized + Visit<T>,
605{
606    ControlFlow::Continue(())
607}
608
609#[inline(always)]
610pub fn visit_immediate_push_value<V, T>(
611    _visitor: &mut V,
612    _imm: &Immediate<PushValue>,
613) -> ControlFlow<T>
614where
615    V: ?Sized + Visit<T>,
616{
617    ControlFlow::Continue(())
618}
619
620#[inline(always)]
621pub fn visit_immediate_error_message<V, T>(_visitor: &mut V, _imm: &ErrorMsg) -> ControlFlow<T>
622where
623    V: ?Sized + Visit<T>,
624{
625    ControlFlow::Continue(())
626}
627
628/// Represents a mutable AST visitor, whose "early return" type is `T` (by default `()`).
629///
630/// Mutable visitors are primarily used to perform rewrites of the AST, either for desugaring
631/// purposes, optimization purposes, or to iteratively flesh out details in the AST as more
632/// information is discovered during compilation (such as the absolute path to a procedure that
633/// is imported from another module).
634///
635/// Unless explicitly overridden, all methods of this trait will perform a default depth-first
636/// traversal of the AST. When a node is overridden, you must ensure that the corresponding free
637/// function in this module is called at an appropriate point if you wish to visit all of the
638/// children of that node. For example, if visiting procedures, you must call
639/// `visit::visit_mut_procedure` either before you do your analysis for that procedure, or after,
640/// corresponding to whether you are rewriting top-down, or bottom-up. If you do not do this, none
641/// of the children of the [Procedure] node will be visited. This is perfectly valid! Sometimes you
642/// only need to rewrite specific nodes that cannot appear further down the tree, in which case you
643/// do not need to visit any of the children. It is just important to be aware that this is one of
644/// the elements placed in the hands of the visitor implementation.
645///
646/// The methods of this trait all return [core::ops::ControlFlow], which can be used to break out
647/// of the traversal early via `ControlFlow::Break`. The `T` type parameter of this trait controls
648/// what the value associated with an early return will be. In most cases, the default of `()` is
649/// all you need - but in some cases it can be useful to return an error or other value, that
650/// indicates why the traversal ended early.
651pub trait VisitMut<T = ()> {
652    fn visit_mut_module(&mut self, module: &mut Module) -> ControlFlow<T> {
653        visit_mut_module(self, module)
654    }
655    fn visit_mut_import(&mut self, import: &mut Import) -> ControlFlow<T> {
656        visit_mut_import(self, import)
657    }
658    fn visit_mut_export(&mut self, export: &mut Item) -> ControlFlow<T> {
659        visit_mut_export(self, export)
660    }
661    fn visit_mut_procedure(&mut self, procedure: &mut Procedure) -> ControlFlow<T> {
662        visit_mut_procedure(self, procedure)
663    }
664    fn visit_mut_constant(&mut self, constant: &mut Constant) -> ControlFlow<T> {
665        visit_mut_constant(self, constant)
666    }
667    fn visit_mut_constant_expr(&mut self, expr: &mut ConstantExpr) -> ControlFlow<T> {
668        visit_mut_constant_expr(self, expr)
669    }
670    fn visit_mut_constant_ref(&mut self, path: &mut Span<Arc<Path>>) -> ControlFlow<T> {
671        visit_mut_constant_ref(self, path)
672    }
673    fn visit_mut_type_decl(&mut self, ty: &mut TypeDecl) -> ControlFlow<T> {
674        visit_mut_type_decl(self, ty)
675    }
676    fn visit_mut_type_alias(&mut self, ty: &mut TypeAlias) -> ControlFlow<T> {
677        visit_mut_type_alias(self, ty)
678    }
679    fn visit_mut_type_expr(&mut self, ty: &mut TypeExpr) -> ControlFlow<T> {
680        visit_mut_type_expr(self, ty)
681    }
682    fn visit_mut_type_ref(&mut self, path: &mut Span<Arc<Path>>) -> ControlFlow<T> {
683        visit_mut_type_ref(self, path)
684    }
685    fn visit_mut_enum(&mut self, ty: &mut EnumType) -> ControlFlow<T> {
686        visit_mut_enum(self, ty)
687    }
688    fn visit_mut_enum_variant(&mut self, variant: &mut Variant) -> ControlFlow<T> {
689        visit_mut_enum_variant(self, variant)
690    }
691    fn visit_mut_block(&mut self, block: &mut Block) -> ControlFlow<T> {
692        visit_mut_block(self, block)
693    }
694    fn visit_mut_op(&mut self, op: &mut Op) -> ControlFlow<T> {
695        visit_mut_op(self, op)
696    }
697    fn visit_mut_inst(&mut self, inst: &mut Span<Instruction>) -> ControlFlow<T> {
698        visit_mut_inst(self, inst)
699    }
700    fn visit_mut_system_event(&mut self, sys_event: Span<&mut SystemEventNode>) -> ControlFlow<T> {
701        visit_mut_system_event(self, sys_event)
702    }
703
704    fn visit_mut_exec(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
705        visit_mut_exec(self, target)
706    }
707    fn visit_mut_call(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
708        visit_mut_call(self, target)
709    }
710    fn visit_mut_syscall(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
711        visit_mut_syscall(self, target)
712    }
713    fn visit_mut_procref(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
714        visit_mut_procref(self, target)
715    }
716    fn visit_mut_invoke_target(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
717        visit_mut_invoke_target(self, target)
718    }
719    fn visit_mut_immediate_u8(&mut self, imm: &mut Immediate<u8>) -> ControlFlow<T> {
720        visit_mut_immediate_u8(self, imm)
721    }
722    fn visit_mut_immediate_u16(&mut self, imm: &mut Immediate<u16>) -> ControlFlow<T> {
723        visit_mut_immediate_u16(self, imm)
724    }
725    fn visit_mut_immediate_u32(&mut self, imm: &mut Immediate<u32>) -> ControlFlow<T> {
726        visit_mut_immediate_u32(self, imm)
727    }
728    fn visit_mut_immediate_felt(&mut self, imm: &mut Immediate<Felt>) -> ControlFlow<T> {
729        visit_mut_immediate_felt(self, imm)
730    }
731    fn visit_mut_immediate_word_value(&mut self, imm: &mut Immediate<WordValue>) -> ControlFlow<T> {
732        visit_mut_immediate_word_value(self, imm)
733    }
734    fn visit_mut_immediate_push_value(&mut self, imm: &mut Immediate<PushValue>) -> ControlFlow<T> {
735        visit_mut_immediate_push_value(self, imm)
736    }
737    fn visit_mut_immediate_error_message(&mut self, code: &mut ErrorMsg) -> ControlFlow<T> {
738        visit_mut_immediate_error_message(self, code)
739    }
740}
741
742impl<V, T> VisitMut<T> for &mut V
743where
744    V: ?Sized + VisitMut<T>,
745{
746    fn visit_mut_module(&mut self, module: &mut Module) -> ControlFlow<T> {
747        (**self).visit_mut_module(module)
748    }
749    fn visit_mut_import(&mut self, import: &mut Import) -> ControlFlow<T> {
750        (**self).visit_mut_import(import)
751    }
752    fn visit_mut_export(&mut self, export: &mut Item) -> ControlFlow<T> {
753        (**self).visit_mut_export(export)
754    }
755    fn visit_mut_procedure(&mut self, procedure: &mut Procedure) -> ControlFlow<T> {
756        (**self).visit_mut_procedure(procedure)
757    }
758    fn visit_mut_constant(&mut self, constant: &mut Constant) -> ControlFlow<T> {
759        (**self).visit_mut_constant(constant)
760    }
761    fn visit_mut_constant_expr(&mut self, expr: &mut ConstantExpr) -> ControlFlow<T> {
762        (**self).visit_mut_constant_expr(expr)
763    }
764    fn visit_mut_constant_ref(&mut self, path: &mut Span<Arc<Path>>) -> ControlFlow<T> {
765        (**self).visit_mut_constant_ref(path)
766    }
767    fn visit_mut_type_decl(&mut self, ty: &mut TypeDecl) -> ControlFlow<T> {
768        (**self).visit_mut_type_decl(ty)
769    }
770    fn visit_mut_type_alias(&mut self, ty: &mut TypeAlias) -> ControlFlow<T> {
771        (**self).visit_mut_type_alias(ty)
772    }
773    fn visit_mut_type_expr(&mut self, ty: &mut TypeExpr) -> ControlFlow<T> {
774        (**self).visit_mut_type_expr(ty)
775    }
776    fn visit_mut_type_ref(&mut self, path: &mut Span<Arc<Path>>) -> ControlFlow<T> {
777        (**self).visit_mut_type_ref(path)
778    }
779    fn visit_mut_enum(&mut self, ty: &mut EnumType) -> ControlFlow<T> {
780        (**self).visit_mut_enum(ty)
781    }
782    fn visit_mut_enum_variant(&mut self, variant: &mut Variant) -> ControlFlow<T> {
783        (**self).visit_mut_enum_variant(variant)
784    }
785    fn visit_mut_block(&mut self, block: &mut Block) -> ControlFlow<T> {
786        (**self).visit_mut_block(block)
787    }
788    fn visit_mut_op(&mut self, op: &mut Op) -> ControlFlow<T> {
789        (**self).visit_mut_op(op)
790    }
791    fn visit_mut_inst(&mut self, inst: &mut Span<Instruction>) -> ControlFlow<T> {
792        (**self).visit_mut_inst(inst)
793    }
794    fn visit_mut_system_event(&mut self, sys_event: Span<&mut SystemEventNode>) -> ControlFlow<T> {
795        (**self).visit_mut_system_event(sys_event)
796    }
797
798    fn visit_mut_exec(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
799        (**self).visit_mut_exec(target)
800    }
801    fn visit_mut_call(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
802        (**self).visit_mut_call(target)
803    }
804    fn visit_mut_syscall(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
805        (**self).visit_mut_syscall(target)
806    }
807    fn visit_mut_procref(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
808        (**self).visit_mut_procref(target)
809    }
810    fn visit_mut_invoke_target(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
811        (**self).visit_mut_invoke_target(target)
812    }
813    fn visit_mut_immediate_u8(&mut self, imm: &mut Immediate<u8>) -> ControlFlow<T> {
814        (**self).visit_mut_immediate_u8(imm)
815    }
816    fn visit_mut_immediate_u16(&mut self, imm: &mut Immediate<u16>) -> ControlFlow<T> {
817        (**self).visit_mut_immediate_u16(imm)
818    }
819    fn visit_mut_immediate_u32(&mut self, imm: &mut Immediate<u32>) -> ControlFlow<T> {
820        (**self).visit_mut_immediate_u32(imm)
821    }
822    fn visit_mut_immediate_felt(&mut self, imm: &mut Immediate<Felt>) -> ControlFlow<T> {
823        (**self).visit_mut_immediate_felt(imm)
824    }
825    fn visit_mut_immediate_word_value(&mut self, imm: &mut Immediate<WordValue>) -> ControlFlow<T> {
826        (**self).visit_mut_immediate_word_value(imm)
827    }
828    fn visit_mut_immediate_push_value(&mut self, imm: &mut Immediate<PushValue>) -> ControlFlow<T> {
829        (**self).visit_mut_immediate_push_value(imm)
830    }
831    fn visit_mut_immediate_error_message(&mut self, code: &mut ErrorMsg) -> ControlFlow<T> {
832        (**self).visit_mut_immediate_error_message(code)
833    }
834}
835
836pub fn visit_mut_module<V, T>(visitor: &mut V, module: &mut Module) -> ControlFlow<T>
837where
838    V: ?Sized + VisitMut<T>,
839{
840    for export in module.items_mut() {
841        visitor.visit_mut_export(export)?;
842    }
843
844    ControlFlow::Continue(())
845}
846
847#[inline(always)]
848pub fn visit_mut_import<V, T>(_visitor: &mut V, _import: &mut Import) -> ControlFlow<T>
849where
850    V: ?Sized + VisitMut<T>,
851{
852    ControlFlow::Continue(())
853}
854
855pub fn visit_mut_export<V, T>(visitor: &mut V, export: &mut Item) -> ControlFlow<T>
856where
857    V: ?Sized + VisitMut<T>,
858{
859    match export {
860        Item::Procedure(item) => visitor.visit_mut_procedure(item),
861        Item::Constant(item) => visitor.visit_mut_constant(item),
862        Item::Type(item) => visitor.visit_mut_type_decl(item),
863    }
864}
865
866pub fn visit_mut_procedure<V, T>(visitor: &mut V, procedure: &mut Procedure) -> ControlFlow<T>
867where
868    V: ?Sized + VisitMut<T>,
869{
870    if let Some(signature) = procedure.signature_mut() {
871        for ty in signature.args.iter_mut().chain(signature.results.iter_mut()) {
872            visitor.visit_mut_type_expr(ty)?;
873        }
874    }
875    visitor.visit_mut_block(procedure.body_mut())
876}
877
878#[inline(always)]
879pub fn visit_mut_constant<V, T>(visitor: &mut V, constant: &mut Constant) -> ControlFlow<T>
880where
881    V: ?Sized + VisitMut<T>,
882{
883    visitor.visit_mut_constant_expr(&mut constant.value)
884}
885
886pub fn visit_mut_constant_expr<V, T>(visitor: &mut V, expr: &mut ConstantExpr) -> ControlFlow<T>
887where
888    V: ?Sized + VisitMut<T>,
889{
890    match expr {
891        ConstantExpr::Var(path) => visitor.visit_mut_constant_ref(path),
892        ConstantExpr::BinaryOp { lhs, rhs, .. } => {
893            visitor.visit_mut_constant_expr(lhs)?;
894            visitor.visit_mut_constant_expr(rhs)
895        },
896        ConstantExpr::Hash(..)
897        | ConstantExpr::Int(_)
898        | ConstantExpr::String(_)
899        | ConstantExpr::Word(_) => ControlFlow::Continue(()),
900    }
901}
902
903#[inline(always)]
904pub fn visit_mut_constant_ref<V, T>(_visitor: &mut V, _path: &mut Span<Arc<Path>>) -> ControlFlow<T>
905where
906    V: ?Sized + VisitMut<T>,
907{
908    ControlFlow::Continue(())
909}
910
911pub fn visit_mut_type_decl<V, T>(visitor: &mut V, ty: &mut TypeDecl) -> ControlFlow<T>
912where
913    V: ?Sized + VisitMut<T>,
914{
915    match ty {
916        TypeDecl::Alias(ty) => visitor.visit_mut_type_alias(ty),
917        TypeDecl::Enum(ty) => visitor.visit_mut_enum(ty),
918    }
919}
920
921pub fn visit_mut_type_alias<V, T>(visitor: &mut V, ty: &mut TypeAlias) -> ControlFlow<T>
922where
923    V: ?Sized + VisitMut<T>,
924{
925    visitor.visit_mut_type_expr(&mut ty.ty)
926}
927
928pub fn visit_mut_type_expr<V, T>(visitor: &mut V, ty: &mut TypeExpr) -> ControlFlow<T>
929where
930    V: ?Sized + VisitMut<T>,
931{
932    match ty {
933        TypeExpr::Ref(path) => visitor.visit_mut_type_ref(path),
934        TypeExpr::Primitive(_) => ControlFlow::Continue(()),
935        TypeExpr::Array(ty) => visitor.visit_mut_type_expr(&mut ty.elem),
936        TypeExpr::Ptr(ty) => visitor.visit_mut_type_expr(&mut ty.pointee),
937        TypeExpr::Struct(ty) => {
938            for field in ty.fields.iter_mut() {
939                visitor.visit_mut_type_expr(&mut field.ty)?;
940            }
941            ControlFlow::Continue(())
942        },
943    }
944}
945
946#[inline(always)]
947pub fn visit_mut_type_ref<V, T>(_visitor: &mut V, _path: &mut Span<Arc<Path>>) -> ControlFlow<T>
948where
949    V: ?Sized + VisitMut<T>,
950{
951    ControlFlow::Continue(())
952}
953
954pub fn visit_mut_enum<V, T>(visitor: &mut V, ty: &mut EnumType) -> ControlFlow<T>
955where
956    V: ?Sized + VisitMut<T>,
957{
958    for variant in ty.variants_mut() {
959        visitor.visit_mut_enum_variant(variant)?;
960    }
961    ControlFlow::Continue(())
962}
963
964pub fn visit_mut_enum_variant<V, T>(visitor: &mut V, variant: &mut Variant) -> ControlFlow<T>
965where
966    V: ?Sized + VisitMut<T>,
967{
968    visitor.visit_mut_constant_expr(&mut variant.discriminant)?;
969    if let Some(value_ty) = variant.value_ty.as_mut() {
970        visitor.visit_mut_type_expr(value_ty)
971    } else {
972        ControlFlow::Continue(())
973    }
974}
975
976pub fn visit_mut_block<V, T>(visitor: &mut V, block: &mut Block) -> ControlFlow<T>
977where
978    V: ?Sized + VisitMut<T>,
979{
980    for op in block.iter_mut() {
981        visitor.visit_mut_op(op)?;
982    }
983    ControlFlow::Continue(())
984}
985
986pub fn visit_mut_op<V, T>(visitor: &mut V, op: &mut Op) -> ControlFlow<T>
987where
988    V: ?Sized + VisitMut<T>,
989{
990    match op {
991        Op::If { then_blk, else_blk, .. } => {
992            visitor.visit_mut_block(then_blk)?;
993            visitor.visit_mut_block(else_blk)
994        },
995        Op::While { body, .. } => visitor.visit_mut_block(body),
996        Op::DoWhile { body, condition, .. } => {
997            visitor.visit_mut_block(body)?;
998            visitor.visit_mut_block(condition)
999        },
1000        Op::Inst(inst) => visitor.visit_mut_inst(inst),
1001        Op::Repeat { count, body, .. } => {
1002            visitor.visit_mut_immediate_u32(count)?;
1003            visitor.visit_mut_block(body)
1004        },
1005    }
1006}
1007
1008pub fn visit_mut_inst<V, T>(visitor: &mut V, inst: &mut Span<Instruction>) -> ControlFlow<T>
1009where
1010    V: ?Sized + VisitMut<T>,
1011{
1012    use Instruction::*;
1013    let span = inst.span();
1014    match &mut **inst {
1015        U32ShrImm(imm) | U32ShlImm(imm) | U32RotrImm(imm) | U32RotlImm(imm) => {
1016            visitor.visit_mut_immediate_u8(imm)
1017        },
1018        Locaddr(imm) | LocLoad(imm) | LocLoadWBe(imm) | LocLoadWLe(imm) | LocStore(imm)
1019        | LocStoreWBe(imm) | LocStoreWLe(imm) => visitor.visit_mut_immediate_u16(imm),
1020        AssertWithError(code)
1021        | AssertEqWithError(code)
1022        | AssertEqwWithError(code)
1023        | AssertzWithError(code)
1024        | U32AssertWithError(code)
1025        | U32Assert2WithError(code)
1026        | U32AssertWWithError(code)
1027        | MTreeVerifyWithError(code) => visitor.visit_mut_immediate_error_message(code),
1028        AddImm(imm) | SubImm(imm) | MulImm(imm) | DivImm(imm) | ExpImm(imm) | EqImm(imm)
1029        | NeqImm(imm) | LtImm(imm) | LteImm(imm) | GtImm(imm) | GteImm(imm) => {
1030            visitor.visit_mut_immediate_felt(imm)
1031        },
1032        Push(imm) => visitor.visit_mut_immediate_push_value(imm),
1033        PushSlice(imm, _) => visitor.visit_mut_immediate_word_value(imm),
1034        U32WrappingAddImm(imm)
1035        | U32OverflowingAddImm(imm)
1036        | U32WideningAddImm(imm)
1037        | U32WrappingSubImm(imm)
1038        | U32OverflowingSubImm(imm)
1039        | U32WrappingMulImm(imm)
1040        | U32WideningMulImm(imm)
1041        | U32DivImm(imm)
1042        | U32ModImm(imm)
1043        | U32DivModImm(imm)
1044        | MemLoadImm(imm)
1045        | MemLoadWBeImm(imm)
1046        | MemLoadWLeImm(imm)
1047        | MemStoreImm(imm)
1048        | MemStoreWBeImm(imm)
1049        | MemStoreWLeImm(imm) => visitor.visit_mut_immediate_u32(imm),
1050        EmitImm(EventImmediate::Immediate(imm)) | TraceImm(EventImmediate::Immediate(imm)) => {
1051            visitor.visit_mut_immediate_felt(imm)
1052        },
1053        EmitImm(EventImmediate::Name(_)) | TraceImm(EventImmediate::Name(_)) => {
1054            ControlFlow::Continue(())
1055        },
1056        SysEvent(sys_event) => visitor.visit_mut_system_event(Span::new(span, sys_event)),
1057        Exec(target) => visitor.visit_mut_exec(target),
1058        Call(target) => visitor.visit_mut_call(target),
1059        SysCall(target) => visitor.visit_mut_syscall(target),
1060        ProcRef(target) => visitor.visit_mut_procref(target),
1061
1062        Nop | Assert | AssertEq | AssertEqw | Assertz | Add | Sub | Mul | Div | Neg | ILog2
1063        | Inv | Incr | Pow2 | Exp | ExpBitLength(_) | Not | And | Or | Xor | Eq | Neq | Eqw
1064        | Lt | Lte | Gt | Gte | IsOdd | Ext2Add | Ext2Sub | Ext2Mul | Ext2Div | Ext2Neg
1065        | Ext2Inv | U32Test | U32TestW | U32Assert | U32Assert2 | U32AssertW | U32Split
1066        | U32Cast | U32WrappingAdd | U32OverflowingAdd | U32WideningAdd | U32OverflowingAdd3
1067        | U32WideningAdd3 | U32WrappingAdd3 | U32WrappingSub | U32OverflowingSub
1068        | U32WrappingMul | U32WideningMul | U32WideningMadd | U32WrappingMadd | U32Div | U32Mod
1069        | U32DivMod | U32And | U32Or | U32Xor | U32Not | U32Shr | U32Shl | U32Rotr | U32Rotl
1070        | U32Popcnt | U32Clz | U32Ctz | U32Clo | U32Cto | U32Lt | U32Lte | U32Gt | U32Gte
1071        | U32Min | U32Max | Drop | DropW | PadW | Dup0 | Dup1 | Dup2 | Dup3 | Dup4 | Dup5
1072        | Dup6 | Dup7 | Dup8 | Dup9 | Dup10 | Dup11 | Dup12 | Dup13 | Dup14 | Dup15 | DupW0
1073        | DupW1 | DupW2 | DupW3 | Swap1 | Swap2 | Swap3 | Swap4 | Swap5 | Swap6 | Swap7 | Swap8
1074        | Swap9 | Swap10 | Swap11 | Swap12 | Swap13 | Swap14 | Swap15 | SwapW1 | SwapW2
1075        | SwapW3 | SwapDw | MovUp2 | MovUp3 | MovUp4 | MovUp5 | MovUp6 | MovUp7 | MovUp8
1076        | MovUp9 | MovUp10 | MovUp11 | MovUp12 | MovUp13 | MovUp14 | MovUp15 | MovUpW2
1077        | MovUpW3 | MovDn2 | MovDn3 | MovDn4 | MovDn5 | MovDn6 | MovDn7 | MovDn8 | MovDn9
1078        | MovDn10 | MovDn11 | MovDn12 | MovDn13 | MovDn14 | MovDn15 | MovDnW2 | MovDnW3
1079        | Reversew | Reversedw | CSwap | CSwapW | CDrop | CDropW | PushFeltList(_) | Sdepth
1080        | Caller | Clk | MemLoad | MemLoadWBe | MemLoadWLe | MemStore | MemStoreWBe
1081        | MemStoreWLe | MemStream | AdvPipe | AdvPush | AdvPushW | AdvLoadW | Hash | HMerge
1082        | HPerm | MTreeGet | MTreeSet | MTreeMerge | MTreeVerify | FriExt2Fold4 | DynExec
1083        | DynCall | DebugVar(_) | DebugInlineCall(_) | DebugInlineCallClear | HornerBase
1084        | HornerExt | EvalCircuit | CryptoStream | LogDeferred | Emit | Trace => {
1085            ControlFlow::Continue(())
1086        },
1087    }
1088}
1089
1090pub fn visit_mut_system_event<V, T>(
1091    _visitor: &mut V,
1092    _node: Span<&mut SystemEventNode>,
1093) -> ControlFlow<T>
1094where
1095    V: ?Sized + VisitMut<T>,
1096{
1097    ControlFlow::Continue(())
1098}
1099
1100#[inline]
1101pub fn visit_mut_exec<V, T>(visitor: &mut V, target: &mut InvocationTarget) -> ControlFlow<T>
1102where
1103    V: ?Sized + VisitMut<T>,
1104{
1105    visitor.visit_mut_invoke_target(target)
1106}
1107
1108#[inline]
1109pub fn visit_mut_call<V, T>(visitor: &mut V, target: &mut InvocationTarget) -> ControlFlow<T>
1110where
1111    V: ?Sized + VisitMut<T>,
1112{
1113    visitor.visit_mut_invoke_target(target)
1114}
1115
1116#[inline]
1117pub fn visit_mut_syscall<V, T>(visitor: &mut V, target: &mut InvocationTarget) -> ControlFlow<T>
1118where
1119    V: ?Sized + VisitMut<T>,
1120{
1121    visitor.visit_mut_invoke_target(target)
1122}
1123
1124#[inline]
1125pub fn visit_mut_procref<V, T>(visitor: &mut V, target: &mut InvocationTarget) -> ControlFlow<T>
1126where
1127    V: ?Sized + VisitMut<T>,
1128{
1129    visitor.visit_mut_invoke_target(target)
1130}
1131
1132#[inline(always)]
1133pub fn visit_mut_invoke_target<V, T>(
1134    _visitor: &mut V,
1135    _target: &mut InvocationTarget,
1136) -> ControlFlow<T>
1137where
1138    V: ?Sized + VisitMut<T>,
1139{
1140    ControlFlow::Continue(())
1141}
1142
1143#[inline(always)]
1144pub fn visit_mut_immediate_u8<V, T>(_visitor: &mut V, _imm: &mut Immediate<u8>) -> ControlFlow<T>
1145where
1146    V: ?Sized + VisitMut<T>,
1147{
1148    ControlFlow::Continue(())
1149}
1150
1151#[inline(always)]
1152pub fn visit_mut_immediate_u16<V, T>(_visitor: &mut V, _imm: &mut Immediate<u16>) -> ControlFlow<T>
1153where
1154    V: ?Sized + VisitMut<T>,
1155{
1156    ControlFlow::Continue(())
1157}
1158
1159#[inline(always)]
1160pub fn visit_mut_immediate_u32<V, T>(_visitor: &mut V, _imm: &mut Immediate<u32>) -> ControlFlow<T>
1161where
1162    V: ?Sized + VisitMut<T>,
1163{
1164    ControlFlow::Continue(())
1165}
1166
1167#[inline(always)]
1168pub fn visit_mut_immediate_felt<V, T>(
1169    _visitor: &mut V,
1170    _imm: &mut Immediate<Felt>,
1171) -> ControlFlow<T>
1172where
1173    V: ?Sized + VisitMut<T>,
1174{
1175    ControlFlow::Continue(())
1176}
1177
1178#[inline(always)]
1179pub fn visit_mut_immediate_word_value<V, T>(
1180    _visitor: &mut V,
1181    _imm: &mut Immediate<WordValue>,
1182) -> ControlFlow<T>
1183where
1184    V: ?Sized + VisitMut<T>,
1185{
1186    ControlFlow::Continue(())
1187}
1188
1189#[inline(always)]
1190pub fn visit_mut_immediate_push_value<V, T>(
1191    _visitor: &mut V,
1192    _imm: &mut Immediate<PushValue>,
1193) -> ControlFlow<T>
1194where
1195    V: ?Sized + VisitMut<T>,
1196{
1197    ControlFlow::Continue(())
1198}
1199
1200#[inline(always)]
1201pub fn visit_mut_immediate_error_message<V, T>(
1202    _visitor: &mut V,
1203    _imm: &mut ErrorMsg,
1204) -> ControlFlow<T>
1205where
1206    V: ?Sized + VisitMut<T>,
1207{
1208    ControlFlow::Continue(())
1209}