prune_lang/utils/
ident.rs1use super::intern::InternStr;
2use std::fmt;
3use std::sync::atomic;
4
5static COUNTER: atomic::AtomicUsize = atomic::AtomicUsize::new(1);
7
8#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
9pub struct Ident {
10 pub name: InternStr,
11 pub index: usize,
12}
13
14impl Ident {
15 pub fn fresh<S: AsRef<str>>(s: &S) -> Ident {
16 let name = InternStr::new(s.as_ref());
17 let index = COUNTER.fetch_add(1, atomic::Ordering::Relaxed);
18 Ident { name, index }
19 }
20
21 pub fn dummy<S: AsRef<str>>(s: &S) -> Ident {
22 let name = InternStr::new(s.as_ref());
23 Ident { name, index: 0 }
24 }
25
26 pub fn is_dummy(&self) -> bool {
27 self.index == 0
28 }
29
30 pub fn uniquify(&self) -> Ident {
31 let name = self.name;
32 let index = COUNTER.fetch_add(1, atomic::Ordering::Relaxed);
33 Ident { name, index }
34 }
35
36 pub fn as_str(&self) -> &'static str {
37 self.name.as_str()
38 }
39
40 pub fn tag_ctx(self, ctx: usize) -> IdentCtx {
41 IdentCtx { ident: self, ctx }
42 }
43}
44
45impl fmt::Debug for Ident {
46 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
47 if self.is_dummy() {
48 write!(f, "{:?}", self.name)
49 } else {
50 write!(f, "{:?}_{:?}", self.name, self.index)
51 }
52 }
53}
54
55impl fmt::Display for Ident {
56 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57 write!(f, "{}", self.name)
58 }
59}
60
61impl AsRef<str> for Ident {
62 fn as_ref(&self) -> &str {
63 self.name.as_str()
64 }
65}
66
67#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
68pub struct IdentCtx {
69 pub ident: Ident,
70 pub ctx: usize,
71}
72
73impl fmt::Debug for IdentCtx {
74 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75 write!(f, "{:?}_{:?}", self.ident, self.ctx)
76 }
77}
78
79impl fmt::Display for IdentCtx {
80 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81 write!(f, "{}_{}", self.ident, self.ctx)
82 }
83}
84
85#[test]
86fn ident_fresh_test() {
87 let s1 = InternStr::new(&"foo");
88 let x1 = Ident::fresh(&s1);
89 let x2 = Ident::fresh(&s1);
90 let x3 = Ident::fresh(&s1);
91 assert_ne!(x1, x2);
92 assert_ne!(x1, x3);
93 assert_ne!(x2, x3);
94 assert_eq!(x1.name, x2.name);
95 assert_eq!(x1.name, x3.name);
96 assert_eq!(x2.name, x3.name);
97}
98
99#[test]
100fn ident_uniquify_test() {
101 let s1 = InternStr::new(&"foo");
102 let x1 = Ident::fresh(&s1);
103 let x2 = x1.uniquify();
104 assert_ne!(x1, x2);
105 assert_eq!(x1.name, x2.name);
106}