Skip to main content

prune_lang/utils/
ident.rs

1use super::intern::InternStr;
2use std::fmt;
3use std::sync::atomic;
4
5// counter zero is reserved for dummy ident
6static 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}