1use super::functions::*;
6use crate::expr_util::lift_loose_bvars;
7use std::collections::HashMap;
8
9#[allow(dead_code)]
11pub struct PathBuf {
12 components: Vec<String>,
13}
14#[allow(dead_code)]
15impl PathBuf {
16 pub fn new() -> Self {
18 Self {
19 components: Vec::new(),
20 }
21 }
22 pub fn push(&mut self, comp: impl Into<String>) {
24 self.components.push(comp.into());
25 }
26 pub fn pop(&mut self) {
28 self.components.pop();
29 }
30 pub fn as_str(&self) -> String {
32 self.components.join("/")
33 }
34 pub fn depth(&self) -> usize {
36 self.components.len()
37 }
38 pub fn clear(&mut self) {
40 self.components.clear();
41 }
42}
43#[allow(dead_code)]
45pub struct RawFnPtr {
46 ptr: usize,
48 arity: usize,
49 name: String,
50}
51#[allow(dead_code)]
52impl RawFnPtr {
53 pub fn new(ptr: usize, arity: usize, name: impl Into<String>) -> Self {
55 Self {
56 ptr,
57 arity,
58 name: name.into(),
59 }
60 }
61 pub fn arity(&self) -> usize {
63 self.arity
64 }
65 pub fn name(&self) -> &str {
67 &self.name
68 }
69 pub fn raw(&self) -> usize {
71 self.ptr
72 }
73}
74#[allow(dead_code)]
76pub struct TransformStat {
77 before: StatSummary,
78 after: StatSummary,
79}
80#[allow(dead_code)]
81impl TransformStat {
82 pub fn new() -> Self {
84 Self {
85 before: StatSummary::new(),
86 after: StatSummary::new(),
87 }
88 }
89 pub fn record_before(&mut self, v: f64) {
91 self.before.record(v);
92 }
93 pub fn record_after(&mut self, v: f64) {
95 self.after.record(v);
96 }
97 pub fn mean_ratio(&self) -> Option<f64> {
99 let b = self.before.mean()?;
100 let a = self.after.mean()?;
101 if b.abs() < f64::EPSILON {
102 return None;
103 }
104 Some(a / b)
105 }
106}
107#[allow(dead_code)]
109pub struct TokenBucket {
110 capacity: u64,
111 tokens: u64,
112 refill_per_ms: u64,
113 last_refill: crate::wall_clock::Instant,
114}
115#[allow(dead_code)]
116impl TokenBucket {
117 pub fn new(capacity: u64, refill_per_ms: u64) -> Self {
119 Self {
120 capacity,
121 tokens: capacity,
122 refill_per_ms,
123 last_refill: crate::wall_clock::Instant::now(),
124 }
125 }
126 pub fn try_consume(&mut self, n: u64) -> bool {
128 self.refill();
129 if self.tokens >= n {
130 self.tokens -= n;
131 true
132 } else {
133 false
134 }
135 }
136 fn refill(&mut self) {
137 let now = crate::wall_clock::Instant::now();
138 let elapsed_ms = now.duration_since(self.last_refill).as_millis() as u64;
139 if elapsed_ms > 0 {
140 let new_tokens = elapsed_ms * self.refill_per_ms;
141 self.tokens = (self.tokens + new_tokens).min(self.capacity);
142 self.last_refill = now;
143 }
144 }
145 pub fn available(&self) -> u64 {
147 self.tokens
148 }
149 pub fn capacity(&self) -> u64 {
151 self.capacity
152 }
153}
154#[allow(dead_code)]
156pub struct SlidingSum {
157 window: Vec<f64>,
158 capacity: usize,
159 pos: usize,
160 sum: f64,
161 count: usize,
162}
163#[allow(dead_code)]
164impl SlidingSum {
165 pub fn new(capacity: usize) -> Self {
167 Self {
168 window: vec![0.0; capacity],
169 capacity,
170 pos: 0,
171 sum: 0.0,
172 count: 0,
173 }
174 }
175 pub fn push(&mut self, val: f64) {
177 let oldest = self.window[self.pos];
178 self.sum -= oldest;
179 self.sum += val;
180 self.window[self.pos] = val;
181 self.pos = (self.pos + 1) % self.capacity;
182 if self.count < self.capacity {
183 self.count += 1;
184 }
185 }
186 pub fn sum(&self) -> f64 {
188 self.sum
189 }
190 pub fn mean(&self) -> Option<f64> {
192 if self.count == 0 {
193 None
194 } else {
195 Some(self.sum / self.count as f64)
196 }
197 }
198 pub fn count(&self) -> usize {
200 self.count
201 }
202}
203#[allow(dead_code)]
205pub struct ConfigNode {
206 key: String,
207 value: Option<String>,
208 children: Vec<ConfigNode>,
209}
210#[allow(dead_code)]
211impl ConfigNode {
212 pub fn leaf(key: impl Into<String>, value: impl Into<String>) -> Self {
214 Self {
215 key: key.into(),
216 value: Some(value.into()),
217 children: Vec::new(),
218 }
219 }
220 pub fn section(key: impl Into<String>) -> Self {
222 Self {
223 key: key.into(),
224 value: None,
225 children: Vec::new(),
226 }
227 }
228 pub fn add_child(&mut self, child: ConfigNode) {
230 self.children.push(child);
231 }
232 pub fn key(&self) -> &str {
234 &self.key
235 }
236 pub fn value(&self) -> Option<&str> {
238 self.value.as_deref()
239 }
240 pub fn num_children(&self) -> usize {
242 self.children.len()
243 }
244 pub fn lookup(&self, path: &str) -> Option<&str> {
246 let mut parts = path.splitn(2, '.');
247 let head = parts.next()?;
248 let tail = parts.next();
249 if head != self.key {
250 return None;
251 }
252 match tail {
253 None => self.value.as_deref(),
254 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
255 }
256 }
257 fn lookup_relative(&self, path: &str) -> Option<&str> {
258 let mut parts = path.splitn(2, '.');
259 let head = parts.next()?;
260 let tail = parts.next();
261 if head != self.key {
262 return None;
263 }
264 match tail {
265 None => self.value.as_deref(),
266 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
267 }
268 }
269}
270#[allow(dead_code)]
272pub struct SimpleDag {
273 edges: Vec<Vec<usize>>,
275}
276#[allow(dead_code)]
277impl SimpleDag {
278 pub fn new(n: usize) -> Self {
280 Self {
281 edges: vec![Vec::new(); n],
282 }
283 }
284 pub fn add_edge(&mut self, from: usize, to: usize) {
286 if from < self.edges.len() {
287 self.edges[from].push(to);
288 }
289 }
290 pub fn successors(&self, node: usize) -> &[usize] {
292 self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
293 }
294 pub fn can_reach(&self, from: usize, to: usize) -> bool {
296 let mut visited = vec![false; self.edges.len()];
297 self.dfs(from, to, &mut visited)
298 }
299 fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
300 if cur == target {
301 return true;
302 }
303 if cur >= visited.len() || visited[cur] {
304 return false;
305 }
306 visited[cur] = true;
307 for &next in self.successors(cur) {
308 if self.dfs(next, target, visited) {
309 return true;
310 }
311 }
312 false
313 }
314 pub fn topological_sort(&self) -> Option<Vec<usize>> {
316 let n = self.edges.len();
317 let mut in_degree = vec![0usize; n];
318 for succs in &self.edges {
319 for &s in succs {
320 if s < n {
321 in_degree[s] += 1;
322 }
323 }
324 }
325 let mut queue: std::collections::VecDeque<usize> =
326 (0..n).filter(|&i| in_degree[i] == 0).collect();
327 let mut order = Vec::new();
328 while let Some(node) = queue.pop_front() {
329 order.push(node);
330 for &s in self.successors(node) {
331 if s < n {
332 in_degree[s] -= 1;
333 if in_degree[s] == 0 {
334 queue.push_back(s);
335 }
336 }
337 }
338 }
339 if order.len() == n {
340 Some(order)
341 } else {
342 None
343 }
344 }
345 pub fn num_nodes(&self) -> usize {
347 self.edges.len()
348 }
349}
350#[allow(dead_code)]
352pub enum Either2<A, B> {
353 First(A),
355 Second(B),
357}
358#[allow(dead_code)]
359impl<A, B> Either2<A, B> {
360 pub fn is_first(&self) -> bool {
362 matches!(self, Either2::First(_))
363 }
364 pub fn is_second(&self) -> bool {
366 matches!(self, Either2::Second(_))
367 }
368 pub fn first(self) -> Option<A> {
370 match self {
371 Either2::First(a) => Some(a),
372 _ => None,
373 }
374 }
375 pub fn second(self) -> Option<B> {
377 match self {
378 Either2::Second(b) => Some(b),
379 _ => None,
380 }
381 }
382 pub fn map_first<C, F: FnOnce(A) -> C>(self, f: F) -> Either2<C, B> {
384 match self {
385 Either2::First(a) => Either2::First(f(a)),
386 Either2::Second(b) => Either2::Second(b),
387 }
388 }
389}
390#[allow(dead_code)]
392#[allow(missing_docs)]
393pub enum DecisionNode {
394 Leaf(String),
396 Branch {
398 key: String,
399 val: String,
400 yes_branch: Box<DecisionNode>,
401 no_branch: Box<DecisionNode>,
402 },
403}
404#[allow(dead_code)]
405impl DecisionNode {
406 pub fn evaluate(&self, ctx: &std::collections::HashMap<String, String>) -> &str {
408 match self {
409 DecisionNode::Leaf(action) => action.as_str(),
410 DecisionNode::Branch {
411 key,
412 val,
413 yes_branch,
414 no_branch,
415 } => {
416 let actual = ctx.get(key).map(|s| s.as_str()).unwrap_or("");
417 if actual == val.as_str() {
418 yes_branch.evaluate(ctx)
419 } else {
420 no_branch.evaluate(ctx)
421 }
422 }
423 }
424 }
425 pub fn depth(&self) -> usize {
427 match self {
428 DecisionNode::Leaf(_) => 0,
429 DecisionNode::Branch {
430 yes_branch,
431 no_branch,
432 ..
433 } => 1 + yes_branch.depth().max(no_branch.depth()),
434 }
435 }
436}
437#[allow(dead_code)]
439pub struct StackCalc {
440 stack: Vec<i64>,
441}
442#[allow(dead_code)]
443impl StackCalc {
444 pub fn new() -> Self {
446 Self { stack: Vec::new() }
447 }
448 pub fn push(&mut self, n: i64) {
450 self.stack.push(n);
451 }
452 fn apply_binary(&mut self, op: impl FnOnce(i64, i64) -> i64) -> Option<i64> {
456 let (rest_len, a, b) = match self.stack[..] {
457 [ref rest @ .., a, b] => (rest.len(), a, b),
458 _ => return None,
459 };
460 let value = op(a, b);
461 self.stack.truncate(rest_len);
462 self.stack.push(value);
463 Some(value)
464 }
465 pub fn add(&mut self) -> Option<i64> {
469 self.apply_binary(|a, b| a + b)
470 }
471 pub fn sub(&mut self) -> Option<i64> {
475 self.apply_binary(|a, b| a - b)
476 }
477 pub fn mul(&mut self) -> Option<i64> {
481 self.apply_binary(|a, b| a * b)
482 }
483 pub fn peek(&self) -> Option<i64> {
485 self.stack.last().copied()
486 }
487 pub fn depth(&self) -> usize {
489 self.stack.len()
490 }
491}
492#[allow(dead_code)]
494pub struct Stopwatch {
495 start: crate::wall_clock::Instant,
496 splits: Vec<f64>,
497}
498#[allow(dead_code)]
499impl Stopwatch {
500 pub fn start() -> Self {
502 Self {
503 start: crate::wall_clock::Instant::now(),
504 splits: Vec::new(),
505 }
506 }
507 pub fn split(&mut self) {
509 self.splits.push(self.elapsed_ms());
510 }
511 pub fn elapsed_ms(&self) -> f64 {
513 self.start.elapsed().as_secs_f64() * 1000.0
514 }
515 pub fn splits(&self) -> &[f64] {
517 &self.splits
518 }
519 pub fn num_splits(&self) -> usize {
521 self.splits.len()
522 }
523}
524pub struct CacheManager {
526 pub(crate) whnf: WhnfCache,
527 pub(crate) defeq: DefEqCache,
528 pub(crate) infer: InferCache,
529}
530impl CacheManager {
531 pub fn new() -> Self {
533 CacheManager {
534 whnf: WhnfCache::new(1024, false),
535 defeq: DefEqCache::new(512),
536 infer: InferCache::new(256),
537 }
538 }
539 pub fn with_capacities(whnf_cap: usize, defeq_cap: usize, infer_cap: usize) -> Self {
541 CacheManager {
542 whnf: WhnfCache::new(whnf_cap, false),
543 defeq: DefEqCache::new(defeq_cap),
544 infer: InferCache::new(infer_cap),
545 }
546 }
547 pub fn whnf_mut(&mut self) -> &mut WhnfCache {
549 &mut self.whnf
550 }
551 pub fn defeq_mut(&mut self) -> &mut DefEqCache {
553 &mut self.defeq
554 }
555 pub fn infer_mut(&mut self) -> &mut InferCache {
557 &mut self.infer
558 }
559 pub fn clear_all(&mut self) {
561 self.whnf.clear();
562 self.defeq.clear();
563 self.infer.clear();
564 }
565 pub fn resize_all(&mut self, whnf_cap: usize, defeq_cap: usize, infer_cap: usize) {
567 self.whnf = WhnfCache::new(whnf_cap, self.whnf.is_transparent());
568 self.defeq = DefEqCache::new(defeq_cap);
569 self.infer = InferCache::new(infer_cap);
570 }
571 pub fn statistics(&self) -> CacheStatistics {
573 let (whnf_hits, whnf_misses) = self.whnf.stats();
574 let (defeq_hits, defeq_misses) = self.defeq.stats();
575 let (infer_hits, infer_misses) = self.infer.stats();
576 CacheStatistics {
577 whnf_hits,
578 whnf_misses,
579 whnf_hit_rate: self.whnf.hit_rate(),
580 defeq_hits,
581 defeq_misses,
582 defeq_hit_rate: self.defeq.hit_rate(),
583 infer_hits,
584 infer_misses,
585 infer_hit_rate: self.infer.hit_rate(),
586 }
587 }
588}
589#[derive(Clone, Debug, PartialEq, Eq)]
593pub enum SimplifiedExpr {
594 Var(String),
596 App(Box<SimplifiedExpr>, Box<SimplifiedExpr>),
598 Lambda(String, Box<SimplifiedExpr>),
600 Pi(String, Box<SimplifiedExpr>, Box<SimplifiedExpr>),
602}
603impl SimplifiedExpr {
604 pub fn hash(&self) -> u64 {
606 match self {
607 SimplifiedExpr::Var(name) => {
608 let mut bytes = vec![0u8];
609 bytes.extend_from_slice(name.as_bytes());
610 fnv1a_hash(&bytes)
611 }
612 SimplifiedExpr::App(f, arg) => {
613 let f_hash = f.hash();
614 let arg_hash = arg.hash();
615 let mut bytes = vec![1u8];
616 bytes.extend_from_slice(&f_hash.to_le_bytes());
617 bytes.extend_from_slice(&arg_hash.to_le_bytes());
618 fnv1a_hash(&bytes)
619 }
620 SimplifiedExpr::Lambda(name, body) => {
621 let body_hash = body.hash();
622 let mut bytes = vec![2u8];
623 bytes.extend_from_slice(name.as_bytes());
624 bytes.extend_from_slice(&body_hash.to_le_bytes());
625 fnv1a_hash(&bytes)
626 }
627 SimplifiedExpr::Pi(name, typ, body) => {
628 let typ_hash = typ.hash();
629 let body_hash = body.hash();
630 let mut bytes = vec![3u8];
631 bytes.extend_from_slice(name.as_bytes());
632 bytes.extend_from_slice(&typ_hash.to_le_bytes());
633 bytes.extend_from_slice(&body_hash.to_le_bytes());
634 fnv1a_hash(&bytes)
635 }
636 }
637 }
638}
639#[allow(dead_code)]
641pub struct WindowIterator<'a, T> {
642 pub(super) data: &'a [T],
643 pub(super) pos: usize,
644 pub(super) window: usize,
645}
646#[allow(dead_code)]
647impl<'a, T> WindowIterator<'a, T> {
648 pub fn new(data: &'a [T], window: usize) -> Self {
650 Self {
651 data,
652 pos: 0,
653 window,
654 }
655 }
656}
657#[allow(dead_code)]
659pub struct RewriteRuleSet {
660 rules: Vec<RewriteRule>,
661}
662#[allow(dead_code)]
663impl RewriteRuleSet {
664 pub fn new() -> Self {
666 Self { rules: Vec::new() }
667 }
668 pub fn add(&mut self, rule: RewriteRule) {
670 self.rules.push(rule);
671 }
672 pub fn len(&self) -> usize {
674 self.rules.len()
675 }
676 pub fn is_empty(&self) -> bool {
678 self.rules.is_empty()
679 }
680 pub fn conditional_rules(&self) -> Vec<&RewriteRule> {
682 self.rules.iter().filter(|r| r.conditional).collect()
683 }
684 pub fn unconditional_rules(&self) -> Vec<&RewriteRule> {
686 self.rules.iter().filter(|r| !r.conditional).collect()
687 }
688 pub fn get(&self, name: &str) -> Option<&RewriteRule> {
690 self.rules.iter().find(|r| r.name == name)
691 }
692}
693pub struct LruCache<K: Clone + Eq + std::hash::Hash, V: Clone> {
695 capacity: usize,
696 map: HashMap<K, usize>,
697 nodes: Vec<Node<K, V>>,
698 head: Option<usize>,
699 tail: Option<usize>,
700 hits: u64,
701 misses: u64,
702}
703impl<K: Clone + Eq + std::hash::Hash, V: Clone> LruCache<K, V> {
704 pub fn new(capacity: usize) -> Self {
706 assert!(capacity > 0, "LRU cache capacity must be > 0");
707 LruCache {
708 capacity,
709 map: HashMap::new(),
710 nodes: Vec::new(),
711 head: None,
712 tail: None,
713 hits: 0,
714 misses: 0,
715 }
716 }
717 pub fn get(&mut self, key: &K) -> Option<V> {
719 if let Some(&idx) = self.map.get(key) {
720 self.hits += 1;
721 self.move_to_head(idx);
722 Some(self.nodes[idx].value.clone())
723 } else {
724 self.misses += 1;
725 None
726 }
727 }
728 pub fn insert(&mut self, key: K, value: V) {
730 if let Some(&idx) = self.map.get(&key) {
731 self.nodes[idx].value = value;
732 self.move_to_head(idx);
733 } else {
734 if self.nodes.len() >= self.capacity {
735 self.evict_lru();
736 }
737 let new_idx = self.nodes.len();
738 let node = Node {
739 key: key.clone(),
740 value,
741 prev: None,
742 next: self.head,
743 };
744 self.nodes.push(node);
745 self.map.insert(key, new_idx);
746 if let Some(old_head) = self.head {
747 self.nodes[old_head].prev = Some(new_idx);
748 }
749 self.head = Some(new_idx);
750 if self.tail.is_none() {
751 self.tail = Some(new_idx);
752 }
753 }
754 }
755 pub fn remove(&mut self, key: &K) -> Option<V> {
757 if let Some(&idx) = self.map.get(key) {
758 let node = &self.nodes[idx];
759 let prev = node.prev;
760 let next = node.next;
761 if let Some(p) = prev {
762 self.nodes[p].next = next;
763 } else {
764 self.tail = next;
765 }
766 if let Some(n) = next {
767 self.nodes[n].prev = prev;
768 } else {
769 self.head = prev;
770 }
771 self.map.remove(key);
772 Some(self.nodes[idx].value.clone())
773 } else {
774 None
775 }
776 }
777 pub fn contains_key(&self, key: &K) -> bool {
779 self.map.contains_key(key)
780 }
781 pub fn len(&self) -> usize {
783 self.map.len()
784 }
785 pub fn is_empty(&self) -> bool {
787 self.map.is_empty()
788 }
789 pub fn capacity(&self) -> usize {
791 self.capacity
792 }
793 pub fn clear(&mut self) {
795 self.map.clear();
796 self.nodes.clear();
797 self.head = None;
798 self.tail = None;
799 self.hits = 0;
800 self.misses = 0;
801 }
802 pub fn stats(&self) -> (u64, u64) {
804 (self.hits, self.misses)
805 }
806 pub fn hit_rate(&self) -> f64 {
808 let total = self.hits + self.misses;
809 if total == 0 {
810 0.0
811 } else {
812 (self.hits as f64 / total as f64) * 100.0
813 }
814 }
815 fn move_to_head(&mut self, idx: usize) {
816 if self.head == Some(idx) {
817 return;
818 }
819 let prev = self.nodes[idx].prev;
820 let next = self.nodes[idx].next;
821 if let Some(p) = prev {
822 self.nodes[p].next = next;
823 }
824 if let Some(n) = next {
825 self.nodes[n].prev = prev;
826 } else {
827 self.tail = prev;
828 }
829 self.nodes[idx].prev = None;
830 self.nodes[idx].next = self.head;
831 if let Some(old_head) = self.head {
832 self.nodes[old_head].prev = Some(idx);
833 }
834 self.head = Some(idx);
835 }
836 fn evict_lru(&mut self) {
837 if let Some(tail_idx) = self.tail {
838 let key = self.nodes[tail_idx].key.clone();
839 let prev = self.nodes[tail_idx].prev;
840 if let Some(p) = prev {
841 self.nodes[p].next = None;
842 self.head = Some(p);
843 } else {
844 self.head = None;
845 }
846 self.tail = prev;
847 self.map.remove(&key);
848 self.nodes.remove(tail_idx);
849 self.nodes.iter().enumerate().for_each(|(i, node)| {
850 *self
851 .map
852 .get_mut(&node.key)
853 .expect("node key must exist in map") = i;
854 });
855 }
856 }
857}
858pub struct BloomFilterApprox {
863 bits: Vec<bool>,
864 size: usize,
865}
866impl BloomFilterApprox {
867 pub fn new(size: usize) -> Self {
869 Self {
870 bits: vec![false; size],
871 size,
872 }
873 }
874 fn hash1(data: &[u8], size: usize) -> usize {
875 fnv1a_hash(data) as usize % size
876 }
877 fn hash2(data: &[u8], size: usize) -> usize {
878 let h = fnv1a_hash(data).wrapping_mul(0x9e3779b9_7f4a7c15);
879 h as usize % size
880 }
881 pub fn insert<T: AsRef<[u8]>>(&mut self, key: T) {
883 let bytes = key.as_ref();
884 let h1 = Self::hash1(bytes, self.size);
885 let h2 = Self::hash2(bytes, self.size);
886 self.bits[h1] = true;
887 self.bits[h2] = true;
888 }
889 pub fn might_contain<T: AsRef<[u8]>>(&self, key: T) -> bool {
891 let bytes = key.as_ref();
892 let h1 = Self::hash1(bytes, self.size);
893 let h2 = Self::hash2(bytes, self.size);
894 self.bits[h1] && self.bits[h2]
895 }
896 pub fn clear(&mut self) {
898 self.bits.iter_mut().for_each(|b| *b = false);
899 }
900 pub fn set_bit_count(&self) -> usize {
902 self.bits.iter().filter(|&&b| b).count()
903 }
904 pub fn size(&self) -> usize {
906 self.size
907 }
908}
909pub struct MultiLevelCache<K: Clone + Eq + std::hash::Hash, V: Clone> {
914 l1: LruCache<K, V>,
915 l2: LruCache<K, V>,
916 l1_hits: u64,
917 l2_hits: u64,
918 misses: u64,
919}
920impl<K: Clone + Eq + std::hash::Hash, V: Clone> MultiLevelCache<K, V> {
921 pub fn new(l1_cap: usize, l2_cap: usize) -> Self {
923 Self {
924 l1: LruCache::new(l1_cap),
925 l2: LruCache::new(l2_cap),
926 l1_hits: 0,
927 l2_hits: 0,
928 misses: 0,
929 }
930 }
931 pub fn get(&mut self, key: &K) -> Option<V> {
933 if let Some(v) = self.l1.get(key) {
934 self.l1_hits += 1;
935 return Some(v);
936 }
937 if let Some(v) = self.l2.get(key) {
938 self.l2_hits += 1;
939 self.l1.insert(key.clone(), v.clone());
940 return Some(v);
941 }
942 self.misses += 1;
943 None
944 }
945 pub fn insert(&mut self, key: K, value: V) {
947 self.l1.insert(key.clone(), value.clone());
948 self.l2.insert(key, value);
949 }
950 pub fn insert_l2_only(&mut self, key: K, value: V) {
952 self.l2.insert(key, value);
953 }
954 pub fn clear_l1(&mut self) {
956 self.l1.clear();
957 }
958 pub fn clear_all(&mut self) {
960 self.l1.clear();
961 self.l2.clear();
962 self.l1_hits = 0;
963 self.l2_hits = 0;
964 self.misses = 0;
965 }
966 pub fn l1_hits(&self) -> u64 {
968 self.l1_hits
969 }
970 pub fn l2_hits(&self) -> u64 {
972 self.l2_hits
973 }
974 pub fn misses(&self) -> u64 {
976 self.misses
977 }
978 pub fn total_requests(&self) -> u64 {
980 self.l1_hits + self.l2_hits + self.misses
981 }
982 pub fn hit_rate(&self) -> f64 {
984 let total = self.total_requests();
985 if total == 0 {
986 0.0
987 } else {
988 ((self.l1_hits + self.l2_hits) as f64 / total as f64) * 100.0
989 }
990 }
991}
992pub struct DefEqCache {
994 pub(crate) cache: LruCache<(u64, u64), bool>,
995}
996impl DefEqCache {
997 pub fn new(capacity: usize) -> Self {
999 DefEqCache {
1000 cache: LruCache::new(capacity),
1001 }
1002 }
1003 pub fn check_cache(&mut self, expr1: &SimplifiedExpr, expr2: &SimplifiedExpr) -> Option<bool> {
1005 let hash1 = expr1.hash();
1006 let hash2 = expr2.hash();
1007 if let Some(result) = self.cache.get(&(hash1, hash2)) {
1008 return Some(result);
1009 }
1010 if let Some(result) = self.cache.get(&(hash2, hash1)) {
1011 return Some(result);
1012 }
1013 None
1014 }
1015 pub fn store_result(&mut self, expr1: &SimplifiedExpr, expr2: &SimplifiedExpr, result: bool) {
1017 let hash1 = expr1.hash();
1018 let hash2 = expr2.hash();
1019 self.cache.insert((hash1, hash2), result);
1020 self.cache.insert((hash2, hash1), result);
1021 }
1022 pub fn clear(&mut self) {
1024 self.cache.clear();
1025 }
1026 pub fn stats(&self) -> (u64, u64) {
1028 self.cache.stats()
1029 }
1030 pub fn hit_rate(&self) -> f64 {
1032 self.cache.hit_rate()
1033 }
1034}
1035#[allow(dead_code)]
1037pub struct FocusStack<T> {
1038 items: Vec<T>,
1039}
1040#[allow(dead_code)]
1041impl<T> FocusStack<T> {
1042 pub fn new() -> Self {
1044 Self { items: Vec::new() }
1045 }
1046 pub fn focus(&mut self, item: T) {
1048 self.items.push(item);
1049 }
1050 pub fn blur(&mut self) -> Option<T> {
1052 self.items.pop()
1053 }
1054 pub fn current(&self) -> Option<&T> {
1056 self.items.last()
1057 }
1058 pub fn depth(&self) -> usize {
1060 self.items.len()
1061 }
1062 pub fn is_empty(&self) -> bool {
1064 self.items.is_empty()
1065 }
1066}
1067#[allow(dead_code)]
1069pub struct StatSummary {
1070 count: u64,
1071 sum: f64,
1072 min: f64,
1073 max: f64,
1074}
1075#[allow(dead_code)]
1076impl StatSummary {
1077 pub fn new() -> Self {
1079 Self {
1080 count: 0,
1081 sum: 0.0,
1082 min: f64::INFINITY,
1083 max: f64::NEG_INFINITY,
1084 }
1085 }
1086 pub fn record(&mut self, val: f64) {
1088 self.count += 1;
1089 self.sum += val;
1090 if val < self.min {
1091 self.min = val;
1092 }
1093 if val > self.max {
1094 self.max = val;
1095 }
1096 }
1097 pub fn mean(&self) -> Option<f64> {
1099 if self.count == 0 {
1100 None
1101 } else {
1102 Some(self.sum / self.count as f64)
1103 }
1104 }
1105 pub fn min(&self) -> Option<f64> {
1107 if self.count == 0 {
1108 None
1109 } else {
1110 Some(self.min)
1111 }
1112 }
1113 pub fn max(&self) -> Option<f64> {
1115 if self.count == 0 {
1116 None
1117 } else {
1118 Some(self.max)
1119 }
1120 }
1121 pub fn count(&self) -> u64 {
1123 self.count
1124 }
1125}
1126#[derive(Clone, Debug)]
1127struct TtlEntry<V> {
1128 value: V,
1129 expires_at: u64,
1130}
1131#[allow(dead_code)]
1133pub struct SparseVec<T: Default + Clone + PartialEq> {
1134 entries: std::collections::HashMap<usize, T>,
1135 default_: T,
1136 logical_len: usize,
1137}
1138#[allow(dead_code)]
1139impl<T: Default + Clone + PartialEq> SparseVec<T> {
1140 pub fn new(len: usize) -> Self {
1142 Self {
1143 entries: std::collections::HashMap::new(),
1144 default_: T::default(),
1145 logical_len: len,
1146 }
1147 }
1148 pub fn set(&mut self, idx: usize, val: T) {
1150 if val == self.default_ {
1151 self.entries.remove(&idx);
1152 } else {
1153 self.entries.insert(idx, val);
1154 }
1155 }
1156 pub fn get(&self, idx: usize) -> &T {
1158 self.entries.get(&idx).unwrap_or(&self.default_)
1159 }
1160 pub fn len(&self) -> usize {
1162 self.logical_len
1163 }
1164 pub fn is_empty(&self) -> bool {
1166 self.len() == 0
1167 }
1168 pub fn nnz(&self) -> usize {
1170 self.entries.len()
1171 }
1172}
1173#[allow(dead_code)]
1175#[allow(missing_docs)]
1176pub struct RewriteRule {
1177 pub name: String,
1179 pub lhs: String,
1181 pub rhs: String,
1183 pub conditional: bool,
1185}
1186#[allow(dead_code)]
1187impl RewriteRule {
1188 pub fn unconditional(
1190 name: impl Into<String>,
1191 lhs: impl Into<String>,
1192 rhs: impl Into<String>,
1193 ) -> Self {
1194 Self {
1195 name: name.into(),
1196 lhs: lhs.into(),
1197 rhs: rhs.into(),
1198 conditional: false,
1199 }
1200 }
1201 pub fn conditional(
1203 name: impl Into<String>,
1204 lhs: impl Into<String>,
1205 rhs: impl Into<String>,
1206 ) -> Self {
1207 Self {
1208 name: name.into(),
1209 lhs: lhs.into(),
1210 rhs: rhs.into(),
1211 conditional: true,
1212 }
1213 }
1214 pub fn display(&self) -> String {
1216 format!("{}: {} → {}", self.name, self.lhs, self.rhs)
1217 }
1218}
1219#[derive(Clone, Debug)]
1223pub struct CacheStatistics {
1224 pub whnf_hits: u64,
1226 pub whnf_misses: u64,
1228 pub whnf_hit_rate: f64,
1230 pub defeq_hits: u64,
1232 pub defeq_misses: u64,
1234 pub defeq_hit_rate: f64,
1236 pub infer_hits: u64,
1238 pub infer_misses: u64,
1240 pub infer_hit_rate: f64,
1242}
1243impl CacheStatistics {
1244 pub fn total_hits(&self) -> u64 {
1246 self.whnf_hits + self.defeq_hits + self.infer_hits
1247 }
1248 pub fn total_misses(&self) -> u64 {
1250 self.whnf_misses + self.defeq_misses + self.infer_misses
1251 }
1252 pub fn overall_hit_rate(&self) -> f64 {
1254 let total = self.total_hits() + self.total_misses();
1255 if total == 0 {
1256 0.0
1257 } else {
1258 (self.total_hits() as f64 / total as f64) * 100.0
1259 }
1260 }
1261}
1262#[allow(dead_code)]
1264pub struct FlatSubstitution {
1265 pairs: Vec<(String, String)>,
1266}
1267#[allow(dead_code)]
1268impl FlatSubstitution {
1269 pub fn new() -> Self {
1271 Self { pairs: Vec::new() }
1272 }
1273 pub fn add(&mut self, from: impl Into<String>, to: impl Into<String>) {
1275 self.pairs.push((from.into(), to.into()));
1276 }
1277 pub fn apply(&self, s: &str) -> String {
1279 let mut result = s.to_string();
1280 for (from, to) in &self.pairs {
1281 result = result.replace(from.as_str(), to.as_str());
1282 }
1283 result
1284 }
1285 pub fn len(&self) -> usize {
1287 self.pairs.len()
1288 }
1289 pub fn is_empty(&self) -> bool {
1291 self.pairs.is_empty()
1292 }
1293}
1294#[allow(dead_code)]
1296pub struct NonEmptyVec<T> {
1297 head: T,
1298 tail: Vec<T>,
1299}
1300#[allow(dead_code)]
1301impl<T> NonEmptyVec<T> {
1302 pub fn singleton(val: T) -> Self {
1304 Self {
1305 head: val,
1306 tail: Vec::new(),
1307 }
1308 }
1309 pub fn push(&mut self, val: T) {
1311 self.tail.push(val);
1312 }
1313 pub fn first(&self) -> &T {
1315 &self.head
1316 }
1317 pub fn last(&self) -> &T {
1319 self.tail.last().unwrap_or(&self.head)
1320 }
1321 pub fn len(&self) -> usize {
1323 1 + self.tail.len()
1324 }
1325 pub fn is_empty(&self) -> bool {
1327 self.len() == 0
1328 }
1329 pub fn to_vec(&self) -> Vec<&T> {
1331 let mut v = vec![&self.head];
1332 v.extend(self.tail.iter());
1333 v
1334 }
1335}
1336pub struct InferCache {
1338 pub(crate) cache: LruCache<u64, SimplifiedExpr>,
1339}
1340impl InferCache {
1341 pub fn new(capacity: usize) -> Self {
1343 InferCache {
1344 cache: LruCache::new(capacity),
1345 }
1346 }
1347 pub fn lookup(&mut self, expr: &SimplifiedExpr) -> Option<SimplifiedExpr> {
1349 let hash = expr.hash();
1350 self.cache.get(&hash)
1351 }
1352 pub fn store(&mut self, expr: &SimplifiedExpr, inferred_type: SimplifiedExpr) {
1354 let hash = expr.hash();
1355 self.cache.insert(hash, inferred_type);
1356 }
1357 pub fn clear(&mut self) {
1359 self.cache.clear();
1360 }
1361 pub fn stats(&self) -> (u64, u64) {
1363 self.cache.stats()
1364 }
1365 pub fn hit_rate(&self) -> f64 {
1367 self.cache.hit_rate()
1368 }
1369 pub fn len(&self) -> usize {
1371 self.cache.len()
1372 }
1373 pub fn is_empty(&self) -> bool {
1375 self.cache.is_empty()
1376 }
1377}
1378#[allow(dead_code)]
1380pub struct StringPool {
1381 free: Vec<String>,
1382}
1383#[allow(dead_code)]
1384impl StringPool {
1385 pub fn new() -> Self {
1387 Self { free: Vec::new() }
1388 }
1389 pub fn take(&mut self) -> String {
1391 self.free.pop().unwrap_or_default()
1392 }
1393 pub fn give(&mut self, mut s: String) {
1395 s.clear();
1396 self.free.push(s);
1397 }
1398 pub fn free_count(&self) -> usize {
1400 self.free.len()
1401 }
1402}
1403pub struct WhnfCache {
1405 pub(crate) cache: LruCache<u64, SimplifiedExpr>,
1406 transparency_mode: bool,
1407}
1408impl WhnfCache {
1409 pub fn new(capacity: usize, transparency_mode: bool) -> Self {
1411 WhnfCache {
1412 cache: LruCache::new(capacity),
1413 transparency_mode,
1414 }
1415 }
1416 pub fn lookup(&mut self, expr: &SimplifiedExpr) -> Option<SimplifiedExpr> {
1418 if !self.transparency_mode {
1419 let hash = expr.hash();
1420 self.cache.get(&hash)
1421 } else {
1422 None
1423 }
1424 }
1425 pub fn store(&mut self, expr: &SimplifiedExpr, whnf: SimplifiedExpr) {
1427 if !self.transparency_mode {
1428 let hash = expr.hash();
1429 self.cache.insert(hash, whnf);
1430 }
1431 }
1432 pub fn clear(&mut self) {
1434 self.cache.clear();
1435 }
1436 pub fn stats(&self) -> (u64, u64) {
1438 self.cache.stats()
1439 }
1440 pub fn hit_rate(&self) -> f64 {
1442 self.cache.hit_rate()
1443 }
1444 pub fn set_transparency(&mut self, mode: bool) {
1446 self.transparency_mode = mode;
1447 if mode {
1448 self.cache.clear();
1449 }
1450 }
1451 pub fn is_transparent(&self) -> bool {
1453 self.transparency_mode
1454 }
1455}
1456#[allow(dead_code)]
1458pub struct VersionedRecord<T: Clone> {
1459 earlier: Vec<T>,
1461 current: T,
1463}
1464#[allow(dead_code)]
1465impl<T: Clone> VersionedRecord<T> {
1466 pub fn new(initial: T) -> Self {
1468 Self {
1469 earlier: Vec::new(),
1470 current: initial,
1471 }
1472 }
1473 pub fn update(&mut self, val: T) {
1475 let previous = std::mem::replace(&mut self.current, val);
1476 self.earlier.push(previous);
1477 }
1478 pub fn current(&self) -> &T {
1480 &self.current
1481 }
1482 pub fn at_version(&self, n: usize) -> Option<&T> {
1484 match self.earlier.get(n) {
1485 Some(value) => Some(value),
1486 None if n == self.earlier.len() => Some(&self.current),
1487 None => None,
1488 }
1489 }
1490 pub fn version(&self) -> usize {
1492 self.earlier.len()
1493 }
1494 pub fn has_history(&self) -> bool {
1496 !self.earlier.is_empty()
1497 }
1498}
1499pub struct TtlCache<K: Clone + Eq + std::hash::Hash, V: Clone> {
1504 entries: HashMap<K, TtlEntry<V>>,
1505 step: u64,
1507 default_ttl: u64,
1509}
1510impl<K: Clone + Eq + std::hash::Hash, V: Clone> TtlCache<K, V> {
1511 pub fn new(default_ttl: u64) -> Self {
1513 Self {
1514 entries: HashMap::new(),
1515 step: 0,
1516 default_ttl,
1517 }
1518 }
1519 pub fn tick(&mut self) {
1521 self.step += 1;
1522 }
1523 pub fn tick_n(&mut self, n: u64) {
1525 self.step += n;
1526 }
1527 pub fn insert(&mut self, key: K, value: V) {
1529 self.entries.insert(
1530 key,
1531 TtlEntry {
1532 value,
1533 expires_at: self.step + self.default_ttl,
1534 },
1535 );
1536 }
1537 pub fn insert_with_ttl(&mut self, key: K, value: V, ttl: u64) {
1539 self.entries.insert(
1540 key,
1541 TtlEntry {
1542 value,
1543 expires_at: self.step + ttl,
1544 },
1545 );
1546 }
1547 pub fn get(&self, key: &K) -> Option<V> {
1549 self.entries.get(key).and_then(|e| {
1550 if self.step < e.expires_at {
1551 Some(e.value.clone())
1552 } else {
1553 None
1554 }
1555 })
1556 }
1557 pub fn purge_expired(&mut self) {
1559 let step = self.step;
1560 self.entries.retain(|_, e| step < e.expires_at);
1561 }
1562 pub fn len(&self) -> usize {
1564 self.entries.len()
1565 }
1566 pub fn is_empty(&self) -> bool {
1568 self.entries.is_empty()
1569 }
1570 pub fn current_step(&self) -> u64 {
1572 self.step
1573 }
1574 pub fn clear(&mut self) {
1576 self.entries.clear();
1577 }
1578}
1579#[allow(dead_code)]
1581pub struct WriteOnce<T> {
1582 value: std::cell::Cell<Option<T>>,
1583}
1584#[allow(dead_code)]
1585impl<T: Copy> WriteOnce<T> {
1586 pub fn new() -> Self {
1588 Self {
1589 value: std::cell::Cell::new(None),
1590 }
1591 }
1592 pub fn write(&self, val: T) -> bool {
1594 if self.value.get().is_some() {
1595 return false;
1596 }
1597 self.value.set(Some(val));
1598 true
1599 }
1600 pub fn read(&self) -> Option<T> {
1602 self.value.get()
1603 }
1604 pub fn is_written(&self) -> bool {
1606 self.value.get().is_some()
1607 }
1608}
1609#[derive(Clone, Debug)]
1611struct Node<K, V> {
1612 key: K,
1613 value: V,
1614 prev: Option<usize>,
1615 next: Option<usize>,
1616}
1617#[allow(dead_code)]
1619pub struct LabelSet {
1620 labels: Vec<String>,
1621}
1622#[allow(dead_code)]
1623impl LabelSet {
1624 pub fn new() -> Self {
1626 Self { labels: Vec::new() }
1627 }
1628 pub fn add(&mut self, label: impl Into<String>) {
1630 let s = label.into();
1631 if !self.labels.contains(&s) {
1632 self.labels.push(s);
1633 }
1634 }
1635 pub fn has(&self, label: &str) -> bool {
1637 self.labels.iter().any(|l| l == label)
1638 }
1639 pub fn count(&self) -> usize {
1641 self.labels.len()
1642 }
1643 pub fn all(&self) -> &[String] {
1645 &self.labels
1646 }
1647}
1648#[allow(dead_code)]
1650pub struct TransitiveClosure {
1651 adj: Vec<Vec<usize>>,
1652 n: usize,
1653}
1654#[allow(dead_code)]
1655impl TransitiveClosure {
1656 pub fn new(n: usize) -> Self {
1658 Self {
1659 adj: vec![Vec::new(); n],
1660 n,
1661 }
1662 }
1663 pub fn add_edge(&mut self, from: usize, to: usize) {
1665 if from < self.n {
1666 self.adj[from].push(to);
1667 }
1668 }
1669 pub fn reachable_from(&self, start: usize) -> Vec<usize> {
1671 let mut visited = vec![false; self.n];
1672 let mut queue = std::collections::VecDeque::new();
1673 queue.push_back(start);
1674 while let Some(node) = queue.pop_front() {
1675 if node >= self.n || visited[node] {
1676 continue;
1677 }
1678 visited[node] = true;
1679 for &next in &self.adj[node] {
1680 queue.push_back(next);
1681 }
1682 }
1683 (0..self.n).filter(|&i| visited[i]).collect()
1684 }
1685 pub fn can_reach(&self, from: usize, to: usize) -> bool {
1687 self.reachable_from(from).contains(&to)
1688 }
1689}
1690#[allow(dead_code)]
1692pub struct SmallMap<K: Ord + Clone, V: Clone> {
1693 entries: Vec<(K, V)>,
1694}
1695#[allow(dead_code)]
1696impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
1697 pub fn new() -> Self {
1699 Self {
1700 entries: Vec::new(),
1701 }
1702 }
1703 pub fn insert(&mut self, key: K, val: V) {
1705 match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
1706 Ok(i) => self.entries[i].1 = val,
1707 Err(i) => self.entries.insert(i, (key, val)),
1708 }
1709 }
1710 pub fn get(&self, key: &K) -> Option<&V> {
1712 self.entries
1713 .binary_search_by_key(&key, |(k, _)| k)
1714 .ok()
1715 .map(|i| &self.entries[i].1)
1716 }
1717 pub fn len(&self) -> usize {
1719 self.entries.len()
1720 }
1721 pub fn is_empty(&self) -> bool {
1723 self.entries.is_empty()
1724 }
1725 pub fn keys(&self) -> Vec<&K> {
1727 self.entries.iter().map(|(k, _)| k).collect()
1728 }
1729 pub fn values(&self) -> Vec<&V> {
1731 self.entries.iter().map(|(_, v)| v).collect()
1732 }
1733}