1use crate::{Declaration, Environment, KernelError, TypeChecker};
6#[cfg(test)]
7use crate::{Expr, Name};
8
9use super::functions::*;
10use std::collections::HashMap;
11
12#[derive(Debug, Clone)]
17pub struct CheckConfig {
18 pub check_type_is_sort: bool,
20 pub check_value_type: bool,
22 pub check_no_free_vars: bool,
24 pub max_depth: u32,
26 pub allow_axioms: bool,
28}
29impl CheckConfig {
30 pub fn new() -> Self {
32 Self::default()
33 }
34 pub fn lenient() -> Self {
36 CheckConfig {
37 check_type_is_sort: true,
38 check_value_type: false,
39 check_no_free_vars: false,
40 max_depth: 0,
41 allow_axioms: true,
42 }
43 }
44 pub fn strict() -> Self {
46 CheckConfig {
47 check_type_is_sort: true,
48 check_value_type: true,
49 check_no_free_vars: true,
50 max_depth: 500,
51 allow_axioms: false,
52 }
53 }
54}
55pub struct TempEnvScope<'a> {
63 env: &'a mut Environment,
64 added_names: Vec<crate::Name>,
65}
66impl<'a> TempEnvScope<'a> {
67 pub fn new(env: &'a mut Environment) -> Self {
69 TempEnvScope {
70 env,
71 added_names: Vec::new(),
72 }
73 }
74 #[allow(clippy::result_large_err)]
76 pub fn add(&mut self, decl: Declaration) -> Result<(), KernelError> {
77 let name = decl.name().clone();
78 check_declaration(self.env, decl)?;
79 self.added_names.push(name);
80 Ok(())
81 }
82 pub fn env(&self) -> &Environment {
84 self.env
85 }
86 pub fn env_mut(&mut self) -> &mut Environment {
88 self.env
89 }
90 pub fn num_added(&self) -> usize {
92 self.added_names.len()
93 }
94}
95#[allow(dead_code)]
97pub struct WindowIterator<'a, T> {
98 pub(super) data: &'a [T],
99 pub(super) pos: usize,
100 pub(super) window: usize,
101}
102#[allow(dead_code)]
103impl<'a, T> WindowIterator<'a, T> {
104 pub fn new(data: &'a [T], window: usize) -> Self {
106 Self {
107 data,
108 pos: 0,
109 window,
110 }
111 }
112}
113#[derive(Debug, Clone, PartialEq, Eq)]
115pub enum DeclKind {
116 Axiom,
118 Definition,
120 Theorem,
122 Opaque,
124}
125impl DeclKind {
126 pub fn as_str(&self) -> &'static str {
128 match self {
129 DeclKind::Axiom => "axiom",
130 DeclKind::Definition => "def",
131 DeclKind::Theorem => "theorem",
132 DeclKind::Opaque => "opaque",
133 }
134 }
135 pub fn is_proven(&self) -> bool {
137 matches!(self, DeclKind::Theorem)
138 }
139 pub fn is_assumed(&self) -> bool {
141 matches!(self, DeclKind::Axiom)
142 }
143 pub fn is_definition(&self) -> bool {
145 matches!(self, DeclKind::Definition | DeclKind::Opaque)
146 }
147}
148#[derive(Debug, Clone, Default)]
150pub struct CheckStats {
151 pub num_axioms: usize,
153 pub num_definitions: usize,
155 pub num_theorems: usize,
157 pub num_opaques: usize,
159 pub num_failures: usize,
161}
162impl CheckStats {
163 pub fn new() -> Self {
165 Self::default()
166 }
167 pub fn total(&self) -> usize {
169 self.num_axioms + self.num_definitions + self.num_theorems + self.num_opaques
170 }
171 pub fn num_ok(&self) -> usize {
173 self.total()
174 }
175}
176#[allow(dead_code)]
178pub struct PathBuf {
179 components: Vec<String>,
180}
181#[allow(dead_code)]
182impl PathBuf {
183 pub fn new() -> Self {
185 Self {
186 components: Vec::new(),
187 }
188 }
189 pub fn push(&mut self, comp: impl Into<String>) {
191 self.components.push(comp.into());
192 }
193 pub fn pop(&mut self) {
195 self.components.pop();
196 }
197 pub fn as_str(&self) -> String {
199 self.components.join("/")
200 }
201 pub fn depth(&self) -> usize {
203 self.components.len()
204 }
205 pub fn clear(&mut self) {
207 self.components.clear();
208 }
209}
210#[allow(dead_code)]
212pub struct RewriteRuleSet {
213 rules: Vec<RewriteRule>,
214}
215#[allow(dead_code)]
216impl RewriteRuleSet {
217 pub fn new() -> Self {
219 Self { rules: Vec::new() }
220 }
221 pub fn add(&mut self, rule: RewriteRule) {
223 self.rules.push(rule);
224 }
225 pub fn len(&self) -> usize {
227 self.rules.len()
228 }
229 pub fn is_empty(&self) -> bool {
231 self.rules.is_empty()
232 }
233 pub fn conditional_rules(&self) -> Vec<&RewriteRule> {
235 self.rules.iter().filter(|r| r.conditional).collect()
236 }
237 pub fn unconditional_rules(&self) -> Vec<&RewriteRule> {
239 self.rules.iter().filter(|r| !r.conditional).collect()
240 }
241 pub fn get(&self, name: &str) -> Option<&RewriteRule> {
243 self.rules.iter().find(|r| r.name == name)
244 }
245}
246#[allow(dead_code)]
248#[allow(missing_docs)]
249pub enum DecisionNode {
250 Leaf(String),
252 Branch {
254 key: String,
255 val: String,
256 yes_branch: Box<DecisionNode>,
257 no_branch: Box<DecisionNode>,
258 },
259}
260#[allow(dead_code)]
261impl DecisionNode {
262 pub fn evaluate(&self, ctx: &std::collections::HashMap<String, String>) -> &str {
264 match self {
265 DecisionNode::Leaf(action) => action.as_str(),
266 DecisionNode::Branch {
267 key,
268 val,
269 yes_branch,
270 no_branch,
271 } => {
272 let actual = ctx.get(key).map(|s| s.as_str()).unwrap_or("");
273 if actual == val.as_str() {
274 yes_branch.evaluate(ctx)
275 } else {
276 no_branch.evaluate(ctx)
277 }
278 }
279 }
280 }
281 pub fn depth(&self) -> usize {
283 match self {
284 DecisionNode::Leaf(_) => 0,
285 DecisionNode::Branch {
286 yes_branch,
287 no_branch,
288 ..
289 } => 1 + yes_branch.depth().max(no_branch.depth()),
290 }
291 }
292}
293#[allow(dead_code)]
295pub enum Either2<A, B> {
296 First(A),
298 Second(B),
300}
301#[allow(dead_code)]
302impl<A, B> Either2<A, B> {
303 pub fn is_first(&self) -> bool {
305 matches!(self, Either2::First(_))
306 }
307 pub fn is_second(&self) -> bool {
309 matches!(self, Either2::Second(_))
310 }
311 pub fn first(self) -> Option<A> {
313 match self {
314 Either2::First(a) => Some(a),
315 _ => None,
316 }
317 }
318 pub fn second(self) -> Option<B> {
320 match self {
321 Either2::Second(b) => Some(b),
322 _ => None,
323 }
324 }
325 pub fn map_first<C, F: FnOnce(A) -> C>(self, f: F) -> Either2<C, B> {
327 match self {
328 Either2::First(a) => Either2::First(f(a)),
329 Either2::Second(b) => Either2::Second(b),
330 }
331 }
332}
333#[derive(Debug, Clone)]
335pub struct BatchCheckResult {
336 pub num_ok: usize,
338 pub num_failed: usize,
340 pub errors: Vec<(String, String)>,
342}
343impl BatchCheckResult {
344 pub fn all_ok(&self) -> bool {
346 self.num_failed == 0
347 }
348 pub fn total(&self) -> usize {
350 self.num_ok + self.num_failed
351 }
352 pub fn error_messages(&self) -> impl Iterator<Item = String> + '_ {
354 self.errors
355 .iter()
356 .map(|(name, err)| format!("{}: {}", name, err))
357 }
358}
359#[allow(dead_code)]
361pub struct SmallMap<K: Ord + Clone, V: Clone> {
362 entries: Vec<(K, V)>,
363}
364#[allow(dead_code)]
365impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
366 pub fn new() -> Self {
368 Self {
369 entries: Vec::new(),
370 }
371 }
372 pub fn insert(&mut self, key: K, val: V) {
374 match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
375 Ok(i) => self.entries[i].1 = val,
376 Err(i) => self.entries.insert(i, (key, val)),
377 }
378 }
379 pub fn get(&self, key: &K) -> Option<&V> {
381 self.entries
382 .binary_search_by_key(&key, |(k, _)| k)
383 .ok()
384 .map(|i| &self.entries[i].1)
385 }
386 pub fn len(&self) -> usize {
388 self.entries.len()
389 }
390 pub fn is_empty(&self) -> bool {
392 self.entries.is_empty()
393 }
394 pub fn keys(&self) -> Vec<&K> {
396 self.entries.iter().map(|(k, _)| k).collect()
397 }
398 pub fn values(&self) -> Vec<&V> {
400 self.entries.iter().map(|(_, v)| v).collect()
401 }
402}
403#[derive(Debug, Clone)]
405pub struct DeclSummary {
406 pub name: String,
408 pub kind: DeclKind,
410 pub has_body: bool,
412 pub num_univ_params: usize,
414}
415#[allow(dead_code)]
417pub struct RawFnPtr {
418 ptr: usize,
420 arity: usize,
421 name: String,
422}
423#[allow(dead_code)]
424impl RawFnPtr {
425 pub fn new(ptr: usize, arity: usize, name: impl Into<String>) -> Self {
427 Self {
428 ptr,
429 arity,
430 name: name.into(),
431 }
432 }
433 pub fn arity(&self) -> usize {
435 self.arity
436 }
437 pub fn name(&self) -> &str {
439 &self.name
440 }
441 pub fn raw(&self) -> usize {
443 self.ptr
444 }
445}
446#[allow(dead_code)]
448pub struct TokenBucket {
449 capacity: u64,
450 tokens: u64,
451 refill_per_ms: u64,
452 last_refill: std::time::Instant,
453}
454#[allow(dead_code)]
455impl TokenBucket {
456 pub fn new(capacity: u64, refill_per_ms: u64) -> Self {
458 Self {
459 capacity,
460 tokens: capacity,
461 refill_per_ms,
462 last_refill: std::time::Instant::now(),
463 }
464 }
465 pub fn try_consume(&mut self, n: u64) -> bool {
467 self.refill();
468 if self.tokens >= n {
469 self.tokens -= n;
470 true
471 } else {
472 false
473 }
474 }
475 fn refill(&mut self) {
476 let now = std::time::Instant::now();
477 let elapsed_ms = now.duration_since(self.last_refill).as_millis() as u64;
478 if elapsed_ms > 0 {
479 let new_tokens = elapsed_ms * self.refill_per_ms;
480 self.tokens = (self.tokens + new_tokens).min(self.capacity);
481 self.last_refill = now;
482 }
483 }
484 pub fn available(&self) -> u64 {
486 self.tokens
487 }
488 pub fn capacity(&self) -> u64 {
490 self.capacity
491 }
492}
493#[allow(dead_code)]
495pub struct LabelSet {
496 labels: Vec<String>,
497}
498#[allow(dead_code)]
499impl LabelSet {
500 pub fn new() -> Self {
502 Self { labels: Vec::new() }
503 }
504 pub fn add(&mut self, label: impl Into<String>) {
506 let s = label.into();
507 if !self.labels.contains(&s) {
508 self.labels.push(s);
509 }
510 }
511 pub fn has(&self, label: &str) -> bool {
513 self.labels.iter().any(|l| l == label)
514 }
515 pub fn count(&self) -> usize {
517 self.labels.len()
518 }
519 pub fn all(&self) -> &[String] {
521 &self.labels
522 }
523}
524#[allow(dead_code)]
526pub struct SparseVec<T: Default + Clone + PartialEq> {
527 entries: std::collections::HashMap<usize, T>,
528 default_: T,
529 logical_len: usize,
530}
531#[allow(dead_code)]
532impl<T: Default + Clone + PartialEq> SparseVec<T> {
533 pub fn new(len: usize) -> Self {
535 Self {
536 entries: std::collections::HashMap::new(),
537 default_: T::default(),
538 logical_len: len,
539 }
540 }
541 pub fn set(&mut self, idx: usize, val: T) {
543 if val == self.default_ {
544 self.entries.remove(&idx);
545 } else {
546 self.entries.insert(idx, val);
547 }
548 }
549 pub fn get(&self, idx: usize) -> &T {
551 self.entries.get(&idx).unwrap_or(&self.default_)
552 }
553 pub fn len(&self) -> usize {
555 self.logical_len
556 }
557 pub fn is_empty(&self) -> bool {
559 self.len() == 0
560 }
561 pub fn nnz(&self) -> usize {
563 self.entries.len()
564 }
565}
566#[allow(dead_code)]
568pub struct TransitiveClosure {
569 adj: Vec<Vec<usize>>,
570 n: usize,
571}
572#[allow(dead_code)]
573impl TransitiveClosure {
574 pub fn new(n: usize) -> Self {
576 Self {
577 adj: vec![Vec::new(); n],
578 n,
579 }
580 }
581 pub fn add_edge(&mut self, from: usize, to: usize) {
583 if from < self.n {
584 self.adj[from].push(to);
585 }
586 }
587 pub fn reachable_from(&self, start: usize) -> Vec<usize> {
589 let mut visited = vec![false; self.n];
590 let mut queue = std::collections::VecDeque::new();
591 queue.push_back(start);
592 while let Some(node) = queue.pop_front() {
593 if node >= self.n || visited[node] {
594 continue;
595 }
596 visited[node] = true;
597 for &next in &self.adj[node] {
598 queue.push_back(next);
599 }
600 }
601 (0..self.n).filter(|&i| visited[i]).collect()
602 }
603 pub fn can_reach(&self, from: usize, to: usize) -> bool {
605 self.reachable_from(from).contains(&to)
606 }
607}
608#[allow(dead_code)]
610pub struct StatSummary {
611 count: u64,
612 sum: f64,
613 min: f64,
614 max: f64,
615}
616#[allow(dead_code)]
617impl StatSummary {
618 pub fn new() -> Self {
620 Self {
621 count: 0,
622 sum: 0.0,
623 min: f64::INFINITY,
624 max: f64::NEG_INFINITY,
625 }
626 }
627 pub fn record(&mut self, val: f64) {
629 self.count += 1;
630 self.sum += val;
631 if val < self.min {
632 self.min = val;
633 }
634 if val > self.max {
635 self.max = val;
636 }
637 }
638 pub fn mean(&self) -> Option<f64> {
640 if self.count == 0 {
641 None
642 } else {
643 Some(self.sum / self.count as f64)
644 }
645 }
646 pub fn min(&self) -> Option<f64> {
648 if self.count == 0 {
649 None
650 } else {
651 Some(self.min)
652 }
653 }
654 pub fn max(&self) -> Option<f64> {
656 if self.count == 0 {
657 None
658 } else {
659 Some(self.max)
660 }
661 }
662 pub fn count(&self) -> u64 {
664 self.count
665 }
666}
667#[allow(dead_code)]
669pub struct Stopwatch {
670 start: std::time::Instant,
671 splits: Vec<f64>,
672}
673#[allow(dead_code)]
674impl Stopwatch {
675 pub fn start() -> Self {
677 Self {
678 start: std::time::Instant::now(),
679 splits: Vec::new(),
680 }
681 }
682 pub fn split(&mut self) {
684 self.splits.push(self.elapsed_ms());
685 }
686 pub fn elapsed_ms(&self) -> f64 {
688 self.start.elapsed().as_secs_f64() * 1000.0
689 }
690 pub fn splits(&self) -> &[f64] {
692 &self.splits
693 }
694 pub fn num_splits(&self) -> usize {
696 self.splits.len()
697 }
698}
699#[allow(dead_code)]
701pub struct FocusStack<T> {
702 items: Vec<T>,
703}
704#[allow(dead_code)]
705impl<T> FocusStack<T> {
706 pub fn new() -> Self {
708 Self { items: Vec::new() }
709 }
710 pub fn focus(&mut self, item: T) {
712 self.items.push(item);
713 }
714 pub fn blur(&mut self) -> Option<T> {
716 self.items.pop()
717 }
718 pub fn current(&self) -> Option<&T> {
720 self.items.last()
721 }
722 pub fn depth(&self) -> usize {
724 self.items.len()
725 }
726 pub fn is_empty(&self) -> bool {
728 self.items.is_empty()
729 }
730}
731#[derive(Debug, Clone, PartialEq, Eq)]
733pub enum WellFormedResult {
734 Ok,
736 TypeNotSort {
738 description: String,
740 },
741 TypeMismatch {
743 description: String,
745 },
746 FreeVariables {
748 vars: Vec<String>,
750 },
751 DuplicateName {
753 name: String,
755 },
756 UniverseError {
758 description: String,
760 },
761}
762impl WellFormedResult {
763 pub fn is_ok(&self) -> bool {
765 matches!(self, WellFormedResult::Ok)
766 }
767 pub fn description(&self) -> String {
769 match self {
770 WellFormedResult::Ok => "well-formed".to_string(),
771 WellFormedResult::TypeNotSort { description } => {
772 format!("type is not a sort: {}", description)
773 }
774 WellFormedResult::TypeMismatch { description } => {
775 format!("type mismatch: {}", description)
776 }
777 WellFormedResult::FreeVariables { vars } => {
778 format!("free variables: {}", vars.join(", "))
779 }
780 WellFormedResult::DuplicateName { name } => {
781 format!("duplicate declaration: {}", name)
782 }
783 WellFormedResult::UniverseError { description } => {
784 format!("universe error: {}", description)
785 }
786 }
787 }
788}
789#[allow(dead_code)]
791pub struct StringPool {
792 free: Vec<String>,
793}
794#[allow(dead_code)]
795impl StringPool {
796 pub fn new() -> Self {
798 Self { free: Vec::new() }
799 }
800 pub fn take(&mut self) -> String {
802 self.free.pop().unwrap_or_default()
803 }
804 pub fn give(&mut self, mut s: String) {
806 s.clear();
807 self.free.push(s);
808 }
809 pub fn free_count(&self) -> usize {
811 self.free.len()
812 }
813}
814#[allow(dead_code)]
816pub struct NonEmptyVec<T> {
817 head: T,
818 tail: Vec<T>,
819}
820#[allow(dead_code)]
821impl<T> NonEmptyVec<T> {
822 pub fn singleton(val: T) -> Self {
824 Self {
825 head: val,
826 tail: Vec::new(),
827 }
828 }
829 pub fn push(&mut self, val: T) {
831 self.tail.push(val);
832 }
833 pub fn first(&self) -> &T {
835 &self.head
836 }
837 pub fn last(&self) -> &T {
839 self.tail.last().unwrap_or(&self.head)
840 }
841 pub fn len(&self) -> usize {
843 1 + self.tail.len()
844 }
845 pub fn is_empty(&self) -> bool {
847 self.len() == 0
848 }
849 pub fn to_vec(&self) -> Vec<&T> {
851 let mut v = vec![&self.head];
852 v.extend(self.tail.iter());
853 v
854 }
855}
856#[allow(dead_code)]
858pub struct TransformStat {
859 before: StatSummary,
860 after: StatSummary,
861}
862#[allow(dead_code)]
863impl TransformStat {
864 pub fn new() -> Self {
866 Self {
867 before: StatSummary::new(),
868 after: StatSummary::new(),
869 }
870 }
871 pub fn record_before(&mut self, v: f64) {
873 self.before.record(v);
874 }
875 pub fn record_after(&mut self, v: f64) {
877 self.after.record(v);
878 }
879 pub fn mean_ratio(&self) -> Option<f64> {
881 let b = self.before.mean()?;
882 let a = self.after.mean()?;
883 if b.abs() < f64::EPSILON {
884 return None;
885 }
886 Some(a / b)
887 }
888}
889#[allow(dead_code)]
891pub struct SlidingSum {
892 window: Vec<f64>,
893 capacity: usize,
894 pos: usize,
895 sum: f64,
896 count: usize,
897}
898#[allow(dead_code)]
899impl SlidingSum {
900 pub fn new(capacity: usize) -> Self {
902 Self {
903 window: vec![0.0; capacity],
904 capacity,
905 pos: 0,
906 sum: 0.0,
907 count: 0,
908 }
909 }
910 pub fn push(&mut self, val: f64) {
912 let oldest = self.window[self.pos];
913 self.sum -= oldest;
914 self.sum += val;
915 self.window[self.pos] = val;
916 self.pos = (self.pos + 1) % self.capacity;
917 if self.count < self.capacity {
918 self.count += 1;
919 }
920 }
921 pub fn sum(&self) -> f64 {
923 self.sum
924 }
925 pub fn mean(&self) -> Option<f64> {
927 if self.count == 0 {
928 None
929 } else {
930 Some(self.sum / self.count as f64)
931 }
932 }
933 pub fn count(&self) -> usize {
935 self.count
936 }
937}
938#[allow(dead_code)]
940#[allow(missing_docs)]
941pub struct RewriteRule {
942 pub name: String,
944 pub lhs: String,
946 pub rhs: String,
948 pub conditional: bool,
950}
951#[allow(dead_code)]
952impl RewriteRule {
953 pub fn unconditional(
955 name: impl Into<String>,
956 lhs: impl Into<String>,
957 rhs: impl Into<String>,
958 ) -> Self {
959 Self {
960 name: name.into(),
961 lhs: lhs.into(),
962 rhs: rhs.into(),
963 conditional: false,
964 }
965 }
966 pub fn conditional(
968 name: impl Into<String>,
969 lhs: impl Into<String>,
970 rhs: impl Into<String>,
971 ) -> Self {
972 Self {
973 name: name.into(),
974 lhs: lhs.into(),
975 rhs: rhs.into(),
976 conditional: true,
977 }
978 }
979 pub fn display(&self) -> String {
981 format!("{}: {} → {}", self.name, self.lhs, self.rhs)
982 }
983}
984#[allow(dead_code)]
986pub struct WriteOnce<T> {
987 value: std::cell::Cell<Option<T>>,
988}
989#[allow(dead_code)]
990impl<T: Copy> WriteOnce<T> {
991 pub fn new() -> Self {
993 Self {
994 value: std::cell::Cell::new(None),
995 }
996 }
997 pub fn write(&self, val: T) -> bool {
999 if self.value.get().is_some() {
1000 return false;
1001 }
1002 self.value.set(Some(val));
1003 true
1004 }
1005 pub fn read(&self) -> Option<T> {
1007 self.value.get()
1008 }
1009 pub fn is_written(&self) -> bool {
1011 self.value.get().is_some()
1012 }
1013}
1014#[derive(Default)]
1019pub struct EnvBuilder {
1020 env: Environment,
1021 stats: CheckStats,
1022 errors: Vec<(String, String)>,
1023}
1024impl EnvBuilder {
1025 pub fn new() -> Self {
1027 Self::default()
1028 }
1029 pub fn add(&mut self, decl: Declaration) -> bool {
1031 let name = format!("{}", decl.name());
1032 let kind = summarize_declaration(&decl).kind;
1033 match check_declaration(&mut self.env, decl) {
1034 Ok(()) => {
1035 match kind {
1036 DeclKind::Axiom => self.stats.num_axioms += 1,
1037 DeclKind::Definition => self.stats.num_definitions += 1,
1038 DeclKind::Theorem => self.stats.num_theorems += 1,
1039 DeclKind::Opaque => self.stats.num_opaques += 1,
1040 }
1041 true
1042 }
1043 Err(e) => {
1044 self.stats.num_failures += 1;
1045 self.errors.push((name, format!("{:?}", e)));
1046 false
1047 }
1048 }
1049 }
1050 pub fn add_all(&mut self, decls: Vec<Declaration>) -> usize {
1052 decls.into_iter().filter(|d| self.add(d.clone())).count()
1053 }
1054 pub fn build(self) -> (Environment, CheckStats, Vec<(String, String)>) {
1056 (self.env, self.stats, self.errors)
1057 }
1058 pub fn env(&self) -> &Environment {
1060 &self.env
1061 }
1062 pub fn stats(&self) -> &CheckStats {
1064 &self.stats
1065 }
1066 pub fn errors(&self) -> &[(String, String)] {
1068 &self.errors
1069 }
1070 pub fn is_clean(&self) -> bool {
1072 self.errors.is_empty()
1073 }
1074}
1075#[allow(dead_code)]
1077pub struct FlatSubstitution {
1078 pairs: Vec<(String, String)>,
1079}
1080#[allow(dead_code)]
1081impl FlatSubstitution {
1082 pub fn new() -> Self {
1084 Self { pairs: Vec::new() }
1085 }
1086 pub fn add(&mut self, from: impl Into<String>, to: impl Into<String>) {
1088 self.pairs.push((from.into(), to.into()));
1089 }
1090 pub fn apply(&self, s: &str) -> String {
1092 let mut result = s.to_string();
1093 for (from, to) in &self.pairs {
1094 result = result.replace(from.as_str(), to.as_str());
1095 }
1096 result
1097 }
1098 pub fn len(&self) -> usize {
1100 self.pairs.len()
1101 }
1102 pub fn is_empty(&self) -> bool {
1104 self.pairs.is_empty()
1105 }
1106}
1107#[allow(dead_code)]
1109pub struct ConfigNode {
1110 key: String,
1111 value: Option<String>,
1112 children: Vec<ConfigNode>,
1113}
1114#[allow(dead_code)]
1115impl ConfigNode {
1116 pub fn leaf(key: impl Into<String>, value: impl Into<String>) -> Self {
1118 Self {
1119 key: key.into(),
1120 value: Some(value.into()),
1121 children: Vec::new(),
1122 }
1123 }
1124 pub fn section(key: impl Into<String>) -> Self {
1126 Self {
1127 key: key.into(),
1128 value: None,
1129 children: Vec::new(),
1130 }
1131 }
1132 pub fn add_child(&mut self, child: ConfigNode) {
1134 self.children.push(child);
1135 }
1136 pub fn key(&self) -> &str {
1138 &self.key
1139 }
1140 pub fn value(&self) -> Option<&str> {
1142 self.value.as_deref()
1143 }
1144 pub fn num_children(&self) -> usize {
1146 self.children.len()
1147 }
1148 pub fn lookup(&self, path: &str) -> Option<&str> {
1150 let mut parts = path.splitn(2, '.');
1151 let head = parts.next()?;
1152 let tail = parts.next();
1153 if head != self.key {
1154 return None;
1155 }
1156 match tail {
1157 None => self.value.as_deref(),
1158 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
1159 }
1160 }
1161 fn lookup_relative(&self, path: &str) -> Option<&str> {
1162 let mut parts = path.splitn(2, '.');
1163 let head = parts.next()?;
1164 let tail = parts.next();
1165 if head != self.key {
1166 return None;
1167 }
1168 match tail {
1169 None => self.value.as_deref(),
1170 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
1171 }
1172 }
1173}
1174#[allow(dead_code)]
1176pub struct StackCalc {
1177 stack: Vec<i64>,
1178}
1179#[allow(dead_code)]
1180impl StackCalc {
1181 pub fn new() -> Self {
1183 Self { stack: Vec::new() }
1184 }
1185 pub fn push(&mut self, n: i64) {
1187 self.stack.push(n);
1188 }
1189 pub fn add(&mut self) {
1191 let b = self
1192 .stack
1193 .pop()
1194 .expect("stack must have at least two values for add");
1195 let a = self
1196 .stack
1197 .pop()
1198 .expect("stack must have at least two values for add");
1199 self.stack.push(a + b);
1200 }
1201 pub fn sub(&mut self) {
1203 let b = self
1204 .stack
1205 .pop()
1206 .expect("stack must have at least two values for sub");
1207 let a = self
1208 .stack
1209 .pop()
1210 .expect("stack must have at least two values for sub");
1211 self.stack.push(a - b);
1212 }
1213 pub fn mul(&mut self) {
1215 let b = self
1216 .stack
1217 .pop()
1218 .expect("stack must have at least two values for mul");
1219 let a = self
1220 .stack
1221 .pop()
1222 .expect("stack must have at least two values for mul");
1223 self.stack.push(a * b);
1224 }
1225 pub fn peek(&self) -> Option<i64> {
1227 self.stack.last().copied()
1228 }
1229 pub fn depth(&self) -> usize {
1231 self.stack.len()
1232 }
1233}
1234#[allow(dead_code)]
1236pub struct SimpleDag {
1237 edges: Vec<Vec<usize>>,
1239}
1240#[allow(dead_code)]
1241impl SimpleDag {
1242 pub fn new(n: usize) -> Self {
1244 Self {
1245 edges: vec![Vec::new(); n],
1246 }
1247 }
1248 pub fn add_edge(&mut self, from: usize, to: usize) {
1250 if from < self.edges.len() {
1251 self.edges[from].push(to);
1252 }
1253 }
1254 pub fn successors(&self, node: usize) -> &[usize] {
1256 self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
1257 }
1258 pub fn can_reach(&self, from: usize, to: usize) -> bool {
1260 let mut visited = vec![false; self.edges.len()];
1261 self.dfs(from, to, &mut visited)
1262 }
1263 fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
1264 if cur == target {
1265 return true;
1266 }
1267 if cur >= visited.len() || visited[cur] {
1268 return false;
1269 }
1270 visited[cur] = true;
1271 for &next in self.successors(cur) {
1272 if self.dfs(next, target, visited) {
1273 return true;
1274 }
1275 }
1276 false
1277 }
1278 pub fn topological_sort(&self) -> Option<Vec<usize>> {
1280 let n = self.edges.len();
1281 let mut in_degree = vec![0usize; n];
1282 for succs in &self.edges {
1283 for &s in succs {
1284 if s < n {
1285 in_degree[s] += 1;
1286 }
1287 }
1288 }
1289 let mut queue: std::collections::VecDeque<usize> =
1290 (0..n).filter(|&i| in_degree[i] == 0).collect();
1291 let mut order = Vec::new();
1292 while let Some(node) = queue.pop_front() {
1293 order.push(node);
1294 for &s in self.successors(node) {
1295 if s < n {
1296 in_degree[s] -= 1;
1297 if in_degree[s] == 0 {
1298 queue.push_back(s);
1299 }
1300 }
1301 }
1302 }
1303 if order.len() == n {
1304 Some(order)
1305 } else {
1306 None
1307 }
1308 }
1309 pub fn num_nodes(&self) -> usize {
1311 self.edges.len()
1312 }
1313}
1314#[allow(dead_code)]
1316pub struct VersionedRecord<T: Clone> {
1317 history: Vec<T>,
1318}
1319#[allow(dead_code)]
1320impl<T: Clone> VersionedRecord<T> {
1321 pub fn new(initial: T) -> Self {
1323 Self {
1324 history: vec![initial],
1325 }
1326 }
1327 pub fn update(&mut self, val: T) {
1329 self.history.push(val);
1330 }
1331 pub fn current(&self) -> &T {
1333 self.history
1334 .last()
1335 .expect("VersionedRecord history is always non-empty after construction")
1336 }
1337 pub fn at_version(&self, n: usize) -> Option<&T> {
1339 self.history.get(n)
1340 }
1341 pub fn version(&self) -> usize {
1343 self.history.len() - 1
1344 }
1345 pub fn has_history(&self) -> bool {
1347 self.history.len() > 1
1348 }
1349}