1use crate::{BinderInfo, Expr, Level, Literal, Name};
6use std::collections::HashMap;
7use std::hash::{Hash, Hasher};
8
9#[allow(dead_code)]
11pub struct TransformStat {
12 before: StatSummary,
13 after: StatSummary,
14}
15#[allow(dead_code)]
16impl TransformStat {
17 pub fn new() -> Self {
19 Self {
20 before: StatSummary::new(),
21 after: StatSummary::new(),
22 }
23 }
24 pub fn record_before(&mut self, v: f64) {
26 self.before.record(v);
27 }
28 pub fn record_after(&mut self, v: f64) {
30 self.after.record(v);
31 }
32 pub fn mean_ratio(&self) -> Option<f64> {
34 let b = self.before.mean()?;
35 let a = self.after.mean()?;
36 if b.abs() < f64::EPSILON {
37 return None;
38 }
39 Some(a / b)
40 }
41}
42#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
47pub struct ExprId(pub(crate) u32);
48impl ExprId {
49 pub fn as_u32(&self) -> u32 {
51 self.0
52 }
53}
54pub struct ExprHashcons {
60 id_to_expr: Vec<Expr>,
62 expr_to_id: HashMap<ExprKey, ExprId>,
64 hit_count: u64,
66 miss_count: u64,
68}
69impl ExprHashcons {
70 pub fn new() -> Self {
72 ExprHashcons {
73 id_to_expr: Vec::new(),
74 expr_to_id: HashMap::new(),
75 hit_count: 0,
76 miss_count: 0,
77 }
78 }
79 pub fn intern(&mut self, expr: Expr) -> (ExprId, bool) {
84 let key = ExprKey(expr.clone());
85 if let Some(&id) = self.expr_to_id.get(&key) {
86 self.hit_count += 1;
87 (id, false)
88 } else {
89 let id = ExprId(self.id_to_expr.len() as u32);
90 self.id_to_expr.push(expr);
91 self.expr_to_id.insert(key, id);
92 self.miss_count += 1;
93 (id, true)
94 }
95 }
96 pub fn get(&self, id: ExprId) -> Option<&Expr> {
101 self.id_to_expr.get(id.0 as usize)
102 }
103 pub fn get_id(&self, expr: &Expr) -> Option<ExprId> {
107 let key = ExprKey(expr.clone());
108 self.expr_to_id.get(&key).copied()
109 }
110 pub fn size(&self) -> usize {
112 self.id_to_expr.len()
113 }
114 pub fn hit_rate(&self) -> f64 {
118 let total = self.hit_count + self.miss_count;
119 if total == 0 {
120 0.0
121 } else {
122 self.hit_count as f64 / total as f64
123 }
124 }
125 pub fn stats(&self) -> String {
127 format!(
128 "ExprHashcons {{ size: {}, hits: {}, misses: {}, hit_rate: {:.2}% }}",
129 self.size(),
130 self.hit_count,
131 self.miss_count,
132 self.hit_rate() * 100.0,
133 )
134 }
135}
136#[allow(dead_code)]
138pub enum Either2<A, B> {
139 First(A),
141 Second(B),
143}
144#[allow(dead_code)]
145impl<A, B> Either2<A, B> {
146 pub fn is_first(&self) -> bool {
148 matches!(self, Either2::First(_))
149 }
150 pub fn is_second(&self) -> bool {
152 matches!(self, Either2::Second(_))
153 }
154 pub fn first(self) -> Option<A> {
156 match self {
157 Either2::First(a) => Some(a),
158 _ => None,
159 }
160 }
161 pub fn second(self) -> Option<B> {
163 match self {
164 Either2::Second(b) => Some(b),
165 _ => None,
166 }
167 }
168 pub fn map_first<C, F: FnOnce(A) -> C>(self, f: F) -> Either2<C, B> {
170 match self {
171 Either2::First(a) => Either2::First(f(a)),
172 Either2::Second(b) => Either2::Second(b),
173 }
174 }
175}
176#[allow(dead_code)]
178pub struct BitSet64 {
179 bits: u64,
180}
181#[allow(dead_code)]
182impl BitSet64 {
183 pub const fn new() -> Self {
185 Self { bits: 0 }
186 }
187 pub fn insert(&mut self, i: u32) {
189 if i < 64 {
190 self.bits |= 1u64 << i;
191 }
192 }
193 pub fn remove(&mut self, i: u32) {
195 if i < 64 {
196 self.bits &= !(1u64 << i);
197 }
198 }
199 pub fn contains(&self, i: u32) -> bool {
201 i < 64 && (self.bits >> i) & 1 != 0
202 }
203 pub fn len(&self) -> u32 {
205 self.bits.count_ones()
206 }
207 pub fn is_empty(&self) -> bool {
209 self.bits == 0
210 }
211 pub fn union(self, other: BitSet64) -> BitSet64 {
213 BitSet64 {
214 bits: self.bits | other.bits,
215 }
216 }
217 pub fn intersect(self, other: BitSet64) -> BitSet64 {
219 BitSet64 {
220 bits: self.bits & other.bits,
221 }
222 }
223}
224#[allow(dead_code)]
226pub struct StringPool {
227 free: Vec<String>,
228}
229#[allow(dead_code)]
230impl StringPool {
231 pub fn new() -> Self {
233 Self { free: Vec::new() }
234 }
235 pub fn take(&mut self) -> String {
237 self.free.pop().unwrap_or_default()
238 }
239 pub fn give(&mut self, mut s: String) {
241 s.clear();
242 self.free.push(s);
243 }
244 pub fn free_count(&self) -> usize {
246 self.free.len()
247 }
248}
249#[allow(dead_code)]
251#[allow(missing_docs)]
252pub enum DecisionNode {
253 Leaf(String),
255 Branch {
257 key: String,
258 val: String,
259 yes_branch: Box<DecisionNode>,
260 no_branch: Box<DecisionNode>,
261 },
262}
263#[allow(dead_code)]
264impl DecisionNode {
265 pub fn evaluate(&self, ctx: &std::collections::HashMap<String, String>) -> &str {
267 match self {
268 DecisionNode::Leaf(action) => action.as_str(),
269 DecisionNode::Branch {
270 key,
271 val,
272 yes_branch,
273 no_branch,
274 } => {
275 let actual = ctx.get(key).map(|s| s.as_str()).unwrap_or("");
276 if actual == val.as_str() {
277 yes_branch.evaluate(ctx)
278 } else {
279 no_branch.evaluate(ctx)
280 }
281 }
282 }
283 }
284 pub fn depth(&self) -> usize {
286 match self {
287 DecisionNode::Leaf(_) => 0,
288 DecisionNode::Branch {
289 yes_branch,
290 no_branch,
291 ..
292 } => 1 + yes_branch.depth().max(no_branch.depth()),
293 }
294 }
295}
296#[allow(dead_code)]
298pub struct WindowIterator<'a, T> {
299 pub(super) data: &'a [T],
300 pub(super) pos: usize,
301 pub(super) window: usize,
302}
303#[allow(dead_code)]
304impl<'a, T> WindowIterator<'a, T> {
305 pub fn new(data: &'a [T], window: usize) -> Self {
307 Self {
308 data,
309 pos: 0,
310 window,
311 }
312 }
313}
314#[allow(dead_code)]
316pub struct TokenBucket {
317 capacity: u64,
318 tokens: u64,
319 refill_per_ms: u64,
320 last_refill: crate::wall_clock::Instant,
321}
322#[allow(dead_code)]
323impl TokenBucket {
324 pub fn new(capacity: u64, refill_per_ms: u64) -> Self {
326 Self {
327 capacity,
328 tokens: capacity,
329 refill_per_ms,
330 last_refill: crate::wall_clock::Instant::now(),
331 }
332 }
333 pub fn try_consume(&mut self, n: u64) -> bool {
335 self.refill();
336 if self.tokens >= n {
337 self.tokens -= n;
338 true
339 } else {
340 false
341 }
342 }
343 fn refill(&mut self) {
344 let now = crate::wall_clock::Instant::now();
345 let elapsed_ms = now.duration_since(self.last_refill).as_millis() as u64;
346 if elapsed_ms > 0 {
347 let new_tokens = elapsed_ms * self.refill_per_ms;
348 self.tokens = (self.tokens + new_tokens).min(self.capacity);
349 self.last_refill = now;
350 }
351 }
352 pub fn available(&self) -> u64 {
354 self.tokens
355 }
356 pub fn capacity(&self) -> u64 {
358 self.capacity
359 }
360}
361#[allow(dead_code)]
363pub struct SmallMap<K: Ord + Clone, V: Clone> {
364 entries: Vec<(K, V)>,
365}
366#[allow(dead_code)]
367impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
368 pub fn new() -> Self {
370 Self {
371 entries: Vec::new(),
372 }
373 }
374 pub fn insert(&mut self, key: K, val: V) {
376 match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
377 Ok(i) => self.entries[i].1 = val,
378 Err(i) => self.entries.insert(i, (key, val)),
379 }
380 }
381 pub fn get(&self, key: &K) -> Option<&V> {
383 self.entries
384 .binary_search_by_key(&key, |(k, _)| k)
385 .ok()
386 .map(|i| &self.entries[i].1)
387 }
388 pub fn len(&self) -> usize {
390 self.entries.len()
391 }
392 pub fn is_empty(&self) -> bool {
394 self.entries.is_empty()
395 }
396 pub fn keys(&self) -> Vec<&K> {
398 self.entries.iter().map(|(k, _)| k).collect()
399 }
400 pub fn values(&self) -> Vec<&V> {
402 self.entries.iter().map(|(_, v)| v).collect()
403 }
404}
405#[allow(dead_code)]
407pub struct FocusStack<T> {
408 items: Vec<T>,
409}
410#[allow(dead_code)]
411impl<T> FocusStack<T> {
412 pub fn new() -> Self {
414 Self { items: Vec::new() }
415 }
416 pub fn focus(&mut self, item: T) {
418 self.items.push(item);
419 }
420 pub fn blur(&mut self) -> Option<T> {
422 self.items.pop()
423 }
424 pub fn current(&self) -> Option<&T> {
426 self.items.last()
427 }
428 pub fn depth(&self) -> usize {
430 self.items.len()
431 }
432 pub fn is_empty(&self) -> bool {
434 self.items.is_empty()
435 }
436}
437#[allow(dead_code)]
439pub struct LabelSet {
440 labels: Vec<String>,
441}
442#[allow(dead_code)]
443impl LabelSet {
444 pub fn new() -> Self {
446 Self { labels: Vec::new() }
447 }
448 pub fn add(&mut self, label: impl Into<String>) {
450 let s = label.into();
451 if !self.labels.contains(&s) {
452 self.labels.push(s);
453 }
454 }
455 pub fn has(&self, label: &str) -> bool {
457 self.labels.iter().any(|l| l == label)
458 }
459 pub fn count(&self) -> usize {
461 self.labels.len()
462 }
463 pub fn all(&self) -> &[String] {
465 &self.labels
466 }
467}
468#[allow(dead_code)]
470#[allow(missing_docs)]
471pub struct RewriteRule {
472 pub name: String,
474 pub lhs: String,
476 pub rhs: String,
478 pub conditional: bool,
480}
481#[allow(dead_code)]
482impl RewriteRule {
483 pub fn unconditional(
485 name: impl Into<String>,
486 lhs: impl Into<String>,
487 rhs: impl Into<String>,
488 ) -> Self {
489 Self {
490 name: name.into(),
491 lhs: lhs.into(),
492 rhs: rhs.into(),
493 conditional: false,
494 }
495 }
496 pub fn conditional(
498 name: impl Into<String>,
499 lhs: impl Into<String>,
500 rhs: impl Into<String>,
501 ) -> Self {
502 Self {
503 name: name.into(),
504 lhs: lhs.into(),
505 rhs: rhs.into(),
506 conditional: true,
507 }
508 }
509 pub fn display(&self) -> String {
511 format!("{}: {} → {}", self.name, self.lhs, self.rhs)
512 }
513}
514#[allow(dead_code)]
516pub struct SimpleDag {
517 edges: Vec<Vec<usize>>,
519}
520#[allow(dead_code)]
521impl SimpleDag {
522 pub fn new(n: usize) -> Self {
524 Self {
525 edges: vec![Vec::new(); n],
526 }
527 }
528 pub fn add_edge(&mut self, from: usize, to: usize) {
530 if from < self.edges.len() {
531 self.edges[from].push(to);
532 }
533 }
534 pub fn successors(&self, node: usize) -> &[usize] {
536 self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
537 }
538 pub fn can_reach(&self, from: usize, to: usize) -> bool {
540 let mut visited = vec![false; self.edges.len()];
541 self.dfs(from, to, &mut visited)
542 }
543 fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
544 if cur == target {
545 return true;
546 }
547 if cur >= visited.len() || visited[cur] {
548 return false;
549 }
550 visited[cur] = true;
551 for &next in self.successors(cur) {
552 if self.dfs(next, target, visited) {
553 return true;
554 }
555 }
556 false
557 }
558 pub fn topological_sort(&self) -> Option<Vec<usize>> {
560 let n = self.edges.len();
561 let mut in_degree = vec![0usize; n];
562 for succs in &self.edges {
563 for &s in succs {
564 if s < n {
565 in_degree[s] += 1;
566 }
567 }
568 }
569 let mut queue: std::collections::VecDeque<usize> =
570 (0..n).filter(|&i| in_degree[i] == 0).collect();
571 let mut order = Vec::new();
572 while let Some(node) = queue.pop_front() {
573 order.push(node);
574 for &s in self.successors(node) {
575 if s < n {
576 in_degree[s] -= 1;
577 if in_degree[s] == 0 {
578 queue.push_back(s);
579 }
580 }
581 }
582 }
583 if order.len() == n {
584 Some(order)
585 } else {
586 None
587 }
588 }
589 pub fn num_nodes(&self) -> usize {
591 self.edges.len()
592 }
593}
594#[allow(dead_code)]
596pub struct RawFnPtr {
597 ptr: usize,
599 arity: usize,
600 name: String,
601}
602#[allow(dead_code)]
603impl RawFnPtr {
604 pub fn new(ptr: usize, arity: usize, name: impl Into<String>) -> Self {
606 Self {
607 ptr,
608 arity,
609 name: name.into(),
610 }
611 }
612 pub fn arity(&self) -> usize {
614 self.arity
615 }
616 pub fn name(&self) -> &str {
618 &self.name
619 }
620 pub fn raw(&self) -> usize {
622 self.ptr
623 }
624}
625#[allow(dead_code)]
627#[derive(Debug, Clone, Default)]
628pub struct CacheSessionStats {
629 pub hits: u64,
630 pub misses: u64,
631 pub insertions: u64,
632 pub evictions: u64,
633}
634#[allow(dead_code)]
635impl CacheSessionStats {
636 pub fn new() -> Self {
638 CacheSessionStats::default()
639 }
640 pub fn hit_rate(&self) -> f64 {
642 let total = self.hits + self.misses;
643 if total == 0 {
644 1.0
645 } else {
646 self.hits as f64 / total as f64
647 }
648 }
649 pub fn merge(&mut self, other: &CacheSessionStats) {
651 self.hits += other.hits;
652 self.misses += other.misses;
653 self.insertions += other.insertions;
654 self.evictions += other.evictions;
655 }
656 pub fn reset(&mut self) {
658 *self = CacheSessionStats::default();
659 }
660 pub fn summary(&self) -> String {
662 format!(
663 "hits={} misses={} insertions={} evictions={} hit_rate={:.1}%",
664 self.hits,
665 self.misses,
666 self.insertions,
667 self.evictions,
668 self.hit_rate() * 100.0
669 )
670 }
671}
672#[allow(dead_code)]
674pub struct NonEmptyVec<T> {
675 head: T,
676 tail: Vec<T>,
677}
678#[allow(dead_code)]
679impl<T> NonEmptyVec<T> {
680 pub fn singleton(val: T) -> Self {
682 Self {
683 head: val,
684 tail: Vec::new(),
685 }
686 }
687 pub fn push(&mut self, val: T) {
689 self.tail.push(val);
690 }
691 pub fn first(&self) -> &T {
693 &self.head
694 }
695 pub fn last(&self) -> &T {
697 self.tail.last().unwrap_or(&self.head)
698 }
699 pub fn len(&self) -> usize {
701 1 + self.tail.len()
702 }
703 pub fn is_empty(&self) -> bool {
705 self.len() == 0
706 }
707 pub fn to_vec(&self) -> Vec<&T> {
709 let mut v = vec![&self.head];
710 v.extend(self.tail.iter());
711 v
712 }
713}
714#[allow(dead_code)]
716pub struct MinHeap<T: Ord> {
717 data: Vec<T>,
718}
719#[allow(dead_code)]
720impl<T: Ord> MinHeap<T> {
721 pub fn new() -> Self {
723 Self { data: Vec::new() }
724 }
725 pub fn push(&mut self, val: T) {
727 self.data.push(val);
728 self.sift_up(self.data.len() - 1);
729 }
730 pub fn pop(&mut self) -> Option<T> {
732 if self.data.is_empty() {
733 return None;
734 }
735 let n = self.data.len();
736 self.data.swap(0, n - 1);
737 let min = self.data.pop();
738 if !self.data.is_empty() {
739 self.sift_down(0);
740 }
741 min
742 }
743 pub fn peek(&self) -> Option<&T> {
745 self.data.first()
746 }
747 pub fn len(&self) -> usize {
749 self.data.len()
750 }
751 pub fn is_empty(&self) -> bool {
753 self.data.is_empty()
754 }
755 fn sift_up(&mut self, mut i: usize) {
756 while i > 0 {
757 let parent = (i - 1) / 2;
758 if self.data[i] < self.data[parent] {
759 self.data.swap(i, parent);
760 i = parent;
761 } else {
762 break;
763 }
764 }
765 }
766 fn sift_down(&mut self, mut i: usize) {
767 let n = self.data.len();
768 loop {
769 let left = 2 * i + 1;
770 let right = 2 * i + 2;
771 let mut smallest = i;
772 if left < n && self.data[left] < self.data[smallest] {
773 smallest = left;
774 }
775 if right < n && self.data[right] < self.data[smallest] {
776 smallest = right;
777 }
778 if smallest == i {
779 break;
780 }
781 self.data.swap(i, smallest);
782 i = smallest;
783 }
784 }
785}
786#[allow(dead_code)]
788pub struct PrefixCounter {
789 children: std::collections::HashMap<char, PrefixCounter>,
790 count: usize,
791}
792#[allow(dead_code)]
793impl PrefixCounter {
794 pub fn new() -> Self {
796 Self {
797 children: std::collections::HashMap::new(),
798 count: 0,
799 }
800 }
801 pub fn record(&mut self, s: &str) {
803 self.count += 1;
804 let mut node = self;
805 for c in s.chars() {
806 node = node.children.entry(c).or_default();
807 node.count += 1;
808 }
809 }
810 pub fn count_with_prefix(&self, prefix: &str) -> usize {
812 let mut node = self;
813 for c in prefix.chars() {
814 match node.children.get(&c) {
815 Some(n) => node = n,
816 None => return 0,
817 }
818 }
819 node.count
820 }
821}
822#[allow(dead_code)]
824pub struct TwoLevelCache {
825 hot: MemoTable,
826 cold: MemoTable,
827 hot_capacity: usize,
828 stats: CacheSessionStats,
829}
830#[allow(dead_code)]
831impl TwoLevelCache {
832 pub fn new(hot_capacity: usize) -> Self {
834 TwoLevelCache {
835 hot: MemoTable::new(),
836 cold: MemoTable::new(),
837 hot_capacity,
838 stats: CacheSessionStats::new(),
839 }
840 }
841 pub fn get(&mut self, key: u64) -> Option<u64> {
843 if let Some(v) = self.hot.get(key) {
844 self.stats.hits += 1;
845 return Some(v);
846 }
847 if let Some(v) = self.cold.get(key) {
848 self.stats.hits += 1;
849 self.promote(key, v);
850 return Some(v);
851 }
852 self.stats.misses += 1;
853 None
854 }
855 pub fn insert(&mut self, key: u64, val: u64) {
857 if self.hot.len() >= self.hot_capacity {
858 if let Some((k, v)) = self.hot.entries.first().copied() {
859 self.hot.remove(k);
860 self.cold.insert(k, v);
861 self.stats.evictions += 1;
862 }
863 }
864 self.hot.insert(key, val);
865 self.stats.insertions += 1;
866 }
867 fn promote(&mut self, key: u64, val: u64) {
868 self.cold.remove(key);
869 self.insert(key, val);
870 }
871 pub fn stats(&self) -> &CacheSessionStats {
873 &self.stats
874 }
875 pub fn total_len(&self) -> usize {
877 self.hot.len() + self.cold.len()
878 }
879 pub fn clear(&mut self) {
881 self.hot.clear();
882 self.cold.clear();
883 self.stats.reset();
884 }
885}
886#[allow(dead_code)]
888pub struct TransitiveClosure {
889 adj: Vec<Vec<usize>>,
890 n: usize,
891}
892#[allow(dead_code)]
893impl TransitiveClosure {
894 pub fn new(n: usize) -> Self {
896 Self {
897 adj: vec![Vec::new(); n],
898 n,
899 }
900 }
901 pub fn add_edge(&mut self, from: usize, to: usize) {
903 if from < self.n {
904 self.adj[from].push(to);
905 }
906 }
907 pub fn reachable_from(&self, start: usize) -> Vec<usize> {
909 let mut visited = vec![false; self.n];
910 let mut queue = std::collections::VecDeque::new();
911 queue.push_back(start);
912 while let Some(node) = queue.pop_front() {
913 if node >= self.n || visited[node] {
914 continue;
915 }
916 visited[node] = true;
917 for &next in &self.adj[node] {
918 queue.push_back(next);
919 }
920 }
921 (0..self.n).filter(|&i| visited[i]).collect()
922 }
923 pub fn can_reach(&self, from: usize, to: usize) -> bool {
925 self.reachable_from(from).contains(&to)
926 }
927}
928#[allow(dead_code)]
929struct PathNode {
930 key: u32,
931 value: Option<u64>,
932 children: Vec<usize>,
933}
934#[allow(dead_code)]
936pub struct SparseVec<T: Default + Clone + PartialEq> {
937 entries: std::collections::HashMap<usize, T>,
938 default_: T,
939 logical_len: usize,
940}
941#[allow(dead_code)]
942impl<T: Default + Clone + PartialEq> SparseVec<T> {
943 pub fn new(len: usize) -> Self {
945 Self {
946 entries: std::collections::HashMap::new(),
947 default_: T::default(),
948 logical_len: len,
949 }
950 }
951 pub fn set(&mut self, idx: usize, val: T) {
953 if val == self.default_ {
954 self.entries.remove(&idx);
955 } else {
956 self.entries.insert(idx, val);
957 }
958 }
959 pub fn get(&self, idx: usize) -> &T {
961 self.entries.get(&idx).unwrap_or(&self.default_)
962 }
963 pub fn len(&self) -> usize {
965 self.logical_len
966 }
967 pub fn is_empty(&self) -> bool {
969 self.len() == 0
970 }
971 pub fn nnz(&self) -> usize {
973 self.entries.len()
974 }
975}
976#[allow(dead_code)]
978pub struct Fixture {
979 data: std::collections::HashMap<String, String>,
980}
981#[allow(dead_code)]
982impl Fixture {
983 pub fn new() -> Self {
985 Self {
986 data: std::collections::HashMap::new(),
987 }
988 }
989 pub fn set(&mut self, key: impl Into<String>, val: impl Into<String>) {
991 self.data.insert(key.into(), val.into());
992 }
993 pub fn get(&self, key: &str) -> Option<&str> {
995 self.data.get(key).map(|s| s.as_str())
996 }
997 pub fn len(&self) -> usize {
999 self.data.len()
1000 }
1001 pub fn is_empty(&self) -> bool {
1003 self.len() == 0
1004 }
1005}
1006#[allow(dead_code)]
1008pub struct VersionedRecord<T: Clone> {
1009 earlier: Vec<T>,
1011 current: T,
1013}
1014#[allow(dead_code)]
1015impl<T: Clone> VersionedRecord<T> {
1016 pub fn new(initial: T) -> Self {
1018 Self {
1019 earlier: Vec::new(),
1020 current: initial,
1021 }
1022 }
1023 pub fn update(&mut self, val: T) {
1025 let previous = std::mem::replace(&mut self.current, val);
1026 self.earlier.push(previous);
1027 }
1028 pub fn current(&self) -> &T {
1030 &self.current
1031 }
1032 pub fn at_version(&self, n: usize) -> Option<&T> {
1034 match self.earlier.get(n) {
1035 Some(value) => Some(value),
1036 None if n == self.earlier.len() => Some(&self.current),
1037 None => None,
1038 }
1039 }
1040 pub fn version(&self) -> usize {
1042 self.earlier.len()
1043 }
1044 pub fn has_history(&self) -> bool {
1046 !self.earlier.is_empty()
1047 }
1048}
1049#[allow(dead_code)]
1051pub struct InvalidationSet {
1052 ids: Vec<u64>,
1053}
1054#[allow(dead_code)]
1055impl InvalidationSet {
1056 pub fn new() -> Self {
1058 InvalidationSet { ids: Vec::new() }
1059 }
1060 pub fn add(&mut self, id: u64) {
1062 if !self.ids.contains(&id) {
1063 self.ids.push(id);
1064 }
1065 }
1066 pub fn contains(&self, id: u64) -> bool {
1068 self.ids.contains(&id)
1069 }
1070 pub fn ids(&self) -> &[u64] {
1072 &self.ids
1073 }
1074 pub fn clear(&mut self) {
1076 self.ids.clear();
1077 }
1078 pub fn len(&self) -> usize {
1080 self.ids.len()
1081 }
1082 pub fn is_empty(&self) -> bool {
1084 self.ids.is_empty()
1085 }
1086}
1087#[allow(dead_code)]
1089pub struct RcExprPool {
1090 entries: Vec<SharedCacheEntry>,
1091}
1092#[allow(dead_code)]
1093impl RcExprPool {
1094 pub fn new() -> Self {
1096 RcExprPool {
1097 entries: Vec::new(),
1098 }
1099 }
1100 pub fn alloc(&mut self, hash: u64) -> usize {
1102 let id = self.entries.len() as u64;
1103 self.entries.push(SharedCacheEntry::new(id, hash));
1104 self.entries.len() - 1
1105 }
1106 pub fn inc_ref(&mut self, idx: usize) {
1108 if let Some(e) = self.entries.get_mut(idx) {
1109 e.inc_ref();
1110 }
1111 }
1112 pub fn dec_ref(&mut self, idx: usize) -> bool {
1114 if let Some(e) = self.entries.get_mut(idx) {
1115 e.dec_ref()
1116 } else {
1117 false
1118 }
1119 }
1120 pub fn collect_garbage(&mut self) -> Vec<usize> {
1122 self.entries
1123 .iter()
1124 .enumerate()
1125 .filter(|(_, e)| e.is_dead())
1126 .map(|(i, _)| i)
1127 .collect()
1128 }
1129 pub fn len(&self) -> usize {
1131 self.entries.len()
1132 }
1133 pub fn is_empty(&self) -> bool {
1135 self.entries.is_empty()
1136 }
1137 pub fn live_count(&self) -> usize {
1139 self.entries.iter().filter(|e| !e.is_dead()).count()
1140 }
1141}
1142#[allow(dead_code)]
1144pub struct EvictionTracker {
1145 capacity: usize,
1146 order: Vec<u64>,
1147}
1148#[allow(dead_code)]
1149impl EvictionTracker {
1150 pub fn new(capacity: usize) -> Self {
1152 EvictionTracker {
1153 capacity,
1154 order: Vec::with_capacity(capacity),
1155 }
1156 }
1157 pub fn access(&mut self, id: u64) {
1159 if let Some(pos) = self.order.iter().position(|&x| x == id) {
1160 self.order.remove(pos);
1161 }
1162 self.order.push(id);
1163 while self.order.len() > self.capacity {
1164 self.order.remove(0);
1165 }
1166 }
1167 pub fn lru(&self) -> Option<u64> {
1169 self.order.first().copied()
1170 }
1171 pub fn mru(&self) -> Option<u64> {
1173 self.order.last().copied()
1174 }
1175 pub fn len(&self) -> usize {
1177 self.order.len()
1178 }
1179 pub fn is_empty(&self) -> bool {
1181 self.order.is_empty()
1182 }
1183 pub fn evict_lru(&mut self) -> Option<u64> {
1185 if self.order.is_empty() {
1186 None
1187 } else {
1188 Some(self.order.remove(0))
1189 }
1190 }
1191}
1192#[allow(dead_code)]
1194pub struct StatSummary {
1195 count: u64,
1196 sum: f64,
1197 min: f64,
1198 max: f64,
1199}
1200#[allow(dead_code)]
1201impl StatSummary {
1202 pub fn new() -> Self {
1204 Self {
1205 count: 0,
1206 sum: 0.0,
1207 min: f64::INFINITY,
1208 max: f64::NEG_INFINITY,
1209 }
1210 }
1211 pub fn record(&mut self, val: f64) {
1213 self.count += 1;
1214 self.sum += val;
1215 if val < self.min {
1216 self.min = val;
1217 }
1218 if val > self.max {
1219 self.max = val;
1220 }
1221 }
1222 pub fn mean(&self) -> Option<f64> {
1224 if self.count == 0 {
1225 None
1226 } else {
1227 Some(self.sum / self.count as f64)
1228 }
1229 }
1230 pub fn min(&self) -> Option<f64> {
1232 if self.count == 0 {
1233 None
1234 } else {
1235 Some(self.min)
1236 }
1237 }
1238 pub fn max(&self) -> Option<f64> {
1240 if self.count == 0 {
1241 None
1242 } else {
1243 Some(self.max)
1244 }
1245 }
1246 pub fn count(&self) -> u64 {
1248 self.count
1249 }
1250}
1251#[allow(dead_code)]
1253pub struct ConfigNode {
1254 key: String,
1255 value: Option<String>,
1256 children: Vec<ConfigNode>,
1257}
1258#[allow(dead_code)]
1259impl ConfigNode {
1260 pub fn leaf(key: impl Into<String>, value: impl Into<String>) -> Self {
1262 Self {
1263 key: key.into(),
1264 value: Some(value.into()),
1265 children: Vec::new(),
1266 }
1267 }
1268 pub fn section(key: impl Into<String>) -> Self {
1270 Self {
1271 key: key.into(),
1272 value: None,
1273 children: Vec::new(),
1274 }
1275 }
1276 pub fn add_child(&mut self, child: ConfigNode) {
1278 self.children.push(child);
1279 }
1280 pub fn key(&self) -> &str {
1282 &self.key
1283 }
1284 pub fn value(&self) -> Option<&str> {
1286 self.value.as_deref()
1287 }
1288 pub fn num_children(&self) -> usize {
1290 self.children.len()
1291 }
1292 pub fn lookup(&self, path: &str) -> Option<&str> {
1294 let mut parts = path.splitn(2, '.');
1295 let head = parts.next()?;
1296 let tail = parts.next();
1297 if head != self.key {
1298 return None;
1299 }
1300 match tail {
1301 None => self.value.as_deref(),
1302 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
1303 }
1304 }
1305 fn lookup_relative(&self, path: &str) -> Option<&str> {
1306 let mut parts = path.splitn(2, '.');
1307 let head = parts.next()?;
1308 let tail = parts.next();
1309 if head != self.key {
1310 return None;
1311 }
1312 match tail {
1313 None => self.value.as_deref(),
1314 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
1315 }
1316 }
1317}
1318#[allow(dead_code)]
1320pub struct RewriteRuleSet {
1321 rules: Vec<RewriteRule>,
1322}
1323#[allow(dead_code)]
1324impl RewriteRuleSet {
1325 pub fn new() -> Self {
1327 Self { rules: Vec::new() }
1328 }
1329 pub fn add(&mut self, rule: RewriteRule) {
1331 self.rules.push(rule);
1332 }
1333 pub fn len(&self) -> usize {
1335 self.rules.len()
1336 }
1337 pub fn is_empty(&self) -> bool {
1339 self.rules.is_empty()
1340 }
1341 pub fn conditional_rules(&self) -> Vec<&RewriteRule> {
1343 self.rules.iter().filter(|r| r.conditional).collect()
1344 }
1345 pub fn unconditional_rules(&self) -> Vec<&RewriteRule> {
1347 self.rules.iter().filter(|r| !r.conditional).collect()
1348 }
1349 pub fn get(&self, name: &str) -> Option<&RewriteRule> {
1351 self.rules.iter().find(|r| r.name == name)
1352 }
1353}
1354#[allow(dead_code)]
1356pub struct StackCalc {
1357 stack: Vec<i64>,
1358}
1359#[allow(dead_code)]
1360impl StackCalc {
1361 pub fn new() -> Self {
1363 Self { stack: Vec::new() }
1364 }
1365 pub fn push(&mut self, n: i64) {
1367 self.stack.push(n);
1368 }
1369 fn apply_binary(&mut self, op: impl FnOnce(i64, i64) -> i64) -> Option<i64> {
1373 let (rest_len, a, b) = match self.stack[..] {
1374 [ref rest @ .., a, b] => (rest.len(), a, b),
1375 _ => return None,
1376 };
1377 let value = op(a, b);
1378 self.stack.truncate(rest_len);
1379 self.stack.push(value);
1380 Some(value)
1381 }
1382 pub fn add(&mut self) -> Option<i64> {
1386 self.apply_binary(|a, b| a + b)
1387 }
1388 pub fn sub(&mut self) -> Option<i64> {
1392 self.apply_binary(|a, b| a - b)
1393 }
1394 pub fn mul(&mut self) -> Option<i64> {
1398 self.apply_binary(|a, b| a * b)
1399 }
1400 pub fn peek(&self) -> Option<i64> {
1402 self.stack.last().copied()
1403 }
1404 pub fn depth(&self) -> usize {
1406 self.stack.len()
1407 }
1408}
1409#[allow(dead_code)]
1411pub struct VersionedCache {
1412 entries: Vec<(u64, u64, u64)>,
1413 current_version: u64,
1414}
1415#[allow(dead_code)]
1416impl VersionedCache {
1417 pub fn new() -> Self {
1419 VersionedCache {
1420 entries: Vec::new(),
1421 current_version: 0,
1422 }
1423 }
1424 pub fn bump_version(&mut self) {
1426 self.current_version += 1;
1427 }
1428 pub fn insert(&mut self, key: u64, val: u64) {
1430 let ver = self.current_version;
1431 if let Some(e) = self.entries.iter_mut().find(|(k, _, _)| *k == key) {
1432 e.1 = val;
1433 e.2 = ver;
1434 } else {
1435 self.entries.push((key, val, ver));
1436 }
1437 }
1438 pub fn get(&self, key: u64) -> Option<u64> {
1440 self.entries
1441 .iter()
1442 .find(|(k, _, v)| *k == key && *v == self.current_version)
1443 .map(|(_, val, _)| *val)
1444 }
1445 pub fn version(&self) -> u64 {
1447 self.current_version
1448 }
1449 pub fn evict_stale(&mut self) {
1451 let cur = self.current_version;
1452 self.entries.retain(|(_, _, v)| *v == cur);
1453 }
1454 pub fn valid_count(&self) -> usize {
1456 let cur = self.current_version;
1457 self.entries.iter().filter(|(_, _, v)| *v == cur).count()
1458 }
1459}
1460#[allow(dead_code)]
1462pub struct SlidingSum {
1463 window: Vec<f64>,
1464 capacity: usize,
1465 pos: usize,
1466 sum: f64,
1467 count: usize,
1468}
1469#[allow(dead_code)]
1470impl SlidingSum {
1471 pub fn new(capacity: usize) -> Self {
1473 Self {
1474 window: vec![0.0; capacity],
1475 capacity,
1476 pos: 0,
1477 sum: 0.0,
1478 count: 0,
1479 }
1480 }
1481 pub fn push(&mut self, val: f64) {
1483 let oldest = self.window[self.pos];
1484 self.sum -= oldest;
1485 self.sum += val;
1486 self.window[self.pos] = val;
1487 self.pos = (self.pos + 1) % self.capacity;
1488 if self.count < self.capacity {
1489 self.count += 1;
1490 }
1491 }
1492 pub fn sum(&self) -> f64 {
1494 self.sum
1495 }
1496 pub fn mean(&self) -> Option<f64> {
1498 if self.count == 0 {
1499 None
1500 } else {
1501 Some(self.sum / self.count as f64)
1502 }
1503 }
1504 pub fn count(&self) -> usize {
1506 self.count
1507 }
1508}
1509#[allow(dead_code)]
1511pub struct BucketCounter<const N: usize> {
1512 buckets: [u64; N],
1513}
1514#[allow(dead_code)]
1515impl<const N: usize> BucketCounter<N> {
1516 pub const fn new() -> Self {
1518 Self { buckets: [0u64; N] }
1519 }
1520 pub fn inc(&mut self, i: usize) {
1522 if i < N {
1523 self.buckets[i] += 1;
1524 }
1525 }
1526 pub fn get(&self, i: usize) -> u64 {
1528 if i < N {
1529 self.buckets[i]
1530 } else {
1531 0
1532 }
1533 }
1534 pub fn total(&self) -> u64 {
1536 self.buckets.iter().sum()
1537 }
1538 pub fn argmax(&self) -> usize {
1540 self.buckets
1541 .iter()
1542 .enumerate()
1543 .max_by_key(|(_, &v)| v)
1544 .map(|(i, _)| i)
1545 .unwrap_or(0)
1546 }
1547}
1548#[allow(dead_code)]
1550pub struct FlatSubstitution {
1551 pairs: Vec<(String, String)>,
1552}
1553#[allow(dead_code)]
1554impl FlatSubstitution {
1555 pub fn new() -> Self {
1557 Self { pairs: Vec::new() }
1558 }
1559 pub fn add(&mut self, from: impl Into<String>, to: impl Into<String>) {
1561 self.pairs.push((from.into(), to.into()));
1562 }
1563 pub fn apply(&self, s: &str) -> String {
1565 let mut result = s.to_string();
1566 for (from, to) in &self.pairs {
1567 result = result.replace(from.as_str(), to.as_str());
1568 }
1569 result
1570 }
1571 pub fn len(&self) -> usize {
1573 self.pairs.len()
1574 }
1575 pub fn is_empty(&self) -> bool {
1577 self.pairs.is_empty()
1578 }
1579}
1580#[allow(dead_code)]
1582pub struct PathCache {
1583 nodes: Vec<PathNode>,
1584}
1585#[allow(dead_code)]
1586impl PathCache {
1587 pub fn new() -> Self {
1589 PathCache {
1590 nodes: vec![PathNode {
1591 key: 0,
1592 value: None,
1593 children: Vec::new(),
1594 }],
1595 }
1596 }
1597 pub fn insert(&mut self, path: &[u32], id: u64) {
1599 let mut node_idx = 0;
1600 for &step in path {
1601 let child_idx = self.nodes[node_idx]
1602 .children
1603 .iter()
1604 .copied()
1605 .find(|&c| self.nodes[c].key == step);
1606 match child_idx {
1607 Some(ci) => node_idx = ci,
1608 None => {
1609 let new_idx = self.nodes.len();
1610 self.nodes.push(PathNode {
1611 key: step,
1612 value: None,
1613 children: Vec::new(),
1614 });
1615 self.nodes[node_idx].children.push(new_idx);
1616 node_idx = new_idx;
1617 }
1618 }
1619 }
1620 self.nodes[node_idx].value = Some(id);
1621 }
1622 pub fn get(&self, path: &[u32]) -> Option<u64> {
1624 let mut node_idx = 0;
1625 for &step in path {
1626 let child_idx = self.nodes[node_idx]
1627 .children
1628 .iter()
1629 .copied()
1630 .find(|&c| self.nodes[c].key == step)?;
1631 node_idx = child_idx;
1632 }
1633 self.nodes[node_idx].value
1634 }
1635 pub fn node_count(&self) -> usize {
1637 self.nodes.len()
1638 }
1639}
1640#[allow(dead_code)]
1642pub struct Stopwatch {
1643 start: crate::wall_clock::Instant,
1644 splits: Vec<f64>,
1645}
1646#[allow(dead_code)]
1647impl Stopwatch {
1648 pub fn start() -> Self {
1650 Self {
1651 start: crate::wall_clock::Instant::now(),
1652 splits: Vec::new(),
1653 }
1654 }
1655 pub fn split(&mut self) {
1657 self.splits.push(self.elapsed_ms());
1658 }
1659 pub fn elapsed_ms(&self) -> f64 {
1661 self.start.elapsed().as_secs_f64() * 1000.0
1662 }
1663 pub fn splits(&self) -> &[f64] {
1665 &self.splits
1666 }
1667 pub fn num_splits(&self) -> usize {
1669 self.splits.len()
1670 }
1671}
1672#[allow(dead_code)]
1674#[derive(Debug, Clone)]
1675pub struct SharedCacheEntry {
1676 pub id: u64,
1677 pub hash: u64,
1678 pub ref_count: u32,
1679}
1680#[allow(dead_code)]
1681impl SharedCacheEntry {
1682 pub fn new(id: u64, hash: u64) -> Self {
1684 SharedCacheEntry {
1685 id,
1686 hash,
1687 ref_count: 1,
1688 }
1689 }
1690 pub fn inc_ref(&mut self) {
1692 self.ref_count = self.ref_count.saturating_add(1);
1693 }
1694 pub fn dec_ref(&mut self) -> bool {
1696 if self.ref_count > 0 {
1697 self.ref_count -= 1;
1698 }
1699 self.ref_count > 0
1700 }
1701 pub fn is_dead(&self) -> bool {
1703 self.ref_count == 0
1704 }
1705}
1706#[allow(dead_code)]
1708pub struct PathBuf {
1709 components: Vec<String>,
1710}
1711#[allow(dead_code)]
1712impl PathBuf {
1713 pub fn new() -> Self {
1715 Self {
1716 components: Vec::new(),
1717 }
1718 }
1719 pub fn push(&mut self, comp: impl Into<String>) {
1721 self.components.push(comp.into());
1722 }
1723 pub fn pop(&mut self) {
1725 self.components.pop();
1726 }
1727 pub fn as_str(&self) -> String {
1729 self.components.join("/")
1730 }
1731 pub fn depth(&self) -> usize {
1733 self.components.len()
1734 }
1735 pub fn clear(&mut self) {
1737 self.components.clear();
1738 }
1739}
1740#[allow(dead_code)]
1742pub struct MemoTable {
1743 entries: Vec<(u64, u64)>,
1744}
1745#[allow(dead_code)]
1746impl MemoTable {
1747 pub fn new() -> Self {
1749 MemoTable {
1750 entries: Vec::new(),
1751 }
1752 }
1753 pub fn insert(&mut self, key: u64, val: u64) {
1755 if let Some(e) = self.entries.iter_mut().find(|(k, _)| *k == key) {
1756 e.1 = val;
1757 } else {
1758 self.entries.push((key, val));
1759 }
1760 }
1761 pub fn get(&self, key: u64) -> Option<u64> {
1763 self.entries
1764 .iter()
1765 .find(|(k, _)| *k == key)
1766 .map(|(_, v)| *v)
1767 }
1768 pub fn remove(&mut self, key: u64) -> Option<u64> {
1770 if let Some(pos) = self.entries.iter().position(|(k, _)| *k == key) {
1771 Some(self.entries.remove(pos).1)
1772 } else {
1773 None
1774 }
1775 }
1776 pub fn len(&self) -> usize {
1778 self.entries.len()
1779 }
1780 pub fn is_empty(&self) -> bool {
1782 self.entries.is_empty()
1783 }
1784 pub fn clear(&mut self) {
1786 self.entries.clear();
1787 }
1788 pub fn drain_all(&mut self) -> Vec<(u64, u64)> {
1790 let v = self.entries.clone();
1791 self.entries.clear();
1792 v
1793 }
1794}
1795#[derive(Clone, Debug)]
1800pub(crate) struct ExprKey(pub(crate) Expr);
1801pub struct ExprPool {
1807 hashcons: ExprHashcons,
1809 roots: Vec<ExprId>,
1811}
1812impl ExprPool {
1813 pub fn new() -> Self {
1815 ExprPool {
1816 hashcons: ExprHashcons::new(),
1817 roots: Vec::new(),
1818 }
1819 }
1820 pub fn add(&mut self, expr: Expr) -> ExprId {
1822 let (id, _) = self.hashcons.intern(expr);
1823 id
1824 }
1825 pub fn add_root(&mut self, expr: Expr) -> ExprId {
1827 let (id, _) = self.hashcons.intern(expr);
1828 self.roots.push(id);
1829 id
1830 }
1831 pub fn get(&self, id: ExprId) -> Option<&Expr> {
1833 self.hashcons.get(id)
1834 }
1835 pub fn mark_root(&mut self, id: ExprId) {
1840 self.roots.push(id);
1841 }
1842 pub fn live_count(&self) -> usize {
1846 let mut seen = std::collections::HashSet::new();
1847 for &id in &self.roots {
1848 seen.insert(id);
1849 }
1850 seen.len()
1851 }
1852 pub fn total_count(&self) -> usize {
1854 self.hashcons.size()
1855 }
1856 pub fn dedup_ratio(&self) -> f64 {
1861 self.hashcons.hit_rate()
1862 }
1863 pub fn get_id(&self, expr: &Expr) -> Option<ExprId> {
1865 self.hashcons.get_id(expr)
1866 }
1867}
1868#[allow(dead_code)]
1870pub struct WriteOnce<T> {
1871 value: std::cell::Cell<Option<T>>,
1872}
1873#[allow(dead_code)]
1874impl<T: Copy> WriteOnce<T> {
1875 pub fn new() -> Self {
1877 Self {
1878 value: std::cell::Cell::new(None),
1879 }
1880 }
1881 pub fn write(&self, val: T) -> bool {
1883 if self.value.get().is_some() {
1884 return false;
1885 }
1886 self.value.set(Some(val));
1887 true
1888 }
1889 pub fn read(&self) -> Option<T> {
1891 self.value.get()
1892 }
1893 pub fn is_written(&self) -> bool {
1895 self.value.get().is_some()
1896 }
1897}