miden_core/mast/node/
external.rs1use alloc::{boxed::Box, vec::Vec};
2use core::fmt;
3
4use miden_crypto::{Felt, Word};
5use miden_formatting::{
6 hex::ToHex,
7 prettier::{Document, PrettyPrint, const_text, nl, text},
8};
9#[cfg(feature = "serde")]
10use serde::{Deserialize, Serialize};
11
12use super::{MastNodeErrorContext, MastNodeExt};
13use crate::mast::{DecoratedOpLink, DecoratorId, MastForest, MastNodeId, Remapping};
14
15#[derive(Clone, Debug, PartialEq, Eq)]
27#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
28pub struct ExternalNode {
29 digest: Word,
30 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Vec::is_empty"))]
31 before_enter: Vec<DecoratorId>,
32 #[cfg_attr(feature = "serde", serde(default, skip_serializing_if = "Vec::is_empty"))]
33 after_exit: Vec<DecoratorId>,
34}
35
36impl ExternalNode {
37 pub fn new(procedure_hash: Word) -> Self {
39 Self {
40 digest: procedure_hash,
41 before_enter: Vec::new(),
42 after_exit: Vec::new(),
43 }
44 }
45}
46
47impl MastNodeErrorContext for ExternalNode {
48 fn decorators(&self) -> impl Iterator<Item = DecoratedOpLink> {
49 self.before_enter.iter().chain(&self.after_exit).copied().enumerate()
50 }
51}
52
53impl ExternalNode {
57 pub(super) fn to_display<'a>(&'a self, mast_forest: &'a MastForest) -> impl fmt::Display + 'a {
58 ExternalNodePrettyPrint { node: self, mast_forest }
59 }
60
61 pub(super) fn to_pretty_print<'a>(
62 &'a self,
63 mast_forest: &'a MastForest,
64 ) -> impl PrettyPrint + 'a {
65 ExternalNodePrettyPrint { node: self, mast_forest }
66 }
67}
68
69struct ExternalNodePrettyPrint<'a> {
70 node: &'a ExternalNode,
71 mast_forest: &'a MastForest,
72}
73
74impl ExternalNodePrettyPrint<'_> {
75 fn concatenate_decorators(
78 &self,
79 decorator_ids: &[DecoratorId],
80 prepend: Document,
81 append: Document,
82 ) -> Document {
83 let decorators = decorator_ids
84 .iter()
85 .map(|&decorator_id| self.mast_forest[decorator_id].render())
86 .reduce(|acc, doc| acc + const_text(" ") + doc)
87 .unwrap_or_default();
88
89 if decorators.is_empty() {
90 decorators
91 } else {
92 prepend + decorators + append
93 }
94 }
95
96 fn single_line_pre_decorators(&self) -> Document {
97 self.concatenate_decorators(self.node.before_enter(), Document::Empty, const_text(" "))
98 }
99
100 fn single_line_post_decorators(&self) -> Document {
101 self.concatenate_decorators(self.node.after_exit(), const_text(" "), Document::Empty)
102 }
103
104 fn multi_line_pre_decorators(&self) -> Document {
105 self.concatenate_decorators(self.node.before_enter(), Document::Empty, nl())
106 }
107
108 fn multi_line_post_decorators(&self) -> Document {
109 self.concatenate_decorators(self.node.after_exit(), nl(), Document::Empty)
110 }
111}
112
113impl crate::prettier::PrettyPrint for ExternalNodePrettyPrint<'_> {
114 fn render(&self) -> crate::prettier::Document {
115 let external = const_text("external")
116 + const_text(".")
117 + text(self.node.digest.as_bytes().to_hex_with_prefix());
118
119 let single_line = self.single_line_pre_decorators()
120 + external.clone()
121 + self.single_line_post_decorators();
122 let multi_line =
123 self.multi_line_pre_decorators() + external + self.multi_line_post_decorators();
124
125 single_line | multi_line
126 }
127}
128
129impl fmt::Display for ExternalNodePrettyPrint<'_> {
130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131 use crate::prettier::PrettyPrint;
132 self.pretty_print(f)
133 }
134}
135
136impl MastNodeExt for ExternalNode {
140 fn digest(&self) -> Word {
146 self.digest
147 }
148
149 fn before_enter(&self) -> &[DecoratorId] {
151 &self.before_enter
152 }
153
154 fn after_exit(&self) -> &[DecoratorId] {
156 &self.after_exit
157 }
158
159 fn append_before_enter(&mut self, decorator_ids: &[DecoratorId]) {
161 self.before_enter.extend_from_slice(decorator_ids);
162 }
163
164 fn append_after_exit(&mut self, decorator_ids: &[DecoratorId]) {
166 self.after_exit.extend_from_slice(decorator_ids);
167 }
168
169 fn remove_decorators(&mut self) {
171 self.before_enter.truncate(0);
172 self.after_exit.truncate(0);
173 }
174
175 fn to_display<'a>(&'a self, mast_forest: &'a MastForest) -> Box<dyn fmt::Display + 'a> {
176 Box::new(ExternalNode::to_display(self, mast_forest))
177 }
178
179 fn to_pretty_print<'a>(&'a self, mast_forest: &'a MastForest) -> Box<dyn PrettyPrint + 'a> {
180 Box::new(ExternalNode::to_pretty_print(self, mast_forest))
181 }
182
183 fn remap_children(&self, _remapping: &Remapping) -> Self {
184 self.clone()
185 }
186
187 fn has_children(&self) -> bool {
188 false
189 }
190
191 fn append_children_to(&self, _target: &mut Vec<MastNodeId>) {
192 }
194
195 fn for_each_child<F>(&self, _f: F)
196 where
197 F: FnMut(MastNodeId),
198 {
199 }
201
202 fn domain(&self) -> Felt {
203 panic!("Can't fetch domain for an `External` node.")
204 }
205}