miden_assembly/linker/
symbols.rs

1use alloc::boxed::Box;
2use core::cell::{Cell, RefCell};
3
4use miden_assembly_syntax::{
5    ast::{self, GlobalItemIndex, Ident, Visibility},
6    library::ItemInfo,
7};
8
9use super::LinkStatus;
10
11/// A [Symbol] is a named, linkable item defined within a module.
12#[derive(Debug, Clone)]
13pub struct Symbol {
14    /// The name of the symbol in it's containing module.
15    name: Ident,
16    /// The external visibility of the symbol
17    visibility: Visibility,
18    /// The link status of the symbol, i.e. unlinked, partially, or fully linked.
19    status: Cell<LinkStatus>,
20    /// The type of item associated with this symbol.
21    item: SymbolItem,
22}
23
24/// A [SymbolItem] represents the type of item associated with a [Symbol].
25#[derive(Debug, Clone)]
26pub enum SymbolItem {
27    /// An alias of an externally-defined item
28    Alias {
29        /// The original alias item
30        alias: ast::Alias,
31        /// Once the alias has been resolved, we set this to `Some(target_gid)` so that we can
32        /// simply shortcut to the resolved target once known.
33        resolved: Cell<Option<GlobalItemIndex>>,
34    },
35    /// A constant declaration in AST form
36    Constant(ast::Constant),
37    /// A type or enum declaration in AST form
38    Type(ast::TypeDecl),
39    /// Procedure symbols are wrapped in a `RefCell` to allow us to mutate the procedure body when
40    /// linking any externally-defined symbols it contains.
41    Procedure(RefCell<Box<ast::Procedure>>),
42    /// An already-assembled item
43    Compiled(ItemInfo),
44}
45
46impl Symbol {
47    /// Create a new [Symbol].
48    #[inline]
49    pub fn new(name: Ident, visibility: Visibility, status: LinkStatus, item: SymbolItem) -> Self {
50        Self {
51            name,
52            visibility,
53            status: Cell::new(status),
54            item,
55        }
56    }
57
58    /// Get the module-local name of this symbol
59    #[inline(always)]
60    pub fn name(&self) -> &Ident {
61        &self.name
62    }
63
64    /// Get the external visibility of this symbol
65    #[inline(always)]
66    pub fn visibility(&self) -> Visibility {
67        self.visibility
68    }
69
70    /// Get the item associated with this symbol
71    #[inline(always)]
72    pub fn item(&self) -> &SymbolItem {
73        &self.item
74    }
75
76    /// Get the current link status of this symbol
77    #[inline(always)]
78    pub fn status(&self) -> LinkStatus {
79        self.status.get()
80    }
81
82    /// Set the link status of this symbol
83    #[inline]
84    pub fn set_status(&self, status: LinkStatus) {
85        self.status.set(status);
86    }
87
88    /// Returns true if this symbol has not yet been visited by the linker.
89    #[inline]
90    pub fn is_unlinked(&self) -> bool {
91        matches!(self.status.get(), LinkStatus::Unlinked)
92    }
93
94    /// Returns true if this symbol is fully-linked.
95    #[inline]
96    pub fn is_linked(&self) -> bool {
97        matches!(self.status.get(), LinkStatus::Linked)
98    }
99
100    /// Returns true if this symbol represents a procedure definition.
101    pub fn is_procedure(&self) -> bool {
102        matches!(
103            &self.item,
104            SymbolItem::Compiled(ItemInfo::Procedure(_)) | SymbolItem::Procedure(_)
105        )
106    }
107}