Expand description
This module provides an implementation of the visitor pattern for the AST of Miden Assembly.
The pattern is implemented in terms of two traits, Visit and VisitMut, corresponding to
whether or not the visitor has mutable access to each AST node.
In addition to the visitor traits, there are a number of free functions that correspond to the
methods of those traits. For example, the visit methods for a Procedure are
Visit::visit_procedure and VisitMut::visit_mut_procedure. There are two free functions that
are used in conjunction with these methods: visit_procedure, and visit_mut_procedure, which
are typically not imported directly, but are referenced through the visit module, e.g.
visit::visit_procedure. These free functions implement the default visitor for the AST node
they correspond to. By default, all methods of the Visit and VisitMut traits delegate to
these functions. As a result, impl Visit for MyVisitor {} is technically a valid visitor, and
will traverse the entire AST if invoked.
Obviously, that visitor wouldn’t be very useful, but in practice, the free functions are called to resume traversal of the AST either before or after executing the desired behavior for a given AST node. Doing so essentially corresponds to either a post- or preorder traversal of the AST respectively.
How do you choose between performing a postorder vs preorder visit? It depends on the semantics of the visitor, but here are some examples:
-
When implementing a visitor that performs constant folding/propagation, you need to visit the operands of an expression before the operator, in order to determine whether it is possible to fold, and if so, what the actual values of the operands are. As a result, this is implemented as a postorder visitor, so that the AST node corresponding to the expression is rewritten after all of it’s children.
-
When implementing an analysis based on lexical scope, it is necessary to “push down” context from the root to the leaves of the AST - the context being the contents of each AST nodes inherited scope. As a result, this is implemented as a preorder traversal, so that the context at each node can be computed before visiting the children of that node.
In both cases, the implementor must call the free function corresponding to the current AST node at the appropriate point (i.e. before/after executing the logic for the node), so that the visitor will resume its traversal of the tree correctly. Put another way, failing to do so will cause the traversal to stop at that node (it will continue visiting sibling nodes, if applicable, but it will go no deeper in the tree).
§FAQs
- Why are the free
visitfunctions needed?
Technically they aren’t - you could reimplement the visit pattern for every AST node, in each visitor, independently. However, this is a lot of boilerplate (as you can see below), and would represent a major maintenance burden if the AST changes shape at all. By implementing the default pattern in those free functions, they can be reused everywhere, and a visitor need only override the methods of those nodes it cares about. Changes to the AST only require modifying the code in this module, with the exception of visitors whose logic must be updated to reflect modifications to specific nodes they care about.
Traits§
- Visit
- Represents an immutable AST visitor, whose “early return” type is
T(by default()). - Visit
Mut - Represents a mutable AST visitor, whose “early return” type is
T(by default()).
Functions§
- visit_
alias - visit_
alias_ target - visit_
block - visit_
call - visit_
constant - visit_
constant_ expr - visit_
constant_ ref - visit_
debug_ options - visit_
enum - visit_
enum_ variant - visit_
exec - visit_
export - visit_
immediate_ error_ message - visit_
immediate_ felt - visit_
immediate_ push_ value - visit_
immediate_ u8 - visit_
immediate_ u16 - visit_
immediate_ u32 - visit_
immediate_ word_ value - visit_
inst - visit_
invoke_ target - visit_
module - visit_
mut_ alias - visit_
mut_ alias_ target - visit_
mut_ block - visit_
mut_ call - visit_
mut_ constant - visit_
mut_ constant_ expr - visit_
mut_ constant_ ref - visit_
mut_ debug_ options - visit_
mut_ enum - visit_
mut_ enum_ variant - visit_
mut_ exec - visit_
mut_ export - visit_
mut_ immediate_ error_ message - visit_
mut_ immediate_ felt - visit_
mut_ immediate_ push_ value - visit_
mut_ immediate_ u8 - visit_
mut_ immediate_ u16 - visit_
mut_ immediate_ u32 - visit_
mut_ immediate_ word_ value - visit_
mut_ inst - visit_
mut_ invoke_ target - visit_
mut_ module - visit_
mut_ op - visit_
mut_ procedure - visit_
mut_ procref - visit_
mut_ syscall - visit_
mut_ system_ event - visit_
mut_ type_ alias - visit_
mut_ type_ decl - visit_
mut_ type_ expr - visit_
mut_ type_ ref - visit_
op - visit_
procedure - visit_
procref - visit_
syscall - visit_
system_ event - visit_
type_ alias - visit_
type_ decl - visit_
type_ expr - visit_
type_ ref