miden_core/mast/node/
external.rs1use alloc::vec::Vec;
2use core::fmt;
3
4use miden_crypto::Word;
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: Word,
27 before_enter: Vec<DecoratorId>,
28 after_exit: Vec<DecoratorId>,
29}
30
31impl ExternalNode {
32 pub fn new(procedure_hash: Word) -> 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) -> Word {
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 {
62 pub fn append_before_enter(&mut self, decorator_ids: &[DecoratorId]) {
64 self.before_enter.extend_from_slice(decorator_ids);
65 }
66
67 pub fn append_after_exit(&mut self, decorator_ids: &[DecoratorId]) {
69 self.after_exit.extend_from_slice(decorator_ids);
70 }
71
72 pub fn remove_decorators(&mut self) {
74 self.before_enter.truncate(0);
75 self.after_exit.truncate(0);
76 }
77}
78
79impl MastNodeExt for ExternalNode {
80 fn decorators(&self) -> impl Iterator<Item = (usize, DecoratorId)> {
81 self.before_enter.iter().chain(&self.after_exit).copied().enumerate()
82 }
83}
84
85impl ExternalNode {
89 pub(super) fn to_display<'a>(&'a self, mast_forest: &'a MastForest) -> impl fmt::Display + 'a {
90 ExternalNodePrettyPrint { node: self, mast_forest }
91 }
92
93 pub(super) fn to_pretty_print<'a>(
94 &'a self,
95 mast_forest: &'a MastForest,
96 ) -> impl PrettyPrint + 'a {
97 ExternalNodePrettyPrint { node: self, mast_forest }
98 }
99}
100
101struct ExternalNodePrettyPrint<'a> {
102 node: &'a ExternalNode,
103 mast_forest: &'a MastForest,
104}
105
106impl ExternalNodePrettyPrint<'_> {
107 fn concatenate_decorators(
110 &self,
111 decorator_ids: &[DecoratorId],
112 prepend: Document,
113 append: Document,
114 ) -> Document {
115 let decorators = decorator_ids
116 .iter()
117 .map(|&decorator_id| self.mast_forest[decorator_id].render())
118 .reduce(|acc, doc| acc + const_text(" ") + doc)
119 .unwrap_or_default();
120
121 if decorators.is_empty() {
122 decorators
123 } else {
124 prepend + decorators + append
125 }
126 }
127
128 fn single_line_pre_decorators(&self) -> Document {
129 self.concatenate_decorators(self.node.before_enter(), Document::Empty, const_text(" "))
130 }
131
132 fn single_line_post_decorators(&self) -> Document {
133 self.concatenate_decorators(self.node.after_exit(), const_text(" "), Document::Empty)
134 }
135
136 fn multi_line_pre_decorators(&self) -> Document {
137 self.concatenate_decorators(self.node.before_enter(), Document::Empty, nl())
138 }
139
140 fn multi_line_post_decorators(&self) -> Document {
141 self.concatenate_decorators(self.node.after_exit(), nl(), Document::Empty)
142 }
143}
144
145impl crate::prettier::PrettyPrint for ExternalNodePrettyPrint<'_> {
146 fn render(&self) -> crate::prettier::Document {
147 let external = const_text("external")
148 + const_text(".")
149 + text(self.node.digest.as_bytes().to_hex_with_prefix());
150
151 let single_line = self.single_line_pre_decorators()
152 + external.clone()
153 + self.single_line_post_decorators();
154 let multi_line =
155 self.multi_line_pre_decorators() + external + self.multi_line_post_decorators();
156
157 single_line | multi_line
158 }
159}
160
161impl fmt::Display for ExternalNodePrettyPrint<'_> {
162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163 use crate::prettier::PrettyPrint;
164 self.pretty_print(f)
165 }
166}