use alloc::sync::Arc;
use miden_assembly_syntax::{
ast::{Path, Visibility, types::FunctionType},
debuginfo::{SourceManager, SourceSpan, Spanned},
};
use miden_core::{Word, mast::MastNodeId};
use super::GlobalItemIndex;
pub struct ProcedureContext {
source_manager: Arc<dyn SourceManager>,
gid: GlobalItemIndex,
is_program_entrypoint: bool,
span: SourceSpan,
path: Arc<Path>,
signature: Option<Arc<FunctionType>>,
visibility: Visibility,
is_kernel: bool,
num_locals: u16,
}
impl ProcedureContext {
pub fn new(
gid: GlobalItemIndex,
is_program_entrypoint: bool,
path: Arc<Path>,
visibility: Visibility,
signature: Option<Arc<FunctionType>>,
is_kernel: bool,
source_manager: Arc<dyn SourceManager>,
) -> Self {
Self {
source_manager,
gid,
is_program_entrypoint,
span: SourceSpan::UNKNOWN,
path,
visibility,
signature,
is_kernel,
num_locals: 0,
}
}
pub fn with_num_locals(mut self, num_locals: u16) -> Self {
self.num_locals = num_locals;
self
}
pub fn with_span(mut self, span: SourceSpan) -> Self {
self.span = span;
self
}
}
impl ProcedureContext {
pub fn id(&self) -> GlobalItemIndex {
self.gid
}
pub fn is_program_entrypoint(&self) -> bool {
self.is_program_entrypoint
}
pub fn path(&self) -> &Arc<Path> {
&self.path
}
pub fn signature(&self) -> Option<Arc<FunctionType>> {
self.signature.clone()
}
pub fn set_signature(&mut self, signature: Option<Arc<FunctionType>>) {
self.signature = signature;
}
pub fn num_locals(&self) -> u16 {
self.num_locals
}
pub fn module(&self) -> &Path {
self.path.parent().unwrap()
}
pub fn is_kernel(&self) -> bool {
self.is_kernel
}
#[inline(always)]
pub fn source_manager(&self) -> &dyn SourceManager {
self.source_manager.as_ref()
}
}
impl ProcedureContext {
pub fn into_procedure(self, mast_root: Word, mast_node_id: MastNodeId) -> Procedure {
let is_syscall = self.is_kernel && self.visibility.is_public();
Procedure::new(
self.path,
self.visibility,
self.signature,
is_syscall,
self.num_locals as u32,
mast_root,
mast_node_id,
)
.with_span(self.span)
}
}
impl Spanned for ProcedureContext {
fn span(&self) -> SourceSpan {
self.span
}
}
#[derive(Clone, Debug)]
pub struct Procedure {
span: SourceSpan,
path: Arc<Path>,
signature: Option<Arc<FunctionType>>,
visibility: Visibility,
is_syscall: bool,
num_locals: u32,
mast_root: Word,
body_node_id: MastNodeId,
}
impl Procedure {
fn new(
path: Arc<Path>,
visibility: Visibility,
signature: Option<Arc<FunctionType>>,
is_syscall: bool,
num_locals: u32,
mast_root: Word,
body_node_id: MastNodeId,
) -> Self {
Self {
span: SourceSpan::default(),
path,
visibility,
signature,
is_syscall,
num_locals,
mast_root,
body_node_id,
}
}
pub(crate) fn with_span(mut self, span: SourceSpan) -> Self {
self.span = span;
self
}
}
impl Procedure {
pub fn span(&self) -> &SourceSpan {
&self.span
}
pub fn path(&self) -> &Arc<Path> {
&self.path
}
#[inline(always)]
pub const fn is_syscall(&self) -> bool {
self.is_syscall
}
pub fn visibility(&self) -> Visibility {
self.visibility
}
pub fn module(&self) -> &Path {
self.path.parent().unwrap()
}
pub fn signature(&self) -> Option<Arc<FunctionType>> {
self.signature.clone()
}
pub fn num_locals(&self) -> u32 {
self.num_locals
}
pub fn mast_root(&self) -> Word {
self.mast_root
}
pub fn body_node_id(&self) -> MastNodeId {
self.body_node_id
}
}
impl Spanned for Procedure {
fn span(&self) -> SourceSpan {
self.span
}
}