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 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 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 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 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#[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 pub fn name_id_p(id: u64, name: &[&str]) -> Loc<NameID> {
141 NameID(id, Path::from_strs(name)).nowhere()
142 }
143}