miden_assembly_syntax/ast/procedure/
mod.rs

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