forked from egraphs-good/egg
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil.rs
99 lines (86 loc) · 2.96 KB
/
util.rs
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use std::fmt;
use symbolic_expressions::Sexp;
use fmt::{Debug, Display, Formatter};
#[allow(unused_imports)]
use crate::*;
/// An interned string.
///
/// This is provided by the [`symbol_table`](https://crates.io/crates/symbol_table) crate.
///
/// Internally, `egg` frequently compares [`Var`]s and elements of
/// [`Language`]s. To keep comparisons fast, `egg` provides [`Symbol`] a simple
/// wrapper providing interned strings.
///
/// You may wish to use [`Symbol`] in your own [`Language`]s to increase
/// performance and keep enode sizes down (a [`Symbol`] is only 4 bytes,
/// compared to 24 for a `String`.)
///
/// A [`Symbol`] is simply a wrapper around an integer.
/// When creating a [`Symbol`] from a string, `egg` looks up it up in a global
/// table, returning the index (inserting it if not found).
/// That integer is used to cheaply implement
/// `Copy`, `Clone`, `PartialEq`, `Eq`, `PartialOrd`, `Ord`, and `Hash`.
///
/// The internal symbol cache leaks the strings, which should be
/// fine if you only put in things like variable names and identifiers.
///
/// # Example
/// ```rust
/// use egg::Symbol;
///
/// assert_eq!(Symbol::from("foo"), Symbol::from("foo"));
/// assert_eq!(Symbol::from("foo"), "foo".parse().unwrap());
///
/// assert_ne!(Symbol::from("foo"), Symbol::from("bar"));
/// ```
///
pub use symbol_table::GlobalSymbol as Symbol;
pub(crate) type BuildHasher = fxhash::FxBuildHasher;
pub(crate) type HashMap<K, V> = hashbrown::HashMap<K, V, BuildHasher>;
pub(crate) type HashSet<K> = hashbrown::HashSet<K, BuildHasher>;
pub(crate) type IndexMap<K, V> = indexmap::IndexMap<K, V, BuildHasher>;
pub(crate) type IndexSet<K> = indexmap::IndexSet<K, BuildHasher>;
pub(crate) type Instant = instant::Instant;
pub(crate) type Duration = instant::Duration;
pub(crate) fn concat_vecs<T>(to: &mut Vec<T>, mut from: Vec<T>) {
if to.len() < from.len() {
std::mem::swap(to, &mut from)
}
to.extend(from);
}
pub(crate) fn pretty_print(
buf: &mut String,
sexp: &Sexp,
width: usize,
level: usize,
) -> std::fmt::Result {
use std::fmt::Write;
if let Sexp::List(list) = sexp {
let indent = sexp.to_string().len() > width;
write!(buf, "(")?;
for (i, val) in list.iter().enumerate() {
if indent && i > 0 {
writeln!(buf)?;
for _ in 0..level {
write!(buf, " ")?;
}
}
pretty_print(buf, val, width, level + 1)?;
if !indent && i < list.len() - 1 {
write!(buf, " ")?;
}
}
write!(buf, ")")?;
Ok(())
} else {
// I don't care about quotes
write!(buf, "{}", sexp.to_string().trim_matches('"'))
}
}
/// A wrapper that uses display implementation as debug
pub(crate) struct DisplayAsDebug<T>(pub T);
impl<T: Display> Debug for DisplayAsDebug<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Display::fmt(&self.0, f)
}
}