1use crate::declaration::{ConstantInfo, ConstantVal, DefinitionSafety, DefinitionVal};
6use crate::reduce::ReducibilityHint;
7use crate::{Expr, Level, Name};
8use std::collections::HashMap;
9
10#[allow(dead_code)]
12#[allow(missing_docs)]
13pub struct RewriteRule {
14 pub name: String,
16 pub lhs: String,
18 pub rhs: String,
20 pub conditional: bool,
22}
23#[allow(dead_code)]
24impl RewriteRule {
25 pub fn unconditional(
27 name: impl Into<String>,
28 lhs: impl Into<String>,
29 rhs: impl Into<String>,
30 ) -> Self {
31 Self {
32 name: name.into(),
33 lhs: lhs.into(),
34 rhs: rhs.into(),
35 conditional: false,
36 }
37 }
38 pub fn conditional(
40 name: impl Into<String>,
41 lhs: impl Into<String>,
42 rhs: impl Into<String>,
43 ) -> Self {
44 Self {
45 name: name.into(),
46 lhs: lhs.into(),
47 rhs: rhs.into(),
48 conditional: true,
49 }
50 }
51 pub fn display(&self) -> String {
53 format!("{}: {} → {}", self.name, self.lhs, self.rhs)
54 }
55}
56#[allow(dead_code)]
58pub struct RewriteRuleSet {
59 rules: Vec<RewriteRule>,
60}
61#[allow(dead_code)]
62impl RewriteRuleSet {
63 pub fn new() -> Self {
65 Self { rules: Vec::new() }
66 }
67 pub fn add(&mut self, rule: RewriteRule) {
69 self.rules.push(rule);
70 }
71 pub fn len(&self) -> usize {
73 self.rules.len()
74 }
75 pub fn is_empty(&self) -> bool {
77 self.rules.is_empty()
78 }
79 pub fn conditional_rules(&self) -> Vec<&RewriteRule> {
81 self.rules.iter().filter(|r| r.conditional).collect()
82 }
83 pub fn unconditional_rules(&self) -> Vec<&RewriteRule> {
85 self.rules.iter().filter(|r| !r.conditional).collect()
86 }
87 pub fn get(&self, name: &str) -> Option<&RewriteRule> {
89 self.rules.iter().find(|r| r.name == name)
90 }
91}
92#[allow(dead_code)]
94pub struct VersionedRecord<T: Clone> {
95 earlier: Vec<T>,
97 current: T,
99}
100#[allow(dead_code)]
101impl<T: Clone> VersionedRecord<T> {
102 pub fn new(initial: T) -> Self {
104 Self {
105 earlier: Vec::new(),
106 current: initial,
107 }
108 }
109 pub fn update(&mut self, val: T) {
111 let previous = std::mem::replace(&mut self.current, val);
112 self.earlier.push(previous);
113 }
114 pub fn current(&self) -> &T {
116 &self.current
117 }
118 pub fn at_version(&self, n: usize) -> Option<&T> {
120 match self.earlier.get(n) {
121 Some(value) => Some(value),
122 None if n == self.earlier.len() => Some(&self.current),
123 None => None,
124 }
125 }
126 pub fn version(&self) -> usize {
128 self.earlier.len()
129 }
130 pub fn has_history(&self) -> bool {
132 !self.earlier.is_empty()
133 }
134}
135#[allow(dead_code)]
137pub struct FocusStack<T> {
138 items: Vec<T>,
139}
140#[allow(dead_code)]
141impl<T> FocusStack<T> {
142 pub fn new() -> Self {
144 Self { items: Vec::new() }
145 }
146 pub fn focus(&mut self, item: T) {
148 self.items.push(item);
149 }
150 pub fn blur(&mut self) -> Option<T> {
152 self.items.pop()
153 }
154 pub fn current(&self) -> Option<&T> {
156 self.items.last()
157 }
158 pub fn depth(&self) -> usize {
160 self.items.len()
161 }
162 pub fn is_empty(&self) -> bool {
164 self.items.is_empty()
165 }
166}
167#[allow(dead_code)]
169pub struct SparseVec<T: Default + Clone + PartialEq> {
170 entries: std::collections::HashMap<usize, T>,
171 default_: T,
172 logical_len: usize,
173}
174#[allow(dead_code)]
175impl<T: Default + Clone + PartialEq> SparseVec<T> {
176 pub fn new(len: usize) -> Self {
178 Self {
179 entries: std::collections::HashMap::new(),
180 default_: T::default(),
181 logical_len: len,
182 }
183 }
184 pub fn set(&mut self, idx: usize, val: T) {
186 if val == self.default_ {
187 self.entries.remove(&idx);
188 } else {
189 self.entries.insert(idx, val);
190 }
191 }
192 pub fn get(&self, idx: usize) -> &T {
194 self.entries.get(&idx).unwrap_or(&self.default_)
195 }
196 pub fn len(&self) -> usize {
198 self.logical_len
199 }
200 pub fn is_empty(&self) -> bool {
202 self.len() == 0
203 }
204 pub fn nnz(&self) -> usize {
206 self.entries.len()
207 }
208}
209#[allow(dead_code)]
211pub struct WindowIterator<'a, T> {
212 pub(super) data: &'a [T],
213 pub(super) pos: usize,
214 pub(super) window: usize,
215}
216#[allow(dead_code)]
217impl<'a, T> WindowIterator<'a, T> {
218 pub fn new(data: &'a [T], window: usize) -> Self {
220 Self {
221 data,
222 pos: 0,
223 window,
224 }
225 }
226}
227#[derive(Clone, Debug, Default)]
229pub struct Environment {
230 declarations: HashMap<Name, Declaration>,
232 constants: HashMap<Name, ConstantInfo>,
234 quot_initialized: bool,
238}
239impl Environment {
240 pub fn new() -> Self {
242 Self {
243 declarations: HashMap::new(),
244 constants: HashMap::new(),
245 quot_initialized: false,
246 }
247 }
248 pub fn add(&mut self, decl: Declaration) -> Result<(), EnvError> {
252 let name = decl.name().clone();
253 if self.declarations.contains_key(&name) || self.constants.contains_key(&name) {
254 return Err(EnvError::DuplicateDeclaration(name));
255 }
256 let ci = decl.to_constant_info();
257 self.constants.insert(name.clone(), ci);
258 self.declarations.insert(name, decl);
259 Ok(())
260 }
261 pub fn add_constant(&mut self, ci: ConstantInfo) -> Result<(), EnvError> {
269 if ci.is_quotient() {
270 return Err(EnvError::InvalidQuotient(
271 "quotient constants may only be added via Environment::add_quot".to_string(),
272 ));
273 }
274 let name = ci.name().clone();
275 if self.declarations.contains_key(&name) || self.constants.contains_key(&name) {
276 return Err(EnvError::DuplicateDeclaration(name));
277 }
278 self.constants.insert(name, ci);
279 Ok(())
280 }
281 pub fn quot_initialized(&self) -> bool {
283 self.quot_initialized
284 }
285 pub(crate) fn insert_quotient(&mut self, ci: ConstantInfo) {
291 debug_assert!(ci.is_quotient());
292 let name = ci.name().clone();
293 self.constants.insert(name, ci);
294 }
295 pub(crate) fn set_quot_initialized(&mut self) {
297 self.quot_initialized = true;
298 }
299 pub fn get(&self, name: &Name) -> Option<&Declaration> {
301 self.declarations.get(name)
302 }
303 pub fn find(&self, name: &Name) -> Option<&ConstantInfo> {
305 self.constants.get(name)
306 }
307 pub fn contains(&self, name: &Name) -> bool {
309 self.declarations.contains_key(name) || self.constants.contains_key(name)
310 }
311 pub fn len(&self) -> usize {
313 self.constants.len().max(self.declarations.len())
314 }
315 pub fn is_empty(&self) -> bool {
317 self.declarations.is_empty() && self.constants.is_empty()
318 }
319 pub fn get_defn(&self, name: &Name) -> Option<(Expr, ReducibilityHint)> {
321 if let Some(ci) = self.constants.get(name) {
322 if let Some(val) = ci.value() {
323 return Some((val.clone(), ci.reducibility_hint()));
324 }
325 }
326 self.declarations.get(name).and_then(|decl| {
327 decl.value()
328 .map(|val| (val.clone(), decl.reducibility_hint()))
329 })
330 }
331 pub fn is_inductive(&self, name: &Name) -> bool {
333 self.constants.get(name).is_some_and(|ci| ci.is_inductive())
334 }
335 pub fn is_constructor(&self, name: &Name) -> bool {
337 self.constants
338 .get(name)
339 .is_some_and(|ci| ci.is_constructor())
340 }
341 pub fn is_recursor(&self, name: &Name) -> bool {
343 self.constants.get(name).is_some_and(|ci| ci.is_recursor())
344 }
345 pub fn is_quotient(&self, name: &Name) -> bool {
347 self.constants.get(name).is_some_and(|ci| ci.is_quotient())
348 }
349 pub fn is_structure_like(&self, name: &Name) -> bool {
351 self.constants
352 .get(name)
353 .is_some_and(|ci| ci.is_structure_like())
354 }
355 pub fn get_inductive_val(&self, name: &Name) -> Option<&crate::declaration::InductiveVal> {
357 self.constants
358 .get(name)
359 .and_then(|ci| ci.to_inductive_val())
360 }
361 pub fn get_constructor_val(&self, name: &Name) -> Option<&crate::declaration::ConstructorVal> {
363 self.constants
364 .get(name)
365 .and_then(|ci| ci.to_constructor_val())
366 }
367 pub fn get_recursor_val(&self, name: &Name) -> Option<&crate::declaration::RecursorVal> {
369 self.constants.get(name).and_then(|ci| ci.to_recursor_val())
370 }
371 pub fn get_quotient_val(&self, name: &Name) -> Option<&crate::declaration::QuotVal> {
373 self.constants.get(name).and_then(|ci| ci.to_quotient_val())
374 }
375 pub fn get_type(&self, name: &Name) -> Option<&Expr> {
377 self.constants.get(name).map(|ci| ci.ty())
378 }
379 pub fn get_level_params(&self, name: &Name) -> Option<&[Name]> {
381 self.constants.get(name).map(|ci| ci.level_params())
382 }
383 pub fn instantiate_const_type(&self, name: &Name, levels: &[Level]) -> Option<Expr> {
385 let ci = self.constants.get(name)?;
386 let params = ci.level_params();
387 if params.is_empty() || levels.is_empty() {
388 return Some(ci.ty().clone());
389 }
390 Some(crate::declaration::instantiate_level_params(
391 ci.ty(),
392 params,
393 levels,
394 ))
395 }
396 pub fn constant_names(&self) -> impl Iterator<Item = &Name> {
398 self.constants.keys()
399 }
400 pub fn constant_infos(&self) -> impl Iterator<Item = (&Name, &ConstantInfo)> {
402 self.constants.iter()
403 }
404}
405#[allow(dead_code)]
407#[derive(Debug, Clone, Default)]
408pub struct EnvKindCounts {
409 pub axioms: usize,
411 pub inductives: usize,
413 pub constructors: usize,
415 pub recursors: usize,
417 pub definitions: usize,
419 pub theorems: usize,
421 pub other: usize,
423}
424impl EnvKindCounts {
425 #[allow(dead_code)]
427 pub fn total(&self) -> usize {
428 self.axioms
429 + self.inductives
430 + self.constructors
431 + self.recursors
432 + self.definitions
433 + self.theorems
434 + self.other
435 }
436}
437#[derive(Clone, Debug)]
439pub enum Declaration {
440 Axiom {
442 name: Name,
444 univ_params: Vec<Name>,
446 ty: Expr,
448 },
449 Definition {
451 name: Name,
453 univ_params: Vec<Name>,
455 ty: Expr,
457 val: Expr,
459 hint: ReducibilityHint,
461 },
462 Theorem {
464 name: Name,
466 univ_params: Vec<Name>,
468 ty: Expr,
470 val: Expr,
472 },
473 Opaque {
475 name: Name,
477 univ_params: Vec<Name>,
479 ty: Expr,
481 val: Expr,
483 },
484}
485impl Declaration {
486 pub fn name(&self) -> &Name {
488 match self {
489 Declaration::Axiom { name, .. }
490 | Declaration::Definition { name, .. }
491 | Declaration::Theorem { name, .. }
492 | Declaration::Opaque { name, .. } => name,
493 }
494 }
495 pub fn ty(&self) -> &Expr {
497 match self {
498 Declaration::Axiom { ty, .. }
499 | Declaration::Definition { ty, .. }
500 | Declaration::Theorem { ty, .. }
501 | Declaration::Opaque { ty, .. } => ty,
502 }
503 }
504 pub fn univ_params(&self) -> &[Name] {
506 match self {
507 Declaration::Axiom { univ_params, .. }
508 | Declaration::Definition { univ_params, .. }
509 | Declaration::Theorem { univ_params, .. }
510 | Declaration::Opaque { univ_params, .. } => univ_params,
511 }
512 }
513 pub fn value(&self) -> Option<&Expr> {
515 match self {
516 Declaration::Axiom { .. } => None,
517 Declaration::Definition { val, .. }
518 | Declaration::Theorem { val, .. }
519 | Declaration::Opaque { val, .. } => Some(val),
520 }
521 }
522 pub fn reducibility_hint(&self) -> ReducibilityHint {
524 match self {
525 Declaration::Axiom { .. } => ReducibilityHint::Opaque,
526 Declaration::Definition { hint, .. } => *hint,
527 Declaration::Theorem { .. } | Declaration::Opaque { .. } => ReducibilityHint::Opaque,
528 }
529 }
530 pub fn to_constant_info(&self) -> ConstantInfo {
532 match self {
533 Declaration::Axiom {
534 name,
535 univ_params,
536 ty,
537 } => ConstantInfo::Axiom(crate::declaration::AxiomVal {
538 common: ConstantVal {
539 name: name.clone(),
540 level_params: univ_params.clone(),
541 ty: ty.clone(),
542 },
543 is_unsafe: false,
544 }),
545 Declaration::Definition {
546 name,
547 univ_params,
548 ty,
549 val,
550 hint,
551 } => ConstantInfo::Definition(DefinitionVal {
552 common: ConstantVal {
553 name: name.clone(),
554 level_params: univ_params.clone(),
555 ty: ty.clone(),
556 },
557 value: val.clone(),
558 hints: *hint,
559 safety: DefinitionSafety::Safe,
560 all: vec![name.clone()],
561 }),
562 Declaration::Theorem {
563 name,
564 univ_params,
565 ty,
566 val,
567 } => ConstantInfo::Theorem(crate::declaration::TheoremVal {
568 common: ConstantVal {
569 name: name.clone(),
570 level_params: univ_params.clone(),
571 ty: ty.clone(),
572 },
573 value: val.clone(),
574 all: vec![name.clone()],
575 }),
576 Declaration::Opaque {
577 name,
578 univ_params,
579 ty,
580 val,
581 } => ConstantInfo::Opaque(crate::declaration::OpaqueVal {
582 common: ConstantVal {
583 name: name.clone(),
584 level_params: univ_params.clone(),
585 ty: ty.clone(),
586 },
587 value: val.clone(),
588 is_unsafe: false,
589 all: vec![name.clone()],
590 }),
591 }
592 }
593}
594#[allow(dead_code)]
596pub struct RawFnPtr {
597 ptr: usize,
599 arity: usize,
600 name: String,
601}
602#[allow(dead_code)]
603impl RawFnPtr {
604 pub fn new(ptr: usize, arity: usize, name: impl Into<String>) -> Self {
606 Self {
607 ptr,
608 arity,
609 name: name.into(),
610 }
611 }
612 pub fn arity(&self) -> usize {
614 self.arity
615 }
616 pub fn name(&self) -> &str {
618 &self.name
619 }
620 pub fn raw(&self) -> usize {
622 self.ptr
623 }
624}
625#[allow(dead_code)]
627pub struct PrefixCounter {
628 children: std::collections::HashMap<char, PrefixCounter>,
629 count: usize,
630}
631#[allow(dead_code)]
632impl PrefixCounter {
633 pub fn new() -> Self {
635 Self {
636 children: std::collections::HashMap::new(),
637 count: 0,
638 }
639 }
640 pub fn record(&mut self, s: &str) {
642 self.count += 1;
643 let mut node = self;
644 for c in s.chars() {
645 node = node.children.entry(c).or_default();
646 node.count += 1;
647 }
648 }
649 pub fn count_with_prefix(&self, prefix: &str) -> usize {
651 let mut node = self;
652 for c in prefix.chars() {
653 match node.children.get(&c) {
654 Some(n) => node = n,
655 None => return 0,
656 }
657 }
658 node.count
659 }
660}
661#[allow(dead_code)]
663pub struct Fixture {
664 data: std::collections::HashMap<String, String>,
665}
666#[allow(dead_code)]
667impl Fixture {
668 pub fn new() -> Self {
670 Self {
671 data: std::collections::HashMap::new(),
672 }
673 }
674 pub fn set(&mut self, key: impl Into<String>, val: impl Into<String>) {
676 self.data.insert(key.into(), val.into());
677 }
678 pub fn get(&self, key: &str) -> Option<&str> {
680 self.data.get(key).map(|s| s.as_str())
681 }
682 pub fn len(&self) -> usize {
684 self.data.len()
685 }
686 pub fn is_empty(&self) -> bool {
688 self.len() == 0
689 }
690}
691#[allow(dead_code)]
693pub struct EnvironmentView<'a> {
694 env: &'a Environment,
695}
696impl<'a> EnvironmentView<'a> {
697 #[allow(dead_code)]
699 pub fn new(env: &'a Environment) -> Self {
700 Self { env }
701 }
702 #[allow(dead_code)]
704 pub fn axiom_names(&self) -> Vec<&Name> {
705 self.env
706 .constant_infos()
707 .filter_map(|(name, ci)| if ci.is_axiom() { Some(name) } else { None })
708 .collect()
709 }
710 #[allow(dead_code)]
712 pub fn inductive_names(&self) -> Vec<&Name> {
713 self.env
714 .constant_infos()
715 .filter_map(|(name, ci)| if ci.is_inductive() { Some(name) } else { None })
716 .collect()
717 }
718 #[allow(dead_code)]
720 pub fn constructor_names(&self) -> Vec<&Name> {
721 self.env
722 .constant_infos()
723 .filter_map(|(name, ci)| {
724 if ci.is_constructor() {
725 Some(name)
726 } else {
727 None
728 }
729 })
730 .collect()
731 }
732 #[allow(dead_code)]
734 pub fn definition_names(&self) -> Vec<&Name> {
735 self.env
736 .constant_infos()
737 .filter_map(|(name, ci)| if ci.is_definition() { Some(name) } else { None })
738 .collect()
739 }
740 #[allow(dead_code)]
742 pub fn count_by_kind(&self) -> EnvKindCounts {
743 let mut counts = EnvKindCounts::default();
744 for (_, ci) in self.env.constant_infos() {
745 if ci.is_axiom() {
746 counts.axioms += 1;
747 } else if ci.is_inductive() {
748 counts.inductives += 1;
749 } else if ci.is_constructor() {
750 counts.constructors += 1;
751 } else if ci.is_recursor() {
752 counts.recursors += 1;
753 } else if ci.is_definition() {
754 counts.definitions += 1;
755 } else if ci.is_theorem() {
756 counts.theorems += 1;
757 } else {
758 counts.other += 1;
759 }
760 }
761 counts
762 }
763}
764#[allow(dead_code)]
766pub struct LabelSet {
767 labels: Vec<String>,
768}
769#[allow(dead_code)]
770impl LabelSet {
771 pub fn new() -> Self {
773 Self { labels: Vec::new() }
774 }
775 pub fn add(&mut self, label: impl Into<String>) {
777 let s = label.into();
778 if !self.labels.contains(&s) {
779 self.labels.push(s);
780 }
781 }
782 pub fn has(&self, label: &str) -> bool {
784 self.labels.iter().any(|l| l == label)
785 }
786 pub fn count(&self) -> usize {
788 self.labels.len()
789 }
790 pub fn all(&self) -> &[String] {
792 &self.labels
793 }
794}
795#[derive(Clone, Debug, Default)]
797pub struct EnvStats {
798 pub total: usize,
800 pub axioms: usize,
802 pub definitions: usize,
804 pub theorems: usize,
806 pub inductives: usize,
808 pub constructors: usize,
810 pub recursors: usize,
812}
813#[allow(dead_code)]
815pub struct StatSummary {
816 count: u64,
817 sum: f64,
818 min: f64,
819 max: f64,
820}
821#[allow(dead_code)]
822impl StatSummary {
823 pub fn new() -> Self {
825 Self {
826 count: 0,
827 sum: 0.0,
828 min: f64::INFINITY,
829 max: f64::NEG_INFINITY,
830 }
831 }
832 pub fn record(&mut self, val: f64) {
834 self.count += 1;
835 self.sum += val;
836 if val < self.min {
837 self.min = val;
838 }
839 if val > self.max {
840 self.max = val;
841 }
842 }
843 pub fn mean(&self) -> Option<f64> {
845 if self.count == 0 {
846 None
847 } else {
848 Some(self.sum / self.count as f64)
849 }
850 }
851 pub fn min(&self) -> Option<f64> {
853 if self.count == 0 {
854 None
855 } else {
856 Some(self.min)
857 }
858 }
859 pub fn max(&self) -> Option<f64> {
861 if self.count == 0 {
862 None
863 } else {
864 Some(self.max)
865 }
866 }
867 pub fn count(&self) -> u64 {
869 self.count
870 }
871}
872#[allow(dead_code)]
874pub struct NonEmptyVec<T> {
875 head: T,
876 tail: Vec<T>,
877}
878#[allow(dead_code)]
879impl<T> NonEmptyVec<T> {
880 pub fn singleton(val: T) -> Self {
882 Self {
883 head: val,
884 tail: Vec::new(),
885 }
886 }
887 pub fn push(&mut self, val: T) {
889 self.tail.push(val);
890 }
891 pub fn first(&self) -> &T {
893 &self.head
894 }
895 pub fn last(&self) -> &T {
897 self.tail.last().unwrap_or(&self.head)
898 }
899 pub fn len(&self) -> usize {
901 1 + self.tail.len()
902 }
903 pub fn is_empty(&self) -> bool {
905 self.len() == 0
906 }
907 pub fn to_vec(&self) -> Vec<&T> {
909 let mut v = vec![&self.head];
910 v.extend(self.tail.iter());
911 v
912 }
913}
914#[allow(dead_code)]
916pub struct Stopwatch {
917 start: crate::wall_clock::Instant,
918 splits: Vec<f64>,
919}
920#[allow(dead_code)]
921impl Stopwatch {
922 pub fn start() -> Self {
924 Self {
925 start: crate::wall_clock::Instant::now(),
926 splits: Vec::new(),
927 }
928 }
929 pub fn split(&mut self) {
931 self.splits.push(self.elapsed_ms());
932 }
933 pub fn elapsed_ms(&self) -> f64 {
935 self.start.elapsed().as_secs_f64() * 1000.0
936 }
937 pub fn splits(&self) -> &[f64] {
939 &self.splits
940 }
941 pub fn num_splits(&self) -> usize {
943 self.splits.len()
944 }
945}
946#[allow(dead_code)]
948pub struct TokenBucket {
949 capacity: u64,
950 tokens: u64,
951 refill_per_ms: u64,
952 last_refill: crate::wall_clock::Instant,
953}
954#[allow(dead_code)]
955impl TokenBucket {
956 pub fn new(capacity: u64, refill_per_ms: u64) -> Self {
958 Self {
959 capacity,
960 tokens: capacity,
961 refill_per_ms,
962 last_refill: crate::wall_clock::Instant::now(),
963 }
964 }
965 pub fn try_consume(&mut self, n: u64) -> bool {
967 self.refill();
968 if self.tokens >= n {
969 self.tokens -= n;
970 true
971 } else {
972 false
973 }
974 }
975 fn refill(&mut self) {
976 let now = crate::wall_clock::Instant::now();
977 let elapsed_ms = now.duration_since(self.last_refill).as_millis() as u64;
978 if elapsed_ms > 0 {
979 let new_tokens = elapsed_ms * self.refill_per_ms;
980 self.tokens = (self.tokens + new_tokens).min(self.capacity);
981 self.last_refill = now;
982 }
983 }
984 pub fn available(&self) -> u64 {
986 self.tokens
987 }
988 pub fn capacity(&self) -> u64 {
990 self.capacity
991 }
992}
993#[allow(dead_code)]
995#[derive(Default)]
996pub struct EnvironmentBuilder {
997 declarations: Vec<Declaration>,
998 constants: Vec<crate::declaration::ConstantInfo>,
999}
1000impl EnvironmentBuilder {
1001 #[allow(dead_code)]
1003 pub fn new() -> Self {
1004 Self::default()
1005 }
1006 #[allow(dead_code)]
1008 pub fn add_decl(mut self, decl: Declaration) -> Self {
1009 self.declarations.push(decl);
1010 self
1011 }
1012 #[allow(dead_code)]
1014 pub fn add_constant(mut self, ci: crate::declaration::ConstantInfo) -> Self {
1015 self.constants.push(ci);
1016 self
1017 }
1018 #[allow(dead_code)]
1020 pub fn build(self) -> Result<Environment, EnvError> {
1021 let mut env = Environment::new();
1022 for decl in self.declarations {
1023 env.add(decl)?;
1024 }
1025 for ci in self.constants {
1026 env.add_constant(ci)?;
1027 }
1028 Ok(env)
1029 }
1030 #[allow(dead_code)]
1032 pub fn len(&self) -> usize {
1033 self.declarations.len() + self.constants.len()
1034 }
1035 #[allow(dead_code)]
1037 pub fn is_empty(&self) -> bool {
1038 self.declarations.is_empty() && self.constants.is_empty()
1039 }
1040}
1041#[allow(dead_code)]
1043#[allow(missing_docs)]
1044pub enum DecisionNode {
1045 Leaf(String),
1047 Branch {
1049 key: String,
1050 val: String,
1051 yes_branch: Box<DecisionNode>,
1052 no_branch: Box<DecisionNode>,
1053 },
1054}
1055#[allow(dead_code)]
1056impl DecisionNode {
1057 pub fn evaluate(&self, ctx: &std::collections::HashMap<String, String>) -> &str {
1059 match self {
1060 DecisionNode::Leaf(action) => action.as_str(),
1061 DecisionNode::Branch {
1062 key,
1063 val,
1064 yes_branch,
1065 no_branch,
1066 } => {
1067 let actual = ctx.get(key).map(|s| s.as_str()).unwrap_or("");
1068 if actual == val.as_str() {
1069 yes_branch.evaluate(ctx)
1070 } else {
1071 no_branch.evaluate(ctx)
1072 }
1073 }
1074 }
1075 }
1076 pub fn depth(&self) -> usize {
1078 match self {
1079 DecisionNode::Leaf(_) => 0,
1080 DecisionNode::Branch {
1081 yes_branch,
1082 no_branch,
1083 ..
1084 } => 1 + yes_branch.depth().max(no_branch.depth()),
1085 }
1086 }
1087}
1088#[allow(dead_code)]
1090pub struct StringPool {
1091 free: Vec<String>,
1092}
1093#[allow(dead_code)]
1094impl StringPool {
1095 pub fn new() -> Self {
1097 Self { free: Vec::new() }
1098 }
1099 pub fn take(&mut self) -> String {
1101 self.free.pop().unwrap_or_default()
1102 }
1103 pub fn give(&mut self, mut s: String) {
1105 s.clear();
1106 self.free.push(s);
1107 }
1108 pub fn free_count(&self) -> usize {
1110 self.free.len()
1111 }
1112}
1113#[allow(dead_code)]
1115pub enum Either2<A, B> {
1116 First(A),
1118 Second(B),
1120}
1121#[allow(dead_code)]
1122impl<A, B> Either2<A, B> {
1123 pub fn is_first(&self) -> bool {
1125 matches!(self, Either2::First(_))
1126 }
1127 pub fn is_second(&self) -> bool {
1129 matches!(self, Either2::Second(_))
1130 }
1131 pub fn first(self) -> Option<A> {
1133 match self {
1134 Either2::First(a) => Some(a),
1135 _ => None,
1136 }
1137 }
1138 pub fn second(self) -> Option<B> {
1140 match self {
1141 Either2::Second(b) => Some(b),
1142 _ => None,
1143 }
1144 }
1145 pub fn map_first<C, F: FnOnce(A) -> C>(self, f: F) -> Either2<C, B> {
1147 match self {
1148 Either2::First(a) => Either2::First(f(a)),
1149 Either2::Second(b) => Either2::Second(b),
1150 }
1151 }
1152}
1153#[allow(dead_code)]
1155pub struct StackCalc {
1156 stack: Vec<i64>,
1157}
1158#[allow(dead_code)]
1159impl StackCalc {
1160 pub fn new() -> Self {
1162 Self { stack: Vec::new() }
1163 }
1164 pub fn push(&mut self, n: i64) {
1166 self.stack.push(n);
1167 }
1168 fn apply_binary(&mut self, op: impl FnOnce(i64, i64) -> i64) -> Option<i64> {
1172 let (rest_len, a, b) = match self.stack[..] {
1173 [ref rest @ .., a, b] => (rest.len(), a, b),
1174 _ => return None,
1175 };
1176 let value = op(a, b);
1177 self.stack.truncate(rest_len);
1178 self.stack.push(value);
1179 Some(value)
1180 }
1181 pub fn add(&mut self) -> Option<i64> {
1185 self.apply_binary(|a, b| a + b)
1186 }
1187 pub fn sub(&mut self) -> Option<i64> {
1191 self.apply_binary(|a, b| a - b)
1192 }
1193 pub fn mul(&mut self) -> Option<i64> {
1197 self.apply_binary(|a, b| a * b)
1198 }
1199 pub fn peek(&self) -> Option<i64> {
1201 self.stack.last().copied()
1202 }
1203 pub fn depth(&self) -> usize {
1205 self.stack.len()
1206 }
1207}
1208#[allow(dead_code)]
1210pub struct SlidingSum {
1211 window: Vec<f64>,
1212 capacity: usize,
1213 pos: usize,
1214 sum: f64,
1215 count: usize,
1216}
1217#[allow(dead_code)]
1218impl SlidingSum {
1219 pub fn new(capacity: usize) -> Self {
1221 Self {
1222 window: vec![0.0; capacity],
1223 capacity,
1224 pos: 0,
1225 sum: 0.0,
1226 count: 0,
1227 }
1228 }
1229 pub fn push(&mut self, val: f64) {
1231 let oldest = self.window[self.pos];
1232 self.sum -= oldest;
1233 self.sum += val;
1234 self.window[self.pos] = val;
1235 self.pos = (self.pos + 1) % self.capacity;
1236 if self.count < self.capacity {
1237 self.count += 1;
1238 }
1239 }
1240 pub fn sum(&self) -> f64 {
1242 self.sum
1243 }
1244 pub fn mean(&self) -> Option<f64> {
1246 if self.count == 0 {
1247 None
1248 } else {
1249 Some(self.sum / self.count as f64)
1250 }
1251 }
1252 pub fn count(&self) -> usize {
1254 self.count
1255 }
1256}
1257#[allow(dead_code)]
1259pub struct PathBuf {
1260 components: Vec<String>,
1261}
1262#[allow(dead_code)]
1263impl PathBuf {
1264 pub fn new() -> Self {
1266 Self {
1267 components: Vec::new(),
1268 }
1269 }
1270 pub fn push(&mut self, comp: impl Into<String>) {
1272 self.components.push(comp.into());
1273 }
1274 pub fn pop(&mut self) {
1276 self.components.pop();
1277 }
1278 pub fn as_str(&self) -> String {
1280 self.components.join("/")
1281 }
1282 pub fn depth(&self) -> usize {
1284 self.components.len()
1285 }
1286 pub fn clear(&mut self) {
1288 self.components.clear();
1289 }
1290}
1291#[allow(dead_code)]
1293pub struct FlatSubstitution {
1294 pairs: Vec<(String, String)>,
1295}
1296#[allow(dead_code)]
1297impl FlatSubstitution {
1298 pub fn new() -> Self {
1300 Self { pairs: Vec::new() }
1301 }
1302 pub fn add(&mut self, from: impl Into<String>, to: impl Into<String>) {
1304 self.pairs.push((from.into(), to.into()));
1305 }
1306 pub fn apply(&self, s: &str) -> String {
1308 let mut result = s.to_string();
1309 for (from, to) in &self.pairs {
1310 result = result.replace(from.as_str(), to.as_str());
1311 }
1312 result
1313 }
1314 pub fn len(&self) -> usize {
1316 self.pairs.len()
1317 }
1318 pub fn is_empty(&self) -> bool {
1320 self.pairs.is_empty()
1321 }
1322}
1323#[derive(Clone, Debug)]
1325pub enum EnvError {
1326 DuplicateDeclaration(Name),
1328 NotFound(Name),
1330 InvalidQuotient(String),
1334}
1335#[allow(dead_code)]
1337pub struct TransformStat {
1338 before: StatSummary,
1339 after: StatSummary,
1340}
1341#[allow(dead_code)]
1342impl TransformStat {
1343 pub fn new() -> Self {
1345 Self {
1346 before: StatSummary::new(),
1347 after: StatSummary::new(),
1348 }
1349 }
1350 pub fn record_before(&mut self, v: f64) {
1352 self.before.record(v);
1353 }
1354 pub fn record_after(&mut self, v: f64) {
1356 self.after.record(v);
1357 }
1358 pub fn mean_ratio(&self) -> Option<f64> {
1360 let b = self.before.mean()?;
1361 let a = self.after.mean()?;
1362 if b.abs() < f64::EPSILON {
1363 return None;
1364 }
1365 Some(a / b)
1366 }
1367}
1368#[allow(dead_code)]
1370pub struct TransitiveClosure {
1371 adj: Vec<Vec<usize>>,
1372 n: usize,
1373}
1374#[allow(dead_code)]
1375impl TransitiveClosure {
1376 pub fn new(n: usize) -> Self {
1378 Self {
1379 adj: vec![Vec::new(); n],
1380 n,
1381 }
1382 }
1383 pub fn add_edge(&mut self, from: usize, to: usize) {
1385 if from < self.n {
1386 self.adj[from].push(to);
1387 }
1388 }
1389 pub fn reachable_from(&self, start: usize) -> Vec<usize> {
1391 let mut visited = vec![false; self.n];
1392 let mut queue = std::collections::VecDeque::new();
1393 queue.push_back(start);
1394 while let Some(node) = queue.pop_front() {
1395 if node >= self.n || visited[node] {
1396 continue;
1397 }
1398 visited[node] = true;
1399 for &next in &self.adj[node] {
1400 queue.push_back(next);
1401 }
1402 }
1403 (0..self.n).filter(|&i| visited[i]).collect()
1404 }
1405 pub fn can_reach(&self, from: usize, to: usize) -> bool {
1407 self.reachable_from(from).contains(&to)
1408 }
1409}
1410#[allow(dead_code)]
1412pub struct MinHeap<T: Ord> {
1413 data: Vec<T>,
1414}
1415#[allow(dead_code)]
1416impl<T: Ord> MinHeap<T> {
1417 pub fn new() -> Self {
1419 Self { data: Vec::new() }
1420 }
1421 pub fn push(&mut self, val: T) {
1423 self.data.push(val);
1424 self.sift_up(self.data.len() - 1);
1425 }
1426 pub fn pop(&mut self) -> Option<T> {
1428 if self.data.is_empty() {
1429 return None;
1430 }
1431 let n = self.data.len();
1432 self.data.swap(0, n - 1);
1433 let min = self.data.pop();
1434 if !self.data.is_empty() {
1435 self.sift_down(0);
1436 }
1437 min
1438 }
1439 pub fn peek(&self) -> Option<&T> {
1441 self.data.first()
1442 }
1443 pub fn len(&self) -> usize {
1445 self.data.len()
1446 }
1447 pub fn is_empty(&self) -> bool {
1449 self.data.is_empty()
1450 }
1451 fn sift_up(&mut self, mut i: usize) {
1452 while i > 0 {
1453 let parent = (i - 1) / 2;
1454 if self.data[i] < self.data[parent] {
1455 self.data.swap(i, parent);
1456 i = parent;
1457 } else {
1458 break;
1459 }
1460 }
1461 }
1462 fn sift_down(&mut self, mut i: usize) {
1463 let n = self.data.len();
1464 loop {
1465 let left = 2 * i + 1;
1466 let right = 2 * i + 2;
1467 let mut smallest = i;
1468 if left < n && self.data[left] < self.data[smallest] {
1469 smallest = left;
1470 }
1471 if right < n && self.data[right] < self.data[smallest] {
1472 smallest = right;
1473 }
1474 if smallest == i {
1475 break;
1476 }
1477 self.data.swap(i, smallest);
1478 i = smallest;
1479 }
1480 }
1481}
1482#[allow(dead_code)]
1484pub struct ConfigNode {
1485 key: String,
1486 value: Option<String>,
1487 children: Vec<ConfigNode>,
1488}
1489#[allow(dead_code)]
1490impl ConfigNode {
1491 pub fn leaf(key: impl Into<String>, value: impl Into<String>) -> Self {
1493 Self {
1494 key: key.into(),
1495 value: Some(value.into()),
1496 children: Vec::new(),
1497 }
1498 }
1499 pub fn section(key: impl Into<String>) -> Self {
1501 Self {
1502 key: key.into(),
1503 value: None,
1504 children: Vec::new(),
1505 }
1506 }
1507 pub fn add_child(&mut self, child: ConfigNode) {
1509 self.children.push(child);
1510 }
1511 pub fn key(&self) -> &str {
1513 &self.key
1514 }
1515 pub fn value(&self) -> Option<&str> {
1517 self.value.as_deref()
1518 }
1519 pub fn num_children(&self) -> usize {
1521 self.children.len()
1522 }
1523 pub fn lookup(&self, path: &str) -> Option<&str> {
1525 let mut parts = path.splitn(2, '.');
1526 let head = parts.next()?;
1527 let tail = parts.next();
1528 if head != self.key {
1529 return None;
1530 }
1531 match tail {
1532 None => self.value.as_deref(),
1533 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
1534 }
1535 }
1536 fn lookup_relative(&self, path: &str) -> Option<&str> {
1537 let mut parts = path.splitn(2, '.');
1538 let head = parts.next()?;
1539 let tail = parts.next();
1540 if head != self.key {
1541 return None;
1542 }
1543 match tail {
1544 None => self.value.as_deref(),
1545 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
1546 }
1547 }
1548}
1549#[derive(Clone, Debug)]
1553pub struct EnvironmentSnapshot {
1554 pub names: Vec<Name>,
1556}
1557impl EnvironmentSnapshot {
1558 pub fn from_env(env: &Environment) -> Self {
1560 let names: Vec<Name> = env.constant_names().cloned().collect();
1561 Self { names }
1562 }
1563 pub fn len(&self) -> usize {
1565 self.names.len()
1566 }
1567 pub fn is_empty(&self) -> bool {
1569 self.names.is_empty()
1570 }
1571 pub fn diff<'a>(&self, new: &'a EnvironmentSnapshot) -> Vec<&'a Name> {
1573 new.names
1574 .iter()
1575 .filter(|n| !self.names.contains(n))
1576 .collect()
1577 }
1578}
1579#[allow(dead_code)]
1581pub struct SmallMap<K: Ord + Clone, V: Clone> {
1582 entries: Vec<(K, V)>,
1583}
1584#[allow(dead_code)]
1585impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
1586 pub fn new() -> Self {
1588 Self {
1589 entries: Vec::new(),
1590 }
1591 }
1592 pub fn insert(&mut self, key: K, val: V) {
1594 match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
1595 Ok(i) => self.entries[i].1 = val,
1596 Err(i) => self.entries.insert(i, (key, val)),
1597 }
1598 }
1599 pub fn get(&self, key: &K) -> Option<&V> {
1601 self.entries
1602 .binary_search_by_key(&key, |(k, _)| k)
1603 .ok()
1604 .map(|i| &self.entries[i].1)
1605 }
1606 pub fn len(&self) -> usize {
1608 self.entries.len()
1609 }
1610 pub fn is_empty(&self) -> bool {
1612 self.entries.is_empty()
1613 }
1614 pub fn keys(&self) -> Vec<&K> {
1616 self.entries.iter().map(|(k, _)| k).collect()
1617 }
1618 pub fn values(&self) -> Vec<&V> {
1620 self.entries.iter().map(|(_, v)| v).collect()
1621 }
1622}
1623#[allow(dead_code)]
1625pub struct SimpleDag {
1626 edges: Vec<Vec<usize>>,
1628}
1629#[allow(dead_code)]
1630impl SimpleDag {
1631 pub fn new(n: usize) -> Self {
1633 Self {
1634 edges: vec![Vec::new(); n],
1635 }
1636 }
1637 pub fn add_edge(&mut self, from: usize, to: usize) {
1639 if from < self.edges.len() {
1640 self.edges[from].push(to);
1641 }
1642 }
1643 pub fn successors(&self, node: usize) -> &[usize] {
1645 self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
1646 }
1647 pub fn can_reach(&self, from: usize, to: usize) -> bool {
1649 let mut visited = vec![false; self.edges.len()];
1650 self.dfs(from, to, &mut visited)
1651 }
1652 fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
1653 if cur == target {
1654 return true;
1655 }
1656 if cur >= visited.len() || visited[cur] {
1657 return false;
1658 }
1659 visited[cur] = true;
1660 for &next in self.successors(cur) {
1661 if self.dfs(next, target, visited) {
1662 return true;
1663 }
1664 }
1665 false
1666 }
1667 pub fn topological_sort(&self) -> Option<Vec<usize>> {
1669 let n = self.edges.len();
1670 let mut in_degree = vec![0usize; n];
1671 for succs in &self.edges {
1672 for &s in succs {
1673 if s < n {
1674 in_degree[s] += 1;
1675 }
1676 }
1677 }
1678 let mut queue: std::collections::VecDeque<usize> =
1679 (0..n).filter(|&i| in_degree[i] == 0).collect();
1680 let mut order = Vec::new();
1681 while let Some(node) = queue.pop_front() {
1682 order.push(node);
1683 for &s in self.successors(node) {
1684 if s < n {
1685 in_degree[s] -= 1;
1686 if in_degree[s] == 0 {
1687 queue.push_back(s);
1688 }
1689 }
1690 }
1691 }
1692 if order.len() == n {
1693 Some(order)
1694 } else {
1695 None
1696 }
1697 }
1698 pub fn num_nodes(&self) -> usize {
1700 self.edges.len()
1701 }
1702}
1703#[allow(dead_code)]
1705pub struct WriteOnce<T> {
1706 value: std::cell::Cell<Option<T>>,
1707}
1708#[allow(dead_code)]
1709impl<T: Copy> WriteOnce<T> {
1710 pub fn new() -> Self {
1712 Self {
1713 value: std::cell::Cell::new(None),
1714 }
1715 }
1716 pub fn write(&self, val: T) -> bool {
1718 if self.value.get().is_some() {
1719 return false;
1720 }
1721 self.value.set(Some(val));
1722 true
1723 }
1724 pub fn read(&self) -> Option<T> {
1726 self.value.get()
1727 }
1728 pub fn is_written(&self) -> bool {
1730 self.value.get().is_some()
1731 }
1732}