calyx_utils/
namegenerator.rs

1use crate::Id;
2use std::collections::{HashMap, HashSet};
3
4/// Simple HashMap-based name generator that generates new names for each
5/// prefix.
6#[derive(Clone, Debug)]
7pub struct NameGenerator {
8    name_hash: HashMap<Id, i64>,
9    generated_names: HashSet<Id>,
10}
11
12impl NameGenerator {
13    /// Create a NameGenerator where `names` are already defined so that this generator
14    /// will never generate those names.
15    pub fn with_prev_defined_names(names: HashSet<Id>) -> Self {
16        NameGenerator {
17            generated_names: names,
18            name_hash: HashMap::default(),
19        }
20    }
21
22    /// Add generated names
23    pub fn add_names(&mut self, names: HashSet<Id>) {
24        self.generated_names.extend(names)
25    }
26
27    /// Returns a new String that starts with `prefix`.
28    /// For example:
29    /// ```
30    /// namegen.gen_name("seq");  // Generates "seq0"
31    /// namegen.gen_name("seq");  // Generates "seq1"
32    /// ```
33    pub fn gen_name<S>(&mut self, prefix: S) -> Id
34    where
35        S: Into<Id>,
36    {
37        let mut cur_prefix: Id = prefix.into();
38        loop {
39            // Insert default value for this prefix if there is no entry.
40            let count = self
41                .name_hash
42                .entry(cur_prefix)
43                .and_modify(|v| *v += 1)
44                .or_insert(-1);
45
46            let name = if *count == -1 {
47                cur_prefix
48            } else {
49                Id::from(cur_prefix.to_string() + &count.to_string())
50            };
51
52            // If we've not generated this name before, return it.
53            if !self.generated_names.contains(&name) {
54                self.generated_names.insert(name);
55                return name;
56            }
57
58            // If the name was generated before, use the current name as the prefix.
59            cur_prefix = name;
60        }
61    }
62}