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,
8 GROUP_SIZE as OP_GROUP_SIZE, OpBatch,
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(super) use mast_forest_contributor::fingerprint_with_child_fingerprints;
37pub use mast_forest_contributor::{MastForestContributor, MastNodeBuilder, MastNodeContext};
38
39use crate::mast::{MastForest, MastNodeId};
40
41pub trait MastNodeExt {
42 fn digest(&self) -> Word;
44
45 fn to_display<'a>(&'a self, mast_forest: &'a MastForest) -> Box<dyn fmt::Display + 'a>;
47
48 fn to_pretty_print<'a>(&'a self, mast_forest: &'a MastForest) -> Box<dyn PrettyPrint + 'a>;
50
51 fn has_children(&self) -> bool;
53
54 fn append_children_to(&self, target: &mut Vec<MastNodeId>);
56
57 fn for_each_child<F>(&self, f: F)
59 where
60 F: FnMut(MastNodeId);
61
62 fn domain(&self) -> Felt;
64
65 type Builder: MastForestContributor;
67
68 fn to_builder(self, forest: &MastForest) -> Self::Builder;
69}
70
71#[derive(Debug, Clone, PartialEq, Eq, From, MastNodeExt)]
75#[mast_node_ext(builder = "MastNodeBuilder")]
76pub enum MastNode {
77 Block(BasicBlockNode),
78 Join(JoinNode),
79 Split(SplitNode),
80 Loop(LoopNode),
81 Call(CallNode),
82 Dyn(DynNode),
83 External(ExternalNode),
84}
85
86impl MastNode {
89 pub(in crate::mast) fn order_class(&self) -> super::MastNodeOrderClass {
91 if self.is_external() {
92 super::MastNodeOrderClass::External
93 } else if self.is_basic_block() {
94 super::MastNodeOrderClass::BasicBlock
95 } else {
96 super::MastNodeOrderClass::Internal
97 }
98 }
99
100 pub fn is_external(&self) -> bool {
102 matches!(self, MastNode::External(_))
103 }
104
105 pub fn is_dyn(&self) -> bool {
107 matches!(self, MastNode::Dyn(_))
108 }
109
110 pub fn is_basic_block(&self) -> bool {
112 matches!(self, Self::Block(_))
113 }
114
115 pub fn get_basic_block(&self) -> Option<&BasicBlockNode> {
118 match self {
119 MastNode::Block(basic_block_node) => Some(basic_block_node),
120 _ => None,
121 }
122 }
123
124 pub fn unwrap_basic_block(&self) -> &BasicBlockNode {
130 match self {
131 Self::Block(basic_block_node) => basic_block_node,
132 other => unwrap_failed(other, "basic block"),
133 }
134 }
135
136 pub fn unwrap_join(&self) -> &JoinNode {
141 match self {
142 Self::Join(join_node) => join_node,
143 other => unwrap_failed(other, "join"),
144 }
145 }
146
147 pub fn unwrap_split(&self) -> &SplitNode {
152 match self {
153 Self::Split(split_node) => split_node,
154 other => unwrap_failed(other, "split"),
155 }
156 }
157
158 pub fn unwrap_loop(&self) -> &LoopNode {
163 match self {
164 Self::Loop(loop_node) => loop_node,
165 other => unwrap_failed(other, "loop"),
166 }
167 }
168
169 pub fn unwrap_call(&self) -> &CallNode {
174 match self {
175 Self::Call(call_node) => call_node,
176 other => unwrap_failed(other, "call"),
177 }
178 }
179
180 pub fn unwrap_dyn(&self) -> &DynNode {
185 match self {
186 Self::Dyn(dyn_node) => dyn_node,
187 other => unwrap_failed(other, "dyn"),
188 }
189 }
190
191 pub fn unwrap_external(&self) -> &ExternalNode {
197 match self {
198 Self::External(external_node) => external_node,
199 other => unwrap_failed(other, "external"),
200 }
201 }
202}
203
204#[cold]
210#[inline(never)]
211#[track_caller]
212fn unwrap_failed(node: &MastNode, expected: &str) -> ! {
213 let actual = match node {
214 MastNode::Block(_) => "basic block",
215 MastNode::Join(_) => "join",
216 MastNode::Split(_) => "split",
217 MastNode::Loop(_) => "loop",
218 MastNode::Call(_) => "call",
219 MastNode::Dyn(_) => "dynamic",
220 MastNode::External(_) => "external",
221 };
222 panic!("tried to unwrap {expected} node, but got {actual}");
223}