petr_utils/
common_types.rs

1//! types used across multiple petr crates
2
3use std::rc::Rc;
4
5#[cfg(feature = "debug")]
6use lazy_static::lazy_static;
7
8use crate::{idx_map_key, IndexMap};
9#[cfg(feature = "debug")]
10lazy_static! {
11    pub static ref SYMBOL_INTERNER: std::sync::RwLock<Vec<String>> = std::sync::RwLock::new(Vec::new());
12}
13
14idx_map_key!(
15    /// The ID type of a type declaration.
16    TypeId
17);
18
19#[derive(Clone, Copy, Debug, PartialEq, Eq)]
20pub struct Identifier {
21    pub id:   SymbolId,
22    pub span: crate::Span,
23}
24
25// ignore the span when comparing with ord and partialord
26impl PartialOrd for Identifier {
27    fn partial_cmp(
28        &self,
29        other: &Self,
30    ) -> Option<std::cmp::Ordering> {
31        Some(self.cmp(other))
32    }
33}
34
35impl Ord for Identifier {
36    fn cmp(
37        &self,
38        other: &Self,
39    ) -> std::cmp::Ordering {
40        self.id.cmp(&other.id)
41    }
42}
43
44impl Identifier {
45    pub fn span(&self) -> crate::Span {
46        self.span
47    }
48}
49
50#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
51pub struct Path {
52    pub identifiers: Box<[Identifier]>,
53}
54
55impl Path {
56    pub fn new(identifiers: Vec<Identifier>) -> Self {
57        Self {
58            identifiers: identifiers.into_boxed_slice(),
59        }
60    }
61}
62
63impl Path {
64    pub fn len(&self) -> usize {
65        self.identifiers.len()
66    }
67
68    pub fn is_empty(&self) -> bool {
69        self.identifiers.is_empty()
70    }
71
72    pub fn iter(&self) -> std::slice::Iter<'_, Identifier> {
73        self.identifiers.iter()
74    }
75}
76
77#[cfg(not(feature = "debug"))]
78idx_map_key!(
79    /// The ID of an ident in the symbol interner
80    SymbolId
81);
82
83#[cfg(feature = "debug")]
84#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
85#[doc = r"The ID of an ident in the symbol interner"]
86pub struct SymbolId(usize);
87
88#[cfg(feature = "debug")]
89impl From<usize> for SymbolId {
90    fn from(value: usize) -> Self {
91        Self(value)
92    }
93}
94#[cfg(feature = "debug")]
95impl From<SymbolId> for usize {
96    fn from(o: SymbolId) -> usize {
97        o.0
98    }
99}
100#[cfg(feature = "debug")]
101impl std::fmt::Display for SymbolId {
102    fn fmt(
103        &self,
104        f: &mut std::fmt::Formatter<'_>,
105    ) -> std::fmt::Result {
106        let name = crate::SYMBOL_INTERNER.read().unwrap().get(self.0).unwrap().to_string();
107        write!(f, "{}", name)
108    }
109}
110
111#[derive(Default, Debug, Clone)]
112pub struct SymbolInterner {
113    symbol_map: IndexMap<SymbolId, Rc<str>>,
114}
115
116impl SymbolInterner {
117    pub fn get_path(
118        &self,
119        path: &Path,
120    ) -> Vec<Rc<str>> {
121        path.iter().map(|id| self.get(id.id)).collect()
122    }
123
124    #[cfg(not(feature = "debug"))]
125    pub fn insert(
126        &mut self,
127        v: Rc<str>,
128    ) -> SymbolId {
129        match self.symbol_map.contains_value(v.clone()) {
130            Some(k) => k,
131            None => self.symbol_map.insert(v),
132        }
133    }
134
135    #[cfg(feature = "debug")]
136    pub fn insert(
137        &mut self,
138        v: Rc<str>,
139    ) -> SymbolId {
140        match self.symbol_map.contains_value(v.clone()) {
141            Some(k) => k,
142            None => {
143                let id = self.symbol_map.insert(v.clone());
144                crate::SYMBOL_INTERNER.write().unwrap().insert(id.0, v.to_string());
145                id
146            },
147        }
148    }
149
150    pub fn get(
151        &self,
152        id: SymbolId,
153    ) -> Rc<str> {
154        self.symbol_map.get(id).clone()
155    }
156}