miden_assembly/ast/procedure/
alias.rs1use alloc::string::String;
2use core::fmt;
3
4use super::{ProcedureName, QualifiedProcedureName};
5use crate::{
6 RpoDigest,
7 ast::InvocationTarget,
8 diagnostics::{SourceSpan, Span, Spanned},
9};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
21pub struct ProcedureAlias {
22 docs: Option<Span<String>>,
24 name: ProcedureName,
26 target: AliasTarget,
32}
33
34impl ProcedureAlias {
35 pub fn new(name: ProcedureName, target: AliasTarget) -> Self {
37 Self { docs: None, name, target }
38 }
39
40 pub fn with_docs(mut self, docs: Option<Span<String>>) -> Self {
42 self.docs = docs;
43 self
44 }
45
46 pub fn docs(&self) -> Option<&Span<String>> {
48 self.docs.as_ref()
49 }
50
51 #[inline]
56 pub fn name(&self) -> &ProcedureName {
57 &self.name
58 }
59
60 #[inline]
62 pub fn target(&self) -> &AliasTarget {
63 &self.target
64 }
65
66 #[inline]
68 pub fn target_mut(&mut self) -> &mut AliasTarget {
69 &mut self.target
70 }
71
72 #[inline]
74 pub fn is_absolute(&self) -> bool {
75 matches!(self.target, AliasTarget::MastRoot(_) | AliasTarget::AbsoluteProcedurePath(_))
76 }
77
78 #[inline]
80 pub fn is_renamed(&self) -> bool {
81 match self.target() {
82 AliasTarget::MastRoot(_) => true,
83 AliasTarget::ProcedurePath(fqn) | AliasTarget::AbsoluteProcedurePath(fqn) => {
84 fqn.name != self.name
85 },
86 }
87 }
88}
89
90impl Spanned for ProcedureAlias {
91 fn span(&self) -> SourceSpan {
92 self.target.span()
93 }
94}
95
96impl crate::prettier::PrettyPrint for ProcedureAlias {
97 fn render(&self) -> crate::prettier::Document {
98 use crate::prettier::*;
99
100 let mut doc = Document::Empty;
101 if let Some(docs) = self.docs.as_deref() {
102 doc = docs
103 .lines()
104 .map(text)
105 .reduce(|acc, line| acc + nl() + text("#! ") + line)
106 .unwrap_or_default();
107 }
108
109 doc += const_text("export.");
110 doc += match &self.target {
111 target @ AliasTarget::MastRoot(_) => display(format_args!("{}->{}", target, self.name)),
112 target => {
113 let prefix = if self.is_absolute() { "::" } else { "" };
114 if self.is_renamed() {
115 display(format_args!("{}{}->{}", prefix, target, &self.name))
116 } else {
117 display(format_args!("{}{}", prefix, target))
118 }
119 },
120 };
121 doc
122 }
123}
124
125#[derive(Debug, Clone, PartialEq, Eq)]
127pub enum AliasTarget {
128 MastRoot(Span<RpoDigest>),
132 ProcedurePath(QualifiedProcedureName),
136 AbsoluteProcedurePath(QualifiedProcedureName),
140}
141
142impl Spanned for AliasTarget {
143 fn span(&self) -> SourceSpan {
144 match self {
145 Self::MastRoot(spanned) => spanned.span(),
146 Self::ProcedurePath(spanned) | Self::AbsoluteProcedurePath(spanned) => spanned.span(),
147 }
148 }
149}
150
151impl From<Span<RpoDigest>> for AliasTarget {
152 fn from(digest: Span<RpoDigest>) -> Self {
153 Self::MastRoot(digest)
154 }
155}
156
157impl TryFrom<InvocationTarget> for AliasTarget {
158 type Error = InvocationTarget;
159
160 fn try_from(target: InvocationTarget) -> Result<Self, Self::Error> {
161 let span = target.span();
162 match target {
163 InvocationTarget::MastRoot(digest) => Ok(Self::MastRoot(digest)),
164 InvocationTarget::ProcedurePath { name, module } => {
165 let ns = crate::LibraryNamespace::from_ident_unchecked(module);
166 let module = crate::LibraryPath::new_from_components(ns, []);
167 Ok(Self::ProcedurePath(QualifiedProcedureName { span, module, name }))
168 },
169 InvocationTarget::AbsoluteProcedurePath { name, path: module } => {
170 Ok(Self::AbsoluteProcedurePath(QualifiedProcedureName { span, module, name }))
171 },
172 target @ InvocationTarget::ProcedureName(_) => Err(target),
173 }
174 }
175}
176
177impl From<&AliasTarget> for InvocationTarget {
178 fn from(target: &AliasTarget) -> Self {
179 match target {
180 AliasTarget::MastRoot(digest) => Self::MastRoot(*digest),
181 AliasTarget::ProcedurePath(fqn) => {
182 let name = fqn.name.clone();
183 let module = fqn.module.last_component().to_ident();
184 Self::ProcedurePath { name, module }
185 },
186 AliasTarget::AbsoluteProcedurePath(fqn) => Self::AbsoluteProcedurePath {
187 name: fqn.name.clone(),
188 path: fqn.module.clone(),
189 },
190 }
191 }
192}
193impl From<AliasTarget> for InvocationTarget {
194 fn from(target: AliasTarget) -> Self {
195 match target {
196 AliasTarget::MastRoot(digest) => Self::MastRoot(digest),
197 AliasTarget::ProcedurePath(fqn) => {
198 let name = fqn.name;
199 let module = fqn.module.last_component().to_ident();
200 Self::ProcedurePath { name, module }
201 },
202 AliasTarget::AbsoluteProcedurePath(fqn) => {
203 Self::AbsoluteProcedurePath { name: fqn.name, path: fqn.module }
204 },
205 }
206 }
207}
208
209impl crate::prettier::PrettyPrint for AliasTarget {
210 fn render(&self) -> crate::prettier::Document {
211 use vm_core::utils::DisplayHex;
212
213 use crate::prettier::*;
214
215 match self {
216 Self::MastRoot(digest) => display(DisplayHex(digest.as_bytes().as_slice())),
217 Self::ProcedurePath(fqn) => display(fqn),
218 Self::AbsoluteProcedurePath(fqn) => display(format_args!("::{}", fqn)),
219 }
220 }
221}
222
223impl fmt::Display for AliasTarget {
224 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
225 use crate::prettier::PrettyPrint;
226
227 self.pretty_print(f)
228 }
229}