miden_assembly_syntax/ast/
import.rs1use alloc::{sync::Arc, vec::Vec};
2
3use miden_debug_types::{SourceSpan, Span, Spanned};
4
5use super::{Ident, Path, Visibility};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum ImportKind {
10 Module,
12 Item,
14}
15
16#[derive(Debug, Clone, PartialEq, Eq)]
18pub enum ImportDecl {
19 Module(ModuleImport),
20 Items(ItemImportGroup),
21}
22
23#[derive(Debug, Clone, PartialEq, Eq)]
25pub enum Import {
26 Module(ModuleImport),
27 Item(ItemImport),
28}
29
30#[derive(Debug, Clone)]
32pub struct ModuleImport {
33 span: SourceSpan,
34 visibility: Visibility,
35 module_path: Span<Arc<Path>>,
36 local_name: Ident,
37 pub uses: usize,
39}
40
41#[derive(Debug, Clone)]
43pub struct ItemImportGroup {
44 span: SourceSpan,
45 visibility: Visibility,
46 module_path: Span<Arc<Path>>,
47 specs: Vec<ImportSpec>,
48}
49
50#[derive(Debug, Clone, PartialEq, Eq)]
52pub struct ImportSpec {
53 source_name: Ident,
54 local_name: Ident,
55}
56
57#[derive(Debug, Clone)]
59pub struct ItemImport {
60 span: SourceSpan,
61 visibility: Visibility,
62 module_path: Span<Arc<Path>>,
63 source_name: Ident,
64 local_name: Ident,
65 pub uses: usize,
67}
68
69impl ImportDecl {
70 pub fn kind(&self) -> ImportKind {
71 match self {
72 Self::Module(_) => ImportKind::Module,
73 Self::Items(_) => ImportKind::Item,
74 }
75 }
76
77 pub fn visibility(&self) -> Visibility {
78 match self {
79 Self::Module(import) => import.visibility(),
80 Self::Items(import) => import.visibility(),
81 }
82 }
83
84 pub fn module_path(&self) -> Span<&Path> {
85 match self {
86 Self::Module(import) => import.module_path(),
87 Self::Items(import) => import.module_path(),
88 }
89 }
90}
91
92impl Import {
93 pub fn kind(&self) -> ImportKind {
94 match self {
95 Self::Module(_) => ImportKind::Module,
96 Self::Item(_) => ImportKind::Item,
97 }
98 }
99
100 pub fn visibility(&self) -> Visibility {
101 match self {
102 Self::Module(import) => import.visibility(),
103 Self::Item(import) => import.visibility(),
104 }
105 }
106
107 pub fn module_path(&self) -> Span<&Path> {
108 match self {
109 Self::Module(import) => import.module_path(),
110 Self::Item(import) => import.module_path(),
111 }
112 }
113
114 pub fn local_name(&self) -> &Ident {
115 match self {
116 Self::Module(import) => import.local_name(),
117 Self::Item(import) => import.local_name(),
118 }
119 }
120
121 pub fn is_used(&self) -> bool {
123 match self {
124 Self::Module(import) => import.is_used(),
125 Self::Item(import) => import.is_used(),
126 }
127 }
128
129 pub fn unused_span(&self) -> SourceSpan {
131 match self {
132 Self::Module(import) => import.local_name().span(),
133 Self::Item(import) => import.local_name().span(),
134 }
135 }
136}
137
138impl ModuleImport {
139 pub fn new(
140 span: SourceSpan,
141 visibility: Visibility,
142 module_path: Span<Arc<Path>>,
143 local_name: Ident,
144 ) -> Self {
145 Self {
146 span,
147 visibility,
148 module_path,
149 local_name,
150 uses: 0,
151 }
152 }
153
154 pub fn visibility(&self) -> Visibility {
155 self.visibility
156 }
157
158 pub fn module_path(&self) -> Span<&Path> {
159 self.module_path.as_deref()
160 }
161
162 pub fn set_module_path(&mut self, path: Span<Arc<Path>>) {
163 self.module_path = path;
164 }
165
166 pub fn local_name(&self) -> &Ident {
167 &self.local_name
168 }
169
170 pub fn is_used(&self) -> bool {
172 self.uses > 0
173 }
174}
175
176impl ItemImportGroup {
177 pub fn new(
178 span: SourceSpan,
179 visibility: Visibility,
180 module_path: Span<Arc<Path>>,
181 specs: Vec<ImportSpec>,
182 ) -> Self {
183 Self { span, visibility, module_path, specs }
184 }
185
186 pub fn visibility(&self) -> Visibility {
187 self.visibility
188 }
189
190 pub fn module_path(&self) -> Span<&Path> {
191 self.module_path.as_deref()
192 }
193
194 pub fn specs(&self) -> &[ImportSpec] {
195 &self.specs
196 }
197}
198
199impl ImportSpec {
200 pub fn new(source_name: Ident, local_name: Ident) -> Self {
201 Self { source_name, local_name }
202 }
203
204 pub fn source_name(&self) -> &Ident {
205 &self.source_name
206 }
207
208 pub fn local_name(&self) -> &Ident {
209 &self.local_name
210 }
211
212 pub fn is_renamed(&self) -> bool {
213 self.source_name != self.local_name
214 }
215}
216
217impl ItemImport {
218 pub fn new(
219 span: SourceSpan,
220 visibility: Visibility,
221 module_path: Span<Arc<Path>>,
222 source_name: Ident,
223 local_name: Ident,
224 ) -> Self {
225 Self {
226 span,
227 visibility,
228 module_path,
229 source_name,
230 local_name,
231 uses: 0,
232 }
233 }
234
235 pub fn visibility(&self) -> Visibility {
236 self.visibility
237 }
238
239 pub fn module_path(&self) -> Span<&Path> {
240 self.module_path.as_deref()
241 }
242
243 pub fn source_name(&self) -> &Ident {
244 &self.source_name
245 }
246
247 pub fn local_name(&self) -> &Ident {
248 &self.local_name
249 }
250
251 pub fn target_path(&self) -> Span<Arc<Path>> {
252 Span::new(self.source_name.span(), self.module_path.inner().join(&self.source_name).into())
253 }
254
255 pub fn is_used(&self) -> bool {
257 self.uses > 0 || self.visibility.is_public()
258 }
259}
260
261impl Spanned for Import {
262 fn span(&self) -> SourceSpan {
263 match self {
264 Self::Module(import) => import.span(),
265 Self::Item(import) => import.span(),
266 }
267 }
268}
269
270impl Spanned for ImportDecl {
271 fn span(&self) -> SourceSpan {
272 match self {
273 Self::Module(import) => import.span(),
274 Self::Items(import) => import.span(),
275 }
276 }
277}
278
279impl Spanned for ModuleImport {
280 fn span(&self) -> SourceSpan {
281 self.span
282 }
283}
284
285impl Spanned for ItemImportGroup {
286 fn span(&self) -> SourceSpan {
287 self.span
288 }
289}
290
291impl Spanned for ImportSpec {
292 fn span(&self) -> SourceSpan {
293 self.source_name.span()
294 }
295}
296
297impl Spanned for ItemImport {
298 fn span(&self) -> SourceSpan {
299 self.span
300 }
301}
302
303impl Eq for ModuleImport {}
304
305impl PartialEq for ModuleImport {
306 fn eq(&self, other: &Self) -> bool {
307 self.visibility == other.visibility
308 && self.module_path.inner() == other.module_path.inner()
309 && self.local_name == other.local_name
310 }
311}
312
313impl Eq for ItemImportGroup {}
314
315impl PartialEq for ItemImportGroup {
316 fn eq(&self, other: &Self) -> bool {
317 self.visibility == other.visibility
318 && self.module_path.inner() == other.module_path.inner()
319 && self.specs == other.specs
320 }
321}
322
323impl Eq for ItemImport {}
324
325impl PartialEq for ItemImport {
326 fn eq(&self, other: &Self) -> bool {
327 self.visibility == other.visibility
328 && self.module_path.inner() == other.module_path.inner()
329 && self.source_name == other.source_name
330 && self.local_name == other.local_name
331 }
332}
333
334impl crate::prettier::PrettyPrint for ImportDecl {
335 fn render(&self) -> crate::prettier::Document {
336 match self {
337 Self::Module(import) => import.render(),
338 Self::Items(import) => import.render(),
339 }
340 }
341}
342
343impl crate::prettier::PrettyPrint for Import {
344 fn render(&self) -> crate::prettier::Document {
345 match self {
346 Self::Module(import) => import.render(),
347 Self::Item(import) => import.render(),
348 }
349 }
350}
351
352impl crate::prettier::PrettyPrint for ModuleImport {
353 fn render(&self) -> crate::prettier::Document {
354 use crate::prettier::*;
355
356 let mut doc = const_text("use") + const_text(" ") + display(self.module_path.inner());
357 if self.module_path.last().is_none_or(|name| name != self.local_name.as_str()) {
358 doc += const_text(" as ") + display(&self.local_name);
359 }
360 doc
361 }
362}
363
364impl crate::prettier::PrettyPrint for ItemImportGroup {
365 fn render(&self) -> crate::prettier::Document {
366 use crate::prettier::*;
367
368 let mut doc = Document::Empty;
369 if self.visibility.is_public() {
370 doc += display(self.visibility) + const_text(" ");
371 }
372 doc += const_text("use {");
373
374 for (index, spec) in self.specs.iter().enumerate() {
375 if index > 0 {
376 doc += const_text(", ");
377 }
378 doc += spec.render();
379 }
380
381 doc + const_text("} from ") + display(self.module_path.inner())
382 }
383}
384
385impl crate::prettier::PrettyPrint for ImportSpec {
386 fn render(&self) -> crate::prettier::Document {
387 use crate::prettier::*;
388
389 let mut doc = display(&self.source_name);
390 if self.is_renamed() {
391 doc += const_text(" as ") + display(&self.local_name);
392 }
393 doc
394 }
395}
396
397impl crate::prettier::PrettyPrint for ItemImport {
398 fn render(&self) -> crate::prettier::Document {
399 use crate::prettier::*;
400
401 let mut doc = Document::Empty;
402 if self.visibility.is_public() {
403 doc += display(self.visibility) + const_text(" ");
404 }
405 doc += const_text("use {") + display(&self.source_name);
406 if self.source_name != self.local_name {
407 doc += const_text(" as ") + display(&self.local_name);
408 }
409 doc + const_text("} from ") + display(self.module_path.inner())
410 }
411}