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