miden_assembly_syntax/ast/item/
index.rs

1/// Represents the index of an item within its respective storage vector in some module
2#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
3#[repr(transparent)]
4pub struct ItemIndex(u16);
5
6impl ItemIndex {
7    pub fn new(id: usize) -> Self {
8        Self(id.try_into().expect("invalid item index: too many items"))
9    }
10
11    #[inline(always)]
12    pub const fn const_new(id: u16) -> Self {
13        Self(id)
14    }
15
16    /// Get the raw index value of this item
17    #[inline(always)]
18    pub const fn as_usize(&self) -> usize {
19        self.0 as usize
20    }
21}
22
23impl core::fmt::Display for ItemIndex {
24    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
25        write!(f, "{}", &self.as_usize())
26    }
27}
28
29/// Uniquely identifies an item in a set of [crate::ast::Module]
30///
31/// A [GlobalItemIndex] is assigned to an item when it is added to the linker's module
32/// graph. The index uniquely identifies that item in the graph, and provides a unique,
33/// copyable, machine-word sized handle that can be trivially stored, passed around, and later used
34/// to perform constant-complexity operations against that item.
35///
36/// <div class="warning">
37/// As a result of this being just an index into a specific instance of a [super::ModuleGraph],
38/// it does not provide any guarantees about uniqueness or stability when the same module is stored
39/// in multiple graphs - each graph may assign it a unique index. You must ensure that you do not
40/// store these indices and attempt to use them with just any module graph - it is only valid with
41/// the one it was assigned from.
42/// </div>
43///
44/// In addition to the linker's module graph, these indices are also used with an instance of a
45/// `MastForestBuilder`. This is because the linker and `MastForestBuilder` instances
46/// are paired, i.e. the linker stores the syntax trees and call graph analysis for a program, while
47/// the `MastForestBuilder` caches the compiled procedures for the same program, as derived from
48/// the corresponding graph.
49///
50/// This is intended for use when we are doing global inter-procedural analysis on a (possibly
51/// growable) set of modules. It is expected that the index of a module in the set, as well as the
52/// index of an item in a module, are stable once allocated in the graph. The set of modules and
53/// items can grow, as long as growing the set only allocates unused identifiers.
54///
55/// NOTE: This struct is the same size as a u32
56#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
57pub struct GlobalItemIndex {
58    /// The index of the containing module in the global set of modules
59    pub module: ModuleIndex,
60    /// The local index of the procedure in the module
61    pub index: ItemIndex,
62}
63
64impl core::fmt::Display for GlobalItemIndex {
65    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
66        write!(f, "{}:{}", &self.module, &self.index)
67    }
68}
69
70/// A strongly-typed index into a set of [crate::ast::Module]
71#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
72#[repr(transparent)]
73pub struct ModuleIndex(u16);
74impl ModuleIndex {
75    pub fn new(index: usize) -> Self {
76        Self(index.try_into().expect("invalid module index: too many modules"))
77    }
78
79    pub const fn const_new(index: u16) -> Self {
80        Self(index)
81    }
82
83    #[inline(always)]
84    pub const fn as_usize(&self) -> usize {
85        self.0 as usize
86    }
87}
88
89impl core::ops::Add<ItemIndex> for ModuleIndex {
90    type Output = GlobalItemIndex;
91
92    fn add(self, rhs: ItemIndex) -> Self::Output {
93        GlobalItemIndex { module: self, index: rhs }
94    }
95}
96
97impl core::fmt::Display for ModuleIndex {
98    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
99        write!(f, "{}", &self.as_usize())
100    }
101}