spade_common/
name.rs

1use serde::{Deserialize, Serialize};
2
3use crate::location_info::{Loc, WithLocation};
4
5#[derive(PartialEq, Debug, Clone, Eq, Hash, Serialize, Deserialize)]
6pub struct Identifier(pub String);
7
8impl std::fmt::Display for Identifier {
9    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10        write!(f, "{}", self.0)
11    }
12}
13
14impl WithLocation for Identifier {}
15
16#[derive(PartialEq, Debug, Clone, Eq, Hash, Serialize, Deserialize)]
17pub struct Path(pub Vec<Loc<Identifier>>);
18impl WithLocation for Path {}
19
20impl Path {
21    pub fn as_strs(&self) -> Vec<&str> {
22        self.0.iter().map(|id| id.inner.0.as_ref()).collect()
23    }
24    pub fn as_strings(&self) -> Vec<String> {
25        self.0.iter().map(|id| id.inner.0.clone()).collect()
26    }
27    /// Generate a path from a list of strings
28    pub fn from_strs(elems: &[&str]) -> Self {
29        Path(
30            elems
31                .iter()
32                .map(|x| Identifier(x.to_string()).nowhere())
33                .collect(),
34        )
35    }
36
37    pub fn ident(ident: Loc<Identifier>) -> Self {
38        Self(vec![ident])
39    }
40
41    pub fn push_ident(&self, ident: Loc<Identifier>) -> Path {
42        let mut result = self.clone();
43        result.0.push(ident);
44        result
45    }
46
47    pub fn pop(&self) -> Self {
48        let mut result = self.clone();
49        result.0.pop().expect("Failed to pop identifier from path");
50        result
51    }
52
53    pub fn join(&self, other: Path) -> Path {
54        let mut result = self.clone();
55        for ident in other.0 {
56            result = result.push_ident(ident);
57        }
58        result
59    }
60
61    /// If the path is lib::<rest> return Some(<rest>), else None
62    pub fn lib_relative(&self) -> Option<Path> {
63        if self.0.first() == Some(&Identifier("lib".to_string()).nowhere()) {
64            Some(Path(Vec::from(&self.0[1..])))
65        } else {
66            None
67        }
68    }
69
70    /// The last element of the path. Panics if the path is empty
71    pub fn tail(&self) -> Identifier {
72        self.0
73            .last()
74            .expect("Tried getting tail of empty path")
75            .inner
76            .clone()
77    }
78
79    /// Returns the whole path apart from the tail. Panics if the path is empty
80    pub fn prelude(&self) -> Path {
81        Self(self.0[0..self.0.len() - 1].to_owned())
82    }
83}
84
85impl std::fmt::Display for Path {
86    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87        write!(f, "{}", self.as_strs().join("::"))
88    }
89}
90
91/// Anything named will get assigned a unique name ID during AST lowering in order to avoid caring
92/// about scopes once HIR has been generated. This is the type of those IDs
93///
94/// The associated string is only used for formatting when printing. The hash and eq methods do not
95/// use it
96#[derive(Clone, Serialize, Deserialize)]
97pub struct NameID(pub u64, pub Path);
98impl WithLocation for NameID {}
99
100impl std::cmp::PartialEq for NameID {
101    fn eq(&self, other: &Self) -> bool {
102        self.0 == other.0
103    }
104}
105
106impl std::cmp::Eq for NameID {}
107
108impl std::cmp::PartialOrd for NameID {
109    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
110        Some(self.0.cmp(&other.0))
111    }
112}
113
114impl std::cmp::Ord for NameID {
115    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
116        self.0.cmp(&other.0)
117    }
118}
119
120impl std::hash::Hash for NameID {
121    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
122        self.0.hash(state);
123    }
124}
125
126impl std::fmt::Debug for NameID {
127    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128        write!(f, "{}#{}", self.1, self.0)
129    }
130}
131impl std::fmt::Display for NameID {
132    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133        write!(f, "{}", self.1)
134    }
135}
136
137pub mod testutil {
138    use super::*;
139    pub fn name_id(id: u64, name: &str) -> Loc<NameID> {
140        NameID(id, Path::from_strs(&[name])).nowhere()
141    }
142
143    /// Shorthand for creating a name_id with static strs as name
144    pub fn name_id_p(id: u64, name: &[&str]) -> Loc<NameID> {
145        NameID(id, Path::from_strs(name)).nowhere()
146    }
147}