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