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)]
16pub struct ModuleInfo {
17 path: Arc<Path>,
18 version: Option<crate::Version>,
21 items: Vec<ItemInfo>,
22 submodules: Vec<SubmoduleDecl>,
23}
24
25impl ModuleInfo {
26 pub(crate) fn raw_items(&self) -> &[ItemInfo] {
27 &self.items
28 }
29
30 pub fn new(path: Arc<Path>, version: Option<crate::Version>) -> Self {
35 Self {
36 version,
37 path,
38 items: Vec::new(),
39 submodules: Vec::new(),
40 }
41 }
42
43 pub fn set_version(&mut self, version: crate::Version) {
45 self.version = Some(version);
46 }
47
48 pub fn add_procedure(
50 &mut self,
51 name: ProcedureName,
52 digest: Word,
53 signature: Option<Arc<FunctionType>>,
54 attributes: AttributeSet,
55 ) {
56 self.add_procedure_with_provenance(name, digest, signature, attributes, None, None, None);
57 }
58
59 pub fn add_procedure_with_provenance(
61 &mut self,
62 name: ProcedureName,
63 digest: Word,
64 signature: Option<Arc<FunctionType>>,
65 attributes: AttributeSet,
66 source_root_id: Option<MastNodeId>,
67 source_debug_root_id: Option<u32>,
68 source_library_commitment: Option<Word>,
69 ) {
70 self.items.push(ItemInfo::Procedure(ProcedureInfo {
71 name,
72 digest,
73 signature,
74 attributes,
75 source_root_id,
76 source_debug_root_id,
77 source_library_commitment,
78 }));
79 }
80
81 pub fn add_constant(&mut self, name: Ident, value: ConstantValue) {
83 self.items.push(ItemInfo::Constant(ConstantInfo { name, value }));
84 }
85
86 pub fn add_type(&mut self, name: Ident, ty: ast::types::Type) {
88 self.items.push(ItemInfo::Type(TypeInfo { name, ty }));
89 }
90
91 pub fn add_submodule(&mut self, submodule: SubmoduleDecl) {
93 self.submodules.push(submodule);
94 }
95
96 pub fn path(&self) -> &Path {
98 &self.path
99 }
100
101 pub fn num_procedures(&self) -> usize {
103 self.items.iter().filter(|item| matches!(item, ItemInfo::Procedure(_))).count()
104 }
105
106 pub fn get_item_by_index(&self, index: ItemIndex) -> Option<&ItemInfo> {
108 self.items.get(index.as_usize())
109 }
110
111 pub fn get_item_index_by_name(&self, name: &str) -> Option<ItemIndex> {
113 self.items.iter().enumerate().find_map(|(idx, info)| {
114 if info.name().as_str() == name {
115 Some(ItemIndex::new(idx))
116 } else {
117 None
118 }
119 })
120 }
121
122 pub fn get_procedure_by_name(&self, name: &str) -> Option<&ProcedureInfo> {
124 self.items.iter().find_map(|info| match info {
125 ItemInfo::Procedure(proc) if proc.name.as_str() == name => Some(proc),
126 _ => None,
127 })
128 }
129
130 pub fn get_procedure_digest_by_name(&self, name: &str) -> Option<Word> {
132 self.get_procedure_by_name(name).map(|proc| proc.digest)
133 }
134
135 pub fn items(&self) -> impl ExactSizeIterator<Item = (ItemIndex, &ItemInfo)> {
138 self.items.iter().enumerate().map(|(idx, item)| (ItemIndex::new(idx), item))
139 }
140
141 pub fn submodules(&self) -> &[SubmoduleDecl] {
143 &self.submodules
144 }
145
146 pub fn procedures(&self) -> impl Iterator<Item = (ItemIndex, &ProcedureInfo)> {
149 self.items.iter().enumerate().filter_map(|(idx, item)| match item {
150 ItemInfo::Procedure(proc) => Some((ItemIndex::new(idx), proc)),
151 _ => None,
152 })
153 }
154
155 pub fn procedure_digests(&self) -> impl Iterator<Item = Word> + '_ {
157 self.items.iter().filter_map(|item| match item {
158 ItemInfo::Procedure(proc) => Some(proc.digest),
159 _ => None,
160 })
161 }
162
163 pub fn constants(&self) -> impl Iterator<Item = (ItemIndex, &ConstantInfo)> {
165 self.items.iter().enumerate().filter_map(|(idx, item)| match item {
166 ItemInfo::Constant(info) => Some((ItemIndex::new(idx), info)),
167 _ => None,
168 })
169 }
170
171 pub fn types(&self) -> impl Iterator<Item = (ItemIndex, &TypeInfo)> {
173 self.items.iter().enumerate().filter_map(|(idx, item)| match item {
174 ItemInfo::Type(info) => Some((ItemIndex::new(idx), info)),
175 _ => None,
176 })
177 }
178}
179
180impl Index<ItemIndex> for ModuleInfo {
181 type Output = ItemInfo;
182
183 fn index(&self, index: ItemIndex) -> &Self::Output {
184 &self.items[index.as_usize()]
185 }
186}
187
188#[derive(Debug, Clone, PartialEq, Eq)]
190pub enum ItemInfo {
191 Procedure(ProcedureInfo),
192 Constant(ConstantInfo),
193 Type(TypeInfo),
194}
195
196impl ItemInfo {
197 pub fn name(&self) -> &Ident {
198 match self {
199 Self::Procedure(info) => info.name.as_ref(),
200 Self::Constant(info) => &info.name,
201 Self::Type(info) => &info.name,
202 }
203 }
204
205 pub fn attributes(&self) -> Option<&AttributeSet> {
206 match self {
207 Self::Procedure(info) => Some(&info.attributes),
208 Self::Constant(_) | Self::Type(_) => None,
209 }
210 }
211
212 pub fn unwrap_procedure(&self) -> &ProcedureInfo {
213 match self {
214 Self::Procedure(info) => info,
215 Self::Constant(_) | Self::Type(_) => panic!("expected item to be a procedure"),
216 }
217 }
218}
219
220#[derive(Debug, Clone, PartialEq, Eq)]
222pub struct ProcedureInfo {
223 pub name: ProcedureName,
224 pub digest: Word,
225 pub signature: Option<Arc<FunctionType>>,
226 pub attributes: AttributeSet,
227 pub source_root_id: Option<MastNodeId>,
232 pub source_library_commitment: Option<Word>,
234 pub source_debug_root_id: Option<u32>,
236}
237
238impl ProcedureInfo {
239 pub fn source_root_id(&self) -> Option<MastNodeId> {
240 self.source_root_id
241 }
242
243 pub fn source_library_commitment(&self) -> Option<Word> {
244 self.source_library_commitment
245 }
246
247 pub fn source_debug_root_id(&self) -> Option<u32> {
248 self.source_debug_root_id
249 }
250}
251
252#[derive(Debug, Clone, PartialEq, Eq)]
254pub struct ConstantInfo {
255 pub name: Ident,
256 pub value: ConstantValue,
257}
258
259#[derive(Debug, Clone, PartialEq, Eq)]
261pub struct TypeInfo {
262 pub name: Ident,
263 pub ty: ast::types::Type,
264}