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}