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(imm) => visitor.visit_immediate_felt(imm),
480        SysEvent(sys_event) => visitor.visit_system_event(Span::new(span, sys_event)),
481        Exec(target) => visitor.visit_exec(target),
482        Call(target) => visitor.visit_call(target),
483        SysCall(target) => visitor.visit_syscall(target),
484        ProcRef(target) => visitor.visit_procref(target),
485
486        Nop | Assert | AssertEq | AssertEqw | Assertz | Add | Sub | Mul | Div | Neg | ILog2
487        | Inv | Incr | Pow2 | Exp | ExpBitLength(_) | Not | And | Or | Xor | Eq | Neq | Eqw
488        | Lt | Lte | Gt | Gte | IsOdd | Ext2Add | Ext2Sub | Ext2Mul | Ext2Div | Ext2Neg
489        | Ext2Inv | U32Test | U32TestW | U32Assert | U32Assert2 | U32AssertW | U32Split
490        | U32Cast | U32WrappingAdd | U32OverflowingAdd | U32WideningAdd | U32OverflowingAdd3
491        | U32WideningAdd3 | U32WrappingAdd3 | U32WrappingSub | U32OverflowingSub
492        | U32WrappingMul | U32WideningMul | U32WideningMadd | U32WrappingMadd | U32Div | U32Mod
493        | U32DivMod | U32And | U32Or | U32Xor | U32Not | U32Shr | U32Shl | U32Rotr | U32Rotl
494        | U32Popcnt | U32Clz | U32Ctz | U32Clo | U32Cto | U32Lt | U32Lte | U32Gt | U32Gte
495        | U32Min | U32Max | Drop | DropW | PadW | Dup0 | Dup1 | Dup2 | Dup3 | Dup4 | Dup5
496        | Dup6 | Dup7 | Dup8 | Dup9 | Dup10 | Dup11 | Dup12 | Dup13 | Dup14 | Dup15 | DupW0
497        | DupW1 | DupW2 | DupW3 | Swap1 | Swap2 | Swap3 | Swap4 | Swap5 | Swap6 | Swap7 | Swap8
498        | Swap9 | Swap10 | Swap11 | Swap12 | Swap13 | Swap14 | Swap15 | SwapW1 | SwapW2
499        | SwapW3 | SwapDw | MovUp2 | MovUp3 | MovUp4 | MovUp5 | MovUp6 | MovUp7 | MovUp8
500        | MovUp9 | MovUp10 | MovUp11 | MovUp12 | MovUp13 | MovUp14 | MovUp15 | MovUpW2
501        | MovUpW3 | MovDn2 | MovDn3 | MovDn4 | MovDn5 | MovDn6 | MovDn7 | MovDn8 | MovDn9
502        | MovDn10 | MovDn11 | MovDn12 | MovDn13 | MovDn14 | MovDn15 | MovDnW2 | MovDnW3
503        | Reversew | Reversedw | CSwap | CSwapW | CDrop | CDropW | PushFeltList(_) | Sdepth
504        | Caller | Clk | MemLoad | MemLoadWBe | MemLoadWLe | MemStore | MemStoreWBe
505        | MemStoreWLe | MemStream | AdvPipe | AdvPush | AdvPushW | AdvLoadW | Hash | HMerge
506        | HPerm | MTreeGet | MTreeSet | MTreeMerge | MTreeVerify | FriExt2Fold4 | DynExec
507        | DynCall | DebugVar(_) | HornerBase | HornerExt | CryptoStream | EvalCircuit
508        | LogPrecompile | Emit => ControlFlow::Continue(()),
509    }
510}
511
512pub fn visit_system_event<V, T>(_visitor: &mut V, _node: Span<&SystemEventNode>) -> ControlFlow<T>
513where
514    V: ?Sized + Visit<T>,
515{
516    ControlFlow::Continue(())
517}
518
519#[inline]
520pub fn visit_exec<V, T>(visitor: &mut V, target: &InvocationTarget) -> ControlFlow<T>
521where
522    V: ?Sized + Visit<T>,
523{
524    visitor.visit_invoke_target(target)
525}
526
527#[inline]
528pub fn visit_call<V, T>(visitor: &mut V, target: &InvocationTarget) -> ControlFlow<T>
529where
530    V: ?Sized + Visit<T>,
531{
532    visitor.visit_invoke_target(target)
533}
534
535#[inline]
536pub fn visit_syscall<V, T>(visitor: &mut V, target: &InvocationTarget) -> ControlFlow<T>
537where
538    V: ?Sized + Visit<T>,
539{
540    visitor.visit_invoke_target(target)
541}
542
543#[inline]
544pub fn visit_procref<V, T>(visitor: &mut V, target: &InvocationTarget) -> ControlFlow<T>
545where
546    V: ?Sized + Visit<T>,
547{
548    visitor.visit_invoke_target(target)
549}
550
551#[inline(always)]
552pub fn visit_invoke_target<V, T>(_visitor: &mut V, _target: &InvocationTarget) -> ControlFlow<T>
553where
554    V: ?Sized + Visit<T>,
555{
556    ControlFlow::Continue(())
557}
558
559#[inline(always)]
560pub fn visit_immediate_u8<V, T>(_visitor: &mut V, _imm: &Immediate<u8>) -> ControlFlow<T>
561where
562    V: ?Sized + Visit<T>,
563{
564    ControlFlow::Continue(())
565}
566
567#[inline(always)]
568pub fn visit_immediate_u16<V, T>(_visitor: &mut V, _imm: &Immediate<u16>) -> ControlFlow<T>
569where
570    V: ?Sized + Visit<T>,
571{
572    ControlFlow::Continue(())
573}
574
575#[inline(always)]
576pub fn visit_immediate_u32<V, T>(_visitor: &mut V, _imm: &Immediate<u32>) -> ControlFlow<T>
577where
578    V: ?Sized + Visit<T>,
579{
580    ControlFlow::Continue(())
581}
582
583#[inline(always)]
584pub fn visit_immediate_felt<V, T>(_visitor: &mut V, _imm: &Immediate<Felt>) -> ControlFlow<T>
585where
586    V: ?Sized + Visit<T>,
587{
588    ControlFlow::Continue(())
589}
590
591#[inline(always)]
592pub fn visit_immediate_word_value<V, T>(
593    _visitor: &mut V,
594    _imm: &Immediate<WordValue>,
595) -> ControlFlow<T>
596where
597    V: ?Sized + Visit<T>,
598{
599    ControlFlow::Continue(())
600}
601
602#[inline(always)]
603pub fn visit_immediate_push_value<V, T>(
604    _visitor: &mut V,
605    _imm: &Immediate<PushValue>,
606) -> ControlFlow<T>
607where
608    V: ?Sized + Visit<T>,
609{
610    ControlFlow::Continue(())
611}
612
613#[inline(always)]
614pub fn visit_immediate_error_message<V, T>(_visitor: &mut V, _imm: &ErrorMsg) -> ControlFlow<T>
615where
616    V: ?Sized + Visit<T>,
617{
618    ControlFlow::Continue(())
619}
620
621/// Represents a mutable AST visitor, whose "early return" type is `T` (by default `()`).
622///
623/// Mutable visitors are primarily used to perform rewrites of the AST, either for desugaring
624/// purposes, optimization purposes, or to iteratively flesh out details in the AST as more
625/// information is discovered during compilation (such as the absolute path to a procedure that
626/// is imported from another module).
627///
628/// Unless explicitly overridden, all methods of this trait will perform a default depth-first
629/// traversal of the AST. When a node is overridden, you must ensure that the corresponding free
630/// function in this module is called at an appropriate point if you wish to visit all of the
631/// children of that node. For example, if visiting procedures, you must call
632/// `visit::visit_mut_procedure` either before you do your analysis for that procedure, or after,
633/// corresponding to whether you are rewriting top-down, or bottom-up. If you do not do this, none
634/// of the children of the [Procedure] node will be visited. This is perfectly valid! Sometimes you
635/// only need to rewrite specific nodes that cannot appear further down the tree, in which case you
636/// do not need to visit any of the children. It is just important to be aware that this is one of
637/// the elements placed in the hands of the visitor implementation.
638///
639/// The methods of this trait all return [core::ops::ControlFlow], which can be used to break out
640/// of the traversal early via `ControlFlow::Break`. The `T` type parameter of this trait controls
641/// what the value associated with an early return will be. In most cases, the default of `()` is
642/// all you need - but in some cases it can be useful to return an error or other value, that
643/// indicates why the traversal ended early.
644pub trait VisitMut<T = ()> {
645    fn visit_mut_module(&mut self, module: &mut Module) -> ControlFlow<T> {
646        visit_mut_module(self, module)
647    }
648    fn visit_mut_import(&mut self, import: &mut Import) -> ControlFlow<T> {
649        visit_mut_import(self, import)
650    }
651    fn visit_mut_export(&mut self, export: &mut Item) -> ControlFlow<T> {
652        visit_mut_export(self, export)
653    }
654    fn visit_mut_procedure(&mut self, procedure: &mut Procedure) -> ControlFlow<T> {
655        visit_mut_procedure(self, procedure)
656    }
657    fn visit_mut_constant(&mut self, constant: &mut Constant) -> ControlFlow<T> {
658        visit_mut_constant(self, constant)
659    }
660    fn visit_mut_constant_expr(&mut self, expr: &mut ConstantExpr) -> ControlFlow<T> {
661        visit_mut_constant_expr(self, expr)
662    }
663    fn visit_mut_constant_ref(&mut self, path: &mut Span<Arc<Path>>) -> ControlFlow<T> {
664        visit_mut_constant_ref(self, path)
665    }
666    fn visit_mut_type_decl(&mut self, ty: &mut TypeDecl) -> ControlFlow<T> {
667        visit_mut_type_decl(self, ty)
668    }
669    fn visit_mut_type_alias(&mut self, ty: &mut TypeAlias) -> ControlFlow<T> {
670        visit_mut_type_alias(self, ty)
671    }
672    fn visit_mut_type_expr(&mut self, ty: &mut TypeExpr) -> ControlFlow<T> {
673        visit_mut_type_expr(self, ty)
674    }
675    fn visit_mut_type_ref(&mut self, path: &mut Span<Arc<Path>>) -> ControlFlow<T> {
676        visit_mut_type_ref(self, path)
677    }
678    fn visit_mut_enum(&mut self, ty: &mut EnumType) -> ControlFlow<T> {
679        visit_mut_enum(self, ty)
680    }
681    fn visit_mut_enum_variant(&mut self, variant: &mut Variant) -> ControlFlow<T> {
682        visit_mut_enum_variant(self, variant)
683    }
684    fn visit_mut_block(&mut self, block: &mut Block) -> ControlFlow<T> {
685        visit_mut_block(self, block)
686    }
687    fn visit_mut_op(&mut self, op: &mut Op) -> ControlFlow<T> {
688        visit_mut_op(self, op)
689    }
690    fn visit_mut_inst(&mut self, inst: &mut Span<Instruction>) -> ControlFlow<T> {
691        visit_mut_inst(self, inst)
692    }
693    fn visit_mut_system_event(&mut self, sys_event: Span<&mut SystemEventNode>) -> ControlFlow<T> {
694        visit_mut_system_event(self, sys_event)
695    }
696
697    fn visit_mut_exec(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
698        visit_mut_exec(self, target)
699    }
700    fn visit_mut_call(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
701        visit_mut_call(self, target)
702    }
703    fn visit_mut_syscall(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
704        visit_mut_syscall(self, target)
705    }
706    fn visit_mut_procref(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
707        visit_mut_procref(self, target)
708    }
709    fn visit_mut_invoke_target(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
710        visit_mut_invoke_target(self, target)
711    }
712    fn visit_mut_immediate_u8(&mut self, imm: &mut Immediate<u8>) -> ControlFlow<T> {
713        visit_mut_immediate_u8(self, imm)
714    }
715    fn visit_mut_immediate_u16(&mut self, imm: &mut Immediate<u16>) -> ControlFlow<T> {
716        visit_mut_immediate_u16(self, imm)
717    }
718    fn visit_mut_immediate_u32(&mut self, imm: &mut Immediate<u32>) -> ControlFlow<T> {
719        visit_mut_immediate_u32(self, imm)
720    }
721    fn visit_mut_immediate_felt(&mut self, imm: &mut Immediate<Felt>) -> ControlFlow<T> {
722        visit_mut_immediate_felt(self, imm)
723    }
724    fn visit_mut_immediate_word_value(&mut self, imm: &mut Immediate<WordValue>) -> ControlFlow<T> {
725        visit_mut_immediate_word_value(self, imm)
726    }
727    fn visit_mut_immediate_push_value(&mut self, imm: &mut Immediate<PushValue>) -> ControlFlow<T> {
728        visit_mut_immediate_push_value(self, imm)
729    }
730    fn visit_mut_immediate_error_message(&mut self, code: &mut ErrorMsg) -> ControlFlow<T> {
731        visit_mut_immediate_error_message(self, code)
732    }
733}
734
735impl<V, T> VisitMut<T> for &mut V
736where
737    V: ?Sized + VisitMut<T>,
738{
739    fn visit_mut_module(&mut self, module: &mut Module) -> ControlFlow<T> {
740        (**self).visit_mut_module(module)
741    }
742    fn visit_mut_import(&mut self, import: &mut Import) -> ControlFlow<T> {
743        (**self).visit_mut_import(import)
744    }
745    fn visit_mut_export(&mut self, export: &mut Item) -> ControlFlow<T> {
746        (**self).visit_mut_export(export)
747    }
748    fn visit_mut_procedure(&mut self, procedure: &mut Procedure) -> ControlFlow<T> {
749        (**self).visit_mut_procedure(procedure)
750    }
751    fn visit_mut_constant(&mut self, constant: &mut Constant) -> ControlFlow<T> {
752        (**self).visit_mut_constant(constant)
753    }
754    fn visit_mut_constant_expr(&mut self, expr: &mut ConstantExpr) -> ControlFlow<T> {
755        (**self).visit_mut_constant_expr(expr)
756    }
757    fn visit_mut_constant_ref(&mut self, path: &mut Span<Arc<Path>>) -> ControlFlow<T> {
758        (**self).visit_mut_constant_ref(path)
759    }
760    fn visit_mut_type_decl(&mut self, ty: &mut TypeDecl) -> ControlFlow<T> {
761        (**self).visit_mut_type_decl(ty)
762    }
763    fn visit_mut_type_alias(&mut self, ty: &mut TypeAlias) -> ControlFlow<T> {
764        (**self).visit_mut_type_alias(ty)
765    }
766    fn visit_mut_type_expr(&mut self, ty: &mut TypeExpr) -> ControlFlow<T> {
767        (**self).visit_mut_type_expr(ty)
768    }
769    fn visit_mut_type_ref(&mut self, path: &mut Span<Arc<Path>>) -> ControlFlow<T> {
770        (**self).visit_mut_type_ref(path)
771    }
772    fn visit_mut_enum(&mut self, ty: &mut EnumType) -> ControlFlow<T> {
773        (**self).visit_mut_enum(ty)
774    }
775    fn visit_mut_enum_variant(&mut self, variant: &mut Variant) -> ControlFlow<T> {
776        (**self).visit_mut_enum_variant(variant)
777    }
778    fn visit_mut_block(&mut self, block: &mut Block) -> ControlFlow<T> {
779        (**self).visit_mut_block(block)
780    }
781    fn visit_mut_op(&mut self, op: &mut Op) -> ControlFlow<T> {
782        (**self).visit_mut_op(op)
783    }
784    fn visit_mut_inst(&mut self, inst: &mut Span<Instruction>) -> ControlFlow<T> {
785        (**self).visit_mut_inst(inst)
786    }
787    fn visit_mut_system_event(&mut self, sys_event: Span<&mut SystemEventNode>) -> ControlFlow<T> {
788        (**self).visit_mut_system_event(sys_event)
789    }
790
791    fn visit_mut_exec(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
792        (**self).visit_mut_exec(target)
793    }
794    fn visit_mut_call(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
795        (**self).visit_mut_call(target)
796    }
797    fn visit_mut_syscall(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
798        (**self).visit_mut_syscall(target)
799    }
800    fn visit_mut_procref(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
801        (**self).visit_mut_procref(target)
802    }
803    fn visit_mut_invoke_target(&mut self, target: &mut InvocationTarget) -> ControlFlow<T> {
804        (**self).visit_mut_invoke_target(target)
805    }
806    fn visit_mut_immediate_u8(&mut self, imm: &mut Immediate<u8>) -> ControlFlow<T> {
807        (**self).visit_mut_immediate_u8(imm)
808    }
809    fn visit_mut_immediate_u16(&mut self, imm: &mut Immediate<u16>) -> ControlFlow<T> {
810        (**self).visit_mut_immediate_u16(imm)
811    }
812    fn visit_mut_immediate_u32(&mut self, imm: &mut Immediate<u32>) -> ControlFlow<T> {
813        (**self).visit_mut_immediate_u32(imm)
814    }
815    fn visit_mut_immediate_felt(&mut self, imm: &mut Immediate<Felt>) -> ControlFlow<T> {
816        (**self).visit_mut_immediate_felt(imm)
817    }
818    fn visit_mut_immediate_word_value(&mut self, imm: &mut Immediate<WordValue>) -> ControlFlow<T> {
819        (**self).visit_mut_immediate_word_value(imm)
820    }
821    fn visit_mut_immediate_push_value(&mut self, imm: &mut Immediate<PushValue>) -> ControlFlow<T> {
822        (**self).visit_mut_immediate_push_value(imm)
823    }
824    fn visit_mut_immediate_error_message(&mut self, code: &mut ErrorMsg) -> ControlFlow<T> {
825        (**self).visit_mut_immediate_error_message(code)
826    }
827}
828
829pub fn visit_mut_module<V, T>(visitor: &mut V, module: &mut Module) -> ControlFlow<T>
830where
831    V: ?Sized + VisitMut<T>,
832{
833    for export in module.items_mut() {
834        visitor.visit_mut_export(export)?;
835    }
836
837    ControlFlow::Continue(())
838}
839
840#[inline(always)]
841pub fn visit_mut_import<V, T>(_visitor: &mut V, _import: &mut Import) -> ControlFlow<T>
842where
843    V: ?Sized + VisitMut<T>,
844{
845    ControlFlow::Continue(())
846}
847
848pub fn visit_mut_export<V, T>(visitor: &mut V, export: &mut Item) -> ControlFlow<T>
849where
850    V: ?Sized + VisitMut<T>,
851{
852    match export {
853        Item::Procedure(item) => visitor.visit_mut_procedure(item),
854        Item::Constant(item) => visitor.visit_mut_constant(item),
855        Item::Type(item) => visitor.visit_mut_type_decl(item),
856    }
857}
858
859pub fn visit_mut_procedure<V, T>(visitor: &mut V, procedure: &mut Procedure) -> ControlFlow<T>
860where
861    V: ?Sized + VisitMut<T>,
862{
863    if let Some(signature) = procedure.signature_mut() {
864        for ty in signature.args.iter_mut().chain(signature.results.iter_mut()) {
865            visitor.visit_mut_type_expr(ty)?;
866        }
867    }
868    visitor.visit_mut_block(procedure.body_mut())
869}
870
871#[inline(always)]
872pub fn visit_mut_constant<V, T>(visitor: &mut V, constant: &mut Constant) -> ControlFlow<T>
873where
874    V: ?Sized + VisitMut<T>,
875{
876    visitor.visit_mut_constant_expr(&mut constant.value)
877}
878
879pub fn visit_mut_constant_expr<V, T>(visitor: &mut V, expr: &mut ConstantExpr) -> ControlFlow<T>
880where
881    V: ?Sized + VisitMut<T>,
882{
883    match expr {
884        ConstantExpr::Var(path) => visitor.visit_mut_constant_ref(path),
885        ConstantExpr::BinaryOp { lhs, rhs, .. } => {
886            visitor.visit_mut_constant_expr(lhs)?;
887            visitor.visit_mut_constant_expr(rhs)
888        },
889        ConstantExpr::Hash(..)
890        | ConstantExpr::Int(_)
891        | ConstantExpr::String(_)
892        | ConstantExpr::Word(_) => ControlFlow::Continue(()),
893    }
894}
895
896#[inline(always)]
897pub fn visit_mut_constant_ref<V, T>(_visitor: &mut V, _path: &mut Span<Arc<Path>>) -> ControlFlow<T>
898where
899    V: ?Sized + VisitMut<T>,
900{
901    ControlFlow::Continue(())
902}
903
904pub fn visit_mut_type_decl<V, T>(visitor: &mut V, ty: &mut TypeDecl) -> ControlFlow<T>
905where
906    V: ?Sized + VisitMut<T>,
907{
908    match ty {
909        TypeDecl::Alias(ty) => visitor.visit_mut_type_alias(ty),
910        TypeDecl::Enum(ty) => visitor.visit_mut_enum(ty),
911    }
912}
913
914pub fn visit_mut_type_alias<V, T>(visitor: &mut V, ty: &mut TypeAlias) -> ControlFlow<T>
915where
916    V: ?Sized + VisitMut<T>,
917{
918    visitor.visit_mut_type_expr(&mut ty.ty)
919}
920
921pub fn visit_mut_type_expr<V, T>(visitor: &mut V, ty: &mut TypeExpr) -> ControlFlow<T>
922where
923    V: ?Sized + VisitMut<T>,
924{
925    match ty {
926        TypeExpr::Ref(path) => visitor.visit_mut_type_ref(path),
927        TypeExpr::Primitive(_) => ControlFlow::Continue(()),
928        TypeExpr::Array(ty) => visitor.visit_mut_type_expr(&mut ty.elem),
929        TypeExpr::Ptr(ty) => visitor.visit_mut_type_expr(&mut ty.pointee),
930        TypeExpr::Struct(ty) => {
931            for field in ty.fields.iter_mut() {
932                visitor.visit_mut_type_expr(&mut field.ty)?;
933            }
934            ControlFlow::Continue(())
935        },
936    }
937}
938
939#[inline(always)]
940pub fn visit_mut_type_ref<V, T>(_visitor: &mut V, _path: &mut Span<Arc<Path>>) -> ControlFlow<T>
941where
942    V: ?Sized + VisitMut<T>,
943{
944    ControlFlow::Continue(())
945}
946
947pub fn visit_mut_enum<V, T>(visitor: &mut V, ty: &mut EnumType) -> ControlFlow<T>
948where
949    V: ?Sized + VisitMut<T>,
950{
951    for variant in ty.variants_mut() {
952        visitor.visit_mut_enum_variant(variant)?;
953    }
954    ControlFlow::Continue(())
955}
956
957pub fn visit_mut_enum_variant<V, T>(visitor: &mut V, variant: &mut Variant) -> ControlFlow<T>
958where
959    V: ?Sized + VisitMut<T>,
960{
961    visitor.visit_mut_constant_expr(&mut variant.discriminant)?;
962    if let Some(value_ty) = variant.value_ty.as_mut() {
963        visitor.visit_mut_type_expr(value_ty)
964    } else {
965        ControlFlow::Continue(())
966    }
967}
968
969pub fn visit_mut_block<V, T>(visitor: &mut V, block: &mut Block) -> ControlFlow<T>
970where
971    V: ?Sized + VisitMut<T>,
972{
973    for op in block.iter_mut() {
974        visitor.visit_mut_op(op)?;
975    }
976    ControlFlow::Continue(())
977}
978
979pub fn visit_mut_op<V, T>(visitor: &mut V, op: &mut Op) -> ControlFlow<T>
980where
981    V: ?Sized + VisitMut<T>,
982{
983    match op {
984        Op::If { then_blk, else_blk, .. } => {
985            visitor.visit_mut_block(then_blk)?;
986            visitor.visit_mut_block(else_blk)
987        },
988        Op::While { body, .. } => visitor.visit_mut_block(body),
989        Op::DoWhile { body, condition, .. } => {
990            visitor.visit_mut_block(body)?;
991            visitor.visit_mut_block(condition)
992        },
993        Op::Inst(inst) => visitor.visit_mut_inst(inst),
994        Op::Repeat { count, body, .. } => {
995            visitor.visit_mut_immediate_u32(count)?;
996            visitor.visit_mut_block(body)
997        },
998    }
999}
1000
1001pub fn visit_mut_inst<V, T>(visitor: &mut V, inst: &mut Span<Instruction>) -> ControlFlow<T>
1002where
1003    V: ?Sized + VisitMut<T>,
1004{
1005    use Instruction::*;
1006    let span = inst.span();
1007    match &mut **inst {
1008        U32ShrImm(imm) | U32ShlImm(imm) | U32RotrImm(imm) | U32RotlImm(imm) => {
1009            visitor.visit_mut_immediate_u8(imm)
1010        },
1011        Locaddr(imm) | LocLoad(imm) | LocLoadWBe(imm) | LocLoadWLe(imm) | LocStore(imm)
1012        | LocStoreWBe(imm) | LocStoreWLe(imm) => visitor.visit_mut_immediate_u16(imm),
1013        AssertWithError(code)
1014        | AssertEqWithError(code)
1015        | AssertEqwWithError(code)
1016        | AssertzWithError(code)
1017        | U32AssertWithError(code)
1018        | U32Assert2WithError(code)
1019        | U32AssertWWithError(code)
1020        | MTreeVerifyWithError(code) => visitor.visit_mut_immediate_error_message(code),
1021        AddImm(imm) | SubImm(imm) | MulImm(imm) | DivImm(imm) | ExpImm(imm) | EqImm(imm)
1022        | NeqImm(imm) | LtImm(imm) | LteImm(imm) | GtImm(imm) | GteImm(imm) => {
1023            visitor.visit_mut_immediate_felt(imm)
1024        },
1025        Push(imm) => visitor.visit_mut_immediate_push_value(imm),
1026        PushSlice(imm, _) => visitor.visit_mut_immediate_word_value(imm),
1027        U32WrappingAddImm(imm)
1028        | U32OverflowingAddImm(imm)
1029        | U32WideningAddImm(imm)
1030        | U32WrappingSubImm(imm)
1031        | U32OverflowingSubImm(imm)
1032        | U32WrappingMulImm(imm)
1033        | U32WideningMulImm(imm)
1034        | U32DivImm(imm)
1035        | U32ModImm(imm)
1036        | U32DivModImm(imm)
1037        | MemLoadImm(imm)
1038        | MemLoadWBeImm(imm)
1039        | MemLoadWLeImm(imm)
1040        | MemStoreImm(imm)
1041        | MemStoreWBeImm(imm)
1042        | MemStoreWLeImm(imm) => visitor.visit_mut_immediate_u32(imm),
1043        EmitImm(imm) => visitor.visit_mut_immediate_felt(imm),
1044        SysEvent(sys_event) => visitor.visit_mut_system_event(Span::new(span, sys_event)),
1045        Exec(target) => visitor.visit_mut_exec(target),
1046        Call(target) => visitor.visit_mut_call(target),
1047        SysCall(target) => visitor.visit_mut_syscall(target),
1048        ProcRef(target) => visitor.visit_mut_procref(target),
1049
1050        Nop | Assert | AssertEq | AssertEqw | Assertz | Add | Sub | Mul | Div | Neg | ILog2
1051        | Inv | Incr | Pow2 | Exp | ExpBitLength(_) | Not | And | Or | Xor | Eq | Neq | Eqw
1052        | Lt | Lte | Gt | Gte | IsOdd | Ext2Add | Ext2Sub | Ext2Mul | Ext2Div | Ext2Neg
1053        | Ext2Inv | U32Test | U32TestW | U32Assert | U32Assert2 | U32AssertW | U32Split
1054        | U32Cast | U32WrappingAdd | U32OverflowingAdd | U32WideningAdd | U32OverflowingAdd3
1055        | U32WideningAdd3 | U32WrappingAdd3 | U32WrappingSub | U32OverflowingSub
1056        | U32WrappingMul | U32WideningMul | U32WideningMadd | U32WrappingMadd | U32Div | U32Mod
1057        | U32DivMod | U32And | U32Or | U32Xor | U32Not | U32Shr | U32Shl | U32Rotr | U32Rotl
1058        | U32Popcnt | U32Clz | U32Ctz | U32Clo | U32Cto | U32Lt | U32Lte | U32Gt | U32Gte
1059        | U32Min | U32Max | Drop | DropW | PadW | Dup0 | Dup1 | Dup2 | Dup3 | Dup4 | Dup5
1060        | Dup6 | Dup7 | Dup8 | Dup9 | Dup10 | Dup11 | Dup12 | Dup13 | Dup14 | Dup15 | DupW0
1061        | DupW1 | DupW2 | DupW3 | Swap1 | Swap2 | Swap3 | Swap4 | Swap5 | Swap6 | Swap7 | Swap8
1062        | Swap9 | Swap10 | Swap11 | Swap12 | Swap13 | Swap14 | Swap15 | SwapW1 | SwapW2
1063        | SwapW3 | SwapDw | MovUp2 | MovUp3 | MovUp4 | MovUp5 | MovUp6 | MovUp7 | MovUp8
1064        | MovUp9 | MovUp10 | MovUp11 | MovUp12 | MovUp13 | MovUp14 | MovUp15 | MovUpW2
1065        | MovUpW3 | MovDn2 | MovDn3 | MovDn4 | MovDn5 | MovDn6 | MovDn7 | MovDn8 | MovDn9
1066        | MovDn10 | MovDn11 | MovDn12 | MovDn13 | MovDn14 | MovDn15 | MovDnW2 | MovDnW3
1067        | Reversew | Reversedw | CSwap | CSwapW | CDrop | CDropW | PushFeltList(_) | Sdepth
1068        | Caller | Clk | MemLoad | MemLoadWBe | MemLoadWLe | MemStore | MemStoreWBe
1069        | MemStoreWLe | MemStream | AdvPipe | AdvPush | AdvPushW | AdvLoadW | Hash | HMerge
1070        | HPerm | MTreeGet | MTreeSet | MTreeMerge | MTreeVerify | FriExt2Fold4 | DynExec
1071        | DynCall | DebugVar(_) | HornerBase | HornerExt | EvalCircuit | CryptoStream
1072        | LogPrecompile | Emit => ControlFlow::Continue(()),
1073    }
1074}
1075
1076pub fn visit_mut_system_event<V, T>(
1077    _visitor: &mut V,
1078    _node: Span<&mut SystemEventNode>,
1079) -> ControlFlow<T>
1080where
1081    V: ?Sized + VisitMut<T>,
1082{
1083    ControlFlow::Continue(())
1084}
1085
1086#[inline]
1087pub fn visit_mut_exec<V, T>(visitor: &mut V, target: &mut InvocationTarget) -> ControlFlow<T>
1088where
1089    V: ?Sized + VisitMut<T>,
1090{
1091    visitor.visit_mut_invoke_target(target)
1092}
1093
1094#[inline]
1095pub fn visit_mut_call<V, T>(visitor: &mut V, target: &mut InvocationTarget) -> ControlFlow<T>
1096where
1097    V: ?Sized + VisitMut<T>,
1098{
1099    visitor.visit_mut_invoke_target(target)
1100}
1101
1102#[inline]
1103pub fn visit_mut_syscall<V, T>(visitor: &mut V, target: &mut InvocationTarget) -> ControlFlow<T>
1104where
1105    V: ?Sized + VisitMut<T>,
1106{
1107    visitor.visit_mut_invoke_target(target)
1108}
1109
1110#[inline]
1111pub fn visit_mut_procref<V, T>(visitor: &mut V, target: &mut InvocationTarget) -> ControlFlow<T>
1112where
1113    V: ?Sized + VisitMut<T>,
1114{
1115    visitor.visit_mut_invoke_target(target)
1116}
1117
1118#[inline(always)]
1119pub fn visit_mut_invoke_target<V, T>(
1120    _visitor: &mut V,
1121    _target: &mut InvocationTarget,
1122) -> ControlFlow<T>
1123where
1124    V: ?Sized + VisitMut<T>,
1125{
1126    ControlFlow::Continue(())
1127}
1128
1129#[inline(always)]
1130pub fn visit_mut_immediate_u8<V, T>(_visitor: &mut V, _imm: &mut Immediate<u8>) -> ControlFlow<T>
1131where
1132    V: ?Sized + VisitMut<T>,
1133{
1134    ControlFlow::Continue(())
1135}
1136
1137#[inline(always)]
1138pub fn visit_mut_immediate_u16<V, T>(_visitor: &mut V, _imm: &mut Immediate<u16>) -> ControlFlow<T>
1139where
1140    V: ?Sized + VisitMut<T>,
1141{
1142    ControlFlow::Continue(())
1143}
1144
1145#[inline(always)]
1146pub fn visit_mut_immediate_u32<V, T>(_visitor: &mut V, _imm: &mut Immediate<u32>) -> ControlFlow<T>
1147where
1148    V: ?Sized + VisitMut<T>,
1149{
1150    ControlFlow::Continue(())
1151}
1152
1153#[inline(always)]
1154pub fn visit_mut_immediate_felt<V, T>(
1155    _visitor: &mut V,
1156    _imm: &mut Immediate<Felt>,
1157) -> ControlFlow<T>
1158where
1159    V: ?Sized + VisitMut<T>,
1160{
1161    ControlFlow::Continue(())
1162}
1163
1164#[inline(always)]
1165pub fn visit_mut_immediate_word_value<V, T>(
1166    _visitor: &mut V,
1167    _imm: &mut Immediate<WordValue>,
1168) -> ControlFlow<T>
1169where
1170    V: ?Sized + VisitMut<T>,
1171{
1172    ControlFlow::Continue(())
1173}
1174
1175#[inline(always)]
1176pub fn visit_mut_immediate_push_value<V, T>(
1177    _visitor: &mut V,
1178    _imm: &mut Immediate<PushValue>,
1179) -> ControlFlow<T>
1180where
1181    V: ?Sized + VisitMut<T>,
1182{
1183    ControlFlow::Continue(())
1184}
1185
1186#[inline(always)]
1187pub fn visit_mut_immediate_error_message<V, T>(
1188    _visitor: &mut V,
1189    _imm: &mut ErrorMsg,
1190) -> ControlFlow<T>
1191where
1192    V: ?Sized + VisitMut<T>,
1193{
1194    ControlFlow::Continue(())
1195}