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::{const_text, nl, text, Document, PrettyPrint},
8};
9
10use crate::mast::{DecoratorId, MastForest};
11
12#[derive(Clone, Debug, PartialEq, Eq)]
24pub struct ExternalNode {
25 digest: RpoDigest,
26 before_enter: Vec<DecoratorId>,
27 after_exit: Vec<DecoratorId>,
28}
29
30impl ExternalNode {
31 pub fn new(procedure_hash: RpoDigest) -> Self {
33 Self {
34 digest: procedure_hash,
35 before_enter: Vec::new(),
36 after_exit: Vec::new(),
37 }
38 }
39}
40
41impl ExternalNode {
42 pub fn digest(&self) -> RpoDigest {
44 self.digest
45 }
46
47 pub fn before_enter(&self) -> &[DecoratorId] {
49 &self.before_enter
50 }
51
52 pub fn after_exit(&self) -> &[DecoratorId] {
54 &self.after_exit
55 }
56}
57
58impl ExternalNode {
60 pub fn set_before_enter(&mut self, decorator_ids: Vec<DecoratorId>) {
62 self.before_enter = decorator_ids;
63 }
64
65 pub fn set_after_exit(&mut self, decorator_ids: Vec<DecoratorId>) {
67 self.after_exit = decorator_ids;
68 }
69}
70
71impl ExternalNode {
75 pub(super) fn to_display<'a>(&'a self, mast_forest: &'a MastForest) -> impl fmt::Display + 'a {
76 ExternalNodePrettyPrint { node: self, mast_forest }
77 }
78
79 pub(super) fn to_pretty_print<'a>(
80 &'a self,
81 mast_forest: &'a MastForest,
82 ) -> impl PrettyPrint + 'a {
83 ExternalNodePrettyPrint { node: self, mast_forest }
84 }
85}
86
87struct ExternalNodePrettyPrint<'a> {
88 node: &'a ExternalNode,
89 mast_forest: &'a MastForest,
90}
91
92impl ExternalNodePrettyPrint<'_> {
93 fn concatenate_decorators(
96 &self,
97 decorator_ids: &[DecoratorId],
98 prepend: Document,
99 append: Document,
100 ) -> Document {
101 let decorators = decorator_ids
102 .iter()
103 .map(|&decorator_id| self.mast_forest[decorator_id].render())
104 .reduce(|acc, doc| acc + const_text(" ") + doc)
105 .unwrap_or_default();
106
107 if decorators.is_empty() {
108 decorators
109 } else {
110 prepend + decorators + append
111 }
112 }
113
114 fn single_line_pre_decorators(&self) -> Document {
115 self.concatenate_decorators(self.node.before_enter(), Document::Empty, const_text(" "))
116 }
117
118 fn single_line_post_decorators(&self) -> Document {
119 self.concatenate_decorators(self.node.after_exit(), const_text(" "), Document::Empty)
120 }
121
122 fn multi_line_pre_decorators(&self) -> Document {
123 self.concatenate_decorators(self.node.before_enter(), Document::Empty, nl())
124 }
125
126 fn multi_line_post_decorators(&self) -> Document {
127 self.concatenate_decorators(self.node.after_exit(), nl(), Document::Empty)
128 }
129}
130
131impl crate::prettier::PrettyPrint for ExternalNodePrettyPrint<'_> {
132 fn render(&self) -> crate::prettier::Document {
133 let external = const_text("external")
134 + const_text(".")
135 + text(self.node.digest.as_bytes().to_hex_with_prefix());
136
137 let single_line = self.single_line_pre_decorators()
138 + external.clone()
139 + self.single_line_post_decorators();
140 let multi_line =
141 self.multi_line_pre_decorators() + external + self.multi_line_post_decorators();
142
143 single_line | multi_line
144 }
145}
146
147impl fmt::Display for ExternalNodePrettyPrint<'_> {
148 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
149 use crate::prettier::PrettyPrint;
150 self.pretty_print(f)
151 }
152}