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