rten_shape_inference/
sym_gen.rs

1//! Symbol name generator.
2
3use std::borrow::Cow;
4
5use crate::sym_expr::{SymExpr, Symbol};
6
7/// Generates named symbols.
8///
9/// Sometimes during shape inference it may be necessary to generate a new
10/// symbol to represent a value that cannot be represented as an expression.
11///
12/// Note that generally it is preferred to represent values computed from other
13/// values as symbolic expressions. This allows the expressions to be compared,
14/// simplified and otherwise manipulated.
15pub struct SymbolGen {
16    prefix: Cow<'static, str>,
17    next_symbol_id: u32,
18}
19
20impl Default for SymbolGen {
21    fn default() -> Self {
22        Self::new()
23    }
24}
25
26impl SymbolGen {
27    pub fn new() -> Self {
28        Self::with_prefix("unknown".into())
29    }
30
31    pub fn with_prefix(prefix: Cow<'static, str>) -> Self {
32        Self {
33            prefix,
34            next_symbol_id: 0,
35        }
36    }
37
38    fn gen_name(&mut self) -> String {
39        self.next_symbol_id += 1;
40        format!("{}_{}", self.prefix, self.next_symbol_id)
41    }
42
43    /// Generate a new symbolic value which is assumed to be positive.
44    pub fn gen_positive(&mut self) -> SymExpr {
45        SymExpr::Var(
46            Symbol {
47                name: self.gen_name(),
48                positive: true,
49            }
50            .into(),
51        )
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::{SymExpr, SymbolGen};
58
59    #[test]
60    fn test_symbol_gen() {
61        let mut sym_gen = SymbolGen::new();
62        assert_eq!(sym_gen.gen_positive(), SymExpr::pos_var("unknown_1"));
63        assert_eq!(sym_gen.gen_positive(), SymExpr::pos_var("unknown_2"));
64
65        let mut sym_gen = SymbolGen::with_prefix("foo".into());
66        assert_eq!(sym_gen.gen_positive(), SymExpr::pos_var("foo_1"));
67        assert_eq!(sym_gen.gen_positive(), SymExpr::pos_var("foo_2"));
68    }
69}