1use crate::{Level, Name};
6
7use std::collections::HashMap;
8
9use super::functions::{
10 collect_consts, collect_fvars, count_bvar_occ, has_loose_bvar, max_loose_bvar_impl,
11};
12
13#[allow(dead_code)]
15pub struct TransformStat {
16 before: StatSummary,
17 after: StatSummary,
18}
19#[allow(dead_code)]
20impl TransformStat {
21 pub fn new() -> Self {
23 Self {
24 before: StatSummary::new(),
25 after: StatSummary::new(),
26 }
27 }
28 pub fn record_before(&mut self, v: f64) {
30 self.before.record(v);
31 }
32 pub fn record_after(&mut self, v: f64) {
34 self.after.record(v);
35 }
36 pub fn mean_ratio(&self) -> Option<f64> {
38 let b = self.before.mean()?;
39 let a = self.after.mean()?;
40 if b.abs() < f64::EPSILON {
41 return None;
42 }
43 Some(a / b)
44 }
45}
46#[allow(dead_code)]
48pub struct TransitiveClosure {
49 adj: Vec<Vec<usize>>,
50 n: usize,
51}
52#[allow(dead_code)]
53impl TransitiveClosure {
54 pub fn new(n: usize) -> Self {
56 Self {
57 adj: vec![Vec::new(); n],
58 n,
59 }
60 }
61 pub fn add_edge(&mut self, from: usize, to: usize) {
63 if from < self.n {
64 self.adj[from].push(to);
65 }
66 }
67 pub fn reachable_from(&self, start: usize) -> Vec<usize> {
69 let mut visited = vec![false; self.n];
70 let mut queue = std::collections::VecDeque::new();
71 queue.push_back(start);
72 while let Some(node) = queue.pop_front() {
73 if node >= self.n || visited[node] {
74 continue;
75 }
76 visited[node] = true;
77 for &next in &self.adj[node] {
78 queue.push_back(next);
79 }
80 }
81 (0..self.n).filter(|&i| visited[i]).collect()
82 }
83 pub fn can_reach(&self, from: usize, to: usize) -> bool {
85 self.reachable_from(from).contains(&to)
86 }
87}
88#[allow(dead_code)]
90pub enum Either2<A, B> {
91 First(A),
93 Second(B),
95}
96#[allow(dead_code)]
97impl<A, B> Either2<A, B> {
98 pub fn is_first(&self) -> bool {
100 matches!(self, Either2::First(_))
101 }
102 pub fn is_second(&self) -> bool {
104 matches!(self, Either2::Second(_))
105 }
106 pub fn first(self) -> Option<A> {
108 match self {
109 Either2::First(a) => Some(a),
110 _ => None,
111 }
112 }
113 pub fn second(self) -> Option<B> {
115 match self {
116 Either2::Second(b) => Some(b),
117 _ => None,
118 }
119 }
120 pub fn map_first<C, F: FnOnce(A) -> C>(self, f: F) -> Either2<C, B> {
122 match self {
123 Either2::First(a) => Either2::First(f(a)),
124 Either2::Second(b) => Either2::Second(b),
125 }
126 }
127}
128#[allow(dead_code)]
130pub struct MinHeap<T: Ord> {
131 data: Vec<T>,
132}
133#[allow(dead_code)]
134impl<T: Ord> MinHeap<T> {
135 pub fn new() -> Self {
137 Self { data: Vec::new() }
138 }
139 pub fn push(&mut self, val: T) {
141 self.data.push(val);
142 self.sift_up(self.data.len() - 1);
143 }
144 pub fn pop(&mut self) -> Option<T> {
146 if self.data.is_empty() {
147 return None;
148 }
149 let n = self.data.len();
150 self.data.swap(0, n - 1);
151 let min = self.data.pop();
152 if !self.data.is_empty() {
153 self.sift_down(0);
154 }
155 min
156 }
157 pub fn peek(&self) -> Option<&T> {
159 self.data.first()
160 }
161 pub fn len(&self) -> usize {
163 self.data.len()
164 }
165 pub fn is_empty(&self) -> bool {
167 self.data.is_empty()
168 }
169 fn sift_up(&mut self, mut i: usize) {
170 while i > 0 {
171 let parent = (i - 1) / 2;
172 if self.data[i] < self.data[parent] {
173 self.data.swap(i, parent);
174 i = parent;
175 } else {
176 break;
177 }
178 }
179 }
180 fn sift_down(&mut self, mut i: usize) {
181 let n = self.data.len();
182 loop {
183 let left = 2 * i + 1;
184 let right = 2 * i + 2;
185 let mut smallest = i;
186 if left < n && self.data[left] < self.data[smallest] {
187 smallest = left;
188 }
189 if right < n && self.data[right] < self.data[smallest] {
190 smallest = right;
191 }
192 if smallest == i {
193 break;
194 }
195 self.data.swap(i, smallest);
196 i = smallest;
197 }
198 }
199}
200#[allow(dead_code)]
202pub struct PathBuf {
203 components: Vec<String>,
204}
205#[allow(dead_code)]
206impl PathBuf {
207 pub fn new() -> Self {
209 Self {
210 components: Vec::new(),
211 }
212 }
213 pub fn push(&mut self, comp: impl Into<String>) {
215 self.components.push(comp.into());
216 }
217 pub fn pop(&mut self) {
219 self.components.pop();
220 }
221 pub fn as_str(&self) -> String {
223 self.components.join("/")
224 }
225 pub fn depth(&self) -> usize {
227 self.components.len()
228 }
229 pub fn clear(&mut self) {
231 self.components.clear();
232 }
233}
234#[allow(dead_code)]
236pub struct FlatSubstitution {
237 pairs: Vec<(String, String)>,
238}
239#[allow(dead_code)]
240impl FlatSubstitution {
241 pub fn new() -> Self {
243 Self { pairs: Vec::new() }
244 }
245 pub fn add(&mut self, from: impl Into<String>, to: impl Into<String>) {
247 self.pairs.push((from.into(), to.into()));
248 }
249 pub fn apply(&self, s: &str) -> String {
251 let mut result = s.to_string();
252 for (from, to) in &self.pairs {
253 result = result.replace(from.as_str(), to.as_str());
254 }
255 result
256 }
257 pub fn len(&self) -> usize {
259 self.pairs.len()
260 }
261 pub fn is_empty(&self) -> bool {
263 self.pairs.is_empty()
264 }
265}
266#[allow(dead_code)]
268pub struct SimpleDag {
269 edges: Vec<Vec<usize>>,
271}
272#[allow(dead_code)]
273impl SimpleDag {
274 pub fn new(n: usize) -> Self {
276 Self {
277 edges: vec![Vec::new(); n],
278 }
279 }
280 pub fn add_edge(&mut self, from: usize, to: usize) {
282 if from < self.edges.len() {
283 self.edges[from].push(to);
284 }
285 }
286 pub fn successors(&self, node: usize) -> &[usize] {
288 self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
289 }
290 pub fn can_reach(&self, from: usize, to: usize) -> bool {
292 let mut visited = vec![false; self.edges.len()];
293 self.dfs(from, to, &mut visited)
294 }
295 fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
296 if cur == target {
297 return true;
298 }
299 if cur >= visited.len() || visited[cur] {
300 return false;
301 }
302 visited[cur] = true;
303 for &next in self.successors(cur) {
304 if self.dfs(next, target, visited) {
305 return true;
306 }
307 }
308 false
309 }
310 pub fn topological_sort(&self) -> Option<Vec<usize>> {
312 let n = self.edges.len();
313 let mut in_degree = vec![0usize; n];
314 for succs in &self.edges {
315 for &s in succs {
316 if s < n {
317 in_degree[s] += 1;
318 }
319 }
320 }
321 let mut queue: std::collections::VecDeque<usize> =
322 (0..n).filter(|&i| in_degree[i] == 0).collect();
323 let mut order = Vec::new();
324 while let Some(node) = queue.pop_front() {
325 order.push(node);
326 for &s in self.successors(node) {
327 if s < n {
328 in_degree[s] -= 1;
329 if in_degree[s] == 0 {
330 queue.push_back(s);
331 }
332 }
333 }
334 }
335 if order.len() == n {
336 Some(order)
337 } else {
338 None
339 }
340 }
341 pub fn num_nodes(&self) -> usize {
343 self.edges.len()
344 }
345}
346#[allow(dead_code)]
348pub struct RawFnPtr {
349 ptr: usize,
351 arity: usize,
352 name: String,
353}
354#[allow(dead_code)]
355impl RawFnPtr {
356 pub fn new(ptr: usize, arity: usize, name: impl Into<String>) -> Self {
358 Self {
359 ptr,
360 arity,
361 name: name.into(),
362 }
363 }
364 pub fn arity(&self) -> usize {
366 self.arity
367 }
368 pub fn name(&self) -> &str {
370 &self.name
371 }
372 pub fn raw(&self) -> usize {
374 self.ptr
375 }
376}
377#[allow(dead_code)]
379pub struct SparseVec<T: Default + Clone + PartialEq> {
380 entries: std::collections::HashMap<usize, T>,
381 default_: T,
382 logical_len: usize,
383}
384#[allow(dead_code)]
385impl<T: Default + Clone + PartialEq> SparseVec<T> {
386 pub fn new(len: usize) -> Self {
388 Self {
389 entries: std::collections::HashMap::new(),
390 default_: T::default(),
391 logical_len: len,
392 }
393 }
394 pub fn set(&mut self, idx: usize, val: T) {
396 if val == self.default_ {
397 self.entries.remove(&idx);
398 } else {
399 self.entries.insert(idx, val);
400 }
401 }
402 pub fn get(&self, idx: usize) -> &T {
404 self.entries.get(&idx).unwrap_or(&self.default_)
405 }
406 pub fn len(&self) -> usize {
408 self.logical_len
409 }
410 pub fn is_empty(&self) -> bool {
412 self.len() == 0
413 }
414 pub fn nnz(&self) -> usize {
416 self.entries.len()
417 }
418}
419#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
423pub enum BinderInfo {
424 Default,
426 Implicit,
428 StrictImplicit,
430 InstImplicit,
432}
433impl BinderInfo {
434 pub fn is_explicit(self) -> bool {
436 matches!(self, BinderInfo::Default)
437 }
438 pub fn is_implicit(self) -> bool {
440 matches!(self, BinderInfo::Implicit | BinderInfo::StrictImplicit)
441 }
442 pub fn is_inst_implicit(self) -> bool {
444 matches!(self, BinderInfo::InstImplicit)
445 }
446 pub fn open_delim(self) -> &'static str {
448 match self {
449 BinderInfo::Default => "(",
450 BinderInfo::Implicit => "{",
451 BinderInfo::StrictImplicit => "⦃",
452 BinderInfo::InstImplicit => "[",
453 }
454 }
455 pub fn close_delim(self) -> &'static str {
457 match self {
458 BinderInfo::Default => ")",
459 BinderInfo::Implicit => "}",
460 BinderInfo::StrictImplicit => "⦄",
461 BinderInfo::InstImplicit => "]",
462 }
463 }
464}
465#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
470pub struct FVarId(pub u64);
471impl FVarId {
472 pub fn new(id: u64) -> Self {
474 FVarId(id)
475 }
476}
477impl FVarId {
478 pub fn raw(self) -> u64 {
480 self.0
481 }
482}
483#[allow(dead_code)]
485pub struct LabelSet {
486 labels: Vec<String>,
487}
488#[allow(dead_code)]
489impl LabelSet {
490 pub fn new() -> Self {
492 Self { labels: Vec::new() }
493 }
494 pub fn add(&mut self, label: impl Into<String>) {
496 let s = label.into();
497 if !self.labels.contains(&s) {
498 self.labels.push(s);
499 }
500 }
501 pub fn has(&self, label: &str) -> bool {
503 self.labels.iter().any(|l| l == label)
504 }
505 pub fn count(&self) -> usize {
507 self.labels.len()
508 }
509 pub fn all(&self) -> &[String] {
511 &self.labels
512 }
513}
514#[allow(dead_code)]
516#[allow(missing_docs)]
517pub enum DecisionNode {
518 Leaf(String),
520 Branch {
522 key: String,
523 val: String,
524 yes_branch: Box<DecisionNode>,
525 no_branch: Box<DecisionNode>,
526 },
527}
528#[allow(dead_code)]
529impl DecisionNode {
530 pub fn evaluate(&self, ctx: &std::collections::HashMap<String, String>) -> &str {
532 match self {
533 DecisionNode::Leaf(action) => action.as_str(),
534 DecisionNode::Branch {
535 key,
536 val,
537 yes_branch,
538 no_branch,
539 } => {
540 let actual = ctx.get(key).map(|s| s.as_str()).unwrap_or("");
541 if actual == val.as_str() {
542 yes_branch.evaluate(ctx)
543 } else {
544 no_branch.evaluate(ctx)
545 }
546 }
547 }
548 }
549 pub fn depth(&self) -> usize {
551 match self {
552 DecisionNode::Leaf(_) => 0,
553 DecisionNode::Branch {
554 yes_branch,
555 no_branch,
556 ..
557 } => 1 + yes_branch.depth().max(no_branch.depth()),
558 }
559 }
560}
561#[allow(dead_code)]
563#[allow(missing_docs)]
564pub struct RewriteRule {
565 pub name: String,
567 pub lhs: String,
569 pub rhs: String,
571 pub conditional: bool,
573}
574#[allow(dead_code)]
575impl RewriteRule {
576 pub fn unconditional(
578 name: impl Into<String>,
579 lhs: impl Into<String>,
580 rhs: impl Into<String>,
581 ) -> Self {
582 Self {
583 name: name.into(),
584 lhs: lhs.into(),
585 rhs: rhs.into(),
586 conditional: false,
587 }
588 }
589 pub fn conditional(
591 name: impl Into<String>,
592 lhs: impl Into<String>,
593 rhs: impl Into<String>,
594 ) -> Self {
595 Self {
596 name: name.into(),
597 lhs: lhs.into(),
598 rhs: rhs.into(),
599 conditional: true,
600 }
601 }
602 pub fn display(&self) -> String {
604 format!("{}: {} → {}", self.name, self.lhs, self.rhs)
605 }
606}
607#[allow(dead_code)]
609pub struct ConfigNode {
610 key: String,
611 value: Option<String>,
612 children: Vec<ConfigNode>,
613}
614#[allow(dead_code)]
615impl ConfigNode {
616 pub fn leaf(key: impl Into<String>, value: impl Into<String>) -> Self {
618 Self {
619 key: key.into(),
620 value: Some(value.into()),
621 children: Vec::new(),
622 }
623 }
624 pub fn section(key: impl Into<String>) -> Self {
626 Self {
627 key: key.into(),
628 value: None,
629 children: Vec::new(),
630 }
631 }
632 pub fn add_child(&mut self, child: ConfigNode) {
634 self.children.push(child);
635 }
636 pub fn key(&self) -> &str {
638 &self.key
639 }
640 pub fn value(&self) -> Option<&str> {
642 self.value.as_deref()
643 }
644 pub fn num_children(&self) -> usize {
646 self.children.len()
647 }
648 pub fn lookup(&self, path: &str) -> Option<&str> {
650 let mut parts = path.splitn(2, '.');
651 let head = parts.next()?;
652 let tail = parts.next();
653 if head != self.key {
654 return None;
655 }
656 match tail {
657 None => self.value.as_deref(),
658 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
659 }
660 }
661 fn lookup_relative(&self, path: &str) -> Option<&str> {
662 let mut parts = path.splitn(2, '.');
663 let head = parts.next()?;
664 let tail = parts.next();
665 if head != self.key {
666 return None;
667 }
668 match tail {
669 None => self.value.as_deref(),
670 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
671 }
672 }
673}
674#[allow(dead_code)]
676pub struct RewriteRuleSet {
677 rules: Vec<RewriteRule>,
678}
679#[allow(dead_code)]
680impl RewriteRuleSet {
681 pub fn new() -> Self {
683 Self { rules: Vec::new() }
684 }
685 pub fn add(&mut self, rule: RewriteRule) {
687 self.rules.push(rule);
688 }
689 pub fn len(&self) -> usize {
691 self.rules.len()
692 }
693 pub fn is_empty(&self) -> bool {
695 self.rules.is_empty()
696 }
697 pub fn conditional_rules(&self) -> Vec<&RewriteRule> {
699 self.rules.iter().filter(|r| r.conditional).collect()
700 }
701 pub fn unconditional_rules(&self) -> Vec<&RewriteRule> {
703 self.rules.iter().filter(|r| !r.conditional).collect()
704 }
705 pub fn get(&self, name: &str) -> Option<&RewriteRule> {
707 self.rules.iter().find(|r| r.name == name)
708 }
709}
710#[allow(dead_code)]
712pub struct Stopwatch {
713 start: std::time::Instant,
714 splits: Vec<f64>,
715}
716#[allow(dead_code)]
717impl Stopwatch {
718 pub fn start() -> Self {
720 Self {
721 start: std::time::Instant::now(),
722 splits: Vec::new(),
723 }
724 }
725 pub fn split(&mut self) {
727 self.splits.push(self.elapsed_ms());
728 }
729 pub fn elapsed_ms(&self) -> f64 {
731 self.start.elapsed().as_secs_f64() * 1000.0
732 }
733 pub fn splits(&self) -> &[f64] {
735 &self.splits
736 }
737 pub fn num_splits(&self) -> usize {
739 self.splits.len()
740 }
741}
742#[allow(dead_code)]
744pub struct WriteOnce<T> {
745 value: std::cell::Cell<Option<T>>,
746}
747#[allow(dead_code)]
748impl<T: Copy> WriteOnce<T> {
749 pub fn new() -> Self {
751 Self {
752 value: std::cell::Cell::new(None),
753 }
754 }
755 pub fn write(&self, val: T) -> bool {
757 if self.value.get().is_some() {
758 return false;
759 }
760 self.value.set(Some(val));
761 true
762 }
763 pub fn read(&self) -> Option<T> {
765 self.value.get()
766 }
767 pub fn is_written(&self) -> bool {
769 self.value.get().is_some()
770 }
771}
772#[allow(dead_code)]
774pub struct StatSummary {
775 count: u64,
776 sum: f64,
777 min: f64,
778 max: f64,
779}
780#[allow(dead_code)]
781impl StatSummary {
782 pub fn new() -> Self {
784 Self {
785 count: 0,
786 sum: 0.0,
787 min: f64::INFINITY,
788 max: f64::NEG_INFINITY,
789 }
790 }
791 pub fn record(&mut self, val: f64) {
793 self.count += 1;
794 self.sum += val;
795 if val < self.min {
796 self.min = val;
797 }
798 if val > self.max {
799 self.max = val;
800 }
801 }
802 pub fn mean(&self) -> Option<f64> {
804 if self.count == 0 {
805 None
806 } else {
807 Some(self.sum / self.count as f64)
808 }
809 }
810 pub fn min(&self) -> Option<f64> {
812 if self.count == 0 {
813 None
814 } else {
815 Some(self.min)
816 }
817 }
818 pub fn max(&self) -> Option<f64> {
820 if self.count == 0 {
821 None
822 } else {
823 Some(self.max)
824 }
825 }
826 pub fn count(&self) -> u64 {
828 self.count
829 }
830}
831#[derive(Clone, PartialEq, Eq, Hash, Debug)]
833pub enum Literal {
834 Nat(u64),
836 Str(String),
838}
839impl Literal {
840 pub fn is_nat(&self) -> bool {
842 matches!(self, Literal::Nat(_))
843 }
844 pub fn is_str(&self) -> bool {
846 matches!(self, Literal::Str(_))
847 }
848 pub fn as_nat(&self) -> Option<u64> {
850 if let Literal::Nat(n) = self {
851 Some(*n)
852 } else {
853 None
854 }
855 }
856 pub fn as_str(&self) -> Option<&str> {
858 if let Literal::Str(s) = self {
859 Some(s.as_str())
860 } else {
861 None
862 }
863 }
864 pub fn type_name(&self) -> &'static str {
866 match self {
867 Literal::Nat(_) => "Nat",
868 Literal::Str(_) => "String",
869 }
870 }
871}
872#[allow(dead_code)]
874pub struct WindowIterator<'a, T> {
875 pub(super) data: &'a [T],
876 pub(super) pos: usize,
877 pub(super) window: usize,
878}
879#[allow(dead_code)]
880impl<'a, T> WindowIterator<'a, T> {
881 pub fn new(data: &'a [T], window: usize) -> Self {
883 Self {
884 data,
885 pos: 0,
886 window,
887 }
888 }
889}
890#[allow(dead_code)]
892pub struct StackCalc {
893 stack: Vec<i64>,
894}
895#[allow(dead_code)]
896impl StackCalc {
897 pub fn new() -> Self {
899 Self { stack: Vec::new() }
900 }
901 pub fn push(&mut self, n: i64) {
903 self.stack.push(n);
904 }
905 pub fn add(&mut self) {
907 let b = self
908 .stack
909 .pop()
910 .expect("stack must have at least two values for add");
911 let a = self
912 .stack
913 .pop()
914 .expect("stack must have at least two values for add");
915 self.stack.push(a + b);
916 }
917 pub fn sub(&mut self) {
919 let b = self
920 .stack
921 .pop()
922 .expect("stack must have at least two values for sub");
923 let a = self
924 .stack
925 .pop()
926 .expect("stack must have at least two values for sub");
927 self.stack.push(a - b);
928 }
929 pub fn mul(&mut self) {
931 let b = self
932 .stack
933 .pop()
934 .expect("stack must have at least two values for mul");
935 let a = self
936 .stack
937 .pop()
938 .expect("stack must have at least two values for mul");
939 self.stack.push(a * b);
940 }
941 pub fn peek(&self) -> Option<i64> {
943 self.stack.last().copied()
944 }
945 pub fn depth(&self) -> usize {
947 self.stack.len()
948 }
949}
950#[allow(dead_code)]
952pub struct StringPool {
953 free: Vec<String>,
954}
955#[allow(dead_code)]
956impl StringPool {
957 pub fn new() -> Self {
959 Self { free: Vec::new() }
960 }
961 pub fn take(&mut self) -> String {
963 self.free.pop().unwrap_or_default()
964 }
965 pub fn give(&mut self, mut s: String) {
967 s.clear();
968 self.free.push(s);
969 }
970 pub fn free_count(&self) -> usize {
972 self.free.len()
973 }
974}
975#[derive(Clone, PartialEq, Eq, Hash, Debug)]
983pub enum Expr {
984 Sort(Level),
989 BVar(u32),
994 FVar(FVarId),
998 Const(Name, Vec<Level>),
1003 App(Box<Expr>, Box<Expr>),
1007 Lam(BinderInfo, Name, Box<Expr>, Box<Expr>),
1009 Pi(BinderInfo, Name, Box<Expr>, Box<Expr>),
1014 Let(Name, Box<Expr>, Box<Expr>, Box<Expr>),
1016 Lit(Literal),
1018 Proj(Name, u32, Box<Expr>),
1020}
1021impl Expr {
1022 pub fn is_sort(&self) -> bool {
1024 matches!(self, Expr::Sort(_))
1025 }
1026 pub fn is_prop(&self) -> bool {
1028 matches!(self, Expr::Sort(l) if l.is_zero())
1029 }
1030 pub fn is_bvar(&self) -> bool {
1032 matches!(self, Expr::BVar(_))
1033 }
1034 pub fn is_fvar(&self) -> bool {
1036 matches!(self, Expr::FVar(_))
1037 }
1038 pub fn is_app(&self) -> bool {
1040 matches!(self, Expr::App(_, _))
1041 }
1042 pub fn is_lambda(&self) -> bool {
1044 matches!(self, Expr::Lam(_, _, _, _))
1045 }
1046 pub fn is_pi(&self) -> bool {
1048 matches!(self, Expr::Pi(_, _, _, _))
1049 }
1050}
1051impl Expr {
1052 pub fn is_let(&self) -> bool {
1054 matches!(self, Expr::Let(_, _, _, _))
1055 }
1056 pub fn is_lit(&self) -> bool {
1058 matches!(self, Expr::Lit(_))
1059 }
1060 pub fn is_const(&self) -> bool {
1062 matches!(self, Expr::Const(_, _))
1063 }
1064 pub fn is_proj(&self) -> bool {
1066 matches!(self, Expr::Proj(_, _, _))
1067 }
1068 pub fn is_atom(&self) -> bool {
1071 matches!(
1072 self,
1073 Expr::Sort(_) | Expr::BVar(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_)
1074 )
1075 }
1076 pub fn as_bvar(&self) -> Option<u32> {
1078 if let Expr::BVar(n) = self {
1079 Some(*n)
1080 } else {
1081 None
1082 }
1083 }
1084 pub fn as_fvar(&self) -> Option<FVarId> {
1086 if let Expr::FVar(id) = self {
1087 Some(*id)
1088 } else {
1089 None
1090 }
1091 }
1092 pub fn as_const_name(&self) -> Option<&Name> {
1094 if let Expr::Const(n, _) = self {
1095 Some(n)
1096 } else {
1097 None
1098 }
1099 }
1100 pub fn as_sort_level(&self) -> Option<&Level> {
1102 if let Expr::Sort(l) = self {
1103 Some(l)
1104 } else {
1105 None
1106 }
1107 }
1108 pub fn app_head_args(&self) -> (&Expr, Vec<&Expr>) {
1112 let mut args = Vec::new();
1113 let mut cur = self;
1114 while let Expr::App(f, a) = cur {
1115 args.push(a.as_ref());
1116 cur = f;
1117 }
1118 args.reverse();
1119 (cur, args)
1120 }
1121 pub fn app_arity(&self) -> usize {
1123 let mut n = 0;
1124 let mut cur = self;
1125 while let Expr::App(f, _) = cur {
1126 n += 1;
1127 cur = f;
1128 }
1129 n
1130 }
1131 pub fn pi_arity(&self) -> usize {
1133 let mut n = 0;
1134 let mut cur = self;
1135 while let Expr::Pi(_, _, _, body) = cur {
1136 n += 1;
1137 cur = body;
1138 }
1139 n
1140 }
1141 pub fn lam_arity(&self) -> usize {
1143 let mut n = 0;
1144 let mut cur = self;
1145 while let Expr::Lam(_, _, _, body) = cur {
1146 n += 1;
1147 cur = body;
1148 }
1149 n
1150 }
1151 pub fn size(&self) -> usize {
1153 match self {
1154 Expr::Sort(_) | Expr::BVar(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_) => 1,
1155 Expr::App(f, a) => 1 + f.size() + a.size(),
1156 Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => 1 + ty.size() + body.size(),
1157 Expr::Let(_, ty, val, body) => 1 + ty.size() + val.size() + body.size(),
1158 Expr::Proj(_, _, s) => 1 + s.size(),
1159 }
1160 }
1161 pub fn ast_depth(&self) -> usize {
1163 match self {
1164 Expr::Sort(_) | Expr::BVar(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_) => 0,
1165 Expr::App(f, a) => 1 + f.ast_depth().max(a.ast_depth()),
1166 Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
1167 1 + ty.ast_depth().max(body.ast_depth())
1168 }
1169 Expr::Let(_, ty, val, body) => {
1170 1 + ty.ast_depth().max(val.ast_depth()).max(body.ast_depth())
1171 }
1172 Expr::Proj(_, _, s) => 1 + s.ast_depth(),
1173 }
1174 }
1175 pub fn mk_app_many(self, args: &[Expr]) -> Expr {
1179 args.iter()
1180 .fold(self, |acc, a| Expr::App(Box::new(acc), Box::new(a.clone())))
1181 }
1182 pub fn has_loose_bvar_at(&self, d: u32) -> bool {
1184 has_loose_bvar(self, d)
1185 }
1186 pub fn count_bvar_occurrences(&self, idx: u32) -> usize {
1188 count_bvar_occ(self, idx)
1189 }
1190 pub fn is_closed(&self) -> bool {
1192 !has_loose_bvar(self, 0) && self.max_loose_bvar().is_none()
1193 }
1194 fn max_loose_bvar(&self) -> Option<u32> {
1196 max_loose_bvar_impl(self, 0)
1197 }
1198 pub fn free_vars(&self) -> std::collections::HashSet<FVarId> {
1200 let mut set = std::collections::HashSet::new();
1201 collect_fvars(self, &mut set);
1202 set
1203 }
1204 pub fn constants(&self) -> std::collections::HashSet<Name> {
1206 let mut set = std::collections::HashSet::new();
1207 collect_consts(self, &mut set);
1208 set
1209 }
1210}
1211#[allow(dead_code)]
1213pub struct NonEmptyVec<T> {
1214 head: T,
1215 tail: Vec<T>,
1216}
1217#[allow(dead_code)]
1218impl<T> NonEmptyVec<T> {
1219 pub fn singleton(val: T) -> Self {
1221 Self {
1222 head: val,
1223 tail: Vec::new(),
1224 }
1225 }
1226 pub fn push(&mut self, val: T) {
1228 self.tail.push(val);
1229 }
1230 pub fn first(&self) -> &T {
1232 &self.head
1233 }
1234 pub fn last(&self) -> &T {
1236 self.tail.last().unwrap_or(&self.head)
1237 }
1238 pub fn len(&self) -> usize {
1240 1 + self.tail.len()
1241 }
1242 pub fn is_empty(&self) -> bool {
1244 self.len() == 0
1245 }
1246 pub fn to_vec(&self) -> Vec<&T> {
1248 let mut v = vec![&self.head];
1249 v.extend(self.tail.iter());
1250 v
1251 }
1252}
1253#[allow(dead_code)]
1255pub struct Fixture {
1256 data: std::collections::HashMap<String, String>,
1257}
1258#[allow(dead_code)]
1259impl Fixture {
1260 pub fn new() -> Self {
1262 Self {
1263 data: std::collections::HashMap::new(),
1264 }
1265 }
1266 pub fn set(&mut self, key: impl Into<String>, val: impl Into<String>) {
1268 self.data.insert(key.into(), val.into());
1269 }
1270 pub fn get(&self, key: &str) -> Option<&str> {
1272 self.data.get(key).map(|s| s.as_str())
1273 }
1274 pub fn len(&self) -> usize {
1276 self.data.len()
1277 }
1278 pub fn is_empty(&self) -> bool {
1280 self.len() == 0
1281 }
1282}
1283#[derive(Debug, Default)]
1287pub struct FVarIdGen {
1288 next: u64,
1289}
1290impl FVarIdGen {
1291 pub fn new() -> Self {
1293 Self::default()
1294 }
1295 pub fn fresh(&mut self) -> FVarId {
1297 let id = FVarId::new(self.next);
1298 self.next += 1;
1299 id
1300 }
1301 pub fn peek(&self) -> FVarId {
1303 FVarId::new(self.next)
1304 }
1305 pub fn reset(&mut self) {
1307 self.next = 0;
1308 }
1309 pub fn current(&self) -> u64 {
1311 self.next
1312 }
1313}
1314#[allow(dead_code)]
1316pub struct SmallMap<K: Ord + Clone, V: Clone> {
1317 entries: Vec<(K, V)>,
1318}
1319#[allow(dead_code)]
1320impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
1321 pub fn new() -> Self {
1323 Self {
1324 entries: Vec::new(),
1325 }
1326 }
1327 pub fn insert(&mut self, key: K, val: V) {
1329 match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
1330 Ok(i) => self.entries[i].1 = val,
1331 Err(i) => self.entries.insert(i, (key, val)),
1332 }
1333 }
1334 pub fn get(&self, key: &K) -> Option<&V> {
1336 self.entries
1337 .binary_search_by_key(&key, |(k, _)| k)
1338 .ok()
1339 .map(|i| &self.entries[i].1)
1340 }
1341 pub fn len(&self) -> usize {
1343 self.entries.len()
1344 }
1345 pub fn is_empty(&self) -> bool {
1347 self.entries.is_empty()
1348 }
1349 pub fn keys(&self) -> Vec<&K> {
1351 self.entries.iter().map(|(k, _)| k).collect()
1352 }
1353 pub fn values(&self) -> Vec<&V> {
1355 self.entries.iter().map(|(_, v)| v).collect()
1356 }
1357}
1358#[allow(dead_code)]
1360pub struct TokenBucket {
1361 capacity: u64,
1362 tokens: u64,
1363 refill_per_ms: u64,
1364 last_refill: std::time::Instant,
1365}
1366#[allow(dead_code)]
1367impl TokenBucket {
1368 pub fn new(capacity: u64, refill_per_ms: u64) -> Self {
1370 Self {
1371 capacity,
1372 tokens: capacity,
1373 refill_per_ms,
1374 last_refill: std::time::Instant::now(),
1375 }
1376 }
1377 pub fn try_consume(&mut self, n: u64) -> bool {
1379 self.refill();
1380 if self.tokens >= n {
1381 self.tokens -= n;
1382 true
1383 } else {
1384 false
1385 }
1386 }
1387 fn refill(&mut self) {
1388 let now = std::time::Instant::now();
1389 let elapsed_ms = now.duration_since(self.last_refill).as_millis() as u64;
1390 if elapsed_ms > 0 {
1391 let new_tokens = elapsed_ms * self.refill_per_ms;
1392 self.tokens = (self.tokens + new_tokens).min(self.capacity);
1393 self.last_refill = now;
1394 }
1395 }
1396 pub fn available(&self) -> u64 {
1398 self.tokens
1399 }
1400 pub fn capacity(&self) -> u64 {
1402 self.capacity
1403 }
1404}
1405#[allow(dead_code)]
1407pub struct SlidingSum {
1408 window: Vec<f64>,
1409 capacity: usize,
1410 pos: usize,
1411 sum: f64,
1412 count: usize,
1413}
1414#[allow(dead_code)]
1415impl SlidingSum {
1416 pub fn new(capacity: usize) -> Self {
1418 Self {
1419 window: vec![0.0; capacity],
1420 capacity,
1421 pos: 0,
1422 sum: 0.0,
1423 count: 0,
1424 }
1425 }
1426 pub fn push(&mut self, val: f64) {
1428 let oldest = self.window[self.pos];
1429 self.sum -= oldest;
1430 self.sum += val;
1431 self.window[self.pos] = val;
1432 self.pos = (self.pos + 1) % self.capacity;
1433 if self.count < self.capacity {
1434 self.count += 1;
1435 }
1436 }
1437 pub fn sum(&self) -> f64 {
1439 self.sum
1440 }
1441 pub fn mean(&self) -> Option<f64> {
1443 if self.count == 0 {
1444 None
1445 } else {
1446 Some(self.sum / self.count as f64)
1447 }
1448 }
1449 pub fn count(&self) -> usize {
1451 self.count
1452 }
1453}
1454#[allow(dead_code)]
1456pub struct VersionedRecord<T: Clone> {
1457 history: Vec<T>,
1458}
1459#[allow(dead_code)]
1460impl<T: Clone> VersionedRecord<T> {
1461 pub fn new(initial: T) -> Self {
1463 Self {
1464 history: vec![initial],
1465 }
1466 }
1467 pub fn update(&mut self, val: T) {
1469 self.history.push(val);
1470 }
1471 pub fn current(&self) -> &T {
1473 self.history
1474 .last()
1475 .expect("VersionedRecord history is always non-empty after construction")
1476 }
1477 pub fn at_version(&self, n: usize) -> Option<&T> {
1479 self.history.get(n)
1480 }
1481 pub fn version(&self) -> usize {
1483 self.history.len() - 1
1484 }
1485 pub fn has_history(&self) -> bool {
1487 self.history.len() > 1
1488 }
1489}
1490#[allow(dead_code)]
1492pub struct FocusStack<T> {
1493 items: Vec<T>,
1494}
1495#[allow(dead_code)]
1496impl<T> FocusStack<T> {
1497 pub fn new() -> Self {
1499 Self { items: Vec::new() }
1500 }
1501 pub fn focus(&mut self, item: T) {
1503 self.items.push(item);
1504 }
1505 pub fn blur(&mut self) -> Option<T> {
1507 self.items.pop()
1508 }
1509 pub fn current(&self) -> Option<&T> {
1511 self.items.last()
1512 }
1513 pub fn depth(&self) -> usize {
1515 self.items.len()
1516 }
1517 pub fn is_empty(&self) -> bool {
1519 self.items.is_empty()
1520 }
1521}
1522#[allow(dead_code)]
1524pub struct PrefixCounter {
1525 children: std::collections::HashMap<char, PrefixCounter>,
1526 count: usize,
1527}
1528#[allow(dead_code)]
1529impl PrefixCounter {
1530 pub fn new() -> Self {
1532 Self {
1533 children: std::collections::HashMap::new(),
1534 count: 0,
1535 }
1536 }
1537 pub fn record(&mut self, s: &str) {
1539 self.count += 1;
1540 let mut node = self;
1541 for c in s.chars() {
1542 node = node.children.entry(c).or_default();
1543 node.count += 1;
1544 }
1545 }
1546 pub fn count_with_prefix(&self, prefix: &str) -> usize {
1548 let mut node = self;
1549 for c in prefix.chars() {
1550 match node.children.get(&c) {
1551 Some(n) => node = n,
1552 None => return 0,
1553 }
1554 }
1555 node.count
1556 }
1557}