erg_common/
fresh.rs

1use std::cell::RefCell;
2use std::rc::Rc;
3use std::sync::atomic::AtomicUsize;
4
5use crate::Str;
6
7#[derive(Debug, Default)]
8pub struct FreshNameGenerator {
9    id: AtomicUsize,
10    /// To avoid conflicts with variable names generated in another phase
11    prefix: &'static str,
12}
13
14impl FreshNameGenerator {
15    pub const fn new(prefix: &'static str) -> Self {
16        Self {
17            id: AtomicUsize::new(0),
18            prefix,
19        }
20    }
21
22    pub fn fresh_varname(&self) -> Str {
23        self.id.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
24        let i = self.id.load(std::sync::atomic::Ordering::SeqCst);
25        Str::from(format!("%v_{}_{i}", self.prefix))
26    }
27
28    pub fn fresh_param_name(&self) -> Str {
29        self.id.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
30        let i = self.id.load(std::sync::atomic::Ordering::SeqCst);
31        Str::from(format!("%p_{}_{i}", self.prefix))
32    }
33}
34
35pub static FRESH_GEN: FreshNameGenerator = FreshNameGenerator::new("global");
36
37#[derive(Debug, Clone, Default)]
38pub struct SharedFreshNameGenerator(Rc<RefCell<FreshNameGenerator>>);
39
40impl SharedFreshNameGenerator {
41    pub fn new(prefix: &'static str) -> Self {
42        Self(Rc::new(RefCell::new(FreshNameGenerator::new(prefix))))
43    }
44
45    pub fn fresh_varname(&self) -> Str {
46        self.0.borrow_mut().fresh_varname()
47    }
48
49    pub fn fresh_param_name(&self) -> Str {
50        self.0.borrow_mut().fresh_param_name()
51    }
52}