1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//! Source

use symbol::Symbol;
use symbol::repr::{SymbolRepr, FIRST_ID};

/// A source of numeric symbols.
#[allow(missing_copy_implementations)]
#[derive(Clone, Debug, Default)]
pub struct SymbolSource {
    next_id: SymbolRepr,
}

impl SymbolSource {
    /// Creates a source of numeric symbols with an empty symbol space.
    pub fn new() -> Self {
        Self::default()
    }
    /// Returns generated symbols.
    pub fn sym<T>(&mut self) -> T
        where T: SymbolContainer
    {
        T::generate(self)
    }
    /// Generates a new unique symbol.
    pub fn next_sym(&mut self) -> Symbol {
        let ret = Symbol::from(self.next_id);
        self.next_id = self.next_id.saturating_add(1 + FIRST_ID) - FIRST_ID;
        ret
    }
    /// Returns the number of symbols in use.
    pub fn num_syms(&self) -> usize {
        self.next_id as usize
    }
    /// Returns an iterator that generates symbols.
    pub fn generate(&mut self) -> Generate {
        Generate { source: self }
    }
}

/// Trait used to generate symbols.
pub trait SymbolContainer {
    /// Generates symbols.
    fn generate(source: &mut SymbolSource) -> Self;
}

macro_rules! impl_generate {
    (Symbol, next_sym, $($T:ident, $next_sym:ident,)*) => (
        impl SymbolContainer for ( Symbol $(, $T)* ) {
            fn generate(source: &mut SymbolSource) -> Self {
                (source.next_sym()
                 $(, source.$next_sym())*)
            }
        }
        impl_generate!($($T, $next_sym,)*);
    );
    // base case
    () => {}
}

impl_generate!(
    Symbol, next_sym, Symbol, next_sym, Symbol, next_sym, Symbol, next_sym,
    Symbol, next_sym, Symbol, next_sym, Symbol, next_sym, Symbol, next_sym,
    Symbol, next_sym, Symbol, next_sym, Symbol, next_sym, Symbol, next_sym,
    Symbol, next_sym, Symbol, next_sym, Symbol, next_sym, Symbol, next_sym,
    Symbol, next_sym, Symbol, next_sym, Symbol, next_sym, Symbol, next_sym,
    Symbol, next_sym, Symbol, next_sym, Symbol, next_sym, Symbol, next_sym,
    Symbol, next_sym, Symbol, next_sym, Symbol, next_sym, Symbol, next_sym,
    Symbol, next_sym, Symbol, next_sym, Symbol, next_sym, Symbol, next_sym,
);

/// Iterator for generating symbols.
pub struct Generate<'a> {
    source: &'a mut SymbolSource,
}

impl<'a> Iterator for Generate<'a> {
    type Item = Symbol;

    fn next(&mut self) -> Option<Self::Item> {
        Some(self.source.next_sym())
    }
}