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