1use std::{
20 borrow::{Borrow, Cow},
21 collections::HashMap,
22 iter,
23 num::NonZeroU32,
24 ops,
25 rc::Rc,
26};
27
28use crate::*;
29
30#[derive(Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
32pub struct SymbolName {
33 name: Rc<str>,
34}
35
36impl ops::Deref for SymbolName {
37 type Target = str;
38
39 fn deref(&self) -> &Self::Target {
40 &self.name[..]
41 }
42}
43
44impl From<Cow<'_, str>> for SymbolName {
45 fn from(value: Cow<'_, str>) -> Self {
46 SymbolName {
47 name: Rc::from(&*value),
48 }
49 }
50}
51
52impl<'a> From<&'a str> for SymbolName {
53 fn from(value: &'a str) -> Self {
54 SymbolName {
55 name: Rc::from(value),
56 }
57 }
58}
59
60impl Borrow<str> for SymbolName {
61 fn borrow(&self) -> &str {
62 &self.name[..]
63 }
64}
65
66#[derive(miniserde::Serialize, miniserde::Deserialize, Clone, Debug, Default)]
68pub struct SymbolSource<T: SymbolPrimitive = NonZeroU32> {
69 next_symbol: Symbol<T>,
70 names: Vec<Option<SymbolName>>,
71}
72
73#[macro_export]
75macro_rules! syms {
76 () => {
77 $crate::SymbolSource::generate_fresh()
78 };
79}
80
81fn advance<T: SymbolPrimitive>(sym: &mut Symbol<T>) {
82 let n: NonZeroU32 = sym.n.into();
83 let x: T = n
84 .saturating_add(1)
85 .try_into()
86 .ok()
87 .expect("unreachable: could not convert +1");
88 *sym = Symbol { n: x };
89 debug_assert_ne!(x.into().get(), T::MAX, "ran out of Symbol space?");
90}
91
92impl<T: SymbolPrimitive> SymbolSource<T> {
93 pub fn new() -> Self {
95 Self {
96 next_symbol: Symbol::first(),
97 names: vec![],
98 }
99 }
100 pub fn sym<'a, const N: usize>(&mut self) -> [Symbol<T>; N] {
102 let mut result = [Symbol::first(); N];
103 for dest in result.iter_mut() {
104 *dest = self.next_sym(None);
105 }
106 result
108 }
109 pub fn with_names<'a, const N: usize, S: Into<Cow<'static, str>>>(
111 &mut self,
112 names: [Option<S>; N],
113 ) -> [Symbol<T>; N] {
114 let mut result = [Symbol::first(); N];
115 for (dest, name) in result.iter_mut().zip(names.into_iter()) {
116 *dest = self.next_sym(name.map(|s| s.into()));
117 }
118 result
120 }
121 pub fn next_sym(&mut self, name: Option<Cow<str>>) -> Symbol<T> {
123 let ret = self.next_symbol;
124 advance(&mut self.next_symbol);
125 self.names.push(name.map(|cow| cow.into()));
126 ret
127 }
128
129 pub fn name_of(&self, sym: Symbol) -> Cow<'_, str> {
135 match self.names.get(sym.usize()) {
136 Some(Some(name)) => Cow::Borrowed(&name.name[..]),
137 Some(None) | None => Cow::Owned(format!("g{}", sym.usize())),
138 }
139 }
140
141 pub fn original_name_of(&self, sym: Symbol) -> Option<&str> {
144 self.names
145 .get(sym.usize())
146 .map(|v| v.as_ref().map(|v| &v.name[..]))
147 .unwrap_or(None)
148 }
149
150 pub fn num_syms(&self) -> usize {
152 self.next_symbol.usize()
153 }
154
155 pub fn generate(&mut self) -> impl Iterator<Item = Symbol<T>> + use<'_, T> {
157 Generate { source: self }
158 }
159
160 pub fn generate_fresh() -> impl Iterator<Item = Symbol<T>> {
163 struct Unfolder<T: SymbolPrimitive>(Symbol<T>);
164
165 impl<T: SymbolPrimitive> Iterator for Unfolder<T> {
166 type Item = Symbol<T>;
167 fn next(&mut self) -> Option<Symbol<T>> {
168 let result = self.0;
169 advance(&mut self.0);
170 Some(result)
171 }
172 }
173
174 Unfolder(Symbol::first())
175 }
176
177 pub fn remap_symbols<F>(&mut self, mut map: F)
180 where
181 F: FnMut(Symbol<T>) -> Symbol<T>,
182 {
183 let mut new_names = vec![];
184 let mut new_source = SymbolSource::<T>::new();
185 for (name, sym) in self.names.iter().zip(new_source.generate()) {
186 let new_sym = map(sym).usize();
187 new_names
188 .extend(iter::repeat(None).take((new_sym + 1).saturating_sub(new_names.len())));
189 new_names[new_sym] = name.clone();
190 }
191 self.names = new_names;
192 }
193
194 pub fn truncate(&mut self, new_len: usize) {
201 assert_ne!(new_len, 0, "cannot truncate to zero length");
202 assert!(
203 new_len as u64 <= T::MAX as u64,
204 "attempt to truncate to a length that exceeds the limit"
205 );
206 self.names.truncate(new_len);
207 self.next_symbol = Symbol {
208 n: NonZeroU32::new(new_len as u32 + 1)
209 .expect("cannot truncate to this length")
210 .try_into()
211 .ok()
212 .expect("cannot truncate to this length (2)"),
213 };
214 }
215
216 pub fn names(&self) -> Vec<Option<SymbolName>> {
223 self.names.clone()
224 }
225
226 pub fn name_map(&self) -> HashMap<SymbolName, Symbol> {
229 self.names
230 .iter()
231 .zip(SymbolSource::generate_fresh())
232 .filter_map(|(opt, i)| opt.clone().map(|name| (name, i)))
233 .collect::<HashMap<_, _>>()
234 }
235}
236
237struct Generate<'a, T: SymbolPrimitive> {
239 source: &'a mut SymbolSource<T>,
240}
241
242impl<'a, T: SymbolPrimitive> Iterator for Generate<'a, T> {
243 type Item = Symbol<T>;
244
245 fn next(&mut self) -> Option<Self::Item> {
246 Some(self.source.next_sym(None))
247 }
248}
249
250mod miniserde_impls {
251 use super::SymbolName;
252 use miniserde::de::{Deserialize, Visitor};
253 use miniserde::{Result, make_place};
254 use miniserde::{Serialize, de, ser};
255 use std::rc::Rc;
256
257 make_place!(Place);
258
259 impl Visitor for Place<SymbolName> {
260 fn string(&mut self, s: &str) -> Result<()> {
261 self.out = Some(SymbolName { name: Rc::from(s) });
262 Ok(())
263 }
264 }
265
266 impl Deserialize for SymbolName {
267 fn begin(out: &mut Option<Self>) -> &mut dyn de::Visitor {
268 Place::new(out)
269 }
270 }
271
272 impl Serialize for SymbolName {
273 fn begin(&self) -> ser::Fragment<'_> {
274 ser::Fragment::Str(self.name.to_string().into())
275 }
276 }
277}