miden_core/mast/node/
mod.rs1mod basic_block_node;
2use alloc::{boxed::Box, vec::Vec};
3use core::fmt;
4
5pub(crate) use basic_block_node::collect_immediate_placements;
6pub use basic_block_node::{
7 BATCH_SIZE as OP_BATCH_SIZE, BasicBlockNode, BasicBlockNodeBuilder, DecoratorOpLinkIterator,
8 GROUP_SIZE as OP_GROUP_SIZE, OpBatch, OperationOrDecorator,
9};
10use derive_more::From;
11use miden_utils_core_derive::MastNodeExt;
12
13mod call_node;
14pub use call_node::{CallNode, CallNodeBuilder};
15
16mod dyn_node;
17pub use dyn_node::{DynNode, DynNodeBuilder};
18
19mod external;
20pub use external::{ExternalNode, ExternalNodeBuilder};
21
22mod join_node;
23pub use join_node::{JoinNode, JoinNodeBuilder};
24
25mod split_node;
26use miden_crypto::{Felt, Word};
27use miden_formatting::prettier::PrettyPrint;
28pub use split_node::{SplitNode, SplitNodeBuilder};
29
30mod loop_node;
31#[cfg(any(test, feature = "arbitrary"))]
32pub use basic_block_node::arbitrary;
33pub use loop_node::{LoopNode, LoopNodeBuilder};
34
35mod mast_forest_contributor;
36pub use mast_forest_contributor::{MastForestContributor, MastNodeBuilder};
37
38mod decorator_store;
39pub use decorator_store::DecoratorStore;
40
41use super::DecoratorId;
42use crate::mast::{MastForest, MastNodeId};
43
44pub trait MastNodeExt {
45 fn digest(&self) -> Word;
47
48 fn before_enter<'a>(&'a self, forest: &'a MastForest) -> &'a [DecoratorId];
50
51 fn after_exit<'a>(&'a self, forest: &'a MastForest) -> &'a [DecoratorId];
53
54 fn to_display<'a>(&'a self, mast_forest: &'a MastForest) -> Box<dyn fmt::Display + 'a>;
56
57 fn to_pretty_print<'a>(&'a self, mast_forest: &'a MastForest) -> Box<dyn PrettyPrint + 'a>;
59
60 fn has_children(&self) -> bool;
62
63 fn append_children_to(&self, target: &mut Vec<MastNodeId>);
65
66 fn for_each_child<F>(&self, f: F)
68 where
69 F: FnMut(MastNodeId);
70
71 fn domain(&self) -> Felt;
73
74 #[cfg(debug_assertions)]
76 fn verify_node_in_forest(&self, forest: &MastForest);
77
78 type Builder: MastForestContributor;
80
81 fn to_builder(self, forest: &MastForest) -> Self::Builder;
82}
83
84#[derive(Debug, Clone, PartialEq, Eq, From, MastNodeExt)]
88#[mast_node_ext(builder = "MastNodeBuilder")]
89pub enum MastNode {
90 Block(BasicBlockNode),
91 Join(JoinNode),
92 Split(SplitNode),
93 Loop(LoopNode),
94 Call(CallNode),
95 Dyn(DynNode),
96 External(ExternalNode),
97}
98
99impl MastNode {
102 pub fn is_external(&self) -> bool {
104 matches!(self, MastNode::External(_))
105 }
106
107 pub fn is_dyn(&self) -> bool {
109 matches!(self, MastNode::Dyn(_))
110 }
111
112 pub fn is_basic_block(&self) -> bool {
114 matches!(self, Self::Block(_))
115 }
116
117 pub fn get_basic_block(&self) -> Option<&BasicBlockNode> {
120 match self {
121 MastNode::Block(basic_block_node) => Some(basic_block_node),
122 _ => None,
123 }
124 }
125
126 pub fn unwrap_basic_block(&self) -> &BasicBlockNode {
132 match self {
133 Self::Block(basic_block_node) => basic_block_node,
134 other => unwrap_failed(other, "basic block"),
135 }
136 }
137
138 pub fn unwrap_join(&self) -> &JoinNode {
143 match self {
144 Self::Join(join_node) => join_node,
145 other => unwrap_failed(other, "join"),
146 }
147 }
148
149 pub fn unwrap_split(&self) -> &SplitNode {
154 match self {
155 Self::Split(split_node) => split_node,
156 other => unwrap_failed(other, "split"),
157 }
158 }
159
160 pub fn unwrap_loop(&self) -> &LoopNode {
165 match self {
166 Self::Loop(loop_node) => loop_node,
167 other => unwrap_failed(other, "loop"),
168 }
169 }
170
171 pub fn unwrap_call(&self) -> &CallNode {
176 match self {
177 Self::Call(call_node) => call_node,
178 other => unwrap_failed(other, "call"),
179 }
180 }
181
182 pub fn unwrap_dyn(&self) -> &DynNode {
187 match self {
188 Self::Dyn(dyn_node) => dyn_node,
189 other => unwrap_failed(other, "dyn"),
190 }
191 }
192
193 pub fn unwrap_external(&self) -> &ExternalNode {
199 match self {
200 Self::External(external_node) => external_node,
201 other => unwrap_failed(other, "external"),
202 }
203 }
204}
205
206pub type DecoratedOpLink = (usize, DecoratorId);
212
213#[cold]
219#[inline(never)]
220#[track_caller]
221fn unwrap_failed(node: &MastNode, expected: &str) -> ! {
222 let actual = match node {
223 MastNode::Block(_) => "basic block",
224 MastNode::Join(_) => "join",
225 MastNode::Split(_) => "split",
226 MastNode::Loop(_) => "loop",
227 MastNode::Call(_) => "call",
228 MastNode::Dyn(_) => "dynamic",
229 MastNode::External(_) => "external",
230 };
231 panic!("tried to unwrap {expected} node, but got {actual}");
232}