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(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
75pub(in crate::mast) enum MastNodeOrderClass {
76 External,
77 BasicBlock,
78 Internal,
79}
80
81#[derive(Debug, Clone, PartialEq, Eq, From, MastNodeExt)]
82#[mast_node_ext(builder = "MastNodeBuilder")]
83pub enum MastNode {
84 Block(BasicBlockNode),
85 Join(JoinNode),
86 Split(SplitNode),
87 Loop(LoopNode),
88 Call(CallNode),
89 Dyn(DynNode),
90 External(ExternalNode),
91}
92
93impl MastNode {
96 pub(in crate::mast) fn order_class(&self) -> MastNodeOrderClass {
98 if self.is_external() {
99 MastNodeOrderClass::External
100 } else if self.is_basic_block() {
101 MastNodeOrderClass::BasicBlock
102 } else {
103 MastNodeOrderClass::Internal
104 }
105 }
106
107 pub fn is_external(&self) -> bool {
109 matches!(self, MastNode::External(_))
110 }
111
112 pub fn is_dyn(&self) -> bool {
114 matches!(self, MastNode::Dyn(_))
115 }
116
117 pub fn is_basic_block(&self) -> bool {
119 matches!(self, Self::Block(_))
120 }
121
122 pub fn get_basic_block(&self) -> Option<&BasicBlockNode> {
125 match self {
126 MastNode::Block(basic_block_node) => Some(basic_block_node),
127 _ => None,
128 }
129 }
130
131 pub fn unwrap_basic_block(&self) -> &BasicBlockNode {
137 match self {
138 Self::Block(basic_block_node) => basic_block_node,
139 other => unwrap_failed(other, "basic block"),
140 }
141 }
142
143 pub fn unwrap_join(&self) -> &JoinNode {
148 match self {
149 Self::Join(join_node) => join_node,
150 other => unwrap_failed(other, "join"),
151 }
152 }
153
154 pub fn unwrap_split(&self) -> &SplitNode {
159 match self {
160 Self::Split(split_node) => split_node,
161 other => unwrap_failed(other, "split"),
162 }
163 }
164
165 pub fn unwrap_loop(&self) -> &LoopNode {
170 match self {
171 Self::Loop(loop_node) => loop_node,
172 other => unwrap_failed(other, "loop"),
173 }
174 }
175
176 pub fn unwrap_call(&self) -> &CallNode {
181 match self {
182 Self::Call(call_node) => call_node,
183 other => unwrap_failed(other, "call"),
184 }
185 }
186
187 pub fn unwrap_dyn(&self) -> &DynNode {
192 match self {
193 Self::Dyn(dyn_node) => dyn_node,
194 other => unwrap_failed(other, "dyn"),
195 }
196 }
197
198 pub fn unwrap_external(&self) -> &ExternalNode {
204 match self {
205 Self::External(external_node) => external_node,
206 other => unwrap_failed(other, "external"),
207 }
208 }
209}
210
211#[cold]
217#[inline(never)]
218#[track_caller]
219fn unwrap_failed(node: &MastNode, expected: &str) -> ! {
220 let actual = match node {
221 MastNode::Block(_) => "basic block",
222 MastNode::Join(_) => "join",
223 MastNode::Split(_) => "split",
224 MastNode::Loop(_) => "loop",
225 MastNode::Call(_) => "call",
226 MastNode::Dyn(_) => "dynamic",
227 MastNode::External(_) => "external",
228 };
229 panic!("tried to unwrap {expected} node, but got {actual}");
230}