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}