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