spade_common/
id_tracker.rs

1use serde::{Deserialize, Serialize};
2use std::sync::atomic::AtomicU64;
3use std::sync::atomic::Ordering::Relaxed;
4
5macro_rules! def_id_tracker {
6    ($name:ident) => {
7        #[derive(Debug, Serialize, Deserialize)]
8        pub struct $name {
9            id: AtomicU64,
10        }
11
12        impl $name {
13            pub fn new() -> Self {
14                Self {
15                    id: AtomicU64::new(0),
16                }
17            }
18
19            pub fn new_at(id: u64) -> Self {
20                Self {
21                    id: AtomicU64::new(id),
22                }
23            }
24
25            pub fn next(&self) -> u64 {
26                self.id.fetch_add(1, Relaxed)
27            }
28
29            pub fn peek(&self) -> u64 {
30                self.id.load(Relaxed)
31            }
32
33            /// Clone this ID tracker. After this is done, only one of the ID trackers may
34            /// be used otherwise duplicate IDs will be generated. It is up to the caller of this
35            /// method to make sure that no mutable references are handed out to one of the clonse
36            pub fn make_clone(&self) -> Self {
37                Self {
38                    id: AtomicU64::new(self.id.load(Relaxed)),
39                }
40            }
41        }
42        impl Default for $name {
43            fn default() -> Self {
44                Self::new()
45            }
46        }
47    };
48}
49
50macro_rules! def_typed_id_tracker {
51    ($name:ident, $type_name:ident) => {
52        #[derive(Debug, Serialize, Deserialize)]
53        pub struct $name {
54            id: AtomicU64,
55        }
56
57        impl $name {
58            pub fn new() -> Self {
59                Self {
60                    id: AtomicU64::new(0),
61                }
62            }
63
64            pub fn new_at(id: u64) -> Self {
65                Self {
66                    id: AtomicU64::new(id),
67                }
68            }
69
70            pub fn next(&self) -> $type_name {
71                let result = self.id.fetch_add(1, Relaxed);
72                $type_name(result)
73            }
74
75            pub fn peek(&self) -> u64 {
76                self.id.load(Relaxed)
77            }
78
79            /// Clone this ID tracker. After this is done, only one of the ID trackers may
80            /// be used otherwise duplicate IDs will be generated. It is up to the caller of this
81            /// method to make sure that no mutable references are handed out to one of the clonse
82            pub fn make_clone(&self) -> Self {
83                Self {
84                    id: AtomicU64::new(self.id.load(Relaxed)),
85                }
86            }
87        }
88        impl Default for $name {
89            fn default() -> Self {
90                Self::new()
91            }
92        }
93    };
94}
95
96pub struct NameIdInner(pub u64);
97
98/// An ID of an expression-like thing. In practice something that has a type in the
99/// type inferer.
100#[derive(Eq, PartialEq, PartialOrd, Ord, Hash, Clone, Copy, Serialize, Deserialize, Debug)]
101pub struct ExprID(pub u64);
102
103#[derive(Eq, PartialEq, PartialOrd, Ord, Hash, Clone, Copy, Serialize, Deserialize, Debug)]
104pub struct ImplID(pub u64);
105
106def_typed_id_tracker!(ExprIdTracker, ExprID);
107def_typed_id_tracker!(ImplIdTracker, ImplID);
108def_id_tracker!(NameIdTracker);
109def_id_tracker!(AAVarTracker);