miden_core/mast/node/
external.rs1use alloc::vec::Vec;
2use core::fmt;
3
4use miden_crypto::hash::rpo::RpoDigest;
5use miden_formatting::{
6 hex::ToHex,
7 prettier::{Document, PrettyPrint, const_text, nl, text},
8};
9
10use super::MastNodeExt;
11use crate::mast::{DecoratorId, MastForest};
12
13#[derive(Clone, Debug, PartialEq, Eq)]
25pub struct ExternalNode {
26 digest: RpoDigest,
27 before_enter: Vec<DecoratorId>,
28 after_exit: Vec<DecoratorId>,
29}
30
31impl ExternalNode {
32 pub fn new(procedure_hash: RpoDigest) -> Self {
34 Self {
35 digest: procedure_hash,
36 before_enter: Vec::new(),
37 after_exit: Vec::new(),
38 }
39 }
40}
41
42impl ExternalNode {
43 pub fn digest(&self) -> RpoDigest {
45 self.digest
46 }
47
48 pub fn before_enter(&self) -> &[DecoratorId] {
50 &self.before_enter
51 }
52
53 pub fn after_exit(&self) -> &[DecoratorId] {
55 &self.after_exit
56 }
57}
58
59impl ExternalNode {
61 pub fn append_before_enter(&mut self, decorator_ids: &[DecoratorId]) {
63 self.before_enter.extend_from_slice(decorator_ids);
64 }
65
66 pub fn append_after_exit(&mut self, decorator_ids: &[DecoratorId]) {
68 self.after_exit.extend_from_slice(decorator_ids);
69 }
70}
71
72impl MastNodeExt for ExternalNode {
73 fn decorators(&self) -> impl Iterator<Item = (usize, DecoratorId)> {
74 self.before_enter.iter().chain(&self.after_exit).copied().enumerate()
75 }
76}
77
78impl ExternalNode {
82 pub(super) fn to_display<'a>(&'a self, mast_forest: &'a MastForest) -> impl fmt::Display + 'a {
83 ExternalNodePrettyPrint { node: self, mast_forest }
84 }
85
86 pub(super) fn to_pretty_print<'a>(
87 &'a self,
88 mast_forest: &'a MastForest,
89 ) -> impl PrettyPrint + 'a {
90 ExternalNodePrettyPrint { node: self, mast_forest }
91 }
92}
93
94struct ExternalNodePrettyPrint<'a> {
95 node: &'a ExternalNode,
96 mast_forest: &'a MastForest,
97}
98
99impl ExternalNodePrettyPrint<'_> {
100 fn concatenate_decorators(
103 &self,
104 decorator_ids: &[DecoratorId],
105 prepend: Document,
106 append: Document,
107 ) -> Document {
108 let decorators = decorator_ids
109 .iter()
110 .map(|&decorator_id| self.mast_forest[decorator_id].render())
111 .reduce(|acc, doc| acc + const_text(" ") + doc)
112 .unwrap_or_default();
113
114 if decorators.is_empty() {
115 decorators
116 } else {
117 prepend + decorators + append
118 }
119 }
120
121 fn single_line_pre_decorators(&self) -> Document {
122 self.concatenate_decorators(self.node.before_enter(), Document::Empty, const_text(" "))
123 }
124
125 fn single_line_post_decorators(&self) -> Document {
126 self.concatenate_decorators(self.node.after_exit(), const_text(" "), Document::Empty)
127 }
128
129 fn multi_line_pre_decorators(&self) -> Document {
130 self.concatenate_decorators(self.node.before_enter(), Document::Empty, nl())
131 }
132
133 fn multi_line_post_decorators(&self) -> Document {
134 self.concatenate_decorators(self.node.after_exit(), nl(), Document::Empty)
135 }
136}
137
138impl crate::prettier::PrettyPrint for ExternalNodePrettyPrint<'_> {
139 fn render(&self) -> crate::prettier::Document {
140 let external = const_text("external")
141 + const_text(".")
142 + text(self.node.digest.as_bytes().to_hex_with_prefix());
143
144 let single_line = self.single_line_pre_decorators()
145 + external.clone()
146 + self.single_line_post_decorators();
147 let multi_line =
148 self.multi_line_pre_decorators() + external + self.multi_line_post_decorators();
149
150 single_line | multi_line
151 }
152}
153
154impl fmt::Display for ExternalNodePrettyPrint<'_> {
155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
156 use crate::prettier::PrettyPrint;
157 self.pretty_print(f)
158 }
159}