miden_assembly_syntax/ast/item/
index.rs1#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
3#[repr(transparent)]
4pub struct ItemIndex(u16);
5
6#[derive(Debug, Copy, Clone, PartialEq, Eq, thiserror::Error)]
7#[error("invalid item index: too many items")]
8pub struct ItemIndexError {
9 attempted: usize,
10}
11
12impl ItemIndex {
13 pub const MAX_ITEMS: usize = u16::MAX as usize + 1;
14
15 pub fn new(id: usize) -> Self {
16 Self::try_new(id).expect("invalid item index: too many items")
17 }
18
19 pub fn try_new(id: usize) -> Result<Self, ItemIndexError> {
20 let raw = id.try_into().map_err(|_| ItemIndexError { attempted: id })?;
21 Ok(Self(raw))
22 }
23
24 #[inline(always)]
25 pub const fn const_new(id: u16) -> Self {
26 Self(id)
27 }
28
29 #[inline(always)]
31 pub const fn as_usize(&self) -> usize {
32 self.0 as usize
33 }
34}
35
36impl core::fmt::Display for ItemIndex {
37 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
38 write!(f, "{}", self.as_usize())
39 }
40}
41
42#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
70pub struct GlobalItemIndex {
71 pub module: ModuleIndex,
73 pub index: ItemIndex,
75}
76
77impl core::fmt::Display for GlobalItemIndex {
78 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
79 write!(f, "{}:{}", self.module, self.index)
80 }
81}
82
83#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
85#[repr(transparent)]
86pub struct ModuleIndex(u16);
87impl ModuleIndex {
88 pub fn new(index: usize) -> Self {
89 Self(index.try_into().expect("invalid module index: too many modules"))
90 }
91
92 pub const fn const_new(index: u16) -> Self {
93 Self(index)
94 }
95
96 #[inline(always)]
97 pub const fn as_usize(&self) -> usize {
98 self.0 as usize
99 }
100}
101
102impl core::ops::Add<ItemIndex> for ModuleIndex {
103 type Output = GlobalItemIndex;
104
105 fn add(self, rhs: ItemIndex) -> Self::Output {
106 GlobalItemIndex { module: self, index: rhs }
107 }
108}
109
110impl core::fmt::Display for ModuleIndex {
111 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
112 write!(f, "{}", self.as_usize())
113 }
114}
115
116#[cfg(test)]
117mod regression_tests {
118 use std::string::String;
119
120 use crate::sema::{LimitKind, SemanticAnalysisError, SyntaxError};
121
122 fn huge_library_masm() -> String {
123 let num_consts = usize::from(u16::MAX) + 2;
124 let mut masm = String::with_capacity(num_consts * 16);
125 masm.push_str("namespace ::m::huge\n\n");
126 for i in 0..num_consts {
127 masm.push_str("const A");
128 masm.push_str(&format!("{i}"));
129 masm.push_str(" = 0\n");
130 }
131 masm
132 }
133
134 #[test]
135 fn too_many_items_in_module_is_rejected_during_analysis() {
136 let test = crate::testing::SyntaxTestContext::new();
137 let err = test
138 .parse_module(&huge_library_masm())
139 .expect_err("expected oversized module to be rejected during analysis");
140
141 let syntax_error = err.downcast_ref::<SyntaxError>().expect("expected SyntaxError report");
142 assert!(
143 syntax_error.errors.iter().any(|error| {
144 matches!(error, SemanticAnalysisError::LimitExceeded { kind: LimitKind::Items, .. })
145 }),
146 "expected item-limit error, got {:?}",
147 syntax_error.errors
148 );
149 }
150}