miden_assembly_syntax/ast/item/
export.rs

1use alloc::string::String;
2
3use crate::{
4    ast::{
5        Alias, AttributeSet, Constant, FunctionType, Ident, Invoke, Procedure, TypeDecl, Visibility,
6    },
7    debuginfo::{SourceSpan, Span, Spanned},
8};
9
10// EXPORT
11// ================================================================================================
12
13/// Represents an exportable item from a [crate::ast::Module].
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub enum Export {
16    /// A locally-defined procedure.
17    Procedure(Procedure),
18    /// A locally-defined constant.
19    Constant(Constant),
20    /// A locally-defined type.
21    Type(TypeDecl),
22    /// An alias for an externally-defined item, i.e. a re-exported import.
23    Alias(Alias),
24}
25
26impl Export {
27    /// Adds documentation to this export.
28    pub fn with_docs(self, docs: Option<Span<String>>) -> Self {
29        match self {
30            Self::Procedure(item) => Self::Procedure(item.with_docs(docs)),
31            Self::Constant(item) => Self::Constant(item.with_docs(docs)),
32            Self::Type(item) => Self::Type(item.with_docs(docs)),
33            Self::Alias(item) => Self::Alias(item.with_docs(docs)),
34        }
35    }
36
37    /// Returns the name of the exported procedure.
38    pub fn name(&self) -> &Ident {
39        match self {
40            Self::Procedure(item) => item.name().as_ref(),
41            Self::Constant(item) => &item.name,
42            Self::Type(item) => item.name(),
43            Self::Alias(item) => item.name(),
44        }
45    }
46
47    /// Returns the documentation for this item.
48    pub fn docs(&self) -> Option<&str> {
49        match self {
50            Self::Procedure(item) => item.docs().map(|spanned| spanned.into_inner()),
51            Self::Constant(item) => item.docs().map(|spanned| spanned.into_inner()),
52            Self::Type(item) => item.docs().map(|spanned| spanned.into_inner()),
53            Self::Alias(item) => item.docs().map(|spanned| spanned.into_inner()),
54        }
55    }
56
57    /// Returns the attributes for this item, if it is a procedure.
58    pub fn attributes(&self) -> Option<&AttributeSet> {
59        match self {
60            Self::Procedure(proc) => Some(proc.attributes()),
61            Self::Constant(_) | Self::Type(_) | Self::Alias(_) => None,
62        }
63    }
64
65    /// Returns the visibility of this item (e.g. public or private).
66    ///
67    /// See [Visibility] for more details on what visibilities are supported.
68    pub fn visibility(&self) -> Visibility {
69        match self {
70            Self::Procedure(item) => item.visibility(),
71            Self::Constant(item) => item.visibility,
72            Self::Type(item) => item.visibility(),
73            Self::Alias(item) => item.visibility(),
74        }
75    }
76
77    /// Returns a reference to the type signature of this item, if it is a procedure, and known.
78    pub fn signature(&self) -> Option<&FunctionType> {
79        match self {
80            Self::Procedure(item) => item.signature(),
81            Self::Constant(_) | Self::Type(_) | Self::Alias(_) => None,
82        }
83    }
84
85    /// Returns the number of automatically-allocated words of memory this item requires
86    /// for the storage of temporaries/local variables.
87    ///
88    /// NOTE: This is only applicable for procedure items - the value 0 will be returned if this
89    /// is a non-procedure item, or if the type of item is not yet known.
90    pub fn num_locals(&self) -> usize {
91        match self {
92            Self::Procedure(proc) => proc.num_locals() as usize,
93            Self::Constant(_) | Self::Type(_) | Self::Alias(_) => 0,
94        }
95    }
96
97    /// Returns true if this procedure is the program entrypoint.
98    pub fn is_main(&self) -> bool {
99        self.name().as_str() == Ident::MAIN
100    }
101
102    /// Unwraps this [Export] as a [Procedure], or panic.
103    #[track_caller]
104    pub fn unwrap_procedure(&self) -> &Procedure {
105        match self {
106            Self::Procedure(item) => item,
107            Self::Constant(_) => panic!("attempted to unwrap constant as procedure definition"),
108            Self::Type(_) => panic!("attempted to unwrap type as procedure definition"),
109            Self::Alias(_) => panic!("attempted to unwrap alias as procedure definition"),
110        }
111    }
112
113    /// Get an iterator over the set of other procedures invoked from this procedure.
114    ///
115    /// NOTE: This only applies to [Procedure]s, other types currently return an empty
116    /// iterator whenever called.
117    pub fn invoked<'a, 'b: 'a>(&'b self) -> impl Iterator<Item = &'a Invoke> + 'a {
118        use crate::ast::procedure::InvokedIter;
119
120        match self {
121            Self::Procedure(item) if item.invoked.is_empty() => InvokedIter::Empty,
122            Self::Procedure(item) => InvokedIter::NonEmpty(item.invoked.iter()),
123            Self::Constant(_) | Self::Type(_) | Self::Alias(_) => InvokedIter::Empty,
124        }
125    }
126}
127
128impl crate::prettier::PrettyPrint for Export {
129    fn render(&self) -> crate::prettier::Document {
130        match self {
131            Self::Procedure(item) => item.render(),
132            Self::Constant(item) => item.render(),
133            Self::Type(item) => item.render(),
134            Self::Alias(item) => item.render(),
135        }
136    }
137}
138
139impl Spanned for Export {
140    fn span(&self) -> SourceSpan {
141        match self {
142            Self::Procedure(spanned) => spanned.span(),
143            Self::Constant(spanned) => spanned.span(),
144            Self::Type(spanned) => spanned.span(),
145            Self::Alias(spanned) => spanned.span(),
146        }
147    }
148}