1use crate::reduce::ReducibilityHint;
6use crate::{Expr, Level, Name};
7
8use std::collections::{HashMap, HashSet, VecDeque};
9
10#[allow(dead_code)]
12pub struct WorkStack<T> {
13 items: Vec<T>,
14}
15#[allow(dead_code)]
16impl<T> WorkStack<T> {
17 pub fn new() -> Self {
19 Self { items: Vec::new() }
20 }
21 pub fn push(&mut self, item: T) {
23 self.items.push(item);
24 }
25 pub fn pop(&mut self) -> Option<T> {
27 self.items.pop()
28 }
29 pub fn is_empty(&self) -> bool {
31 self.items.is_empty()
32 }
33 pub fn len(&self) -> usize {
35 self.items.len()
36 }
37}
38#[allow(dead_code)]
40pub struct MemoSlot<T: Clone> {
41 cached: Option<T>,
42}
43#[allow(dead_code)]
44impl<T: Clone> MemoSlot<T> {
45 pub fn new() -> Self {
47 Self { cached: None }
48 }
49 pub fn get_or_compute(&mut self, f: impl FnOnce() -> T) -> &T {
51 self.cached.get_or_insert_with(f)
52 }
53 pub fn invalidate(&mut self) {
55 self.cached = None;
56 }
57 pub fn is_cached(&self) -> bool {
59 self.cached.is_some()
60 }
61}
62#[derive(Clone, Debug, PartialEq)]
64pub struct ConstantVal {
65 pub name: Name,
67 pub level_params: Vec<Name>,
69 pub ty: Expr,
71}
72#[allow(dead_code)]
74pub struct DeclIndex {
75 map: std::collections::HashMap<String, usize>,
76}
77#[allow(dead_code)]
78impl DeclIndex {
79 pub fn new() -> Self {
81 Self {
82 map: std::collections::HashMap::new(),
83 }
84 }
85 pub fn insert(&mut self, name: impl Into<String>, pos: usize) {
87 self.map.insert(name.into(), pos);
88 }
89 pub fn get(&self, name: &str) -> Option<usize> {
91 self.map.get(name).copied()
92 }
93 pub fn len(&self) -> usize {
95 self.map.len()
96 }
97 pub fn is_empty(&self) -> bool {
99 self.map.is_empty()
100 }
101 pub fn names(&self) -> Vec<&str> {
103 self.map.keys().map(|s| s.as_str()).collect()
104 }
105}
106#[derive(Clone, Debug, PartialEq)]
108pub struct AxiomVal {
109 pub common: ConstantVal,
111 pub is_unsafe: bool,
113}
114#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
116pub enum QuotKind {
117 Type,
119 Mk,
121 Lift,
123 Ind,
125}
126#[derive(Clone, Debug, PartialEq)]
128pub struct ConstructorVal {
129 pub common: ConstantVal,
131 pub induct: Name,
133 pub cidx: u32,
135 pub num_params: u32,
137 pub num_fields: u32,
139 pub is_unsafe: bool,
141}
142#[allow(dead_code)]
144pub struct EventCounter {
145 counts: std::collections::HashMap<String, u64>,
146}
147#[allow(dead_code)]
148impl EventCounter {
149 pub fn new() -> Self {
151 Self {
152 counts: std::collections::HashMap::new(),
153 }
154 }
155 pub fn inc(&mut self, event: &str) {
157 *self.counts.entry(event.to_string()).or_insert(0) += 1;
158 }
159 pub fn add(&mut self, event: &str, n: u64) {
161 *self.counts.entry(event.to_string()).or_insert(0) += n;
162 }
163 pub fn get(&self, event: &str) -> u64 {
165 self.counts.get(event).copied().unwrap_or(0)
166 }
167 pub fn total(&self) -> u64 {
169 self.counts.values().sum()
170 }
171 pub fn reset(&mut self) {
173 self.counts.clear();
174 }
175 pub fn event_names(&self) -> Vec<&str> {
177 self.counts.keys().map(|s| s.as_str()).collect()
178 }
179}
180#[derive(Clone, Debug, PartialEq)]
182pub struct TheoremVal {
183 pub common: ConstantVal,
185 pub value: Expr,
187 pub all: Vec<Name>,
189}
190#[derive(Clone, Debug, PartialEq)]
192pub struct RecursorVal {
193 pub common: ConstantVal,
195 pub all: Vec<Name>,
197 pub num_params: u32,
199 pub num_indices: u32,
201 pub num_motives: u32,
203 pub num_minors: u32,
205 pub rules: Vec<RecursorRule>,
207 pub k: bool,
209 pub is_unsafe: bool,
211}
212impl RecursorVal {
213 pub fn get_major_idx(&self) -> u32 {
218 self.num_params + self.num_motives + self.num_minors + self.num_indices
219 }
220 pub fn get_first_index_idx(&self) -> u32 {
222 self.num_params + self.num_motives + self.num_minors
223 }
224 pub fn get_rule(&self, ctor: &Name) -> Option<&RecursorRule> {
226 self.rules.iter().find(|r| &r.ctor == ctor)
227 }
228}
229#[allow(dead_code)]
231pub struct ScopeStack {
232 names: Vec<String>,
233}
234#[allow(dead_code)]
235impl ScopeStack {
236 pub fn new() -> Self {
238 Self { names: Vec::new() }
239 }
240 pub fn push(&mut self, name: impl Into<String>) {
242 self.names.push(name.into());
243 }
244 pub fn pop(&mut self) -> Option<String> {
246 self.names.pop()
247 }
248 pub fn current(&self) -> Option<&str> {
250 self.names.last().map(|s| s.as_str())
251 }
252 pub fn depth(&self) -> usize {
254 self.names.len()
255 }
256 pub fn is_empty(&self) -> bool {
258 self.names.is_empty()
259 }
260 pub fn path(&self) -> String {
262 self.names.join(".")
263 }
264}
265#[allow(dead_code)]
267pub struct AnnotationTable {
268 map: std::collections::HashMap<String, Vec<String>>,
269}
270#[allow(dead_code)]
271impl AnnotationTable {
272 pub fn new() -> Self {
274 Self {
275 map: std::collections::HashMap::new(),
276 }
277 }
278 pub fn annotate(&mut self, key: impl Into<String>, val: impl Into<String>) {
280 self.map.entry(key.into()).or_default().push(val.into());
281 }
282 pub fn get_all(&self, key: &str) -> &[String] {
284 self.map.get(key).map(|v| v.as_slice()).unwrap_or(&[])
285 }
286 pub fn num_keys(&self) -> usize {
288 self.map.len()
289 }
290 pub fn has(&self, key: &str) -> bool {
292 self.map.contains_key(key)
293 }
294}
295#[allow(dead_code)]
297pub struct LoopClock {
298 start: crate::wall_clock::Instant,
299 iters: u64,
300}
301#[allow(dead_code)]
302impl LoopClock {
303 pub fn start() -> Self {
305 Self {
306 start: crate::wall_clock::Instant::now(),
307 iters: 0,
308 }
309 }
310 pub fn tick(&mut self) {
312 self.iters += 1;
313 }
314 pub fn elapsed_us(&self) -> f64 {
316 self.start.elapsed().as_secs_f64() * 1e6
317 }
318 pub fn avg_us_per_iter(&self) -> f64 {
320 if self.iters == 0 {
321 return 0.0;
322 }
323 self.elapsed_us() / self.iters as f64
324 }
325 pub fn iters(&self) -> u64 {
327 self.iters
328 }
329}
330#[allow(dead_code)]
332pub struct SparseBitSet {
333 words: Vec<u64>,
334}
335#[allow(dead_code)]
336impl SparseBitSet {
337 pub fn new(capacity: usize) -> Self {
339 let words = capacity.div_ceil(64);
340 Self {
341 words: vec![0u64; words],
342 }
343 }
344 pub fn set(&mut self, i: usize) {
346 let word = i / 64;
347 let bit = i % 64;
348 if word < self.words.len() {
349 self.words[word] |= 1u64 << bit;
350 }
351 }
352 pub fn clear(&mut self, i: usize) {
354 let word = i / 64;
355 let bit = i % 64;
356 if word < self.words.len() {
357 self.words[word] &= !(1u64 << bit);
358 }
359 }
360 pub fn get(&self, i: usize) -> bool {
362 let word = i / 64;
363 let bit = i % 64;
364 self.words.get(word).is_some_and(|w| w & (1u64 << bit) != 0)
365 }
366 pub fn count_ones(&self) -> u32 {
368 self.words.iter().map(|w| w.count_ones()).sum()
369 }
370 pub fn union(&self, other: &SparseBitSet) -> SparseBitSet {
372 let len = self.words.len().max(other.words.len());
373 let mut result = SparseBitSet {
374 words: vec![0u64; len],
375 };
376 for i in 0..self.words.len() {
377 result.words[i] |= self.words[i];
378 }
379 for i in 0..other.words.len() {
380 result.words[i] |= other.words[i];
381 }
382 result
383 }
384}
385#[allow(dead_code)]
387#[allow(missing_docs)]
388pub struct StatCache<K: std::hash::Hash + Eq + Clone, V: Clone> {
389 pub inner: SimpleLruCache<K, V>,
391 pub hits: u64,
393 pub misses: u64,
395}
396#[allow(dead_code)]
397impl<K: std::hash::Hash + Eq + Clone, V: Clone> StatCache<K, V> {
398 pub fn new(capacity: usize) -> Self {
400 Self {
401 inner: SimpleLruCache::new(capacity),
402 hits: 0,
403 misses: 0,
404 }
405 }
406 pub fn get(&mut self, key: &K) -> Option<&V> {
408 let result = self.inner.get(key);
409 if result.is_some() {
410 self.hits += 1;
411 } else {
412 self.misses += 1;
413 }
414 None
415 }
416 pub fn put(&mut self, key: K, val: V) {
418 self.inner.put(key, val);
419 }
420 pub fn hit_rate(&self) -> f64 {
422 let total = self.hits + self.misses;
423 if total == 0 {
424 return 0.0;
425 }
426 self.hits as f64 / total as f64
427 }
428}
429#[allow(dead_code)]
431pub struct Slot<T> {
432 inner: Option<T>,
433}
434#[allow(dead_code)]
435impl<T> Slot<T> {
436 pub fn empty() -> Self {
438 Self { inner: None }
439 }
440 pub fn fill(&mut self, val: T) {
442 assert!(self.inner.is_none(), "Slot: already filled");
443 self.inner = Some(val);
444 }
445 pub fn get(&self) -> Option<&T> {
447 self.inner.as_ref()
448 }
449 pub fn is_filled(&self) -> bool {
451 self.inner.is_some()
452 }
453 pub fn take(&mut self) -> Option<T> {
455 self.inner.take()
456 }
457 pub fn get_or_fill_with(&mut self, f: impl FnOnce() -> T) -> &T {
459 self.inner.get_or_insert_with(f)
460 }
461}
462#[allow(dead_code)]
464#[allow(missing_docs)]
465pub struct BeforeAfter<T> {
466 pub before: T,
468 pub after: T,
470}
471#[allow(dead_code)]
472impl<T: PartialEq> BeforeAfter<T> {
473 pub fn new(before: T, after: T) -> Self {
475 Self { before, after }
476 }
477 pub fn unchanged(&self) -> bool {
479 self.before == self.after
480 }
481}
482#[derive(Clone, Debug, PartialEq)]
487pub struct RecursorRule {
488 pub ctor: Name,
490 pub nfields: u32,
492 pub rhs: Expr,
494}
495#[allow(dead_code)]
497#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
498pub struct Timestamp(u64);
499#[allow(dead_code)]
500impl Timestamp {
501 pub const fn from_us(us: u64) -> Self {
503 Self(us)
504 }
505 pub fn as_us(self) -> u64 {
507 self.0
508 }
509 pub fn elapsed_since(self, earlier: Timestamp) -> u64 {
511 self.0.saturating_sub(earlier.0)
512 }
513}
514#[allow(dead_code)]
516#[derive(Clone, Debug, PartialEq, Eq)]
517pub enum DeclAttr {
518 Inline,
520 Simp,
522 Ext,
524 Reducible,
526 Unknown(String),
528}
529#[allow(dead_code)]
530impl DeclAttr {
531 pub fn name(&self) -> &str {
533 match self {
534 DeclAttr::Inline => "inline",
535 DeclAttr::Simp => "simp",
536 DeclAttr::Ext => "ext",
537 DeclAttr::Reducible => "reducible",
538 DeclAttr::Unknown(s) => s.as_str(),
539 }
540 }
541}
542#[derive(Clone, Debug, PartialEq)]
547pub enum ConstantInfo {
548 Axiom(AxiomVal),
550 Definition(DefinitionVal),
552 Theorem(TheoremVal),
554 Opaque(OpaqueVal),
556 Inductive(InductiveVal),
558 Constructor(ConstructorVal),
560 Recursor(RecursorVal),
562 Quotient(QuotVal),
564}
565impl ConstantInfo {
566 pub fn name(&self) -> &Name {
568 &self.common().name
569 }
570 pub fn ty(&self) -> &Expr {
572 &self.common().ty
573 }
574 pub fn level_params(&self) -> &[Name] {
576 &self.common().level_params
577 }
578 pub fn common(&self) -> &ConstantVal {
580 match self {
581 ConstantInfo::Axiom(v) => &v.common,
582 ConstantInfo::Definition(v) => &v.common,
583 ConstantInfo::Theorem(v) => &v.common,
584 ConstantInfo::Opaque(v) => &v.common,
585 ConstantInfo::Inductive(v) => &v.common,
586 ConstantInfo::Constructor(v) => &v.common,
587 ConstantInfo::Recursor(v) => &v.common,
588 ConstantInfo::Quotient(v) => &v.common,
589 }
590 }
591 pub fn is_axiom(&self) -> bool {
593 matches!(self, ConstantInfo::Axiom(_))
594 }
595 pub fn is_definition(&self) -> bool {
597 matches!(self, ConstantInfo::Definition(_))
598 }
599 pub fn is_theorem(&self) -> bool {
601 matches!(self, ConstantInfo::Theorem(_))
602 }
603 pub fn is_opaque(&self) -> bool {
605 matches!(self, ConstantInfo::Opaque(_))
606 }
607 pub fn is_inductive(&self) -> bool {
609 matches!(self, ConstantInfo::Inductive(_))
610 }
611 pub fn is_constructor(&self) -> bool {
613 matches!(self, ConstantInfo::Constructor(_))
614 }
615 pub fn is_recursor(&self) -> bool {
617 matches!(self, ConstantInfo::Recursor(_))
618 }
619 pub fn is_quotient(&self) -> bool {
621 matches!(self, ConstantInfo::Quotient(_))
622 }
623 pub fn to_definition_val(&self) -> Option<&DefinitionVal> {
625 match self {
626 ConstantInfo::Definition(v) => Some(v),
627 _ => None,
628 }
629 }
630 pub fn to_inductive_val(&self) -> Option<&InductiveVal> {
632 match self {
633 ConstantInfo::Inductive(v) => Some(v),
634 _ => None,
635 }
636 }
637 pub fn to_constructor_val(&self) -> Option<&ConstructorVal> {
639 match self {
640 ConstantInfo::Constructor(v) => Some(v),
641 _ => None,
642 }
643 }
644 pub fn to_recursor_val(&self) -> Option<&RecursorVal> {
646 match self {
647 ConstantInfo::Recursor(v) => Some(v),
648 _ => None,
649 }
650 }
651 pub fn to_quotient_val(&self) -> Option<&QuotVal> {
653 match self {
654 ConstantInfo::Quotient(v) => Some(v),
655 _ => None,
656 }
657 }
658 pub fn to_axiom_val(&self) -> Option<&AxiomVal> {
660 match self {
661 ConstantInfo::Axiom(v) => Some(v),
662 _ => None,
663 }
664 }
665 pub fn to_theorem_val(&self) -> Option<&TheoremVal> {
667 match self {
668 ConstantInfo::Theorem(v) => Some(v),
669 _ => None,
670 }
671 }
672 pub fn to_opaque_val(&self) -> Option<&OpaqueVal> {
674 match self {
675 ConstantInfo::Opaque(v) => Some(v),
676 _ => None,
677 }
678 }
679 pub fn has_value(&self, allow_opaque: bool) -> bool {
683 match self {
684 ConstantInfo::Definition(_) | ConstantInfo::Theorem(_) => true,
685 ConstantInfo::Opaque(_) => allow_opaque,
686 _ => false,
687 }
688 }
689 pub fn value(&self) -> Option<&Expr> {
691 match self {
692 ConstantInfo::Definition(v) => Some(&v.value),
693 ConstantInfo::Theorem(v) => Some(&v.value),
694 ConstantInfo::Opaque(v) => Some(&v.value),
695 _ => None,
696 }
697 }
698 pub fn reducibility_hint(&self) -> ReducibilityHint {
700 match self {
701 ConstantInfo::Definition(v) => v.hints,
702 ConstantInfo::Theorem(_) | ConstantInfo::Opaque(_) | ConstantInfo::Axiom(_) => {
703 ReducibilityHint::Opaque
704 }
705 _ => ReducibilityHint::Opaque,
706 }
707 }
708 pub fn is_unsafe(&self) -> bool {
710 match self {
711 ConstantInfo::Axiom(v) => v.is_unsafe,
712 ConstantInfo::Definition(v) => v.safety == DefinitionSafety::Unsafe,
713 ConstantInfo::Opaque(v) => v.is_unsafe,
714 ConstantInfo::Inductive(v) => v.is_unsafe,
715 ConstantInfo::Constructor(v) => v.is_unsafe,
716 ConstantInfo::Recursor(v) => v.is_unsafe,
717 ConstantInfo::Theorem(_) | ConstantInfo::Quotient(_) => false,
718 }
719 }
720 pub fn is_structure_like(&self) -> bool {
727 match self {
728 ConstantInfo::Inductive(v) => v.ctors.len() == 1 && !v.is_rec && v.num_indices == 0,
729 _ => false,
730 }
731 }
732}
733impl ConstantInfo {
734 pub fn kind(&self) -> ConstantKind {
736 match self {
737 ConstantInfo::Axiom(_) => ConstantKind::Axiom,
738 ConstantInfo::Definition(_) => ConstantKind::Definition,
739 ConstantInfo::Theorem(_) => ConstantKind::Theorem,
740 ConstantInfo::Opaque(_) => ConstantKind::Opaque,
741 ConstantInfo::Inductive(_) => ConstantKind::Inductive,
742 ConstantInfo::Constructor(_) => ConstantKind::Constructor,
743 ConstantInfo::Recursor(_) => ConstantKind::Recursor,
744 ConstantInfo::Quotient(_) => ConstantKind::Quotient,
745 }
746 }
747 pub fn summarize(&self) -> ConstantSummary {
749 ConstantSummary {
750 name: self.name().clone(),
751 kind: self.kind(),
752 num_level_params: self.level_params().len(),
753 is_polymorphic: !self.level_params().is_empty(),
754 }
755 }
756 pub fn num_level_params(&self) -> usize {
758 self.level_params().len()
759 }
760 pub fn is_polymorphic(&self) -> bool {
762 !self.level_params().is_empty()
763 }
764 pub fn parent_inductive(&self) -> Option<&Name> {
766 match self {
767 ConstantInfo::Constructor(cv) => Some(&cv.induct),
768 _ => None,
769 }
770 }
771 pub fn inductive_num_params(&self) -> Option<usize> {
773 match self {
774 ConstantInfo::Inductive(iv) => Some(iv.num_params as usize),
775 _ => None,
776 }
777 }
778 pub fn inductive_num_indices(&self) -> Option<usize> {
780 match self {
781 ConstantInfo::Inductive(iv) => Some(iv.num_indices as usize),
782 _ => None,
783 }
784 }
785 pub fn inductive_constructors(&self) -> Option<&[Name]> {
787 match self {
788 ConstantInfo::Inductive(iv) => Some(&iv.ctors),
789 _ => None,
790 }
791 }
792 pub fn ctor_num_fields(&self) -> Option<usize> {
794 match self {
795 ConstantInfo::Constructor(cv) => Some(cv.num_fields as usize),
796 _ => None,
797 }
798 }
799 pub fn recursor_rules(&self) -> Option<&[RecursorRule]> {
801 match self {
802 ConstantInfo::Recursor(rv) => Some(&rv.rules),
803 _ => None,
804 }
805 }
806 pub fn display_string(&self) -> String {
808 let kind = self.kind().as_str();
809 if self.level_params().is_empty() {
810 format!("{} {}", kind, self.name())
811 } else {
812 let params: Vec<String> = self
813 .level_params()
814 .iter()
815 .map(|p| format!("{}", p))
816 .collect();
817 format!("{} {}.{{{}}} ", kind, self.name(), params.join(", "))
818 }
819 }
820}
821#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
823pub enum DefinitionSafety {
824 Safe,
826 Unsafe,
828 Partial,
830}
831impl DefinitionSafety {
832 pub fn is_safe(&self) -> bool {
834 matches!(self, DefinitionSafety::Safe)
835 }
836 pub fn is_partial(&self) -> bool {
838 matches!(self, DefinitionSafety::Partial)
839 }
840 pub fn as_str(&self) -> &'static str {
842 match self {
843 DefinitionSafety::Safe => "safe",
844 DefinitionSafety::Unsafe => "unsafe",
845 DefinitionSafety::Partial => "partial",
846 }
847 }
848}
849#[allow(dead_code)]
851#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
852pub struct TypedId<T> {
853 pub(super) id: u32,
854 _phantom: std::marker::PhantomData<T>,
855}
856#[allow(dead_code)]
857impl<T> TypedId<T> {
858 pub const fn new(id: u32) -> Self {
860 Self {
861 id,
862 _phantom: std::marker::PhantomData,
863 }
864 }
865 pub fn raw(&self) -> u32 {
867 self.id
868 }
869}
870#[allow(dead_code)]
872#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
873pub enum DeclKind {
874 Theorem,
876 Definition,
878 Opaque,
880 Axiom,
882 Structure,
884 Inductive,
886 Recursive,
888 Instance,
890}
891#[allow(dead_code)]
892impl DeclKind {
893 pub fn has_body(self) -> bool {
895 !matches!(self, DeclKind::Axiom)
896 }
897 pub fn is_type_decl(self) -> bool {
899 matches!(self, DeclKind::Structure | DeclKind::Inductive)
900 }
901 pub fn label(self) -> &'static str {
903 match self {
904 DeclKind::Theorem => "theorem",
905 DeclKind::Definition => "def",
906 DeclKind::Opaque => "opaque",
907 DeclKind::Axiom => "axiom",
908 DeclKind::Structure => "structure",
909 DeclKind::Inductive => "inductive",
910 DeclKind::Recursive => "recdef",
911 DeclKind::Instance => "instance",
912 }
913 }
914}
915#[allow(dead_code)]
917pub struct StringInterner {
918 strings: Vec<String>,
919 map: std::collections::HashMap<String, u32>,
920}
921#[allow(dead_code)]
922impl StringInterner {
923 pub fn new() -> Self {
925 Self {
926 strings: Vec::new(),
927 map: std::collections::HashMap::new(),
928 }
929 }
930 pub fn intern(&mut self, s: &str) -> u32 {
932 if let Some(&id) = self.map.get(s) {
933 return id;
934 }
935 let id = self.strings.len() as u32;
936 self.strings.push(s.to_string());
937 self.map.insert(s.to_string(), id);
938 id
939 }
940 pub fn get(&self, id: u32) -> Option<&str> {
942 self.strings.get(id as usize).map(|s| s.as_str())
943 }
944 pub fn len(&self) -> usize {
946 self.strings.len()
947 }
948 pub fn is_empty(&self) -> bool {
950 self.strings.is_empty()
951 }
952}
953#[allow(dead_code)]
955pub struct RingBuffer<T> {
956 data: Vec<Option<T>>,
957 head: usize,
958 tail: usize,
959 count: usize,
960 capacity: usize,
961}
962#[allow(dead_code)]
963impl<T> RingBuffer<T> {
964 pub fn new(capacity: usize) -> Self {
966 let mut data = Vec::with_capacity(capacity);
967 for _ in 0..capacity {
968 data.push(None);
969 }
970 Self {
971 data,
972 head: 0,
973 tail: 0,
974 count: 0,
975 capacity,
976 }
977 }
978 pub fn push(&mut self, val: T) {
980 if self.count == self.capacity {
981 self.data[self.head] = Some(val);
982 self.head = (self.head + 1) % self.capacity;
983 self.tail = (self.tail + 1) % self.capacity;
984 } else {
985 self.data[self.tail] = Some(val);
986 self.tail = (self.tail + 1) % self.capacity;
987 self.count += 1;
988 }
989 }
990 pub fn pop(&mut self) -> Option<T> {
992 if self.count == 0 {
993 return None;
994 }
995 let val = self.data[self.head].take();
996 self.head = (self.head + 1) % self.capacity;
997 self.count -= 1;
998 val
999 }
1000 pub fn len(&self) -> usize {
1002 self.count
1003 }
1004 pub fn is_empty(&self) -> bool {
1006 self.count == 0
1007 }
1008 pub fn is_full(&self) -> bool {
1010 self.count == self.capacity
1011 }
1012}
1013#[derive(Clone, Debug, PartialEq)]
1015pub struct InductiveVal {
1016 pub common: ConstantVal,
1018 pub num_params: u32,
1020 pub num_indices: u32,
1022 pub all: Vec<Name>,
1024 pub ctors: Vec<Name>,
1026 pub num_nested: u32,
1028 pub is_rec: bool,
1030 pub is_unsafe: bool,
1032 pub is_reflexive: bool,
1034 pub is_prop: bool,
1036}
1037#[allow(dead_code)]
1039#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1040pub struct SeqNum(u64);
1041#[allow(dead_code)]
1042impl SeqNum {
1043 pub const ZERO: SeqNum = SeqNum(0);
1045 pub fn next(self) -> SeqNum {
1047 SeqNum(self.0 + 1)
1048 }
1049 pub fn value(self) -> u64 {
1051 self.0
1052 }
1053}
1054#[allow(dead_code)]
1056pub struct BiMap<A: std::hash::Hash + Eq + Clone, B: std::hash::Hash + Eq + Clone> {
1057 forward: std::collections::HashMap<A, B>,
1058 backward: std::collections::HashMap<B, A>,
1059}
1060#[allow(dead_code)]
1061impl<A: std::hash::Hash + Eq + Clone, B: std::hash::Hash + Eq + Clone> BiMap<A, B> {
1062 pub fn new() -> Self {
1064 Self {
1065 forward: std::collections::HashMap::new(),
1066 backward: std::collections::HashMap::new(),
1067 }
1068 }
1069 pub fn insert(&mut self, a: A, b: B) {
1071 self.forward.insert(a.clone(), b.clone());
1072 self.backward.insert(b, a);
1073 }
1074 pub fn get_b(&self, a: &A) -> Option<&B> {
1076 self.forward.get(a)
1077 }
1078 pub fn get_a(&self, b: &B) -> Option<&A> {
1080 self.backward.get(b)
1081 }
1082 pub fn len(&self) -> usize {
1084 self.forward.len()
1085 }
1086 pub fn is_empty(&self) -> bool {
1088 self.forward.is_empty()
1089 }
1090}
1091#[derive(Clone, Debug, PartialEq)]
1093pub struct OpaqueVal {
1094 pub common: ConstantVal,
1096 pub value: Expr,
1098 pub is_unsafe: bool,
1100 pub all: Vec<Name>,
1102}
1103#[allow(dead_code)]
1105#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1106pub enum DeclVisibility {
1107 Public,
1109 Protected,
1111 Private,
1113}
1114#[allow(dead_code)]
1115impl DeclVisibility {
1116 pub fn is_externally_visible(self) -> bool {
1118 matches!(self, DeclVisibility::Public)
1119 }
1120}
1121#[allow(dead_code)]
1123pub struct IdDispenser<T> {
1124 next: u32,
1125 _phantom: std::marker::PhantomData<T>,
1126}
1127#[allow(dead_code)]
1128impl<T> IdDispenser<T> {
1129 pub fn new() -> Self {
1131 Self {
1132 next: 0,
1133 _phantom: std::marker::PhantomData,
1134 }
1135 }
1136 #[allow(clippy::should_implement_trait)]
1138 pub fn next(&mut self) -> TypedId<T> {
1139 let id = TypedId::new(self.next);
1140 self.next += 1;
1141 id
1142 }
1143 pub fn count(&self) -> u32 {
1145 self.next
1146 }
1147}
1148#[allow(dead_code)]
1150pub struct DeclDependencies {
1151 deps: Vec<std::collections::HashSet<usize>>,
1153}
1154#[allow(dead_code)]
1155impl DeclDependencies {
1156 pub fn new(n: usize) -> Self {
1158 Self {
1159 deps: vec![std::collections::HashSet::new(); n],
1160 }
1161 }
1162 pub fn add(&mut self, dependent: usize, dependency: usize) {
1164 if dependent < self.deps.len() {
1165 self.deps[dependent].insert(dependency);
1166 }
1167 }
1168 pub fn deps_of(&self, idx: usize) -> &std::collections::HashSet<usize> {
1170 static EMPTY: std::sync::OnceLock<std::collections::HashSet<usize>> =
1171 std::sync::OnceLock::new();
1172 self.deps
1173 .get(idx)
1174 .unwrap_or_else(|| EMPTY.get_or_init(std::collections::HashSet::new))
1175 }
1176 pub fn directly_depends(&self, dependent: usize, dependency: usize) -> bool {
1178 self.deps_of(dependent).contains(&dependency)
1179 }
1180 pub fn total_edges(&self) -> usize {
1182 self.deps.iter().map(|s| s.len()).sum()
1183 }
1184}
1185#[allow(dead_code)]
1187pub struct IntervalSet {
1188 intervals: Vec<(i64, i64)>,
1189}
1190#[allow(dead_code)]
1191impl IntervalSet {
1192 pub fn new() -> Self {
1194 Self {
1195 intervals: Vec::new(),
1196 }
1197 }
1198 pub fn add(&mut self, lo: i64, hi: i64) {
1200 if lo > hi {
1201 return;
1202 }
1203 let mut new_lo = lo;
1204 let mut new_hi = hi;
1205 let mut i = 0;
1206 while i < self.intervals.len() {
1207 let (il, ih) = self.intervals[i];
1208 if ih < new_lo - 1 {
1209 i += 1;
1210 continue;
1211 }
1212 if il > new_hi + 1 {
1213 break;
1214 }
1215 new_lo = new_lo.min(il);
1216 new_hi = new_hi.max(ih);
1217 self.intervals.remove(i);
1218 }
1219 self.intervals.insert(i, (new_lo, new_hi));
1220 }
1221 pub fn contains(&self, x: i64) -> bool {
1223 self.intervals.iter().any(|&(lo, hi)| x >= lo && x <= hi)
1224 }
1225 pub fn num_intervals(&self) -> usize {
1227 self.intervals.len()
1228 }
1229 pub fn cardinality(&self) -> i64 {
1231 self.intervals.iter().map(|&(lo, hi)| hi - lo + 1).sum()
1232 }
1233}
1234#[allow(dead_code)]
1236#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1237pub struct Generation(u32);
1238#[allow(dead_code)]
1239impl Generation {
1240 pub const INITIAL: Generation = Generation(0);
1242 pub fn advance(self) -> Generation {
1244 Generation(self.0 + 1)
1245 }
1246 pub fn number(self) -> u32 {
1248 self.0
1249 }
1250}
1251#[allow(dead_code)]
1253pub struct WorkQueue<T> {
1254 items: std::collections::VecDeque<T>,
1255}
1256#[allow(dead_code)]
1257impl<T> WorkQueue<T> {
1258 pub fn new() -> Self {
1260 Self {
1261 items: std::collections::VecDeque::new(),
1262 }
1263 }
1264 pub fn enqueue(&mut self, item: T) {
1266 self.items.push_back(item);
1267 }
1268 pub fn dequeue(&mut self) -> Option<T> {
1270 self.items.pop_front()
1271 }
1272 pub fn is_empty(&self) -> bool {
1274 self.items.is_empty()
1275 }
1276 pub fn len(&self) -> usize {
1278 self.items.len()
1279 }
1280}
1281#[derive(Clone, Debug, PartialEq)]
1283pub struct DefinitionVal {
1284 pub common: ConstantVal,
1286 pub value: Expr,
1288 pub hints: ReducibilityHint,
1290 pub safety: DefinitionSafety,
1292 pub all: Vec<Name>,
1294}
1295#[derive(Clone, Debug, PartialEq)]
1297pub struct QuotVal {
1298 pub common: ConstantVal,
1300 pub kind: QuotKind,
1302}
1303#[derive(Debug, Clone)]
1305pub struct ConstantSummary {
1306 pub name: Name,
1308 pub kind: ConstantKind,
1310 pub num_level_params: usize,
1312 pub is_polymorphic: bool,
1314}
1315#[allow(dead_code)]
1317pub struct FrequencyTable<T: std::hash::Hash + Eq + Clone> {
1318 counts: std::collections::HashMap<T, u64>,
1319}
1320#[allow(dead_code)]
1321impl<T: std::hash::Hash + Eq + Clone> FrequencyTable<T> {
1322 pub fn new() -> Self {
1324 Self {
1325 counts: std::collections::HashMap::new(),
1326 }
1327 }
1328 pub fn record(&mut self, item: T) {
1330 *self.counts.entry(item).or_insert(0) += 1;
1331 }
1332 pub fn freq(&self, item: &T) -> u64 {
1334 self.counts.get(item).copied().unwrap_or(0)
1335 }
1336 pub fn most_frequent(&self) -> Option<(&T, u64)> {
1338 self.counts
1339 .iter()
1340 .max_by_key(|(_, &v)| v)
1341 .map(|(k, &v)| (k, v))
1342 }
1343 pub fn total(&self) -> u64 {
1345 self.counts.values().sum()
1346 }
1347 pub fn distinct(&self) -> usize {
1349 self.counts.len()
1350 }
1351}
1352#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1354pub enum ConstantKind {
1355 Axiom,
1357 Definition,
1359 Theorem,
1361 Opaque,
1363 Inductive,
1365 Constructor,
1367 Recursor,
1369 Quotient,
1371}
1372impl ConstantKind {
1373 pub fn as_str(&self) -> &'static str {
1375 match self {
1376 ConstantKind::Axiom => "axiom",
1377 ConstantKind::Definition => "definition",
1378 ConstantKind::Theorem => "theorem",
1379 ConstantKind::Opaque => "opaque",
1380 ConstantKind::Inductive => "inductive",
1381 ConstantKind::Constructor => "constructor",
1382 ConstantKind::Recursor => "recursor",
1383 ConstantKind::Quotient => "quotient",
1384 }
1385 }
1386 pub fn has_body(&self) -> bool {
1388 matches!(
1389 self,
1390 ConstantKind::Definition | ConstantKind::Theorem | ConstantKind::Opaque
1391 )
1392 }
1393 pub fn is_inductive_family(&self) -> bool {
1395 matches!(
1396 self,
1397 ConstantKind::Inductive | ConstantKind::Constructor | ConstantKind::Recursor
1398 )
1399 }
1400}
1401#[allow(dead_code)]
1403pub struct DeclFilter {
1404 allowed_kinds: Option<Vec<DeclKind>>,
1405 ns_prefix: Option<String>,
1406 required_attrs: Vec<DeclAttr>,
1407}
1408#[allow(dead_code)]
1409impl DeclFilter {
1410 pub fn accept_all() -> Self {
1412 Self {
1413 allowed_kinds: None,
1414 ns_prefix: None,
1415 required_attrs: Vec::new(),
1416 }
1417 }
1418 pub fn with_kinds(mut self, kinds: Vec<DeclKind>) -> Self {
1420 self.allowed_kinds = Some(kinds);
1421 self
1422 }
1423 pub fn in_namespace(mut self, prefix: impl Into<String>) -> Self {
1425 self.ns_prefix = Some(prefix.into());
1426 self
1427 }
1428 pub fn with_attr(mut self, attr: DeclAttr) -> Self {
1430 self.required_attrs.push(attr);
1431 self
1432 }
1433 pub fn accepts(&self, sig: &DeclSignature, kind: DeclKind, attrs: &[DeclAttr]) -> bool {
1435 if let Some(ref kinds) = self.allowed_kinds {
1436 if !kinds.contains(&kind) {
1437 return false;
1438 }
1439 }
1440 if let Some(ref prefix) = self.ns_prefix {
1441 if !sig.name.starts_with(prefix.as_str()) {
1442 return false;
1443 }
1444 }
1445 for req in &self.required_attrs {
1446 if !attrs.contains(req) {
1447 return false;
1448 }
1449 }
1450 true
1451 }
1452}
1453#[allow(dead_code)]
1455pub struct SimpleLruCache<K: std::hash::Hash + Eq + Clone, V: Clone> {
1456 capacity: usize,
1457 map: std::collections::HashMap<K, usize>,
1458 keys: Vec<K>,
1459 vals: Vec<V>,
1460 order: Vec<usize>,
1461}
1462#[allow(dead_code)]
1463impl<K: std::hash::Hash + Eq + Clone, V: Clone> SimpleLruCache<K, V> {
1464 pub fn new(capacity: usize) -> Self {
1466 assert!(capacity > 0);
1467 Self {
1468 capacity,
1469 map: std::collections::HashMap::new(),
1470 keys: Vec::new(),
1471 vals: Vec::new(),
1472 order: Vec::new(),
1473 }
1474 }
1475 pub fn put(&mut self, key: K, val: V) {
1477 if let Some(&idx) = self.map.get(&key) {
1486 self.vals[idx] = val;
1489 self.order.retain(|&x| x != idx);
1492 self.order.insert(0, idx);
1493 return;
1494 }
1495 match self.order.last() {
1496 Some(&evict_idx) if self.keys.len() >= self.capacity => {
1500 let map_key = key.clone();
1505 let removed = self.map.remove_entry(&self.keys[evict_idx]);
1506 let old_key = std::mem::replace(&mut self.keys[evict_idx], key);
1510 let old_val = std::mem::replace(&mut self.vals[evict_idx], val);
1511 self.order.rotate_right(1);
1512 self.map.insert(map_key, evict_idx);
1515 drop((removed, old_key, old_val));
1516 }
1517 _ => {
1520 let map_key = key.clone();
1521 let idx = self.keys.len();
1522 self.keys.reserve(1);
1526 self.vals.reserve(1);
1527 self.order.reserve(1);
1528 self.keys.push(key);
1529 self.vals.push(val);
1530 self.order.insert(0, idx);
1531 self.map.insert(map_key, idx);
1532 }
1533 }
1534 }
1535 pub fn get(&mut self, key: &K) -> Option<&V> {
1537 let idx = *self.map.get(key)?;
1540 self.order.retain(|&x| x != idx);
1541 self.order.insert(0, idx);
1542 Some(&self.vals[idx])
1543 }
1544 pub fn len(&self) -> usize {
1546 self.keys.len()
1547 }
1548 pub fn is_empty(&self) -> bool {
1550 self.keys.is_empty()
1551 }
1552}
1553#[allow(dead_code)]
1555#[allow(missing_docs)]
1556pub struct DeclSignature {
1557 pub name: String,
1559 pub ty: String,
1561 pub uparams: Vec<String>,
1563}
1564#[allow(dead_code)]
1565impl DeclSignature {
1566 pub fn new(name: impl Into<String>, ty: impl Into<String>) -> Self {
1568 Self {
1569 name: name.into(),
1570 ty: ty.into(),
1571 uparams: Vec::new(),
1572 }
1573 }
1574 pub fn with_uparam(mut self, u: impl Into<String>) -> Self {
1576 self.uparams.push(u.into());
1577 self
1578 }
1579 pub fn is_universe_poly(&self) -> bool {
1581 !self.uparams.is_empty()
1582 }
1583}
1584#[allow(dead_code)]
1586pub struct DiagMeta {
1587 pub(super) entries: Vec<(String, String)>,
1588}
1589#[allow(dead_code)]
1590impl DiagMeta {
1591 pub fn new() -> Self {
1593 Self {
1594 entries: Vec::new(),
1595 }
1596 }
1597 pub fn add(&mut self, key: impl Into<String>, val: impl Into<String>) {
1599 self.entries.push((key.into(), val.into()));
1600 }
1601 pub fn get(&self, key: &str) -> Option<&str> {
1603 self.entries
1604 .iter()
1605 .find(|(k, _)| k == key)
1606 .map(|(_, v)| v.as_str())
1607 }
1608 pub fn len(&self) -> usize {
1610 self.entries.len()
1611 }
1612 pub fn is_empty(&self) -> bool {
1614 self.entries.is_empty()
1615 }
1616}