use alloc::{boxed::Box, sync::Arc};
use core::cell::{Cell, RefCell};
use miden_assembly_syntax::{
Path,
ast::{self, GlobalItemIndex, Ident, ImportKind, Visibility},
debuginfo::{SourceSpan, Span, Spanned},
module::ItemInfo,
};
use super::LinkStatus;
#[derive(Debug, Clone)]
pub struct Symbol {
name: Ident,
visibility: Visibility,
status: Cell<LinkStatus>,
item: SymbolItem,
}
#[derive(Debug, Clone)]
pub struct Import {
decl: ast::Import,
resolved: Cell<Option<GlobalItemIndex>>,
}
#[derive(Debug, Clone)]
pub enum SymbolItem {
Constant(ast::Constant),
Type(ast::TypeDecl),
Procedure(RefCell<Box<ast::Procedure>>),
Compiled(ItemInfo),
}
impl Import {
#[inline]
pub fn new(decl: ast::Import) -> Self {
Self { decl, resolved: Cell::new(None) }
}
#[inline(always)]
pub fn decl(&self) -> &ast::Import {
&self.decl
}
#[inline(always)]
pub fn kind(&self) -> ImportKind {
self.decl.kind()
}
#[inline(always)]
pub fn local_name(&self) -> &Ident {
self.decl.local_name()
}
#[inline(always)]
pub fn visibility(&self) -> Visibility {
self.decl.visibility()
}
#[inline(always)]
pub fn span(&self) -> SourceSpan {
self.decl.span()
}
#[inline(always)]
pub fn module_path(&self) -> Span<&Path> {
self.decl.module_path()
}
pub fn target_path(&self) -> Span<Arc<Path>> {
match &self.decl {
ast::Import::Module(import) => {
let path = import.module_path();
Span::new(path.span(), Arc::from(*path))
},
ast::Import::Item(import) => import.target_path(),
}
}
#[inline(always)]
pub fn resolved(&self) -> Option<GlobalItemIndex> {
self.resolved.get()
}
#[inline]
pub fn set_resolved(&self, resolved: GlobalItemIndex) {
self.resolved.set(Some(resolved));
}
}
impl Symbol {
#[inline]
pub fn new(name: Ident, visibility: Visibility, status: LinkStatus, item: SymbolItem) -> Self {
Self {
name,
visibility,
status: Cell::new(status),
item,
}
}
#[inline(always)]
pub fn name(&self) -> &Ident {
&self.name
}
#[inline(always)]
pub fn visibility(&self) -> Visibility {
self.visibility
}
#[inline(always)]
pub fn item(&self) -> &SymbolItem {
&self.item
}
#[inline(always)]
pub fn status(&self) -> LinkStatus {
self.status.get()
}
#[inline]
pub fn set_status(&self, status: LinkStatus) {
self.status.set(status);
}
#[inline]
pub fn is_unlinked(&self) -> bool {
matches!(self.status.get(), LinkStatus::Unlinked)
}
#[inline]
pub fn is_linked(&self) -> bool {
matches!(self.status.get(), LinkStatus::Linked)
}
pub fn is_procedure(&self) -> bool {
matches!(
&self.item,
SymbolItem::Compiled(ItemInfo::Procedure(_)) | SymbolItem::Procedure(_)
)
}
}