1use crate::{Level, Name};
6
7use std::collections::HashMap;
8use std::rc::Rc;
9
10use super::functions::{
11 collect_consts, collect_fvars, count_bvar_occ, has_loose_bvar, max_loose_bvar_impl,
12};
13
14#[allow(dead_code)]
16pub struct TransformStat {
17 before: StatSummary,
18 after: StatSummary,
19}
20#[allow(dead_code)]
21impl TransformStat {
22 pub fn new() -> Self {
24 Self {
25 before: StatSummary::new(),
26 after: StatSummary::new(),
27 }
28 }
29 pub fn record_before(&mut self, v: f64) {
31 self.before.record(v);
32 }
33 pub fn record_after(&mut self, v: f64) {
35 self.after.record(v);
36 }
37 pub fn mean_ratio(&self) -> Option<f64> {
39 let b = self.before.mean()?;
40 let a = self.after.mean()?;
41 if b.abs() < f64::EPSILON {
42 return None;
43 }
44 Some(a / b)
45 }
46}
47#[allow(dead_code)]
49pub struct TransitiveClosure {
50 adj: Vec<Vec<usize>>,
51 n: usize,
52}
53#[allow(dead_code)]
54impl TransitiveClosure {
55 pub fn new(n: usize) -> Self {
57 Self {
58 adj: vec![Vec::new(); n],
59 n,
60 }
61 }
62 pub fn add_edge(&mut self, from: usize, to: usize) {
64 if from < self.n {
65 self.adj[from].push(to);
66 }
67 }
68 pub fn reachable_from(&self, start: usize) -> Vec<usize> {
70 let mut visited = vec![false; self.n];
71 let mut queue = std::collections::VecDeque::new();
72 queue.push_back(start);
73 while let Some(node) = queue.pop_front() {
74 if node >= self.n || visited[node] {
75 continue;
76 }
77 visited[node] = true;
78 for &next in &self.adj[node] {
79 queue.push_back(next);
80 }
81 }
82 (0..self.n).filter(|&i| visited[i]).collect()
83 }
84 pub fn can_reach(&self, from: usize, to: usize) -> bool {
86 self.reachable_from(from).contains(&to)
87 }
88}
89#[allow(dead_code)]
91pub enum Either2<A, B> {
92 First(A),
94 Second(B),
96}
97#[allow(dead_code)]
98impl<A, B> Either2<A, B> {
99 pub fn is_first(&self) -> bool {
101 matches!(self, Either2::First(_))
102 }
103 pub fn is_second(&self) -> bool {
105 matches!(self, Either2::Second(_))
106 }
107 pub fn first(self) -> Option<A> {
109 match self {
110 Either2::First(a) => Some(a),
111 _ => None,
112 }
113 }
114 pub fn second(self) -> Option<B> {
116 match self {
117 Either2::Second(b) => Some(b),
118 _ => None,
119 }
120 }
121 pub fn map_first<C, F: FnOnce(A) -> C>(self, f: F) -> Either2<C, B> {
123 match self {
124 Either2::First(a) => Either2::First(f(a)),
125 Either2::Second(b) => Either2::Second(b),
126 }
127 }
128}
129#[allow(dead_code)]
131pub struct MinHeap<T: Ord> {
132 data: Vec<T>,
133}
134#[allow(dead_code)]
135impl<T: Ord> MinHeap<T> {
136 pub fn new() -> Self {
138 Self { data: Vec::new() }
139 }
140 pub fn push(&mut self, val: T) {
142 self.data.push(val);
143 self.sift_up(self.data.len() - 1);
144 }
145 pub fn pop(&mut self) -> Option<T> {
147 if self.data.is_empty() {
148 return None;
149 }
150 let n = self.data.len();
151 self.data.swap(0, n - 1);
152 let min = self.data.pop();
153 if !self.data.is_empty() {
154 self.sift_down(0);
155 }
156 min
157 }
158 pub fn peek(&self) -> Option<&T> {
160 self.data.first()
161 }
162 pub fn len(&self) -> usize {
164 self.data.len()
165 }
166 pub fn is_empty(&self) -> bool {
168 self.data.is_empty()
169 }
170 fn sift_up(&mut self, mut i: usize) {
171 while i > 0 {
172 let parent = (i - 1) / 2;
173 if self.data[i] < self.data[parent] {
174 self.data.swap(i, parent);
175 i = parent;
176 } else {
177 break;
178 }
179 }
180 }
181 fn sift_down(&mut self, mut i: usize) {
182 let n = self.data.len();
183 loop {
184 let left = 2 * i + 1;
185 let right = 2 * i + 2;
186 let mut smallest = i;
187 if left < n && self.data[left] < self.data[smallest] {
188 smallest = left;
189 }
190 if right < n && self.data[right] < self.data[smallest] {
191 smallest = right;
192 }
193 if smallest == i {
194 break;
195 }
196 self.data.swap(i, smallest);
197 i = smallest;
198 }
199 }
200}
201#[allow(dead_code)]
203pub struct PathBuf {
204 components: Vec<String>,
205}
206#[allow(dead_code)]
207impl PathBuf {
208 pub fn new() -> Self {
210 Self {
211 components: Vec::new(),
212 }
213 }
214 pub fn push(&mut self, comp: impl Into<String>) {
216 self.components.push(comp.into());
217 }
218 pub fn pop(&mut self) {
220 self.components.pop();
221 }
222 pub fn as_str(&self) -> String {
224 self.components.join("/")
225 }
226 pub fn depth(&self) -> usize {
228 self.components.len()
229 }
230 pub fn clear(&mut self) {
232 self.components.clear();
233 }
234}
235#[allow(dead_code)]
237pub struct FlatSubstitution {
238 pairs: Vec<(String, String)>,
239}
240#[allow(dead_code)]
241impl FlatSubstitution {
242 pub fn new() -> Self {
244 Self { pairs: Vec::new() }
245 }
246 pub fn add(&mut self, from: impl Into<String>, to: impl Into<String>) {
248 self.pairs.push((from.into(), to.into()));
249 }
250 pub fn apply(&self, s: &str) -> String {
252 let mut result = s.to_string();
253 for (from, to) in &self.pairs {
254 result = result.replace(from.as_str(), to.as_str());
255 }
256 result
257 }
258 pub fn len(&self) -> usize {
260 self.pairs.len()
261 }
262 pub fn is_empty(&self) -> bool {
264 self.pairs.is_empty()
265 }
266}
267#[allow(dead_code)]
269pub struct SimpleDag {
270 edges: Vec<Vec<usize>>,
272}
273#[allow(dead_code)]
274impl SimpleDag {
275 pub fn new(n: usize) -> Self {
277 Self {
278 edges: vec![Vec::new(); n],
279 }
280 }
281 pub fn add_edge(&mut self, from: usize, to: usize) {
283 if from < self.edges.len() {
284 self.edges[from].push(to);
285 }
286 }
287 pub fn successors(&self, node: usize) -> &[usize] {
289 self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
290 }
291 pub fn can_reach(&self, from: usize, to: usize) -> bool {
293 let mut visited = vec![false; self.edges.len()];
294 self.dfs(from, to, &mut visited)
295 }
296 fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
297 if cur == target {
298 return true;
299 }
300 if cur >= visited.len() || visited[cur] {
301 return false;
302 }
303 visited[cur] = true;
304 for &next in self.successors(cur) {
305 if self.dfs(next, target, visited) {
306 return true;
307 }
308 }
309 false
310 }
311 pub fn topological_sort(&self) -> Option<Vec<usize>> {
313 let n = self.edges.len();
314 let mut in_degree = vec![0usize; n];
315 for succs in &self.edges {
316 for &s in succs {
317 if s < n {
318 in_degree[s] += 1;
319 }
320 }
321 }
322 let mut queue: std::collections::VecDeque<usize> =
323 (0..n).filter(|&i| in_degree[i] == 0).collect();
324 let mut order = Vec::new();
325 while let Some(node) = queue.pop_front() {
326 order.push(node);
327 for &s in self.successors(node) {
328 if s < n {
329 in_degree[s] -= 1;
330 if in_degree[s] == 0 {
331 queue.push_back(s);
332 }
333 }
334 }
335 }
336 if order.len() == n {
337 Some(order)
338 } else {
339 None
340 }
341 }
342 pub fn num_nodes(&self) -> usize {
344 self.edges.len()
345 }
346}
347#[allow(dead_code)]
349pub struct RawFnPtr {
350 ptr: usize,
352 arity: usize,
353 name: String,
354}
355#[allow(dead_code)]
356impl RawFnPtr {
357 pub fn new(ptr: usize, arity: usize, name: impl Into<String>) -> Self {
359 Self {
360 ptr,
361 arity,
362 name: name.into(),
363 }
364 }
365 pub fn arity(&self) -> usize {
367 self.arity
368 }
369 pub fn name(&self) -> &str {
371 &self.name
372 }
373 pub fn raw(&self) -> usize {
375 self.ptr
376 }
377}
378#[allow(dead_code)]
380pub struct SparseVec<T: Default + Clone + PartialEq> {
381 entries: std::collections::HashMap<usize, T>,
382 default_: T,
383 logical_len: usize,
384}
385#[allow(dead_code)]
386impl<T: Default + Clone + PartialEq> SparseVec<T> {
387 pub fn new(len: usize) -> Self {
389 Self {
390 entries: std::collections::HashMap::new(),
391 default_: T::default(),
392 logical_len: len,
393 }
394 }
395 pub fn set(&mut self, idx: usize, val: T) {
397 if val == self.default_ {
398 self.entries.remove(&idx);
399 } else {
400 self.entries.insert(idx, val);
401 }
402 }
403 pub fn get(&self, idx: usize) -> &T {
405 self.entries.get(&idx).unwrap_or(&self.default_)
406 }
407 pub fn len(&self) -> usize {
409 self.logical_len
410 }
411 pub fn is_empty(&self) -> bool {
413 self.len() == 0
414 }
415 pub fn nnz(&self) -> usize {
417 self.entries.len()
418 }
419}
420#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
424pub enum BinderInfo {
425 Default,
427 Implicit,
429 StrictImplicit,
431 InstImplicit,
433}
434impl BinderInfo {
435 pub fn is_explicit(self) -> bool {
437 matches!(self, BinderInfo::Default)
438 }
439 pub fn is_implicit(self) -> bool {
441 matches!(self, BinderInfo::Implicit | BinderInfo::StrictImplicit)
442 }
443 pub fn is_inst_implicit(self) -> bool {
445 matches!(self, BinderInfo::InstImplicit)
446 }
447 pub fn open_delim(self) -> &'static str {
449 match self {
450 BinderInfo::Default => "(",
451 BinderInfo::Implicit => "{",
452 BinderInfo::StrictImplicit => "⦃",
453 BinderInfo::InstImplicit => "[",
454 }
455 }
456 pub fn close_delim(self) -> &'static str {
458 match self {
459 BinderInfo::Default => ")",
460 BinderInfo::Implicit => "}",
461 BinderInfo::StrictImplicit => "⦄",
462 BinderInfo::InstImplicit => "]",
463 }
464 }
465}
466#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
471pub struct FVarId(pub u64);
472impl FVarId {
473 pub fn new(id: u64) -> Self {
475 FVarId(id)
476 }
477}
478impl FVarId {
479 pub fn raw(self) -> u64 {
481 self.0
482 }
483}
484#[allow(dead_code)]
486pub struct LabelSet {
487 labels: Vec<String>,
488}
489#[allow(dead_code)]
490impl LabelSet {
491 pub fn new() -> Self {
493 Self { labels: Vec::new() }
494 }
495 pub fn add(&mut self, label: impl Into<String>) {
497 let s = label.into();
498 if !self.labels.contains(&s) {
499 self.labels.push(s);
500 }
501 }
502 pub fn has(&self, label: &str) -> bool {
504 self.labels.iter().any(|l| l == label)
505 }
506 pub fn count(&self) -> usize {
508 self.labels.len()
509 }
510 pub fn all(&self) -> &[String] {
512 &self.labels
513 }
514}
515#[allow(dead_code)]
517#[allow(missing_docs)]
518pub enum DecisionNode {
519 Leaf(String),
521 Branch {
523 key: String,
524 val: String,
525 yes_branch: Box<DecisionNode>,
526 no_branch: Box<DecisionNode>,
527 },
528}
529#[allow(dead_code)]
530impl DecisionNode {
531 pub fn evaluate(&self, ctx: &std::collections::HashMap<String, String>) -> &str {
533 match self {
534 DecisionNode::Leaf(action) => action.as_str(),
535 DecisionNode::Branch {
536 key,
537 val,
538 yes_branch,
539 no_branch,
540 } => {
541 let actual = ctx.get(key).map(|s| s.as_str()).unwrap_or("");
542 if actual == val.as_str() {
543 yes_branch.evaluate(ctx)
544 } else {
545 no_branch.evaluate(ctx)
546 }
547 }
548 }
549 }
550 pub fn depth(&self) -> usize {
552 match self {
553 DecisionNode::Leaf(_) => 0,
554 DecisionNode::Branch {
555 yes_branch,
556 no_branch,
557 ..
558 } => 1 + yes_branch.depth().max(no_branch.depth()),
559 }
560 }
561}
562#[allow(dead_code)]
564#[allow(missing_docs)]
565pub struct RewriteRule {
566 pub name: String,
568 pub lhs: String,
570 pub rhs: String,
572 pub conditional: bool,
574}
575#[allow(dead_code)]
576impl RewriteRule {
577 pub fn unconditional(
579 name: impl Into<String>,
580 lhs: impl Into<String>,
581 rhs: impl Into<String>,
582 ) -> Self {
583 Self {
584 name: name.into(),
585 lhs: lhs.into(),
586 rhs: rhs.into(),
587 conditional: false,
588 }
589 }
590 pub fn conditional(
592 name: impl Into<String>,
593 lhs: impl Into<String>,
594 rhs: impl Into<String>,
595 ) -> Self {
596 Self {
597 name: name.into(),
598 lhs: lhs.into(),
599 rhs: rhs.into(),
600 conditional: true,
601 }
602 }
603 pub fn display(&self) -> String {
605 format!("{}: {} → {}", self.name, self.lhs, self.rhs)
606 }
607}
608#[allow(dead_code)]
610pub struct ConfigNode {
611 key: String,
612 value: Option<String>,
613 children: Vec<ConfigNode>,
614}
615#[allow(dead_code)]
616impl ConfigNode {
617 pub fn leaf(key: impl Into<String>, value: impl Into<String>) -> Self {
619 Self {
620 key: key.into(),
621 value: Some(value.into()),
622 children: Vec::new(),
623 }
624 }
625 pub fn section(key: impl Into<String>) -> Self {
627 Self {
628 key: key.into(),
629 value: None,
630 children: Vec::new(),
631 }
632 }
633 pub fn add_child(&mut self, child: ConfigNode) {
635 self.children.push(child);
636 }
637 pub fn key(&self) -> &str {
639 &self.key
640 }
641 pub fn value(&self) -> Option<&str> {
643 self.value.as_deref()
644 }
645 pub fn num_children(&self) -> usize {
647 self.children.len()
648 }
649 pub fn lookup(&self, path: &str) -> Option<&str> {
651 let mut parts = path.splitn(2, '.');
652 let head = parts.next()?;
653 let tail = parts.next();
654 if head != self.key {
655 return None;
656 }
657 match tail {
658 None => self.value.as_deref(),
659 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
660 }
661 }
662 fn lookup_relative(&self, path: &str) -> Option<&str> {
663 let mut parts = path.splitn(2, '.');
664 let head = parts.next()?;
665 let tail = parts.next();
666 if head != self.key {
667 return None;
668 }
669 match tail {
670 None => self.value.as_deref(),
671 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
672 }
673 }
674}
675#[allow(dead_code)]
677pub struct RewriteRuleSet {
678 rules: Vec<RewriteRule>,
679}
680#[allow(dead_code)]
681impl RewriteRuleSet {
682 pub fn new() -> Self {
684 Self { rules: Vec::new() }
685 }
686 pub fn add(&mut self, rule: RewriteRule) {
688 self.rules.push(rule);
689 }
690 pub fn len(&self) -> usize {
692 self.rules.len()
693 }
694 pub fn is_empty(&self) -> bool {
696 self.rules.is_empty()
697 }
698 pub fn conditional_rules(&self) -> Vec<&RewriteRule> {
700 self.rules.iter().filter(|r| r.conditional).collect()
701 }
702 pub fn unconditional_rules(&self) -> Vec<&RewriteRule> {
704 self.rules.iter().filter(|r| !r.conditional).collect()
705 }
706 pub fn get(&self, name: &str) -> Option<&RewriteRule> {
708 self.rules.iter().find(|r| r.name == name)
709 }
710}
711#[allow(dead_code)]
713pub struct Stopwatch {
714 start: crate::wall_clock::Instant,
715 splits: Vec<f64>,
716}
717#[allow(dead_code)]
718impl Stopwatch {
719 pub fn start() -> Self {
721 Self {
722 start: crate::wall_clock::Instant::now(),
723 splits: Vec::new(),
724 }
725 }
726 pub fn split(&mut self) {
728 self.splits.push(self.elapsed_ms());
729 }
730 pub fn elapsed_ms(&self) -> f64 {
732 self.start.elapsed().as_secs_f64() * 1000.0
733 }
734 pub fn splits(&self) -> &[f64] {
736 &self.splits
737 }
738 pub fn num_splits(&self) -> usize {
740 self.splits.len()
741 }
742}
743#[allow(dead_code)]
745pub struct WriteOnce<T> {
746 value: std::cell::Cell<Option<T>>,
747}
748#[allow(dead_code)]
749impl<T: Copy> WriteOnce<T> {
750 pub fn new() -> Self {
752 Self {
753 value: std::cell::Cell::new(None),
754 }
755 }
756 pub fn write(&self, val: T) -> bool {
758 if self.value.get().is_some() {
759 return false;
760 }
761 self.value.set(Some(val));
762 true
763 }
764 pub fn read(&self) -> Option<T> {
766 self.value.get()
767 }
768 pub fn is_written(&self) -> bool {
770 self.value.get().is_some()
771 }
772}
773#[allow(dead_code)]
775pub struct StatSummary {
776 count: u64,
777 sum: f64,
778 min: f64,
779 max: f64,
780}
781#[allow(dead_code)]
782impl StatSummary {
783 pub fn new() -> Self {
785 Self {
786 count: 0,
787 sum: 0.0,
788 min: f64::INFINITY,
789 max: f64::NEG_INFINITY,
790 }
791 }
792 pub fn record(&mut self, val: f64) {
794 self.count += 1;
795 self.sum += val;
796 if val < self.min {
797 self.min = val;
798 }
799 if val > self.max {
800 self.max = val;
801 }
802 }
803 pub fn mean(&self) -> Option<f64> {
805 if self.count == 0 {
806 None
807 } else {
808 Some(self.sum / self.count as f64)
809 }
810 }
811 pub fn min(&self) -> Option<f64> {
813 if self.count == 0 {
814 None
815 } else {
816 Some(self.min)
817 }
818 }
819 pub fn max(&self) -> Option<f64> {
821 if self.count == 0 {
822 None
823 } else {
824 Some(self.max)
825 }
826 }
827 pub fn count(&self) -> u64 {
829 self.count
830 }
831}
832#[derive(Clone, PartialEq, Eq, Hash, Debug)]
840pub enum Literal {
841 Nat(crate::bignat::BigNat),
843 Str(String),
845}
846impl Literal {
847 pub fn nat(n: u64) -> Self {
849 Literal::Nat(crate::bignat::BigNat::from(n))
850 }
851 pub fn string(s: impl Into<String>) -> Self {
853 Literal::Str(s.into())
854 }
855 pub fn is_nat(&self) -> bool {
857 matches!(self, Literal::Nat(_))
858 }
859 pub fn is_str(&self) -> bool {
861 matches!(self, Literal::Str(_))
862 }
863 pub fn as_nat(&self) -> Option<u64> {
867 if let Literal::Nat(n) = self {
868 n.to_u64()
869 } else {
870 None
871 }
872 }
873 pub fn as_bignat(&self) -> Option<&crate::bignat::BigNat> {
875 if let Literal::Nat(n) = self {
876 Some(n)
877 } else {
878 None
879 }
880 }
881 pub fn as_str(&self) -> Option<&str> {
883 if let Literal::Str(s) = self {
884 Some(s.as_str())
885 } else {
886 None
887 }
888 }
889 pub fn type_name(&self) -> &'static str {
891 match self {
892 Literal::Nat(_) => "Nat",
893 Literal::Str(_) => "String",
894 }
895 }
896}
897impl From<crate::bignat::BigNat> for Literal {
898 fn from(n: crate::bignat::BigNat) -> Self {
899 Literal::Nat(n)
900 }
901}
902impl From<u64> for Literal {
903 fn from(n: u64) -> Self {
904 Literal::nat(n)
905 }
906}
907#[allow(dead_code)]
909pub struct WindowIterator<'a, T> {
910 pub(super) data: &'a [T],
911 pub(super) pos: usize,
912 pub(super) window: usize,
913}
914#[allow(dead_code)]
915impl<'a, T> WindowIterator<'a, T> {
916 pub fn new(data: &'a [T], window: usize) -> Self {
918 Self {
919 data,
920 pos: 0,
921 window,
922 }
923 }
924}
925#[allow(dead_code)]
927pub struct StackCalc {
928 stack: Vec<i64>,
929}
930#[allow(dead_code)]
931impl StackCalc {
932 pub fn new() -> Self {
934 Self { stack: Vec::new() }
935 }
936 pub fn push(&mut self, n: i64) {
938 self.stack.push(n);
939 }
940 fn apply_binary(&mut self, op: impl FnOnce(i64, i64) -> i64) -> Option<i64> {
944 let (rest_len, a, b) = match self.stack[..] {
945 [ref rest @ .., a, b] => (rest.len(), a, b),
946 _ => return None,
947 };
948 let value = op(a, b);
949 self.stack.truncate(rest_len);
950 self.stack.push(value);
951 Some(value)
952 }
953 pub fn add(&mut self) -> Option<i64> {
957 self.apply_binary(|a, b| a + b)
958 }
959 pub fn sub(&mut self) -> Option<i64> {
963 self.apply_binary(|a, b| a - b)
964 }
965 pub fn mul(&mut self) -> Option<i64> {
969 self.apply_binary(|a, b| a * b)
970 }
971 pub fn peek(&self) -> Option<i64> {
973 self.stack.last().copied()
974 }
975 pub fn depth(&self) -> usize {
977 self.stack.len()
978 }
979}
980#[allow(dead_code)]
982pub struct StringPool {
983 free: Vec<String>,
984}
985#[allow(dead_code)]
986impl StringPool {
987 pub fn new() -> Self {
989 Self { free: Vec::new() }
990 }
991 pub fn take(&mut self) -> String {
993 self.free.pop().unwrap_or_default()
994 }
995 pub fn give(&mut self, mut s: String) {
997 s.clear();
998 self.free.push(s);
999 }
1000 pub fn free_count(&self) -> usize {
1002 self.free.len()
1003 }
1004}
1005#[derive(Clone)]
1052pub struct Node {
1053 rc: Rc<Shared>,
1054}
1055
1056struct Shared {
1065 range: u32,
1066 meta: u32,
1069 hash: u64,
1070 #[cfg(feature = "term-depth")]
1073 depth: u32,
1074 expr: Expr,
1075}
1076
1077pub const REBUILD_COST_MAX: u32 = (1 << 29) - 1;
1082
1083impl Node {
1084 #[inline]
1095 pub fn new(e: Expr) -> Node {
1096 #[cfg(feature = "term-depth")]
1097 let depth = {
1098 let depth = e.depth();
1099 crate::fuel::note_term_depth(depth);
1100 depth
1101 };
1102 Node {
1103 rc: Rc::new(Shared {
1104 range: e.range(),
1105 meta: e.rebuild_cost() | e.flags(),
1106 hash: e.structural_hash(),
1107 #[cfg(feature = "term-depth")]
1108 depth,
1109 expr: e,
1110 }),
1111 }
1112 }
1113
1114 #[cfg(feature = "term-depth")]
1116 #[inline]
1117 #[must_use]
1118 pub(crate) fn depth(&self) -> u32 {
1119 self.rc.depth
1120 }
1121
1122 #[inline]
1124 #[must_use]
1125 pub fn range(&self) -> u32 {
1126 self.rc.range
1127 }
1128
1129 #[inline]
1132 #[must_use]
1133 pub fn rebuild_cost(&self) -> u32 {
1134 self.rc.meta & REBUILD_COST_MAX
1135 }
1136
1137 #[inline]
1140 #[must_use]
1141 pub(super) fn flags(&self) -> u32 {
1142 self.rc.meta & !REBUILD_COST_MAX
1143 }
1144
1145 #[inline]
1151 #[must_use]
1152 pub(crate) fn is_shared(&self) -> bool {
1153 Rc::strong_count(&self.rc) > 1
1154 }
1155
1156 #[inline]
1159 #[must_use]
1160 pub(crate) fn structural_hash(&self) -> u64 {
1161 self.rc.hash
1162 }
1163
1164 #[inline]
1172 #[must_use]
1173 pub fn as_ptr(&self) -> *const Expr {
1174 &self.rc.expr
1175 }
1176
1177 #[inline]
1180 #[must_use]
1181 pub fn ptr_eq(this: &Node, other: &Node) -> bool {
1182 Rc::ptr_eq(&this.rc, &other.rc)
1183 }
1184}
1185
1186impl std::ops::Deref for Node {
1187 type Target = Expr;
1188 #[inline]
1189 fn deref(&self) -> &Expr {
1190 &self.rc.expr
1191 }
1192}
1193
1194impl PartialEq for Node {
1195 #[inline]
1200 fn eq(&self, other: &Node) -> bool {
1201 Rc::ptr_eq(&self.rc, &other.rc)
1202 || (self.rc.hash == other.rc.hash && self.rc.expr == other.rc.expr)
1203 }
1204}
1205impl Eq for Node {}
1206impl std::hash::Hash for Node {
1207 #[inline]
1210 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1211 state.write_u64(self.rc.hash);
1212 }
1213}
1214impl std::fmt::Debug for Node {
1215 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1216 std::fmt::Debug::fmt(&self.rc.expr, f)
1217 }
1218}
1219impl std::fmt::Display for Node {
1220 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1221 std::fmt::Display::fmt(&self.rc.expr, f)
1222 }
1223}
1224impl AsRef<Expr> for Node {
1225 #[inline]
1226 fn as_ref(&self) -> &Expr {
1227 &self.rc.expr
1228 }
1229}
1230impl std::borrow::Borrow<Expr> for Node {
1231 #[inline]
1232 fn borrow(&self) -> &Expr {
1233 &self.rc.expr
1234 }
1235}
1236
1237#[derive(PartialEq, Eq, Debug)]
1261pub enum Expr {
1262 Sort(Level),
1267 BVar(u32),
1272 FVar(FVarId),
1276 Const(Name, Vec<Level>),
1281 App(Node, Node),
1285 Lam(BinderInfo, Name, Node, Node),
1287 Pi(BinderInfo, Name, Node, Node),
1292 Let(Name, Node, Node, Node),
1294 Lit(Literal),
1296 Proj(Name, u32, Node),
1298}
1299
1300impl Expr {
1301 #[inline]
1306 #[must_use]
1307 pub fn range(&self) -> u32 {
1308 match self {
1309 Expr::BVar(n) => n.saturating_add(1),
1310 Expr::Sort(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_) => 0,
1311 Expr::App(f, a) => f.range().max(a.range()),
1312 Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
1313 ty.range().max(body.range().saturating_sub(1))
1314 }
1315 Expr::Let(_, ty, val, body) => ty
1316 .range()
1317 .max(val.range())
1318 .max(body.range().saturating_sub(1)),
1319 Expr::Proj(_, _, inner) => inner.range(),
1320 }
1321 }
1322
1323 #[inline]
1331 #[must_use]
1332 pub fn rebuild_cost(&self) -> u32 {
1333 let total = match self {
1336 Expr::Sort(_) | Expr::BVar(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_) => 2,
1337 Expr::App(f, a) => 1 + f.rebuild_cost() + a.rebuild_cost(),
1338 Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
1339 1 + ty.rebuild_cost() + body.rebuild_cost()
1340 }
1341 Expr::Let(_, ty, val, body) => {
1342 1 + ty.rebuild_cost() + val.rebuild_cost() + body.rebuild_cost()
1343 }
1344 Expr::Proj(_, _, inner) => 1 + inner.rebuild_cost(),
1345 };
1346 total.min(REBUILD_COST_MAX)
1347 }
1348
1349 #[must_use]
1362 pub(crate) fn structural_hash(&self) -> u64 {
1363 use crate::structural_hash::{
1364 mix, mix_bytes, mix_words, EXPR_APP, EXPR_BVAR, EXPR_CONST, EXPR_FVAR, EXPR_LAM,
1365 EXPR_LET, EXPR_LIT_NAT, EXPR_LIT_STR, EXPR_PI, EXPR_PROJ, EXPR_SORT,
1366 };
1367 match self {
1368 Expr::Sort(level) => mix(EXPR_SORT, level.structural_hash()),
1369 Expr::BVar(index) => mix(EXPR_BVAR, u64::from(*index)),
1370 Expr::FVar(id) => mix(EXPR_FVAR, id.0),
1371 Expr::Const(name, levels) => levels
1372 .iter()
1373 .fold(mix(EXPR_CONST, name.structural_hash()), |hash, level| {
1374 mix(hash, level.structural_hash())
1375 }),
1376 Expr::App(f, a) => mix(mix(EXPR_APP, f.structural_hash()), a.structural_hash()),
1377 Expr::Lam(bi, name, ty, body) => mix(
1378 mix(
1379 mix(mix(EXPR_LAM, binder_info_code(*bi)), name.structural_hash()),
1380 ty.structural_hash(),
1381 ),
1382 body.structural_hash(),
1383 ),
1384 Expr::Pi(bi, name, ty, body) => mix(
1385 mix(
1386 mix(mix(EXPR_PI, binder_info_code(*bi)), name.structural_hash()),
1387 ty.structural_hash(),
1388 ),
1389 body.structural_hash(),
1390 ),
1391 Expr::Let(name, ty, val, body) => mix(
1392 mix(
1393 mix(mix(EXPR_LET, name.structural_hash()), ty.structural_hash()),
1394 val.structural_hash(),
1395 ),
1396 body.structural_hash(),
1397 ),
1398 Expr::Lit(Literal::Nat(n)) => mix_words(EXPR_LIT_NAT, n.as_limbs()),
1399 Expr::Lit(Literal::Str(s)) => mix_bytes(EXPR_LIT_STR, s.as_bytes()),
1400 Expr::Proj(name, index, inner) => mix(
1401 mix(mix(EXPR_PROJ, name.structural_hash()), u64::from(*index)),
1402 inner.structural_hash(),
1403 ),
1404 }
1405 }
1406}
1407const fn binder_info_code(bi: BinderInfo) -> u64 {
1410 match bi {
1411 BinderInfo::Default => 0,
1412 BinderInfo::Implicit => 1,
1413 BinderInfo::StrictImplicit => 2,
1414 BinderInfo::InstImplicit => 3,
1415 }
1416}
1417impl std::hash::Hash for Expr {
1418 #[inline]
1422 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1423 state.write_u64(self.structural_hash());
1424 }
1425}
1426impl Clone for Expr {
1427 fn clone(&self) -> Self {
1428 crate::fuel::charge(1);
1431 match self {
1432 Expr::Sort(l) => Expr::Sort(l.clone()),
1433 Expr::BVar(n) => Expr::BVar(*n),
1434 Expr::FVar(id) => Expr::FVar(*id),
1435 Expr::Const(name, levels) => Expr::Const(name.clone(), levels.clone()),
1436 Expr::App(f, a) => Expr::App(f.clone(), a.clone()),
1437 Expr::Lam(bi, name, ty, body) => Expr::Lam(*bi, name.clone(), ty.clone(), body.clone()),
1438 Expr::Pi(bi, name, ty, body) => Expr::Pi(*bi, name.clone(), ty.clone(), body.clone()),
1439 Expr::Let(name, ty, val, body) => {
1440 Expr::Let(name.clone(), ty.clone(), val.clone(), body.clone())
1441 }
1442 Expr::Lit(l) => Expr::Lit(l.clone()),
1443 Expr::Proj(name, idx, inner) => Expr::Proj(name.clone(), *idx, inner.clone()),
1444 }
1445 }
1446}
1447impl Expr {
1448 pub fn is_sort(&self) -> bool {
1450 matches!(self, Expr::Sort(_))
1451 }
1452 pub fn is_prop(&self) -> bool {
1454 matches!(self, Expr::Sort(l) if l.is_zero())
1455 }
1456 pub fn is_bvar(&self) -> bool {
1458 matches!(self, Expr::BVar(_))
1459 }
1460 pub fn is_fvar(&self) -> bool {
1462 matches!(self, Expr::FVar(_))
1463 }
1464 pub fn is_app(&self) -> bool {
1466 matches!(self, Expr::App(_, _))
1467 }
1468 pub fn is_lambda(&self) -> bool {
1470 matches!(self, Expr::Lam(_, _, _, _))
1471 }
1472 pub fn is_pi(&self) -> bool {
1474 matches!(self, Expr::Pi(_, _, _, _))
1475 }
1476}
1477impl Expr {
1478 pub fn is_let(&self) -> bool {
1480 matches!(self, Expr::Let(_, _, _, _))
1481 }
1482 pub fn is_lit(&self) -> bool {
1484 matches!(self, Expr::Lit(_))
1485 }
1486 pub fn is_const(&self) -> bool {
1488 matches!(self, Expr::Const(_, _))
1489 }
1490 pub fn is_proj(&self) -> bool {
1492 matches!(self, Expr::Proj(_, _, _))
1493 }
1494 pub fn is_atom(&self) -> bool {
1497 matches!(
1498 self,
1499 Expr::Sort(_) | Expr::BVar(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_)
1500 )
1501 }
1502 pub fn as_bvar(&self) -> Option<u32> {
1504 if let Expr::BVar(n) = self {
1505 Some(*n)
1506 } else {
1507 None
1508 }
1509 }
1510 pub fn as_fvar(&self) -> Option<FVarId> {
1512 if let Expr::FVar(id) = self {
1513 Some(*id)
1514 } else {
1515 None
1516 }
1517 }
1518 pub fn as_const_name(&self) -> Option<&Name> {
1520 if let Expr::Const(n, _) = self {
1521 Some(n)
1522 } else {
1523 None
1524 }
1525 }
1526 pub fn as_sort_level(&self) -> Option<&Level> {
1528 if let Expr::Sort(l) = self {
1529 Some(l)
1530 } else {
1531 None
1532 }
1533 }
1534 pub fn app_head_args(&self) -> (&Expr, Vec<&Expr>) {
1538 let mut args = Vec::new();
1539 let mut cur = self;
1540 while let Expr::App(f, a) = cur {
1541 args.push(a.as_ref());
1542 cur = f;
1543 }
1544 args.reverse();
1545 (cur, args)
1546 }
1547 pub fn app_arity(&self) -> usize {
1549 let mut n = 0;
1550 let mut cur = self;
1551 while let Expr::App(f, _) = cur {
1552 n += 1;
1553 cur = f;
1554 }
1555 n
1556 }
1557 pub fn pi_arity(&self) -> usize {
1559 let mut n = 0;
1560 let mut cur = self;
1561 while let Expr::Pi(_, _, _, body) = cur {
1562 n += 1;
1563 cur = body;
1564 }
1565 n
1566 }
1567 pub fn lam_arity(&self) -> usize {
1569 let mut n = 0;
1570 let mut cur = self;
1571 while let Expr::Lam(_, _, _, body) = cur {
1572 n += 1;
1573 cur = body;
1574 }
1575 n
1576 }
1577 pub fn size(&self) -> usize {
1579 match self {
1580 Expr::Sort(_) | Expr::BVar(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_) => 1,
1581 Expr::App(f, a) => 1 + f.size() + a.size(),
1582 Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => 1 + ty.size() + body.size(),
1583 Expr::Let(_, ty, val, body) => 1 + ty.size() + val.size() + body.size(),
1584 Expr::Proj(_, _, s) => 1 + s.size(),
1585 }
1586 }
1587 pub fn ast_depth(&self) -> usize {
1589 match self {
1590 Expr::Sort(_) | Expr::BVar(_) | Expr::FVar(_) | Expr::Const(_, _) | Expr::Lit(_) => 0,
1591 Expr::App(f, a) => 1 + f.ast_depth().max(a.ast_depth()),
1592 Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
1593 1 + ty.ast_depth().max(body.ast_depth())
1594 }
1595 Expr::Let(_, ty, val, body) => {
1596 1 + ty.ast_depth().max(val.ast_depth()).max(body.ast_depth())
1597 }
1598 Expr::Proj(_, _, s) => 1 + s.ast_depth(),
1599 }
1600 }
1601 pub fn mk_app_many(self, args: &[Expr]) -> Expr {
1605 args.iter().fold(self, |acc, a| {
1606 Expr::App(Node::new(acc), Node::new(a.clone()))
1607 })
1608 }
1609 pub fn has_loose_bvar_at(&self, d: u32) -> bool {
1611 has_loose_bvar(self, d)
1612 }
1613 pub fn count_bvar_occurrences(&self, idx: u32) -> usize {
1615 count_bvar_occ(self, idx)
1616 }
1617 pub fn is_closed(&self) -> bool {
1619 !has_loose_bvar(self, 0) && self.max_loose_bvar().is_none()
1620 }
1621 fn max_loose_bvar(&self) -> Option<u32> {
1623 max_loose_bvar_impl(self, 0)
1624 }
1625 pub fn free_vars(&self) -> std::collections::HashSet<FVarId> {
1627 let mut set = std::collections::HashSet::new();
1628 collect_fvars(self, &mut set);
1629 set
1630 }
1631 pub fn constants(&self) -> std::collections::HashSet<Name> {
1633 let mut set = std::collections::HashSet::new();
1634 collect_consts(self, &mut set);
1635 set
1636 }
1637}
1638#[allow(dead_code)]
1640pub struct NonEmptyVec<T> {
1641 head: T,
1642 tail: Vec<T>,
1643}
1644#[allow(dead_code)]
1645impl<T> NonEmptyVec<T> {
1646 pub fn singleton(val: T) -> Self {
1648 Self {
1649 head: val,
1650 tail: Vec::new(),
1651 }
1652 }
1653 pub fn push(&mut self, val: T) {
1655 self.tail.push(val);
1656 }
1657 pub fn first(&self) -> &T {
1659 &self.head
1660 }
1661 pub fn last(&self) -> &T {
1663 self.tail.last().unwrap_or(&self.head)
1664 }
1665 pub fn len(&self) -> usize {
1667 1 + self.tail.len()
1668 }
1669 pub fn is_empty(&self) -> bool {
1671 self.len() == 0
1672 }
1673 pub fn to_vec(&self) -> Vec<&T> {
1675 let mut v = vec![&self.head];
1676 v.extend(self.tail.iter());
1677 v
1678 }
1679}
1680#[allow(dead_code)]
1682pub struct Fixture {
1683 data: std::collections::HashMap<String, String>,
1684}
1685#[allow(dead_code)]
1686impl Fixture {
1687 pub fn new() -> Self {
1689 Self {
1690 data: std::collections::HashMap::new(),
1691 }
1692 }
1693 pub fn set(&mut self, key: impl Into<String>, val: impl Into<String>) {
1695 self.data.insert(key.into(), val.into());
1696 }
1697 pub fn get(&self, key: &str) -> Option<&str> {
1699 self.data.get(key).map(|s| s.as_str())
1700 }
1701 pub fn len(&self) -> usize {
1703 self.data.len()
1704 }
1705 pub fn is_empty(&self) -> bool {
1707 self.len() == 0
1708 }
1709}
1710#[derive(Debug, Default)]
1714pub struct FVarIdGen {
1715 next: u64,
1716}
1717impl FVarIdGen {
1718 pub fn new() -> Self {
1720 Self::default()
1721 }
1722 pub fn fresh(&mut self) -> FVarId {
1724 let id = FVarId::new(self.next);
1725 self.next += 1;
1726 id
1727 }
1728 pub fn peek(&self) -> FVarId {
1730 FVarId::new(self.next)
1731 }
1732 pub fn reset(&mut self) {
1734 self.next = 0;
1735 }
1736 pub fn current(&self) -> u64 {
1738 self.next
1739 }
1740}
1741#[allow(dead_code)]
1743pub struct SmallMap<K: Ord + Clone, V: Clone> {
1744 entries: Vec<(K, V)>,
1745}
1746#[allow(dead_code)]
1747impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
1748 pub fn new() -> Self {
1750 Self {
1751 entries: Vec::new(),
1752 }
1753 }
1754 pub fn insert(&mut self, key: K, val: V) {
1756 match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
1757 Ok(i) => self.entries[i].1 = val,
1758 Err(i) => self.entries.insert(i, (key, val)),
1759 }
1760 }
1761 pub fn get(&self, key: &K) -> Option<&V> {
1763 self.entries
1764 .binary_search_by_key(&key, |(k, _)| k)
1765 .ok()
1766 .map(|i| &self.entries[i].1)
1767 }
1768 pub fn len(&self) -> usize {
1770 self.entries.len()
1771 }
1772 pub fn is_empty(&self) -> bool {
1774 self.entries.is_empty()
1775 }
1776 pub fn keys(&self) -> Vec<&K> {
1778 self.entries.iter().map(|(k, _)| k).collect()
1779 }
1780 pub fn values(&self) -> Vec<&V> {
1782 self.entries.iter().map(|(_, v)| v).collect()
1783 }
1784}
1785#[allow(dead_code)]
1787pub struct TokenBucket {
1788 capacity: u64,
1789 tokens: u64,
1790 refill_per_ms: u64,
1791 last_refill: crate::wall_clock::Instant,
1792}
1793#[allow(dead_code)]
1794impl TokenBucket {
1795 pub fn new(capacity: u64, refill_per_ms: u64) -> Self {
1797 Self {
1798 capacity,
1799 tokens: capacity,
1800 refill_per_ms,
1801 last_refill: crate::wall_clock::Instant::now(),
1802 }
1803 }
1804 pub fn try_consume(&mut self, n: u64) -> bool {
1806 self.refill();
1807 if self.tokens >= n {
1808 self.tokens -= n;
1809 true
1810 } else {
1811 false
1812 }
1813 }
1814 fn refill(&mut self) {
1815 let now = crate::wall_clock::Instant::now();
1816 let elapsed_ms = now.duration_since(self.last_refill).as_millis() as u64;
1817 if elapsed_ms > 0 {
1818 let new_tokens = elapsed_ms * self.refill_per_ms;
1819 self.tokens = (self.tokens + new_tokens).min(self.capacity);
1820 self.last_refill = now;
1821 }
1822 }
1823 pub fn available(&self) -> u64 {
1825 self.tokens
1826 }
1827 pub fn capacity(&self) -> u64 {
1829 self.capacity
1830 }
1831}
1832#[allow(dead_code)]
1834pub struct SlidingSum {
1835 window: Vec<f64>,
1836 capacity: usize,
1837 pos: usize,
1838 sum: f64,
1839 count: usize,
1840}
1841#[allow(dead_code)]
1842impl SlidingSum {
1843 pub fn new(capacity: usize) -> Self {
1845 Self {
1846 window: vec![0.0; capacity],
1847 capacity,
1848 pos: 0,
1849 sum: 0.0,
1850 count: 0,
1851 }
1852 }
1853 pub fn push(&mut self, val: f64) {
1855 let oldest = self.window[self.pos];
1856 self.sum -= oldest;
1857 self.sum += val;
1858 self.window[self.pos] = val;
1859 self.pos = (self.pos + 1) % self.capacity;
1860 if self.count < self.capacity {
1861 self.count += 1;
1862 }
1863 }
1864 pub fn sum(&self) -> f64 {
1866 self.sum
1867 }
1868 pub fn mean(&self) -> Option<f64> {
1870 if self.count == 0 {
1871 None
1872 } else {
1873 Some(self.sum / self.count as f64)
1874 }
1875 }
1876 pub fn count(&self) -> usize {
1878 self.count
1879 }
1880}
1881#[allow(dead_code)]
1883pub struct VersionedRecord<T: Clone> {
1884 earlier: Vec<T>,
1886 current: T,
1888}
1889#[allow(dead_code)]
1890impl<T: Clone> VersionedRecord<T> {
1891 pub fn new(initial: T) -> Self {
1893 Self {
1894 earlier: Vec::new(),
1895 current: initial,
1896 }
1897 }
1898 pub fn update(&mut self, val: T) {
1900 let previous = std::mem::replace(&mut self.current, val);
1901 self.earlier.push(previous);
1902 }
1903 pub fn current(&self) -> &T {
1905 &self.current
1906 }
1907 pub fn at_version(&self, n: usize) -> Option<&T> {
1909 match self.earlier.get(n) {
1910 Some(value) => Some(value),
1911 None if n == self.earlier.len() => Some(&self.current),
1912 None => None,
1913 }
1914 }
1915 pub fn version(&self) -> usize {
1917 self.earlier.len()
1918 }
1919 pub fn has_history(&self) -> bool {
1921 !self.earlier.is_empty()
1922 }
1923}
1924#[allow(dead_code)]
1926pub struct FocusStack<T> {
1927 items: Vec<T>,
1928}
1929#[allow(dead_code)]
1930impl<T> FocusStack<T> {
1931 pub fn new() -> Self {
1933 Self { items: Vec::new() }
1934 }
1935 pub fn focus(&mut self, item: T) {
1937 self.items.push(item);
1938 }
1939 pub fn blur(&mut self) -> Option<T> {
1941 self.items.pop()
1942 }
1943 pub fn current(&self) -> Option<&T> {
1945 self.items.last()
1946 }
1947 pub fn depth(&self) -> usize {
1949 self.items.len()
1950 }
1951 pub fn is_empty(&self) -> bool {
1953 self.items.is_empty()
1954 }
1955}
1956#[allow(dead_code)]
1958pub struct PrefixCounter {
1959 children: std::collections::HashMap<char, PrefixCounter>,
1960 count: usize,
1961}
1962#[allow(dead_code)]
1963impl PrefixCounter {
1964 pub fn new() -> Self {
1966 Self {
1967 children: std::collections::HashMap::new(),
1968 count: 0,
1969 }
1970 }
1971 pub fn record(&mut self, s: &str) {
1973 self.count += 1;
1974 let mut node = self;
1975 for c in s.chars() {
1976 node = node.children.entry(c).or_default();
1977 node.count += 1;
1978 }
1979 }
1980 pub fn count_with_prefix(&self, prefix: &str) -> usize {
1982 let mut node = self;
1983 for c in prefix.chars() {
1984 match node.children.get(&c) {
1985 Some(n) => node = n,
1986 None => return 0,
1987 }
1988 }
1989 node.count
1990 }
1991}