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 {
722 match self {
723 ConstantInfo::Inductive(v) => v.ctors.len() == 1 && !v.is_rec && v.num_indices == 0,
724 _ => false,
725 }
726 }
727}
728impl ConstantInfo {
729 pub fn kind(&self) -> ConstantKind {
731 match self {
732 ConstantInfo::Axiom(_) => ConstantKind::Axiom,
733 ConstantInfo::Definition(_) => ConstantKind::Definition,
734 ConstantInfo::Theorem(_) => ConstantKind::Theorem,
735 ConstantInfo::Opaque(_) => ConstantKind::Opaque,
736 ConstantInfo::Inductive(_) => ConstantKind::Inductive,
737 ConstantInfo::Constructor(_) => ConstantKind::Constructor,
738 ConstantInfo::Recursor(_) => ConstantKind::Recursor,
739 ConstantInfo::Quotient(_) => ConstantKind::Quotient,
740 }
741 }
742 pub fn summarize(&self) -> ConstantSummary {
744 ConstantSummary {
745 name: self.name().clone(),
746 kind: self.kind(),
747 num_level_params: self.level_params().len(),
748 is_polymorphic: !self.level_params().is_empty(),
749 }
750 }
751 pub fn num_level_params(&self) -> usize {
753 self.level_params().len()
754 }
755 pub fn is_polymorphic(&self) -> bool {
757 !self.level_params().is_empty()
758 }
759 pub fn parent_inductive(&self) -> Option<&Name> {
761 match self {
762 ConstantInfo::Constructor(cv) => Some(&cv.induct),
763 _ => None,
764 }
765 }
766 pub fn inductive_num_params(&self) -> Option<usize> {
768 match self {
769 ConstantInfo::Inductive(iv) => Some(iv.num_params as usize),
770 _ => None,
771 }
772 }
773 pub fn inductive_num_indices(&self) -> Option<usize> {
775 match self {
776 ConstantInfo::Inductive(iv) => Some(iv.num_indices as usize),
777 _ => None,
778 }
779 }
780 pub fn inductive_constructors(&self) -> Option<&[Name]> {
782 match self {
783 ConstantInfo::Inductive(iv) => Some(&iv.ctors),
784 _ => None,
785 }
786 }
787 pub fn ctor_num_fields(&self) -> Option<usize> {
789 match self {
790 ConstantInfo::Constructor(cv) => Some(cv.num_fields as usize),
791 _ => None,
792 }
793 }
794 pub fn recursor_rules(&self) -> Option<&[RecursorRule]> {
796 match self {
797 ConstantInfo::Recursor(rv) => Some(&rv.rules),
798 _ => None,
799 }
800 }
801 pub fn display_string(&self) -> String {
803 let kind = self.kind().as_str();
804 if self.level_params().is_empty() {
805 format!("{} {}", kind, self.name())
806 } else {
807 let params: Vec<String> = self
808 .level_params()
809 .iter()
810 .map(|p| format!("{}", p))
811 .collect();
812 format!("{} {}.{{{}}} ", kind, self.name(), params.join(", "))
813 }
814 }
815}
816#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
818pub enum DefinitionSafety {
819 Safe,
821 Unsafe,
823 Partial,
825}
826impl DefinitionSafety {
827 pub fn is_safe(&self) -> bool {
829 matches!(self, DefinitionSafety::Safe)
830 }
831 pub fn is_partial(&self) -> bool {
833 matches!(self, DefinitionSafety::Partial)
834 }
835 pub fn as_str(&self) -> &'static str {
837 match self {
838 DefinitionSafety::Safe => "safe",
839 DefinitionSafety::Unsafe => "unsafe",
840 DefinitionSafety::Partial => "partial",
841 }
842 }
843}
844#[allow(dead_code)]
846#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
847pub struct TypedId<T> {
848 pub(super) id: u32,
849 _phantom: std::marker::PhantomData<T>,
850}
851#[allow(dead_code)]
852impl<T> TypedId<T> {
853 pub const fn new(id: u32) -> Self {
855 Self {
856 id,
857 _phantom: std::marker::PhantomData,
858 }
859 }
860 pub fn raw(&self) -> u32 {
862 self.id
863 }
864}
865#[allow(dead_code)]
867#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
868pub enum DeclKind {
869 Theorem,
871 Definition,
873 Opaque,
875 Axiom,
877 Structure,
879 Inductive,
881 Recursive,
883 Instance,
885}
886#[allow(dead_code)]
887impl DeclKind {
888 pub fn has_body(self) -> bool {
890 !matches!(self, DeclKind::Axiom)
891 }
892 pub fn is_type_decl(self) -> bool {
894 matches!(self, DeclKind::Structure | DeclKind::Inductive)
895 }
896 pub fn label(self) -> &'static str {
898 match self {
899 DeclKind::Theorem => "theorem",
900 DeclKind::Definition => "def",
901 DeclKind::Opaque => "opaque",
902 DeclKind::Axiom => "axiom",
903 DeclKind::Structure => "structure",
904 DeclKind::Inductive => "inductive",
905 DeclKind::Recursive => "recdef",
906 DeclKind::Instance => "instance",
907 }
908 }
909}
910#[allow(dead_code)]
912pub struct StringInterner {
913 strings: Vec<String>,
914 map: std::collections::HashMap<String, u32>,
915}
916#[allow(dead_code)]
917impl StringInterner {
918 pub fn new() -> Self {
920 Self {
921 strings: Vec::new(),
922 map: std::collections::HashMap::new(),
923 }
924 }
925 pub fn intern(&mut self, s: &str) -> u32 {
927 if let Some(&id) = self.map.get(s) {
928 return id;
929 }
930 let id = self.strings.len() as u32;
931 self.strings.push(s.to_string());
932 self.map.insert(s.to_string(), id);
933 id
934 }
935 pub fn get(&self, id: u32) -> Option<&str> {
937 self.strings.get(id as usize).map(|s| s.as_str())
938 }
939 pub fn len(&self) -> usize {
941 self.strings.len()
942 }
943 pub fn is_empty(&self) -> bool {
945 self.strings.is_empty()
946 }
947}
948#[allow(dead_code)]
950pub struct RingBuffer<T> {
951 data: Vec<Option<T>>,
952 head: usize,
953 tail: usize,
954 count: usize,
955 capacity: usize,
956}
957#[allow(dead_code)]
958impl<T> RingBuffer<T> {
959 pub fn new(capacity: usize) -> Self {
961 let mut data = Vec::with_capacity(capacity);
962 for _ in 0..capacity {
963 data.push(None);
964 }
965 Self {
966 data,
967 head: 0,
968 tail: 0,
969 count: 0,
970 capacity,
971 }
972 }
973 pub fn push(&mut self, val: T) {
975 if self.count == self.capacity {
976 self.data[self.head] = Some(val);
977 self.head = (self.head + 1) % self.capacity;
978 self.tail = (self.tail + 1) % self.capacity;
979 } else {
980 self.data[self.tail] = Some(val);
981 self.tail = (self.tail + 1) % self.capacity;
982 self.count += 1;
983 }
984 }
985 pub fn pop(&mut self) -> Option<T> {
987 if self.count == 0 {
988 return None;
989 }
990 let val = self.data[self.head].take();
991 self.head = (self.head + 1) % self.capacity;
992 self.count -= 1;
993 val
994 }
995 pub fn len(&self) -> usize {
997 self.count
998 }
999 pub fn is_empty(&self) -> bool {
1001 self.count == 0
1002 }
1003 pub fn is_full(&self) -> bool {
1005 self.count == self.capacity
1006 }
1007}
1008#[derive(Clone, Debug, PartialEq)]
1010pub struct InductiveVal {
1011 pub common: ConstantVal,
1013 pub num_params: u32,
1015 pub num_indices: u32,
1017 pub all: Vec<Name>,
1019 pub ctors: Vec<Name>,
1021 pub num_nested: u32,
1023 pub is_rec: bool,
1025 pub is_unsafe: bool,
1027 pub is_reflexive: bool,
1029 pub is_prop: bool,
1031}
1032#[allow(dead_code)]
1034#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1035pub struct SeqNum(u64);
1036#[allow(dead_code)]
1037impl SeqNum {
1038 pub const ZERO: SeqNum = SeqNum(0);
1040 pub fn next(self) -> SeqNum {
1042 SeqNum(self.0 + 1)
1043 }
1044 pub fn value(self) -> u64 {
1046 self.0
1047 }
1048}
1049#[allow(dead_code)]
1051pub struct BiMap<A: std::hash::Hash + Eq + Clone, B: std::hash::Hash + Eq + Clone> {
1052 forward: std::collections::HashMap<A, B>,
1053 backward: std::collections::HashMap<B, A>,
1054}
1055#[allow(dead_code)]
1056impl<A: std::hash::Hash + Eq + Clone, B: std::hash::Hash + Eq + Clone> BiMap<A, B> {
1057 pub fn new() -> Self {
1059 Self {
1060 forward: std::collections::HashMap::new(),
1061 backward: std::collections::HashMap::new(),
1062 }
1063 }
1064 pub fn insert(&mut self, a: A, b: B) {
1066 self.forward.insert(a.clone(), b.clone());
1067 self.backward.insert(b, a);
1068 }
1069 pub fn get_b(&self, a: &A) -> Option<&B> {
1071 self.forward.get(a)
1072 }
1073 pub fn get_a(&self, b: &B) -> Option<&A> {
1075 self.backward.get(b)
1076 }
1077 pub fn len(&self) -> usize {
1079 self.forward.len()
1080 }
1081 pub fn is_empty(&self) -> bool {
1083 self.forward.is_empty()
1084 }
1085}
1086#[derive(Clone, Debug, PartialEq)]
1088pub struct OpaqueVal {
1089 pub common: ConstantVal,
1091 pub value: Expr,
1093 pub is_unsafe: bool,
1095 pub all: Vec<Name>,
1097}
1098#[allow(dead_code)]
1100#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1101pub enum DeclVisibility {
1102 Public,
1104 Protected,
1106 Private,
1108}
1109#[allow(dead_code)]
1110impl DeclVisibility {
1111 pub fn is_externally_visible(self) -> bool {
1113 matches!(self, DeclVisibility::Public)
1114 }
1115}
1116#[allow(dead_code)]
1118pub struct IdDispenser<T> {
1119 next: u32,
1120 _phantom: std::marker::PhantomData<T>,
1121}
1122#[allow(dead_code)]
1123impl<T> IdDispenser<T> {
1124 pub fn new() -> Self {
1126 Self {
1127 next: 0,
1128 _phantom: std::marker::PhantomData,
1129 }
1130 }
1131 #[allow(clippy::should_implement_trait)]
1133 pub fn next(&mut self) -> TypedId<T> {
1134 let id = TypedId::new(self.next);
1135 self.next += 1;
1136 id
1137 }
1138 pub fn count(&self) -> u32 {
1140 self.next
1141 }
1142}
1143#[allow(dead_code)]
1145pub struct DeclDependencies {
1146 deps: Vec<std::collections::HashSet<usize>>,
1148}
1149#[allow(dead_code)]
1150impl DeclDependencies {
1151 pub fn new(n: usize) -> Self {
1153 Self {
1154 deps: vec![std::collections::HashSet::new(); n],
1155 }
1156 }
1157 pub fn add(&mut self, dependent: usize, dependency: usize) {
1159 if dependent < self.deps.len() {
1160 self.deps[dependent].insert(dependency);
1161 }
1162 }
1163 pub fn deps_of(&self, idx: usize) -> &std::collections::HashSet<usize> {
1165 static EMPTY: std::sync::OnceLock<std::collections::HashSet<usize>> =
1166 std::sync::OnceLock::new();
1167 self.deps
1168 .get(idx)
1169 .unwrap_or_else(|| EMPTY.get_or_init(std::collections::HashSet::new))
1170 }
1171 pub fn directly_depends(&self, dependent: usize, dependency: usize) -> bool {
1173 self.deps_of(dependent).contains(&dependency)
1174 }
1175 pub fn total_edges(&self) -> usize {
1177 self.deps.iter().map(|s| s.len()).sum()
1178 }
1179}
1180#[allow(dead_code)]
1182pub struct IntervalSet {
1183 intervals: Vec<(i64, i64)>,
1184}
1185#[allow(dead_code)]
1186impl IntervalSet {
1187 pub fn new() -> Self {
1189 Self {
1190 intervals: Vec::new(),
1191 }
1192 }
1193 pub fn add(&mut self, lo: i64, hi: i64) {
1195 if lo > hi {
1196 return;
1197 }
1198 let mut new_lo = lo;
1199 let mut new_hi = hi;
1200 let mut i = 0;
1201 while i < self.intervals.len() {
1202 let (il, ih) = self.intervals[i];
1203 if ih < new_lo - 1 {
1204 i += 1;
1205 continue;
1206 }
1207 if il > new_hi + 1 {
1208 break;
1209 }
1210 new_lo = new_lo.min(il);
1211 new_hi = new_hi.max(ih);
1212 self.intervals.remove(i);
1213 }
1214 self.intervals.insert(i, (new_lo, new_hi));
1215 }
1216 pub fn contains(&self, x: i64) -> bool {
1218 self.intervals.iter().any(|&(lo, hi)| x >= lo && x <= hi)
1219 }
1220 pub fn num_intervals(&self) -> usize {
1222 self.intervals.len()
1223 }
1224 pub fn cardinality(&self) -> i64 {
1226 self.intervals.iter().map(|&(lo, hi)| hi - lo + 1).sum()
1227 }
1228}
1229#[allow(dead_code)]
1231#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1232pub struct Generation(u32);
1233#[allow(dead_code)]
1234impl Generation {
1235 pub const INITIAL: Generation = Generation(0);
1237 pub fn advance(self) -> Generation {
1239 Generation(self.0 + 1)
1240 }
1241 pub fn number(self) -> u32 {
1243 self.0
1244 }
1245}
1246#[allow(dead_code)]
1248pub struct WorkQueue<T> {
1249 items: std::collections::VecDeque<T>,
1250}
1251#[allow(dead_code)]
1252impl<T> WorkQueue<T> {
1253 pub fn new() -> Self {
1255 Self {
1256 items: std::collections::VecDeque::new(),
1257 }
1258 }
1259 pub fn enqueue(&mut self, item: T) {
1261 self.items.push_back(item);
1262 }
1263 pub fn dequeue(&mut self) -> Option<T> {
1265 self.items.pop_front()
1266 }
1267 pub fn is_empty(&self) -> bool {
1269 self.items.is_empty()
1270 }
1271 pub fn len(&self) -> usize {
1273 self.items.len()
1274 }
1275}
1276#[derive(Clone, Debug, PartialEq)]
1278pub struct DefinitionVal {
1279 pub common: ConstantVal,
1281 pub value: Expr,
1283 pub hints: ReducibilityHint,
1285 pub safety: DefinitionSafety,
1287 pub all: Vec<Name>,
1289}
1290#[derive(Clone, Debug, PartialEq)]
1292pub struct QuotVal {
1293 pub common: ConstantVal,
1295 pub kind: QuotKind,
1297}
1298#[derive(Debug, Clone)]
1300pub struct ConstantSummary {
1301 pub name: Name,
1303 pub kind: ConstantKind,
1305 pub num_level_params: usize,
1307 pub is_polymorphic: bool,
1309}
1310#[allow(dead_code)]
1312pub struct FrequencyTable<T: std::hash::Hash + Eq + Clone> {
1313 counts: std::collections::HashMap<T, u64>,
1314}
1315#[allow(dead_code)]
1316impl<T: std::hash::Hash + Eq + Clone> FrequencyTable<T> {
1317 pub fn new() -> Self {
1319 Self {
1320 counts: std::collections::HashMap::new(),
1321 }
1322 }
1323 pub fn record(&mut self, item: T) {
1325 *self.counts.entry(item).or_insert(0) += 1;
1326 }
1327 pub fn freq(&self, item: &T) -> u64 {
1329 self.counts.get(item).copied().unwrap_or(0)
1330 }
1331 pub fn most_frequent(&self) -> Option<(&T, u64)> {
1333 self.counts
1334 .iter()
1335 .max_by_key(|(_, &v)| v)
1336 .map(|(k, &v)| (k, v))
1337 }
1338 pub fn total(&self) -> u64 {
1340 self.counts.values().sum()
1341 }
1342 pub fn distinct(&self) -> usize {
1344 self.counts.len()
1345 }
1346}
1347#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1349pub enum ConstantKind {
1350 Axiom,
1352 Definition,
1354 Theorem,
1356 Opaque,
1358 Inductive,
1360 Constructor,
1362 Recursor,
1364 Quotient,
1366}
1367impl ConstantKind {
1368 pub fn as_str(&self) -> &'static str {
1370 match self {
1371 ConstantKind::Axiom => "axiom",
1372 ConstantKind::Definition => "definition",
1373 ConstantKind::Theorem => "theorem",
1374 ConstantKind::Opaque => "opaque",
1375 ConstantKind::Inductive => "inductive",
1376 ConstantKind::Constructor => "constructor",
1377 ConstantKind::Recursor => "recursor",
1378 ConstantKind::Quotient => "quotient",
1379 }
1380 }
1381 pub fn has_body(&self) -> bool {
1383 matches!(
1384 self,
1385 ConstantKind::Definition | ConstantKind::Theorem | ConstantKind::Opaque
1386 )
1387 }
1388 pub fn is_inductive_family(&self) -> bool {
1390 matches!(
1391 self,
1392 ConstantKind::Inductive | ConstantKind::Constructor | ConstantKind::Recursor
1393 )
1394 }
1395}
1396#[allow(dead_code)]
1398pub struct DeclFilter {
1399 allowed_kinds: Option<Vec<DeclKind>>,
1400 ns_prefix: Option<String>,
1401 required_attrs: Vec<DeclAttr>,
1402}
1403#[allow(dead_code)]
1404impl DeclFilter {
1405 pub fn accept_all() -> Self {
1407 Self {
1408 allowed_kinds: None,
1409 ns_prefix: None,
1410 required_attrs: Vec::new(),
1411 }
1412 }
1413 pub fn with_kinds(mut self, kinds: Vec<DeclKind>) -> Self {
1415 self.allowed_kinds = Some(kinds);
1416 self
1417 }
1418 pub fn in_namespace(mut self, prefix: impl Into<String>) -> Self {
1420 self.ns_prefix = Some(prefix.into());
1421 self
1422 }
1423 pub fn with_attr(mut self, attr: DeclAttr) -> Self {
1425 self.required_attrs.push(attr);
1426 self
1427 }
1428 pub fn accepts(&self, sig: &DeclSignature, kind: DeclKind, attrs: &[DeclAttr]) -> bool {
1430 if let Some(ref kinds) = self.allowed_kinds {
1431 if !kinds.contains(&kind) {
1432 return false;
1433 }
1434 }
1435 if let Some(ref prefix) = self.ns_prefix {
1436 if !sig.name.starts_with(prefix.as_str()) {
1437 return false;
1438 }
1439 }
1440 for req in &self.required_attrs {
1441 if !attrs.contains(req) {
1442 return false;
1443 }
1444 }
1445 true
1446 }
1447}
1448#[allow(dead_code)]
1450pub struct SimpleLruCache<K: std::hash::Hash + Eq + Clone, V: Clone> {
1451 capacity: usize,
1452 map: std::collections::HashMap<K, usize>,
1453 keys: Vec<K>,
1454 vals: Vec<V>,
1455 order: Vec<usize>,
1456}
1457#[allow(dead_code)]
1458impl<K: std::hash::Hash + Eq + Clone, V: Clone> SimpleLruCache<K, V> {
1459 pub fn new(capacity: usize) -> Self {
1461 assert!(capacity > 0);
1462 Self {
1463 capacity,
1464 map: std::collections::HashMap::new(),
1465 keys: Vec::new(),
1466 vals: Vec::new(),
1467 order: Vec::new(),
1468 }
1469 }
1470 pub fn put(&mut self, key: K, val: V) {
1472 if let Some(&idx) = self.map.get(&key) {
1481 self.vals[idx] = val;
1484 self.order.retain(|&x| x != idx);
1487 self.order.insert(0, idx);
1488 return;
1489 }
1490 match self.order.last() {
1491 Some(&evict_idx) if self.keys.len() >= self.capacity => {
1495 let map_key = key.clone();
1500 let removed = self.map.remove_entry(&self.keys[evict_idx]);
1501 let old_key = std::mem::replace(&mut self.keys[evict_idx], key);
1505 let old_val = std::mem::replace(&mut self.vals[evict_idx], val);
1506 self.order.rotate_right(1);
1507 self.map.insert(map_key, evict_idx);
1510 drop((removed, old_key, old_val));
1511 }
1512 _ => {
1515 let map_key = key.clone();
1516 let idx = self.keys.len();
1517 self.keys.reserve(1);
1521 self.vals.reserve(1);
1522 self.order.reserve(1);
1523 self.keys.push(key);
1524 self.vals.push(val);
1525 self.order.insert(0, idx);
1526 self.map.insert(map_key, idx);
1527 }
1528 }
1529 }
1530 pub fn get(&mut self, key: &K) -> Option<&V> {
1532 let idx = *self.map.get(key)?;
1535 self.order.retain(|&x| x != idx);
1536 self.order.insert(0, idx);
1537 Some(&self.vals[idx])
1538 }
1539 pub fn len(&self) -> usize {
1541 self.keys.len()
1542 }
1543 pub fn is_empty(&self) -> bool {
1545 self.keys.is_empty()
1546 }
1547}
1548#[allow(dead_code)]
1550#[allow(missing_docs)]
1551pub struct DeclSignature {
1552 pub name: String,
1554 pub ty: String,
1556 pub uparams: Vec<String>,
1558}
1559#[allow(dead_code)]
1560impl DeclSignature {
1561 pub fn new(name: impl Into<String>, ty: impl Into<String>) -> Self {
1563 Self {
1564 name: name.into(),
1565 ty: ty.into(),
1566 uparams: Vec::new(),
1567 }
1568 }
1569 pub fn with_uparam(mut self, u: impl Into<String>) -> Self {
1571 self.uparams.push(u.into());
1572 self
1573 }
1574 pub fn is_universe_poly(&self) -> bool {
1576 !self.uparams.is_empty()
1577 }
1578}
1579#[allow(dead_code)]
1581pub struct DiagMeta {
1582 pub(super) entries: Vec<(String, String)>,
1583}
1584#[allow(dead_code)]
1585impl DiagMeta {
1586 pub fn new() -> Self {
1588 Self {
1589 entries: Vec::new(),
1590 }
1591 }
1592 pub fn add(&mut self, key: impl Into<String>, val: impl Into<String>) {
1594 self.entries.push((key.into(), val.into()));
1595 }
1596 pub fn get(&self, key: &str) -> Option<&str> {
1598 self.entries
1599 .iter()
1600 .find(|(k, _)| k == key)
1601 .map(|(_, v)| v.as_str())
1602 }
1603 pub fn len(&self) -> usize {
1605 self.entries.len()
1606 }
1607 pub fn is_empty(&self) -> bool {
1609 self.entries.is_empty()
1610 }
1611}