1use alloc::{sync::Arc, vec::Vec};
2use core::ops::Index;
3
4use miden_core::mast::MastNodeId;
5use midenc_hir_type::FunctionType;
6
7use crate::{
8 Path, Word,
9 ast::{self, AttributeSet, ConstantValue, Ident, ItemIndex, ProcedureName, SubmoduleDecl},
10};
11
12#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct ModuleDescriptor {
18 path: Arc<Path>,
19 version: Option<crate::Version>,
22 items: Vec<ItemInfo>,
23 submodules: Vec<SubmoduleDecl>,
24}
25
26impl ModuleDescriptor {
27 pub(crate) fn raw_items(&self) -> &[ItemInfo] {
28 &self.items
29 }
30
31 pub fn new(path: Arc<Path>, version: Option<crate::Version>) -> Self {
37 Self {
38 version,
39 path,
40 items: Vec::new(),
41 submodules: Vec::new(),
42 }
43 }
44
45 pub fn set_version(&mut self, version: crate::Version) {
47 self.version = Some(version);
48 }
49
50 pub fn add_procedure(
52 &mut self,
53 name: ProcedureName,
54 digest: Word,
55 signature: Option<Arc<FunctionType>>,
56 attributes: AttributeSet,
57 ) {
58 self.add_procedure_with_provenance(name, digest, signature, attributes, None, None, None);
59 }
60
61 pub fn add_procedure_with_provenance(
63 &mut self,
64 name: ProcedureName,
65 digest: Word,
66 signature: Option<Arc<FunctionType>>,
67 attributes: AttributeSet,
68 source_root_id: Option<MastNodeId>,
69 source_debug_root_id: Option<u32>,
70 source_library_commitment: Option<Word>,
71 ) {
72 self.items.push(ItemInfo::Procedure(ProcedureInfo {
73 name,
74 digest,
75 signature,
76 attributes,
77 source_root_id,
78 source_debug_root_id,
79 source_library_commitment,
80 }));
81 }
82
83 pub fn add_constant(&mut self, name: Ident, value: ConstantValue) {
85 self.items.push(ItemInfo::Constant(ConstantInfo { name, value }));
86 }
87
88 pub fn add_type(&mut self, name: Ident, ty: ast::types::Type) {
90 self.items.push(ItemInfo::Type(TypeInfo { name, ty }));
91 }
92
93 pub fn add_submodule(&mut self, submodule: SubmoduleDecl) {
95 self.submodules.push(submodule);
96 }
97
98 pub fn path(&self) -> &Path {
100 &self.path
101 }
102
103 pub fn num_procedures(&self) -> usize {
105 self.items.iter().filter(|item| matches!(item, ItemInfo::Procedure(_))).count()
106 }
107
108 pub fn get_item_by_index(&self, index: ItemIndex) -> Option<&ItemInfo> {
110 self.items.get(index.as_usize())
111 }
112
113 pub fn get_item_index_by_name(&self, name: &str) -> Option<ItemIndex> {
115 self.items.iter().enumerate().find_map(|(idx, info)| {
116 if info.name().as_str() == name {
117 Some(ItemIndex::new(idx))
118 } else {
119 None
120 }
121 })
122 }
123
124 pub fn get_procedure_by_name(&self, name: &str) -> Option<&ProcedureInfo> {
126 self.items.iter().find_map(|info| match info {
127 ItemInfo::Procedure(proc) if proc.name.as_str() == name => Some(proc),
128 _ => None,
129 })
130 }
131
132 pub fn get_procedure_digest_by_name(&self, name: &str) -> Option<Word> {
134 self.get_procedure_by_name(name).map(|proc| proc.digest)
135 }
136
137 pub fn items(&self) -> impl ExactSizeIterator<Item = (ItemIndex, &ItemInfo)> {
140 self.items.iter().enumerate().map(|(idx, item)| (ItemIndex::new(idx), item))
141 }
142
143 pub fn submodules(&self) -> &[SubmoduleDecl] {
145 &self.submodules
146 }
147
148 pub fn procedures(&self) -> impl Iterator<Item = (ItemIndex, &ProcedureInfo)> {
151 self.items.iter().enumerate().filter_map(|(idx, item)| match item {
152 ItemInfo::Procedure(proc) => Some((ItemIndex::new(idx), proc)),
153 _ => None,
154 })
155 }
156
157 pub fn procedure_digests(&self) -> impl Iterator<Item = Word> + '_ {
159 self.items.iter().filter_map(|item| match item {
160 ItemInfo::Procedure(proc) => Some(proc.digest),
161 _ => None,
162 })
163 }
164
165 pub fn constants(&self) -> impl Iterator<Item = (ItemIndex, &ConstantInfo)> {
167 self.items.iter().enumerate().filter_map(|(idx, item)| match item {
168 ItemInfo::Constant(info) => Some((ItemIndex::new(idx), info)),
169 _ => None,
170 })
171 }
172
173 pub fn types(&self) -> impl Iterator<Item = (ItemIndex, &TypeInfo)> {
175 self.items.iter().enumerate().filter_map(|(idx, item)| match item {
176 ItemInfo::Type(info) => Some((ItemIndex::new(idx), info)),
177 _ => None,
178 })
179 }
180}
181
182impl Index<ItemIndex> for ModuleDescriptor {
183 type Output = ItemInfo;
184
185 fn index(&self, index: ItemIndex) -> &Self::Output {
186 &self.items[index.as_usize()]
187 }
188}
189
190#[derive(Debug, Clone, PartialEq, Eq)]
192pub enum ItemInfo {
193 Procedure(ProcedureInfo),
194 Constant(ConstantInfo),
195 Type(TypeInfo),
196}
197
198impl ItemInfo {
199 pub fn name(&self) -> &Ident {
200 match self {
201 Self::Procedure(info) => info.name.as_ref(),
202 Self::Constant(info) => &info.name,
203 Self::Type(info) => &info.name,
204 }
205 }
206
207 pub fn attributes(&self) -> Option<&AttributeSet> {
208 match self {
209 Self::Procedure(info) => Some(&info.attributes),
210 Self::Constant(_) | Self::Type(_) => None,
211 }
212 }
213
214 pub fn unwrap_procedure(&self) -> &ProcedureInfo {
215 match self {
216 Self::Procedure(info) => info,
217 Self::Constant(_) | Self::Type(_) => panic!("expected item to be a procedure"),
218 }
219 }
220}
221
222#[derive(Debug, Clone, PartialEq, Eq)]
224pub struct ProcedureInfo {
225 pub name: ProcedureName,
226 pub digest: Word,
227 pub signature: Option<Arc<FunctionType>>,
228 pub attributes: AttributeSet,
229 pub source_root_id: Option<MastNodeId>,
234 pub source_library_commitment: Option<Word>,
236 pub source_debug_root_id: Option<u32>,
238}
239
240impl ProcedureInfo {
241 pub fn source_root_id(&self) -> Option<MastNodeId> {
242 self.source_root_id
243 }
244
245 pub fn source_library_commitment(&self) -> Option<Word> {
246 self.source_library_commitment
247 }
248
249 pub fn source_debug_root_id(&self) -> Option<u32> {
250 self.source_debug_root_id
251 }
252}
253
254#[derive(Debug, Clone, PartialEq, Eq)]
256pub struct ConstantInfo {
257 pub name: Ident,
258 pub value: ConstantValue,
259}
260
261#[derive(Debug, Clone, PartialEq, Eq)]
263pub struct TypeInfo {
264 pub name: Ident,
265 pub ty: ast::types::Type,
266}