miden_assembly_syntax/ast/
alias.rs1use alloc::{string::String, sync::Arc};
2use core::fmt;
3
4use miden_debug_types::{SourceSpan, Span, Spanned};
5
6use crate::{
7 Path, Word,
8 ast::{DocString, Ident, InvocationTarget, Visibility},
9};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct Alias {
20 docs: Option<DocString>,
22 visibility: Visibility,
24 name: Ident,
26 target: AliasTarget,
34 pub uses: usize,
36}
37
38impl Alias {
39 pub fn new(visibility: Visibility, name: Ident, target: AliasTarget) -> Self {
41 Self {
42 docs: None,
43 visibility,
44 name,
45 target,
46 uses: 0,
47 }
48 }
49
50 pub fn with_docs(mut self, docs: Option<Span<String>>) -> Self {
52 self.docs = docs.map(DocString::new);
53 self
54 }
55
56 pub fn docs(&self) -> Option<Span<&str>> {
58 self.docs.as_ref().map(|docstring| docstring.as_spanned_str())
59 }
60
61 #[inline]
63 pub const fn visibility(&self) -> Visibility {
64 self.visibility
65 }
66
67 #[inline]
72 pub fn name(&self) -> &Ident {
73 &self.name
74 }
75
76 #[inline]
78 pub fn target(&self) -> &AliasTarget {
79 &self.target
80 }
81
82 #[inline]
84 pub fn target_mut(&mut self) -> &mut AliasTarget {
85 &mut self.target
86 }
87
88 #[inline]
90 pub fn is_absolute(&self) -> bool {
91 match self.target() {
92 AliasTarget::MastRoot(_) => true,
93 AliasTarget::Path(path) => path.is_absolute(),
94 }
95 }
96
97 #[inline]
99 pub fn is_renamed(&self) -> bool {
100 match self.target() {
101 AliasTarget::MastRoot(_) => true,
102 AliasTarget::Path(path) => path.last().unwrap() != self.name.as_str(),
103 }
104 }
105
106 pub fn is_used(&self) -> bool {
108 self.uses > 0 || self.visibility.is_public()
109 }
110}
111
112impl Spanned for Alias {
113 fn span(&self) -> SourceSpan {
114 self.target.span()
115 }
116}
117
118impl crate::prettier::PrettyPrint for Alias {
119 fn render(&self) -> crate::prettier::Document {
120 use crate::prettier::*;
121
122 let mut doc = self
123 .docs
124 .as_ref()
125 .map(|docstring| docstring.render())
126 .unwrap_or(Document::Empty);
127
128 if self.visibility.is_public() {
129 doc += display(self.visibility) + const_text(" ");
130 }
131 doc += const_text("use ");
132 doc += match &self.target {
133 target @ AliasTarget::MastRoot(_) => display(format_args!("{}->{}", target, self.name)),
134 target => {
135 let prefix = if self.is_absolute() { "::" } else { "" };
136 if self.is_renamed() {
137 display(format_args!("{}{}->{}", prefix, target, &self.name))
138 } else {
139 display(format_args!("{prefix}{target}"))
140 }
141 },
142 };
143 doc
144 }
145}
146
147#[derive(Debug, Clone, PartialEq, Eq)]
149pub enum AliasTarget {
150 MastRoot(Span<Word>),
156 Path(Span<Arc<Path>>),
161}
162
163impl AliasTarget {
164 pub fn unwrap_path(&self) -> &Arc<Path> {
165 match self {
166 Self::Path(path) => path.inner(),
167 Self::MastRoot(_) => {
168 panic!("expected alias target to be a path, but got a mast digest")
169 },
170 }
171 }
172}
173
174impl Spanned for AliasTarget {
175 fn span(&self) -> SourceSpan {
176 match self {
177 Self::MastRoot(spanned) => spanned.span(),
178 Self::Path(spanned) => spanned.span(),
179 }
180 }
181}
182
183impl From<Span<Word>> for AliasTarget {
184 fn from(digest: Span<Word>) -> Self {
185 Self::MastRoot(digest)
186 }
187}
188
189impl TryFrom<InvocationTarget> for AliasTarget {
190 type Error = InvocationTarget;
191
192 fn try_from(target: InvocationTarget) -> Result<Self, Self::Error> {
193 match target {
194 InvocationTarget::MastRoot(digest) => Ok(Self::MastRoot(digest)),
195 InvocationTarget::Path(path) => Ok(Self::Path(path)),
196 target @ InvocationTarget::Symbol(_) => Err(target),
197 }
198 }
199}
200
201impl From<&AliasTarget> for InvocationTarget {
202 fn from(target: &AliasTarget) -> Self {
203 match target {
204 AliasTarget::MastRoot(digest) => Self::MastRoot(*digest),
205 AliasTarget::Path(path) => Self::Path(path.clone()),
206 }
207 }
208}
209impl From<AliasTarget> for InvocationTarget {
210 fn from(target: AliasTarget) -> Self {
211 match target {
212 AliasTarget::MastRoot(digest) => Self::MastRoot(digest),
213 AliasTarget::Path(path) => Self::Path(path),
214 }
215 }
216}
217
218impl crate::prettier::PrettyPrint for AliasTarget {
219 fn render(&self) -> crate::prettier::Document {
220 use miden_core::utils::DisplayHex;
221
222 use crate::prettier::*;
223
224 match self {
225 Self::MastRoot(digest) => display(DisplayHex(digest.as_bytes().as_slice())),
226 Self::Path(path) => display(path),
227 }
228 }
229}
230
231impl fmt::Display for AliasTarget {
232 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
233 use crate::prettier::PrettyPrint;
234
235 self.pretty_print(f)
236 }
237}