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