1use super::functions::*;
6use crate::{Expr, KernelError, Name};
7use std::collections::HashMap;
8
9#[allow(dead_code)]
11pub struct VersionedRecord<T: Clone> {
12 history: Vec<T>,
13}
14#[allow(dead_code)]
15impl<T: Clone> VersionedRecord<T> {
16 pub fn new(initial: T) -> Self {
18 Self {
19 history: vec![initial],
20 }
21 }
22 pub fn update(&mut self, val: T) {
24 self.history.push(val);
25 }
26 pub fn current(&self) -> &T {
28 self.history
29 .last()
30 .expect("VersionedRecord history is always non-empty after construction")
31 }
32 pub fn at_version(&self, n: usize) -> Option<&T> {
34 self.history.get(n)
35 }
36 pub fn version(&self) -> usize {
38 self.history.len() - 1
39 }
40 pub fn has_history(&self) -> bool {
42 self.history.len() > 1
43 }
44}
45#[allow(dead_code)]
47pub struct PathBuf {
48 components: Vec<String>,
49}
50#[allow(dead_code)]
51impl PathBuf {
52 pub fn new() -> Self {
54 Self {
55 components: Vec::new(),
56 }
57 }
58 pub fn push(&mut self, comp: impl Into<String>) {
60 self.components.push(comp.into());
61 }
62 pub fn pop(&mut self) {
64 self.components.pop();
65 }
66 pub fn as_str(&self) -> String {
68 self.components.join("/")
69 }
70 pub fn depth(&self) -> usize {
72 self.components.len()
73 }
74 pub fn clear(&mut self) {
76 self.components.clear();
77 }
78}
79#[allow(dead_code)]
81pub struct StatSummary {
82 count: u64,
83 sum: f64,
84 min: f64,
85 max: f64,
86}
87#[allow(dead_code)]
88impl StatSummary {
89 pub fn new() -> Self {
91 Self {
92 count: 0,
93 sum: 0.0,
94 min: f64::INFINITY,
95 max: f64::NEG_INFINITY,
96 }
97 }
98 pub fn record(&mut self, val: f64) {
100 self.count += 1;
101 self.sum += val;
102 if val < self.min {
103 self.min = val;
104 }
105 if val > self.max {
106 self.max = val;
107 }
108 }
109 pub fn mean(&self) -> Option<f64> {
111 if self.count == 0 {
112 None
113 } else {
114 Some(self.sum / self.count as f64)
115 }
116 }
117 pub fn min(&self) -> Option<f64> {
119 if self.count == 0 {
120 None
121 } else {
122 Some(self.min)
123 }
124 }
125 pub fn max(&self) -> Option<f64> {
127 if self.count == 0 {
128 None
129 } else {
130 Some(self.max)
131 }
132 }
133 pub fn count(&self) -> u64 {
135 self.count
136 }
137}
138#[allow(dead_code)]
140pub struct NonEmptyVec<T> {
141 head: T,
142 tail: Vec<T>,
143}
144#[allow(dead_code)]
145impl<T> NonEmptyVec<T> {
146 pub fn singleton(val: T) -> Self {
148 Self {
149 head: val,
150 tail: Vec::new(),
151 }
152 }
153 pub fn push(&mut self, val: T) {
155 self.tail.push(val);
156 }
157 pub fn first(&self) -> &T {
159 &self.head
160 }
161 pub fn last(&self) -> &T {
163 self.tail.last().unwrap_or(&self.head)
164 }
165 pub fn len(&self) -> usize {
167 1 + self.tail.len()
168 }
169 pub fn is_empty(&self) -> bool {
171 self.len() == 0
172 }
173 pub fn to_vec(&self) -> Vec<&T> {
175 let mut v = vec![&self.head];
176 v.extend(self.tail.iter());
177 v
178 }
179}
180#[derive(Debug, Clone)]
182pub struct QuotientKernel {
183 quot_types: Vec<QuotientType>,
184}
185impl QuotientKernel {
186 pub fn new() -> Self {
188 Self {
189 quot_types: Vec::new(),
190 }
191 }
192 pub fn register(&mut self, qt: QuotientType) {
194 self.quot_types.push(qt);
195 }
196 pub fn find_by_base(&self, base: &Expr) -> Option<&QuotientType> {
198 self.quot_types.iter().find(|qt| &qt.base_type == base)
199 }
200 pub fn is_quot_type(&self, expr: &Expr) -> bool {
206 if is_quot_type_expr(expr) {
207 return true;
208 }
209 self.quot_types.iter().any(|qt| &qt.quot_type == expr)
210 }
211 pub fn reduce(&self, head: &Expr, args: &[Expr]) -> Option<Expr> {
213 try_reduce_quot(head, args)
214 }
215 pub fn count(&self) -> usize {
217 self.quot_types.len()
218 }
219}
220#[allow(dead_code)]
224pub struct QuotientNormalizer {
225 max_steps: usize,
227 steps_taken: usize,
229}
230impl QuotientNormalizer {
231 #[allow(dead_code)]
233 pub fn new(max_steps: usize) -> Self {
234 Self {
235 max_steps,
236 steps_taken: 0,
237 }
238 }
239 #[allow(dead_code)]
241 pub fn normalize(&mut self, expr: Expr) -> (Expr, bool) {
242 let mut current = expr;
243 let mut changed = false;
244 while self.steps_taken < self.max_steps {
245 let (next, did_change) = self.step(¤t);
246 if !did_change {
247 break;
248 }
249 current = next;
250 changed = true;
251 self.steps_taken += 1;
252 }
253 (current, changed)
254 }
255 fn step(&self, expr: &Expr) -> (Expr, bool) {
256 match expr {
257 Expr::App(f, _) => {
258 let args = collect_args_norm(expr);
259 if let Expr::Const(name, _) = &args[0] {
260 if *name == Name::str("Quot.lift") && args.len() >= 4 {
261 if let Some(r) = reduce_quot_lift(&args[1..]) {
262 return (r, true);
263 }
264 }
265 if *name == Name::str("Quot.ind") && args.len() >= 3 {
266 if let Some(r) = reduce_quot_ind(&args[1..]) {
267 return (r, true);
268 }
269 }
270 }
271 let (f2, cf) = self.step(f);
272 let arg = args.last().cloned().unwrap_or(Expr::BVar(0));
273 let (a2, ca) = self.step(&arg);
274 if cf || ca {
275 return (Expr::App(Box::new(f2), Box::new(a2)), true);
276 }
277 (expr.clone(), false)
278 }
279 _ => (expr.clone(), false),
280 }
281 }
282 #[allow(dead_code)]
284 pub fn steps_taken(&self) -> usize {
285 self.steps_taken
286 }
287 #[allow(dead_code)]
289 pub fn reset(&mut self) {
290 self.steps_taken = 0;
291 }
292}
293#[allow(dead_code)]
295pub struct StringPool {
296 free: Vec<String>,
297}
298#[allow(dead_code)]
299impl StringPool {
300 pub fn new() -> Self {
302 Self { free: Vec::new() }
303 }
304 pub fn take(&mut self) -> String {
306 self.free.pop().unwrap_or_default()
307 }
308 pub fn give(&mut self, mut s: String) {
310 s.clear();
311 self.free.push(s);
312 }
313 pub fn free_count(&self) -> usize {
315 self.free.len()
316 }
317}
318pub struct QuotientDescription {
320 pub base_name: String,
322 pub relation_name: String,
324 pub finite_model_size: Option<usize>,
326}
327impl QuotientDescription {
328 pub fn new(base_name: impl Into<String>, relation_name: impl Into<String>) -> Self {
330 Self {
331 base_name: base_name.into(),
332 relation_name: relation_name.into(),
333 finite_model_size: None,
334 }
335 }
336 pub fn with_model_size(mut self, n: usize) -> Self {
338 self.finite_model_size = Some(n);
339 self
340 }
341 pub fn display(&self) -> String {
343 match self.finite_model_size {
344 Some(n) => {
345 format!(
346 "Quot {} {} ({} elements)",
347 self.base_name, self.relation_name, n
348 )
349 }
350 None => format!("Quot {} {}", self.base_name, self.relation_name),
351 }
352 }
353}
354#[allow(dead_code)]
356pub struct TransformStat {
357 before: StatSummary,
358 after: StatSummary,
359}
360#[allow(dead_code)]
361impl TransformStat {
362 pub fn new() -> Self {
364 Self {
365 before: StatSummary::new(),
366 after: StatSummary::new(),
367 }
368 }
369 pub fn record_before(&mut self, v: f64) {
371 self.before.record(v);
372 }
373 pub fn record_after(&mut self, v: f64) {
375 self.after.record(v);
376 }
377 pub fn mean_ratio(&self) -> Option<f64> {
379 let b = self.before.mean()?;
380 let a = self.after.mean()?;
381 if b.abs() < f64::EPSILON {
382 return None;
383 }
384 Some(a / b)
385 }
386}
387#[allow(dead_code)]
389pub struct LabelSet {
390 labels: Vec<String>,
391}
392#[allow(dead_code)]
393impl LabelSet {
394 pub fn new() -> Self {
396 Self { labels: Vec::new() }
397 }
398 pub fn add(&mut self, label: impl Into<String>) {
400 let s = label.into();
401 if !self.labels.contains(&s) {
402 self.labels.push(s);
403 }
404 }
405 pub fn has(&self, label: &str) -> bool {
407 self.labels.iter().any(|l| l == label)
408 }
409 pub fn count(&self) -> usize {
411 self.labels.len()
412 }
413 pub fn all(&self) -> &[String] {
415 &self.labels
416 }
417}
418pub struct QuotientReducer {
420 steps: Vec<QuotReductionStep>,
421 #[allow(dead_code)]
422 cache: QuotLiftCache,
423 pub(crate) max_steps: usize,
424}
425impl QuotientReducer {
426 pub fn new(max_steps: usize) -> Self {
428 Self {
429 steps: Vec::new(),
430 cache: QuotLiftCache::new(),
431 max_steps,
432 }
433 }
434 pub fn reduce(&mut self, expr: &Expr) -> (Expr, bool) {
436 match expr {
437 Expr::App(f, _arg) => {
438 if let Expr::Const(name, _) = f.as_ref() {
439 if *name == Name::str("Quot.lift") {
440 let args = collect_args(expr);
441 if let Some((reduced, kind)) = try_reduce_quot_full(&args[0], &args[1..]) {
442 let step = QuotReductionStep::new(kind, expr.clone(), reduced.clone());
443 if self.steps.len() < self.max_steps {
444 self.steps.push(step);
445 }
446 return (reduced, true);
447 }
448 }
449 }
450 (expr.clone(), false)
451 }
452 _ => (expr.clone(), false),
453 }
454 }
455 pub fn steps(&self) -> &[QuotReductionStep] {
457 &self.steps
458 }
459 pub fn clear_steps(&mut self) {
461 self.steps.clear();
462 }
463 pub fn step_count(&self) -> usize {
465 self.steps.len()
466 }
467}
468#[derive(Clone, Debug, PartialEq)]
470pub struct QuotientType {
471 pub base_type: Expr,
473 pub relation: Expr,
475 pub quot_type: Expr,
477}
478impl QuotientType {
479 pub fn new(base_type: Expr, relation: Expr) -> Self {
481 let quot_type = Expr::App(
482 Box::new(Expr::App(
483 Box::new(Expr::Const(Name::str("Quot"), vec![])),
484 Box::new(base_type.clone()),
485 )),
486 Box::new(relation.clone()),
487 );
488 Self {
489 base_type,
490 relation,
491 quot_type,
492 }
493 }
494 pub fn mk_const(&self) -> Expr {
496 Expr::Const(Name::str("Quot.mk"), vec![])
497 }
498 pub fn mk_apply(&self, elem: Expr) -> Expr {
500 Expr::App(Box::new(self.mk_const()), Box::new(elem))
501 }
502 pub fn lift_const(&self) -> Expr {
504 Expr::Const(Name::str("Quot.lift"), vec![])
505 }
506 pub fn ind_const(&self) -> Expr {
508 Expr::Const(Name::str("Quot.ind"), vec![])
509 }
510 pub fn sound_const(&self) -> Expr {
512 Expr::Const(Name::str("Quot.sound"), vec![])
513 }
514 pub fn lift_apply(&self, f: Expr, h: Expr, q: Expr) -> Expr {
516 Expr::App(
517 Box::new(Expr::App(
518 Box::new(Expr::App(Box::new(self.lift_const()), Box::new(f))),
519 Box::new(h),
520 )),
521 Box::new(q),
522 )
523 }
524}
525#[derive(Clone, Debug, Default)]
527pub struct QuotLiftCache {
528 cache: std::collections::HashMap<String, Expr>,
529}
530impl QuotLiftCache {
531 pub fn new() -> Self {
533 Self {
534 cache: std::collections::HashMap::new(),
535 }
536 }
537 pub fn get(&self, f: &Expr, a: &Expr) -> Option<&Expr> {
539 let key = format!("{:?}-{:?}", f, a);
540 self.cache.get(&key)
541 }
542 pub fn put(&mut self, f: &Expr, a: &Expr, result: Expr) {
544 let key = format!("{:?}-{:?}", f, a);
545 self.cache.insert(key, result);
546 }
547 pub fn clear(&mut self) {
549 self.cache.clear();
550 }
551 pub fn len(&self) -> usize {
553 self.cache.len()
554 }
555 pub fn is_empty(&self) -> bool {
557 self.cache.is_empty()
558 }
559}
560#[allow(dead_code)]
562pub struct TokenBucket {
563 capacity: u64,
564 tokens: u64,
565 refill_per_ms: u64,
566 last_refill: std::time::Instant,
567}
568#[allow(dead_code)]
569impl TokenBucket {
570 pub fn new(capacity: u64, refill_per_ms: u64) -> Self {
572 Self {
573 capacity,
574 tokens: capacity,
575 refill_per_ms,
576 last_refill: std::time::Instant::now(),
577 }
578 }
579 pub fn try_consume(&mut self, n: u64) -> bool {
581 self.refill();
582 if self.tokens >= n {
583 self.tokens -= n;
584 true
585 } else {
586 false
587 }
588 }
589 fn refill(&mut self) {
590 let now = std::time::Instant::now();
591 let elapsed_ms = now.duration_since(self.last_refill).as_millis() as u64;
592 if elapsed_ms > 0 {
593 let new_tokens = elapsed_ms * self.refill_per_ms;
594 self.tokens = (self.tokens + new_tokens).min(self.capacity);
595 self.last_refill = now;
596 }
597 }
598 pub fn available(&self) -> u64 {
600 self.tokens
601 }
602 pub fn capacity(&self) -> u64 {
604 self.capacity
605 }
606}
607#[derive(Clone, Debug, Default)]
612pub struct EquivClassSystem {
613 reps: std::collections::HashMap<String, Expr>,
615}
616impl EquivClassSystem {
617 pub fn new() -> Self {
619 Self {
620 reps: std::collections::HashMap::new(),
621 }
622 }
623 pub fn insert(&mut self, expr: Expr) {
625 let key = format!("{:?}", expr);
626 self.reps.entry(key).or_insert(expr);
627 }
628 pub fn merge(&mut self, a: &Expr, b: &Expr) {
630 let key_b = format!("{:?}", b);
631 let rep_a = self.rep_of(a).unwrap_or_else(|| a.clone());
632 self.reps.insert(key_b, rep_a);
633 }
634 pub fn rep_of(&self, expr: &Expr) -> Option<Expr> {
636 let key = format!("{:?}", expr);
637 self.reps.get(&key).cloned()
638 }
639 pub fn same_class(&self, a: &Expr, b: &Expr) -> bool {
641 match (self.rep_of(a), self.rep_of(b)) {
642 (Some(ra), Some(rb)) => ra == rb,
643 _ => a == b,
644 }
645 }
646 pub fn len(&self) -> usize {
648 self.reps.len()
649 }
650 pub fn is_empty(&self) -> bool {
652 self.reps.is_empty()
653 }
654}
655#[allow(dead_code)]
657pub struct WindowIterator<'a, T> {
658 pub(super) data: &'a [T],
659 pub(super) pos: usize,
660 pub(super) window: usize,
661}
662#[allow(dead_code)]
663impl<'a, T> WindowIterator<'a, T> {
664 pub fn new(data: &'a [T], window: usize) -> Self {
666 Self {
667 data,
668 pos: 0,
669 window,
670 }
671 }
672}
673#[derive(Debug, Default)]
675pub struct QuotientBuilder {
676 base_type: Option<Expr>,
677 relation: Option<Expr>,
678}
679impl QuotientBuilder {
680 pub fn new() -> Self {
682 Self {
683 base_type: None,
684 relation: None,
685 }
686 }
687 pub fn base(mut self, ty: Expr) -> Self {
689 self.base_type = Some(ty);
690 self
691 }
692 pub fn relation(mut self, rel: Expr) -> Self {
694 self.relation = Some(rel);
695 self
696 }
697 pub fn build(self) -> Option<QuotientType> {
699 Some(QuotientType::new(self.base_type?, self.relation?))
700 }
701}
702#[allow(dead_code)]
704pub struct SlidingSum {
705 window: Vec<f64>,
706 capacity: usize,
707 pos: usize,
708 sum: f64,
709 count: usize,
710}
711#[allow(dead_code)]
712impl SlidingSum {
713 pub fn new(capacity: usize) -> Self {
715 Self {
716 window: vec![0.0; capacity],
717 capacity,
718 pos: 0,
719 sum: 0.0,
720 count: 0,
721 }
722 }
723 pub fn push(&mut self, val: f64) {
725 let oldest = self.window[self.pos];
726 self.sum -= oldest;
727 self.sum += val;
728 self.window[self.pos] = val;
729 self.pos = (self.pos + 1) % self.capacity;
730 if self.count < self.capacity {
731 self.count += 1;
732 }
733 }
734 pub fn sum(&self) -> f64 {
736 self.sum
737 }
738 pub fn mean(&self) -> Option<f64> {
740 if self.count == 0 {
741 None
742 } else {
743 Some(self.sum / self.count as f64)
744 }
745 }
746 pub fn count(&self) -> usize {
748 self.count
749 }
750}
751#[derive(Clone, Debug, PartialEq, Eq)]
753pub enum QuotReductionKind {
754 Lift,
756 Ind,
758 Sound,
760}
761impl QuotReductionKind {
762 pub fn description(&self) -> &'static str {
764 match self {
765 QuotReductionKind::Lift => "Quot.lift reduction",
766 QuotReductionKind::Ind => "Quot.ind reduction",
767 QuotReductionKind::Sound => "Quot.sound",
768 }
769 }
770}
771#[allow(dead_code)]
773pub struct ConfigNode {
774 key: String,
775 value: Option<String>,
776 children: Vec<ConfigNode>,
777}
778#[allow(dead_code)]
779impl ConfigNode {
780 pub fn leaf(key: impl Into<String>, value: impl Into<String>) -> Self {
782 Self {
783 key: key.into(),
784 value: Some(value.into()),
785 children: Vec::new(),
786 }
787 }
788 pub fn section(key: impl Into<String>) -> Self {
790 Self {
791 key: key.into(),
792 value: None,
793 children: Vec::new(),
794 }
795 }
796 pub fn add_child(&mut self, child: ConfigNode) {
798 self.children.push(child);
799 }
800 pub fn key(&self) -> &str {
802 &self.key
803 }
804 pub fn value(&self) -> Option<&str> {
806 self.value.as_deref()
807 }
808 pub fn num_children(&self) -> usize {
810 self.children.len()
811 }
812 pub fn lookup(&self, path: &str) -> Option<&str> {
814 let mut parts = path.splitn(2, '.');
815 let head = parts.next()?;
816 let tail = parts.next();
817 if head != self.key {
818 return None;
819 }
820 match tail {
821 None => self.value.as_deref(),
822 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
823 }
824 }
825 fn lookup_relative(&self, path: &str) -> Option<&str> {
826 let mut parts = path.splitn(2, '.');
827 let head = parts.next()?;
828 let tail = parts.next();
829 if head != self.key {
830 return None;
831 }
832 match tail {
833 None => self.value.as_deref(),
834 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
835 }
836 }
837}
838#[allow(dead_code)]
840pub struct FocusStack<T> {
841 items: Vec<T>,
842}
843#[allow(dead_code)]
844impl<T> FocusStack<T> {
845 pub fn new() -> Self {
847 Self { items: Vec::new() }
848 }
849 pub fn focus(&mut self, item: T) {
851 self.items.push(item);
852 }
853 pub fn blur(&mut self) -> Option<T> {
855 self.items.pop()
856 }
857 pub fn current(&self) -> Option<&T> {
859 self.items.last()
860 }
861 pub fn depth(&self) -> usize {
863 self.items.len()
864 }
865 pub fn is_empty(&self) -> bool {
867 self.items.is_empty()
868 }
869}
870#[derive(Debug, Default, Clone)]
872pub struct QuotStats {
873 pub mk_count: usize,
875 pub lift_count: usize,
877 pub ind_count: usize,
879 pub sound_count: usize,
881}
882impl QuotStats {
883 pub fn compute(expr: &Expr) -> Self {
885 let mut stats = Self::default();
886 Self::walk(expr, &mut stats);
887 stats
888 }
889 fn walk(expr: &Expr, stats: &mut Self) {
890 match expr {
891 Expr::Const(name, _) => {
892 if *name == Name::str("Quot.mk") {
893 stats.mk_count += 1;
894 } else if *name == Name::str("Quot.lift") {
895 stats.lift_count += 1;
896 } else if *name == Name::str("Quot.ind") {
897 stats.ind_count += 1;
898 } else if *name == Name::str("Quot.sound") {
899 stats.sound_count += 1;
900 }
901 }
902 Expr::App(f, a) => {
903 Self::walk(f, stats);
904 Self::walk(a, stats);
905 }
906 Expr::Lam(_, _, ty, body) | Expr::Pi(_, _, ty, body) => {
907 Self::walk(ty, stats);
908 Self::walk(body, stats);
909 }
910 Expr::Let(_, ty, val, body) => {
911 Self::walk(ty, stats);
912 Self::walk(val, stats);
913 Self::walk(body, stats);
914 }
915 _ => {}
916 }
917 }
918 pub fn total(&self) -> usize {
920 self.mk_count + self.lift_count + self.ind_count + self.sound_count
921 }
922 pub fn has_quot(&self) -> bool {
924 self.total() > 0
925 }
926}
927#[derive(Debug, Clone, PartialEq, Eq)]
929pub enum EquivProperty {
930 Reflexive,
932 Symmetric,
934 Transitive,
936}
937#[allow(dead_code)]
939pub struct SimpleDag {
940 edges: Vec<Vec<usize>>,
942}
943#[allow(dead_code)]
944impl SimpleDag {
945 pub fn new(n: usize) -> Self {
947 Self {
948 edges: vec![Vec::new(); n],
949 }
950 }
951 pub fn add_edge(&mut self, from: usize, to: usize) {
953 if from < self.edges.len() {
954 self.edges[from].push(to);
955 }
956 }
957 pub fn successors(&self, node: usize) -> &[usize] {
959 self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
960 }
961 pub fn can_reach(&self, from: usize, to: usize) -> bool {
963 let mut visited = vec![false; self.edges.len()];
964 self.dfs(from, to, &mut visited)
965 }
966 fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
967 if cur == target {
968 return true;
969 }
970 if cur >= visited.len() || visited[cur] {
971 return false;
972 }
973 visited[cur] = true;
974 for &next in self.successors(cur) {
975 if self.dfs(next, target, visited) {
976 return true;
977 }
978 }
979 false
980 }
981 pub fn topological_sort(&self) -> Option<Vec<usize>> {
983 let n = self.edges.len();
984 let mut in_degree = vec![0usize; n];
985 for succs in &self.edges {
986 for &s in succs {
987 if s < n {
988 in_degree[s] += 1;
989 }
990 }
991 }
992 let mut queue: std::collections::VecDeque<usize> =
993 (0..n).filter(|&i| in_degree[i] == 0).collect();
994 let mut order = Vec::new();
995 while let Some(node) = queue.pop_front() {
996 order.push(node);
997 for &s in self.successors(node) {
998 if s < n {
999 in_degree[s] -= 1;
1000 if in_degree[s] == 0 {
1001 queue.push_back(s);
1002 }
1003 }
1004 }
1005 }
1006 if order.len() == n {
1007 Some(order)
1008 } else {
1009 None
1010 }
1011 }
1012 pub fn num_nodes(&self) -> usize {
1014 self.edges.len()
1015 }
1016}
1017#[allow(dead_code)]
1019pub struct RawFnPtr {
1020 ptr: usize,
1022 arity: usize,
1023 name: String,
1024}
1025#[allow(dead_code)]
1026impl RawFnPtr {
1027 pub fn new(ptr: usize, arity: usize, name: impl Into<String>) -> Self {
1029 Self {
1030 ptr,
1031 arity,
1032 name: name.into(),
1033 }
1034 }
1035 pub fn arity(&self) -> usize {
1037 self.arity
1038 }
1039 pub fn name(&self) -> &str {
1041 &self.name
1042 }
1043 pub fn raw(&self) -> usize {
1045 self.ptr
1046 }
1047}
1048#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1050pub enum QuotUsageKind {
1051 Lift,
1053 Ind,
1055}
1056#[allow(dead_code)]
1058pub struct SmallMap<K: Ord + Clone, V: Clone> {
1059 entries: Vec<(K, V)>,
1060}
1061#[allow(dead_code)]
1062impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
1063 pub fn new() -> Self {
1065 Self {
1066 entries: Vec::new(),
1067 }
1068 }
1069 pub fn insert(&mut self, key: K, val: V) {
1071 match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
1072 Ok(i) => self.entries[i].1 = val,
1073 Err(i) => self.entries.insert(i, (key, val)),
1074 }
1075 }
1076 pub fn get(&self, key: &K) -> Option<&V> {
1078 self.entries
1079 .binary_search_by_key(&key, |(k, _)| k)
1080 .ok()
1081 .map(|i| &self.entries[i].1)
1082 }
1083 pub fn len(&self) -> usize {
1085 self.entries.len()
1086 }
1087 pub fn is_empty(&self) -> bool {
1089 self.entries.is_empty()
1090 }
1091 pub fn keys(&self) -> Vec<&K> {
1093 self.entries.iter().map(|(k, _)| k).collect()
1094 }
1095 pub fn values(&self) -> Vec<&V> {
1097 self.entries.iter().map(|(_, v)| v).collect()
1098 }
1099}
1100#[allow(dead_code)]
1102pub struct TransitiveClosure {
1103 adj: Vec<Vec<usize>>,
1104 n: usize,
1105}
1106#[allow(dead_code)]
1107impl TransitiveClosure {
1108 pub fn new(n: usize) -> Self {
1110 Self {
1111 adj: vec![Vec::new(); n],
1112 n,
1113 }
1114 }
1115 pub fn add_edge(&mut self, from: usize, to: usize) {
1117 if from < self.n {
1118 self.adj[from].push(to);
1119 }
1120 }
1121 pub fn reachable_from(&self, start: usize) -> Vec<usize> {
1123 let mut visited = vec![false; self.n];
1124 let mut queue = std::collections::VecDeque::new();
1125 queue.push_back(start);
1126 while let Some(node) = queue.pop_front() {
1127 if node >= self.n || visited[node] {
1128 continue;
1129 }
1130 visited[node] = true;
1131 for &next in &self.adj[node] {
1132 queue.push_back(next);
1133 }
1134 }
1135 (0..self.n).filter(|&i| visited[i]).collect()
1136 }
1137 pub fn can_reach(&self, from: usize, to: usize) -> bool {
1139 self.reachable_from(from).contains(&to)
1140 }
1141}
1142#[allow(dead_code)]
1144#[allow(missing_docs)]
1145pub struct RewriteRule {
1146 pub name: String,
1148 pub lhs: String,
1150 pub rhs: String,
1152 pub conditional: bool,
1154}
1155#[allow(dead_code)]
1156impl RewriteRule {
1157 pub fn unconditional(
1159 name: impl Into<String>,
1160 lhs: impl Into<String>,
1161 rhs: impl Into<String>,
1162 ) -> Self {
1163 Self {
1164 name: name.into(),
1165 lhs: lhs.into(),
1166 rhs: rhs.into(),
1167 conditional: false,
1168 }
1169 }
1170 pub fn conditional(
1172 name: impl Into<String>,
1173 lhs: impl Into<String>,
1174 rhs: impl Into<String>,
1175 ) -> Self {
1176 Self {
1177 name: name.into(),
1178 lhs: lhs.into(),
1179 rhs: rhs.into(),
1180 conditional: true,
1181 }
1182 }
1183 pub fn display(&self) -> String {
1185 format!("{}: {} → {}", self.name, self.lhs, self.rhs)
1186 }
1187}
1188#[derive(Clone, Debug)]
1190pub struct QuotReductionStep {
1191 pub kind: QuotReductionKind,
1193 pub before: Expr,
1195 pub after: Expr,
1197}
1198impl QuotReductionStep {
1199 pub fn new(kind: QuotReductionKind, before: Expr, after: Expr) -> Self {
1201 Self {
1202 kind,
1203 before,
1204 after,
1205 }
1206 }
1207}
1208#[allow(dead_code)]
1210pub struct RewriteRuleSet {
1211 rules: Vec<RewriteRule>,
1212}
1213#[allow(dead_code)]
1214impl RewriteRuleSet {
1215 pub fn new() -> Self {
1217 Self { rules: Vec::new() }
1218 }
1219 pub fn add(&mut self, rule: RewriteRule) {
1221 self.rules.push(rule);
1222 }
1223 pub fn len(&self) -> usize {
1225 self.rules.len()
1226 }
1227 pub fn is_empty(&self) -> bool {
1229 self.rules.is_empty()
1230 }
1231 pub fn conditional_rules(&self) -> Vec<&RewriteRule> {
1233 self.rules.iter().filter(|r| r.conditional).collect()
1234 }
1235 pub fn unconditional_rules(&self) -> Vec<&RewriteRule> {
1237 self.rules.iter().filter(|r| !r.conditional).collect()
1238 }
1239 pub fn get(&self, name: &str) -> Option<&RewriteRule> {
1241 self.rules.iter().find(|r| r.name == name)
1242 }
1243}