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};
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 fn is_external(&self) -> bool {
91 matches!(self, MastNode::External(_))
92 }
93
94 pub fn is_dyn(&self) -> bool {
96 matches!(self, MastNode::Dyn(_))
97 }
98
99 pub fn is_basic_block(&self) -> bool {
101 matches!(self, Self::Block(_))
102 }
103
104 pub fn get_basic_block(&self) -> Option<&BasicBlockNode> {
107 match self {
108 MastNode::Block(basic_block_node) => Some(basic_block_node),
109 _ => None,
110 }
111 }
112
113 pub fn unwrap_basic_block(&self) -> &BasicBlockNode {
119 match self {
120 Self::Block(basic_block_node) => basic_block_node,
121 other => unwrap_failed(other, "basic block"),
122 }
123 }
124
125 pub fn unwrap_join(&self) -> &JoinNode {
130 match self {
131 Self::Join(join_node) => join_node,
132 other => unwrap_failed(other, "join"),
133 }
134 }
135
136 pub fn unwrap_split(&self) -> &SplitNode {
141 match self {
142 Self::Split(split_node) => split_node,
143 other => unwrap_failed(other, "split"),
144 }
145 }
146
147 pub fn unwrap_loop(&self) -> &LoopNode {
152 match self {
153 Self::Loop(loop_node) => loop_node,
154 other => unwrap_failed(other, "loop"),
155 }
156 }
157
158 pub fn unwrap_call(&self) -> &CallNode {
163 match self {
164 Self::Call(call_node) => call_node,
165 other => unwrap_failed(other, "call"),
166 }
167 }
168
169 pub fn unwrap_dyn(&self) -> &DynNode {
174 match self {
175 Self::Dyn(dyn_node) => dyn_node,
176 other => unwrap_failed(other, "dyn"),
177 }
178 }
179
180 pub fn unwrap_external(&self) -> &ExternalNode {
186 match self {
187 Self::External(external_node) => external_node,
188 other => unwrap_failed(other, "external"),
189 }
190 }
191}
192
193#[cold]
199#[inline(never)]
200#[track_caller]
201fn unwrap_failed(node: &MastNode, expected: &str) -> ! {
202 let actual = match node {
203 MastNode::Block(_) => "basic block",
204 MastNode::Join(_) => "join",
205 MastNode::Split(_) => "split",
206 MastNode::Loop(_) => "loop",
207 MastNode::Call(_) => "call",
208 MastNode::Dyn(_) => "dynamic",
209 MastNode::External(_) => "external",
210 };
211 panic!("tried to unwrap {expected} node, but got {actual}");
212}