miden_assembly/
procedure.rs1use alloc::sync::Arc;
2
3use miden_assembly_syntax::{
4 ast::{Path, Visibility, types::FunctionType},
5 debuginfo::{SourceManager, SourceSpan, Spanned},
6 diagnostics::Report,
7};
8use miden_core::Word;
9
10use super::{
11 GlobalItemIndex,
12 assembler::{MAX_PROC_LOCALS, error::AssemblerError},
13 mast_forest_builder::MastNodeRef,
14};
15
16pub struct ProcedureContext {
21 source_manager: Arc<dyn SourceManager>,
22 gid: GlobalItemIndex,
23 is_program_entrypoint: bool,
24 span: SourceSpan,
25 path: Arc<Path>,
26 signature: Option<Arc<FunctionType>>,
27 visibility: Visibility,
28 is_kernel: bool,
29 num_locals: u16,
30}
31
32impl ProcedureContext {
35 pub fn new(
36 gid: GlobalItemIndex,
37 is_program_entrypoint: bool,
38 path: Arc<Path>,
39 visibility: Visibility,
40 signature: Option<Arc<FunctionType>>,
41 is_kernel: bool,
42 source_manager: Arc<dyn SourceManager>,
43 ) -> Self {
44 Self {
45 source_manager,
46 gid,
47 is_program_entrypoint,
48 span: SourceSpan::UNKNOWN,
49 path,
50 visibility,
51 signature,
52 is_kernel,
53 num_locals: 0,
54 }
55 }
56
57 pub fn with_num_locals(mut self, num_locals: u16) -> Result<Self, Report> {
66 if num_locals > MAX_PROC_LOCALS {
67 let source_file = self.source_manager.get(self.span.source_id()).ok();
68 return Err(Report::new(AssemblerError::TooManyProcedureLocals {
69 span: self.span,
70 source_file,
71 max_locals: MAX_PROC_LOCALS,
72 num_locals,
73 }));
74 }
75 self.num_locals = num_locals;
76 Ok(self)
77 }
78
79 pub fn with_span(mut self, span: SourceSpan) -> Self {
80 self.span = span;
81 self
82 }
83}
84
85impl ProcedureContext {
88 pub fn id(&self) -> GlobalItemIndex {
89 self.gid
90 }
91
92 pub fn is_program_entrypoint(&self) -> bool {
93 self.is_program_entrypoint
94 }
95
96 pub fn path(&self) -> &Arc<Path> {
97 &self.path
98 }
99
100 pub fn signature(&self) -> Option<Arc<FunctionType>> {
101 self.signature.clone()
102 }
103
104 pub fn set_signature(&mut self, signature: Option<Arc<FunctionType>>) {
105 self.signature = signature;
106 }
107
108 pub fn num_locals(&self) -> u16 {
109 self.num_locals
110 }
111
112 pub fn module(&self) -> &Path {
113 self.path.parent().unwrap()
114 }
115
116 pub fn is_kernel(&self) -> bool {
118 self.is_kernel
119 }
120
121 #[inline(always)]
122 pub fn source_manager(&self) -> &dyn SourceManager {
123 self.source_manager.as_ref()
124 }
125}
126
127impl ProcedureContext {
130 pub(crate) fn into_procedure(self, mast_root: Word, body_node_ref: MastNodeRef) -> Procedure {
140 let is_syscall = self.is_kernel && self.visibility.is_public();
141 Procedure::new(
142 self.path,
143 self.visibility,
144 self.signature,
145 is_syscall,
146 self.num_locals as u32,
147 mast_root,
148 body_node_ref,
149 )
150 .with_span(self.span)
151 }
152}
153
154impl Spanned for ProcedureContext {
155 fn span(&self) -> SourceSpan {
156 self.span
157 }
158}
159
160#[derive(Clone, Debug)]
173pub struct Procedure {
174 span: SourceSpan,
175 path: Arc<Path>,
176 signature: Option<Arc<FunctionType>>,
177 visibility: Visibility,
178 is_syscall: bool,
179 num_locals: u32,
180 mast_root: Word,
182 body_node_ref: MastNodeRef,
184}
185
186impl Procedure {
189 fn new(
190 path: Arc<Path>,
191 visibility: Visibility,
192 signature: Option<Arc<FunctionType>>,
193 is_syscall: bool,
194 num_locals: u32,
195 mast_root: Word,
196 body_node_ref: MastNodeRef,
197 ) -> Self {
198 Self {
199 span: SourceSpan::default(),
200 path,
201 visibility,
202 signature,
203 is_syscall,
204 num_locals,
205 mast_root,
206 body_node_ref,
207 }
208 }
209
210 pub(crate) fn with_span(mut self, span: SourceSpan) -> Self {
211 self.span = span;
212 self
213 }
214}
215
216impl Procedure {
219 pub fn span(&self) -> &SourceSpan {
221 &self.span
222 }
223
224 pub fn path(&self) -> &Arc<Path> {
226 &self.path
227 }
228
229 #[inline(always)]
231 pub const fn is_syscall(&self) -> bool {
232 self.is_syscall
233 }
234
235 pub fn visibility(&self) -> Visibility {
237 self.visibility
238 }
239
240 pub fn module(&self) -> &Path {
242 self.path.parent().unwrap()
243 }
244
245 pub fn signature(&self) -> Option<Arc<FunctionType>> {
247 self.signature.clone()
248 }
249
250 pub fn num_locals(&self) -> u32 {
252 self.num_locals
253 }
254
255 pub fn mast_root(&self) -> Word {
257 self.mast_root
258 }
259
260 pub(crate) fn body_node_ref(&self) -> MastNodeRef {
262 self.body_node_ref
263 }
264}
265
266impl Spanned for Procedure {
267 fn span(&self) -> SourceSpan {
268 self.span
269 }
270}