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