Skip to main content

oxilean_kernel/level/
types.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use crate::Name;
6
7use std::collections::HashMap;
8
9use super::functions::{is_equivalent, is_leq};
10
11/// A simple decision tree node for rule dispatching.
12#[allow(dead_code)]
13#[allow(missing_docs)]
14pub enum DecisionNode {
15    /// A leaf with an action string.
16    Leaf(String),
17    /// An interior node: check `key` equals `val` → `yes_branch`, else `no_branch`.
18    Branch {
19        key: String,
20        val: String,
21        yes_branch: Box<DecisionNode>,
22        no_branch: Box<DecisionNode>,
23    },
24}
25#[allow(dead_code)]
26impl DecisionNode {
27    /// Evaluates the decision tree with the given context.
28    pub fn evaluate(&self, ctx: &std::collections::HashMap<String, String>) -> &str {
29        match self {
30            DecisionNode::Leaf(action) => action.as_str(),
31            DecisionNode::Branch {
32                key,
33                val,
34                yes_branch,
35                no_branch,
36            } => {
37                let actual = ctx.get(key).map(|s| s.as_str()).unwrap_or("");
38                if actual == val.as_str() {
39                    yes_branch.evaluate(ctx)
40                } else {
41                    no_branch.evaluate(ctx)
42                }
43            }
44        }
45    }
46    /// Returns the depth of the decision tree.
47    pub fn depth(&self) -> usize {
48        match self {
49            DecisionNode::Leaf(_) => 0,
50            DecisionNode::Branch {
51                yes_branch,
52                no_branch,
53                ..
54            } => 1 + yes_branch.depth().max(no_branch.depth()),
55        }
56    }
57}
58/// A flat list of substitution pairs `(from, to)`.
59#[allow(dead_code)]
60pub struct FlatSubstitution {
61    pairs: Vec<(String, String)>,
62}
63#[allow(dead_code)]
64impl FlatSubstitution {
65    /// Creates an empty substitution.
66    pub fn new() -> Self {
67        Self { pairs: Vec::new() }
68    }
69    /// Adds a pair.
70    pub fn add(&mut self, from: impl Into<String>, to: impl Into<String>) {
71        self.pairs.push((from.into(), to.into()));
72    }
73    /// Applies all substitutions to `s` (leftmost-first order).
74    pub fn apply(&self, s: &str) -> String {
75        let mut result = s.to_string();
76        for (from, to) in &self.pairs {
77            result = result.replace(from.as_str(), to.as_str());
78        }
79        result
80    }
81    /// Returns the number of pairs.
82    pub fn len(&self) -> usize {
83        self.pairs.len()
84    }
85    /// Returns `true` if empty.
86    pub fn is_empty(&self) -> bool {
87        self.pairs.is_empty()
88    }
89}
90/// A level constraint: an assertion that l1 ≤ l2 or l1 = l2.
91#[allow(dead_code)]
92#[derive(Debug, Clone, PartialEq)]
93pub enum LevelConstraint {
94    /// l1 ≤ l2
95    Leq(Level, Level),
96    /// l1 = l2 (syntactic equality after normalization)
97    Eq(Level, Level),
98}
99impl LevelConstraint {
100    /// Check whether this constraint is satisfied.
101    ///
102    /// Uses `is_leq` / `is_equivalent` from this module.
103    #[allow(dead_code)]
104    pub fn is_satisfied(&self) -> bool {
105        match self {
106            LevelConstraint::Leq(l1, l2) => is_leq(l1, l2),
107            LevelConstraint::Eq(l1, l2) => is_equivalent(l1, l2),
108        }
109    }
110    /// Return both levels involved in this constraint.
111    #[allow(dead_code)]
112    pub fn levels(&self) -> (&Level, &Level) {
113        match self {
114            LevelConstraint::Leq(l1, l2) | LevelConstraint::Eq(l1, l2) => (l1, l2),
115        }
116    }
117}
118/// A hierarchical configuration tree.
119#[allow(dead_code)]
120pub struct ConfigNode {
121    key: String,
122    value: Option<String>,
123    children: Vec<ConfigNode>,
124}
125#[allow(dead_code)]
126impl ConfigNode {
127    /// Creates a leaf config node with a value.
128    pub fn leaf(key: impl Into<String>, value: impl Into<String>) -> Self {
129        Self {
130            key: key.into(),
131            value: Some(value.into()),
132            children: Vec::new(),
133        }
134    }
135    /// Creates a section node with children.
136    pub fn section(key: impl Into<String>) -> Self {
137        Self {
138            key: key.into(),
139            value: None,
140            children: Vec::new(),
141        }
142    }
143    /// Adds a child node.
144    pub fn add_child(&mut self, child: ConfigNode) {
145        self.children.push(child);
146    }
147    /// Returns the key.
148    pub fn key(&self) -> &str {
149        &self.key
150    }
151    /// Returns the value, or `None` for section nodes.
152    pub fn value(&self) -> Option<&str> {
153        self.value.as_deref()
154    }
155    /// Returns the number of children.
156    pub fn num_children(&self) -> usize {
157        self.children.len()
158    }
159    /// Looks up a dot-separated path.
160    pub fn lookup(&self, path: &str) -> Option<&str> {
161        let mut parts = path.splitn(2, '.');
162        let head = parts.next()?;
163        let tail = parts.next();
164        if head != self.key {
165            return None;
166        }
167        match tail {
168            None => self.value.as_deref(),
169            Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
170        }
171    }
172    fn lookup_relative(&self, path: &str) -> Option<&str> {
173        let mut parts = path.splitn(2, '.');
174        let head = parts.next()?;
175        let tail = parts.next();
176        if head != self.key {
177            return None;
178        }
179        match tail {
180            None => self.value.as_deref(),
181            Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
182        }
183    }
184}
185/// A window iterator that yields overlapping windows of size `n`.
186#[allow(dead_code)]
187pub struct WindowIterator<'a, T> {
188    pub(super) data: &'a [T],
189    pub(super) pos: usize,
190    pub(super) window: usize,
191}
192#[allow(dead_code)]
193impl<'a, T> WindowIterator<'a, T> {
194    /// Creates a new window iterator.
195    pub fn new(data: &'a [T], window: usize) -> Self {
196        Self {
197            data,
198            pos: 0,
199            window,
200        }
201    }
202}
203/// A counter that can measure elapsed time between snapshots.
204#[allow(dead_code)]
205pub struct Stopwatch {
206    start: std::time::Instant,
207    splits: Vec<f64>,
208}
209#[allow(dead_code)]
210impl Stopwatch {
211    /// Creates and starts a new stopwatch.
212    pub fn start() -> Self {
213        Self {
214            start: std::time::Instant::now(),
215            splits: Vec::new(),
216        }
217    }
218    /// Records a split time (elapsed since start).
219    pub fn split(&mut self) {
220        self.splits.push(self.elapsed_ms());
221    }
222    /// Returns total elapsed milliseconds since start.
223    pub fn elapsed_ms(&self) -> f64 {
224        self.start.elapsed().as_secs_f64() * 1000.0
225    }
226    /// Returns all recorded split times.
227    pub fn splits(&self) -> &[f64] {
228        &self.splits
229    }
230    /// Returns the number of splits.
231    pub fn num_splits(&self) -> usize {
232        self.splits.len()
233    }
234}
235/// A write-once cell.
236#[allow(dead_code)]
237pub struct WriteOnce<T> {
238    value: std::cell::Cell<Option<T>>,
239}
240#[allow(dead_code)]
241impl<T: Copy> WriteOnce<T> {
242    /// Creates an empty write-once cell.
243    pub fn new() -> Self {
244        Self {
245            value: std::cell::Cell::new(None),
246        }
247    }
248    /// Writes a value.  Returns `false` if already written.
249    pub fn write(&self, val: T) -> bool {
250        if self.value.get().is_some() {
251            return false;
252        }
253        self.value.set(Some(val));
254        true
255    }
256    /// Returns the value if written.
257    pub fn read(&self) -> Option<T> {
258        self.value.get()
259    }
260    /// Returns `true` if the value has been written.
261    pub fn is_written(&self) -> bool {
262        self.value.get().is_some()
263    }
264}
265/// A tagged union for representing a simple two-case discriminated union.
266#[allow(dead_code)]
267pub enum Either2<A, B> {
268    /// The first alternative.
269    First(A),
270    /// The second alternative.
271    Second(B),
272}
273#[allow(dead_code)]
274impl<A, B> Either2<A, B> {
275    /// Returns `true` if this is the first alternative.
276    pub fn is_first(&self) -> bool {
277        matches!(self, Either2::First(_))
278    }
279    /// Returns `true` if this is the second alternative.
280    pub fn is_second(&self) -> bool {
281        matches!(self, Either2::Second(_))
282    }
283    /// Returns the first value if present.
284    pub fn first(self) -> Option<A> {
285        match self {
286            Either2::First(a) => Some(a),
287            _ => None,
288        }
289    }
290    /// Returns the second value if present.
291    pub fn second(self) -> Option<B> {
292        match self {
293            Either2::Second(b) => Some(b),
294            _ => None,
295        }
296    }
297    /// Maps over the first alternative.
298    pub fn map_first<C, F: FnOnce(A) -> C>(self, f: F) -> Either2<C, B> {
299        match self {
300            Either2::First(a) => Either2::First(f(a)),
301            Either2::Second(b) => Either2::Second(b),
302        }
303    }
304}
305/// A versioned record that stores a history of values.
306#[allow(dead_code)]
307pub struct VersionedRecord<T: Clone> {
308    history: Vec<T>,
309}
310#[allow(dead_code)]
311impl<T: Clone> VersionedRecord<T> {
312    /// Creates a new record with an initial value.
313    pub fn new(initial: T) -> Self {
314        Self {
315            history: vec![initial],
316        }
317    }
318    /// Updates the record with a new version.
319    pub fn update(&mut self, val: T) {
320        self.history.push(val);
321    }
322    /// Returns the current (latest) value.
323    pub fn current(&self) -> &T {
324        self.history
325            .last()
326            .expect("VersionedRecord history is always non-empty after construction")
327    }
328    /// Returns the value at version `n` (0-indexed), or `None`.
329    pub fn at_version(&self, n: usize) -> Option<&T> {
330        self.history.get(n)
331    }
332    /// Returns the version number of the current value.
333    pub fn version(&self) -> usize {
334        self.history.len() - 1
335    }
336    /// Returns `true` if more than one version exists.
337    pub fn has_history(&self) -> bool {
338        self.history.len() > 1
339    }
340}
341/// A simple mutable key-value store for test fixtures.
342#[allow(dead_code)]
343pub struct Fixture {
344    data: std::collections::HashMap<String, String>,
345}
346#[allow(dead_code)]
347impl Fixture {
348    /// Creates an empty fixture.
349    pub fn new() -> Self {
350        Self {
351            data: std::collections::HashMap::new(),
352        }
353    }
354    /// Sets a key.
355    pub fn set(&mut self, key: impl Into<String>, val: impl Into<String>) {
356        self.data.insert(key.into(), val.into());
357    }
358    /// Gets a value.
359    pub fn get(&self, key: &str) -> Option<&str> {
360        self.data.get(key).map(|s| s.as_str())
361    }
362    /// Returns the number of entries.
363    pub fn len(&self) -> usize {
364        self.data.len()
365    }
366    /// Returns whether the collection is empty.
367    pub fn is_empty(&self) -> bool {
368        self.len() == 0
369    }
370}
371/// A type-erased function pointer with arity tracking.
372#[allow(dead_code)]
373pub struct RawFnPtr {
374    /// The raw function pointer (stored as usize for type erasure).
375    ptr: usize,
376    arity: usize,
377    name: String,
378}
379#[allow(dead_code)]
380impl RawFnPtr {
381    /// Creates a new raw function pointer descriptor.
382    pub fn new(ptr: usize, arity: usize, name: impl Into<String>) -> Self {
383        Self {
384            ptr,
385            arity,
386            name: name.into(),
387        }
388    }
389    /// Returns the arity.
390    pub fn arity(&self) -> usize {
391        self.arity
392    }
393    /// Returns the name.
394    pub fn name(&self) -> &str {
395        &self.name
396    }
397    /// Returns the raw pointer value.
398    pub fn raw(&self) -> usize {
399        self.ptr
400    }
401}
402/// A mutable reference stack for tracking the current "focus" in a tree traversal.
403#[allow(dead_code)]
404pub struct FocusStack<T> {
405    items: Vec<T>,
406}
407#[allow(dead_code)]
408impl<T> FocusStack<T> {
409    /// Creates an empty focus stack.
410    pub fn new() -> Self {
411        Self { items: Vec::new() }
412    }
413    /// Focuses on `item`.
414    pub fn focus(&mut self, item: T) {
415        self.items.push(item);
416    }
417    /// Blurs (pops) the current focus.
418    pub fn blur(&mut self) -> Option<T> {
419        self.items.pop()
420    }
421    /// Returns the current focus, or `None`.
422    pub fn current(&self) -> Option<&T> {
423        self.items.last()
424    }
425    /// Returns the focus depth.
426    pub fn depth(&self) -> usize {
427        self.items.len()
428    }
429    /// Returns `true` if there is no current focus.
430    pub fn is_empty(&self) -> bool {
431        self.items.is_empty()
432    }
433}
434/// A dependency closure builder (transitive closure via BFS).
435#[allow(dead_code)]
436pub struct TransitiveClosure {
437    adj: Vec<Vec<usize>>,
438    n: usize,
439}
440#[allow(dead_code)]
441impl TransitiveClosure {
442    /// Creates a transitive closure builder for `n` nodes.
443    pub fn new(n: usize) -> Self {
444        Self {
445            adj: vec![Vec::new(); n],
446            n,
447        }
448    }
449    /// Adds a direct edge.
450    pub fn add_edge(&mut self, from: usize, to: usize) {
451        if from < self.n {
452            self.adj[from].push(to);
453        }
454    }
455    /// Computes all nodes reachable from `start` (including `start`).
456    pub fn reachable_from(&self, start: usize) -> Vec<usize> {
457        let mut visited = vec![false; self.n];
458        let mut queue = std::collections::VecDeque::new();
459        queue.push_back(start);
460        while let Some(node) = queue.pop_front() {
461            if node >= self.n || visited[node] {
462                continue;
463            }
464            visited[node] = true;
465            for &next in &self.adj[node] {
466                queue.push_back(next);
467            }
468        }
469        (0..self.n).filter(|&i| visited[i]).collect()
470    }
471    /// Returns `true` if `from` can transitively reach `to`.
472    pub fn can_reach(&self, from: usize, to: usize) -> bool {
473        self.reachable_from(from).contains(&to)
474    }
475}
476/// A label set for a graph node.
477#[allow(dead_code)]
478pub struct LabelSet {
479    labels: Vec<String>,
480}
481#[allow(dead_code)]
482impl LabelSet {
483    /// Creates a new empty label set.
484    pub fn new() -> Self {
485        Self { labels: Vec::new() }
486    }
487    /// Adds a label (deduplicates).
488    pub fn add(&mut self, label: impl Into<String>) {
489        let s = label.into();
490        if !self.labels.contains(&s) {
491            self.labels.push(s);
492        }
493    }
494    /// Returns `true` if `label` is present.
495    pub fn has(&self, label: &str) -> bool {
496        self.labels.iter().any(|l| l == label)
497    }
498    /// Returns the count of labels.
499    pub fn count(&self) -> usize {
500        self.labels.len()
501    }
502    /// Returns all labels.
503    pub fn all(&self) -> &[String] {
504        &self.labels
505    }
506}
507/// A set of rewrite rules.
508#[allow(dead_code)]
509pub struct RewriteRuleSet {
510    rules: Vec<RewriteRule>,
511}
512#[allow(dead_code)]
513impl RewriteRuleSet {
514    /// Creates an empty rule set.
515    pub fn new() -> Self {
516        Self { rules: Vec::new() }
517    }
518    /// Adds a rule.
519    pub fn add(&mut self, rule: RewriteRule) {
520        self.rules.push(rule);
521    }
522    /// Returns the number of rules.
523    pub fn len(&self) -> usize {
524        self.rules.len()
525    }
526    /// Returns `true` if the set is empty.
527    pub fn is_empty(&self) -> bool {
528        self.rules.is_empty()
529    }
530    /// Returns all conditional rules.
531    pub fn conditional_rules(&self) -> Vec<&RewriteRule> {
532        self.rules.iter().filter(|r| r.conditional).collect()
533    }
534    /// Returns all unconditional rules.
535    pub fn unconditional_rules(&self) -> Vec<&RewriteRule> {
536        self.rules.iter().filter(|r| !r.conditional).collect()
537    }
538    /// Looks up a rule by name.
539    pub fn get(&self, name: &str) -> Option<&RewriteRule> {
540        self.rules.iter().find(|r| r.name == name)
541    }
542}
543/// A simple key-value store backed by a sorted Vec for small maps.
544#[allow(dead_code)]
545pub struct SmallMap<K: Ord + Clone, V: Clone> {
546    entries: Vec<(K, V)>,
547}
548#[allow(dead_code)]
549impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
550    /// Creates a new empty small map.
551    pub fn new() -> Self {
552        Self {
553            entries: Vec::new(),
554        }
555    }
556    /// Inserts or replaces the value for `key`.
557    pub fn insert(&mut self, key: K, val: V) {
558        match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
559            Ok(i) => self.entries[i].1 = val,
560            Err(i) => self.entries.insert(i, (key, val)),
561        }
562    }
563    /// Returns the value for `key`, or `None`.
564    pub fn get(&self, key: &K) -> Option<&V> {
565        self.entries
566            .binary_search_by_key(&key, |(k, _)| k)
567            .ok()
568            .map(|i| &self.entries[i].1)
569    }
570    /// Returns the number of entries.
571    pub fn len(&self) -> usize {
572        self.entries.len()
573    }
574    /// Returns `true` if empty.
575    pub fn is_empty(&self) -> bool {
576        self.entries.is_empty()
577    }
578    /// Returns all keys.
579    pub fn keys(&self) -> Vec<&K> {
580        self.entries.iter().map(|(k, _)| k).collect()
581    }
582    /// Returns all values.
583    pub fn values(&self) -> Vec<&V> {
584        self.entries.iter().map(|(_, v)| v).collect()
585    }
586}
587/// A token bucket rate limiter.
588#[allow(dead_code)]
589pub struct TokenBucket {
590    capacity: u64,
591    tokens: u64,
592    refill_per_ms: u64,
593    last_refill: std::time::Instant,
594}
595#[allow(dead_code)]
596impl TokenBucket {
597    /// Creates a new token bucket.
598    pub fn new(capacity: u64, refill_per_ms: u64) -> Self {
599        Self {
600            capacity,
601            tokens: capacity,
602            refill_per_ms,
603            last_refill: std::time::Instant::now(),
604        }
605    }
606    /// Attempts to consume `n` tokens.  Returns `true` on success.
607    pub fn try_consume(&mut self, n: u64) -> bool {
608        self.refill();
609        if self.tokens >= n {
610            self.tokens -= n;
611            true
612        } else {
613            false
614        }
615    }
616    fn refill(&mut self) {
617        let now = std::time::Instant::now();
618        let elapsed_ms = now.duration_since(self.last_refill).as_millis() as u64;
619        if elapsed_ms > 0 {
620            let new_tokens = elapsed_ms * self.refill_per_ms;
621            self.tokens = (self.tokens + new_tokens).min(self.capacity);
622            self.last_refill = now;
623        }
624    }
625    /// Returns the number of currently available tokens.
626    pub fn available(&self) -> u64 {
627        self.tokens
628    }
629    /// Returns the bucket capacity.
630    pub fn capacity(&self) -> u64 {
631        self.capacity
632    }
633}
634/// A simple stack-based calculator for arithmetic expressions.
635#[allow(dead_code)]
636pub struct StackCalc {
637    stack: Vec<i64>,
638}
639#[allow(dead_code)]
640impl StackCalc {
641    /// Creates a new empty calculator.
642    pub fn new() -> Self {
643        Self { stack: Vec::new() }
644    }
645    /// Pushes an integer literal.
646    pub fn push(&mut self, n: i64) {
647        self.stack.push(n);
648    }
649    /// Adds the top two values.  Panics if fewer than two values.
650    pub fn add(&mut self) {
651        let b = self
652            .stack
653            .pop()
654            .expect("stack must have at least two values for add");
655        let a = self
656            .stack
657            .pop()
658            .expect("stack must have at least two values for add");
659        self.stack.push(a + b);
660    }
661    /// Subtracts top from second.
662    pub fn sub(&mut self) {
663        let b = self
664            .stack
665            .pop()
666            .expect("stack must have at least two values for sub");
667        let a = self
668            .stack
669            .pop()
670            .expect("stack must have at least two values for sub");
671        self.stack.push(a - b);
672    }
673    /// Multiplies the top two values.
674    pub fn mul(&mut self) {
675        let b = self
676            .stack
677            .pop()
678            .expect("stack must have at least two values for mul");
679        let a = self
680            .stack
681            .pop()
682            .expect("stack must have at least two values for mul");
683        self.stack.push(a * b);
684    }
685    /// Peeks the top value.
686    pub fn peek(&self) -> Option<i64> {
687        self.stack.last().copied()
688    }
689    /// Returns the stack depth.
690    pub fn depth(&self) -> usize {
691        self.stack.len()
692    }
693}
694/// Represents a rewrite rule `lhs → rhs`.
695#[allow(dead_code)]
696#[allow(missing_docs)]
697pub struct RewriteRule {
698    /// The name of the rule.
699    pub name: String,
700    /// A string representation of the LHS pattern.
701    pub lhs: String,
702    /// A string representation of the RHS.
703    pub rhs: String,
704    /// Whether this is a conditional rule (has side conditions).
705    pub conditional: bool,
706}
707#[allow(dead_code)]
708impl RewriteRule {
709    /// Creates an unconditional rewrite rule.
710    pub fn unconditional(
711        name: impl Into<String>,
712        lhs: impl Into<String>,
713        rhs: impl Into<String>,
714    ) -> Self {
715        Self {
716            name: name.into(),
717            lhs: lhs.into(),
718            rhs: rhs.into(),
719            conditional: false,
720        }
721    }
722    /// Creates a conditional rewrite rule.
723    pub fn conditional(
724        name: impl Into<String>,
725        lhs: impl Into<String>,
726        rhs: impl Into<String>,
727    ) -> Self {
728        Self {
729            name: name.into(),
730            lhs: lhs.into(),
731            rhs: rhs.into(),
732            conditional: true,
733        }
734    }
735    /// Returns a textual representation.
736    pub fn display(&self) -> String {
737        format!("{}: {} → {}", self.name, self.lhs, self.rhs)
738    }
739}
740/// A constraint set: a collection of level constraints.
741#[allow(dead_code)]
742#[derive(Debug, Default, Clone)]
743pub struct ConstraintSet {
744    constraints: Vec<LevelConstraint>,
745}
746impl ConstraintSet {
747    /// Create an empty constraint set.
748    #[allow(dead_code)]
749    pub fn new() -> Self {
750        Self::default()
751    }
752    /// Add a constraint.
753    #[allow(dead_code)]
754    pub fn add(&mut self, c: LevelConstraint) {
755        self.constraints.push(c);
756    }
757    /// Add a ≤ constraint.
758    #[allow(dead_code)]
759    pub fn add_leq(&mut self, l1: Level, l2: Level) {
760        self.add(LevelConstraint::Leq(l1, l2));
761    }
762    /// Add an = constraint.
763    #[allow(dead_code)]
764    pub fn add_eq(&mut self, l1: Level, l2: Level) {
765        self.add(LevelConstraint::Eq(l1, l2));
766    }
767    /// Check if all constraints are satisfied.
768    #[allow(dead_code)]
769    pub fn all_satisfied(&self) -> bool {
770        self.constraints.iter().all(|c| c.is_satisfied())
771    }
772    /// Return unsatisfied constraints.
773    #[allow(dead_code)]
774    pub fn unsatisfied(&self) -> Vec<&LevelConstraint> {
775        self.constraints
776            .iter()
777            .filter(|c| !c.is_satisfied())
778            .collect()
779    }
780    /// Number of constraints.
781    #[allow(dead_code)]
782    pub fn len(&self) -> usize {
783        self.constraints.len()
784    }
785    /// Whether the set is empty.
786    #[allow(dead_code)]
787    pub fn is_empty(&self) -> bool {
788        self.constraints.is_empty()
789    }
790}
791/// A fixed-size sliding window that computes a running sum.
792#[allow(dead_code)]
793pub struct SlidingSum {
794    window: Vec<f64>,
795    capacity: usize,
796    pos: usize,
797    sum: f64,
798    count: usize,
799}
800#[allow(dead_code)]
801impl SlidingSum {
802    /// Creates a sliding sum with the given window size.
803    pub fn new(capacity: usize) -> Self {
804        Self {
805            window: vec![0.0; capacity],
806            capacity,
807            pos: 0,
808            sum: 0.0,
809            count: 0,
810        }
811    }
812    /// Adds a value to the window, removing the oldest if full.
813    pub fn push(&mut self, val: f64) {
814        let oldest = self.window[self.pos];
815        self.sum -= oldest;
816        self.sum += val;
817        self.window[self.pos] = val;
818        self.pos = (self.pos + 1) % self.capacity;
819        if self.count < self.capacity {
820            self.count += 1;
821        }
822    }
823    /// Returns the current window sum.
824    pub fn sum(&self) -> f64 {
825        self.sum
826    }
827    /// Returns the window mean, or `None` if empty.
828    pub fn mean(&self) -> Option<f64> {
829        if self.count == 0 {
830            None
831        } else {
832            Some(self.sum / self.count as f64)
833        }
834    }
835    /// Returns the current window size (number of valid elements).
836    pub fn count(&self) -> usize {
837        self.count
838    }
839}
840/// A reusable scratch buffer for path computations.
841#[allow(dead_code)]
842pub struct PathBuf {
843    components: Vec<String>,
844}
845#[allow(dead_code)]
846impl PathBuf {
847    /// Creates a new empty path buffer.
848    pub fn new() -> Self {
849        Self {
850            components: Vec::new(),
851        }
852    }
853    /// Pushes a component.
854    pub fn push(&mut self, comp: impl Into<String>) {
855        self.components.push(comp.into());
856    }
857    /// Pops the last component.
858    pub fn pop(&mut self) {
859        self.components.pop();
860    }
861    /// Returns the current path as a `/`-separated string.
862    pub fn as_str(&self) -> String {
863        self.components.join("/")
864    }
865    /// Returns the depth of the path.
866    pub fn depth(&self) -> usize {
867        self.components.len()
868    }
869    /// Clears the path.
870    pub fn clear(&mut self) {
871        self.components.clear();
872    }
873}
874/// A non-empty list (at least one element guaranteed).
875#[allow(dead_code)]
876pub struct NonEmptyVec<T> {
877    head: T,
878    tail: Vec<T>,
879}
880#[allow(dead_code)]
881impl<T> NonEmptyVec<T> {
882    /// Creates a non-empty vec with a single element.
883    pub fn singleton(val: T) -> Self {
884        Self {
885            head: val,
886            tail: Vec::new(),
887        }
888    }
889    /// Pushes an element.
890    pub fn push(&mut self, val: T) {
891        self.tail.push(val);
892    }
893    /// Returns a reference to the first element.
894    pub fn first(&self) -> &T {
895        &self.head
896    }
897    /// Returns a reference to the last element.
898    pub fn last(&self) -> &T {
899        self.tail.last().unwrap_or(&self.head)
900    }
901    /// Returns the number of elements.
902    pub fn len(&self) -> usize {
903        1 + self.tail.len()
904    }
905    /// Returns whether the collection is empty.
906    pub fn is_empty(&self) -> bool {
907        self.len() == 0
908    }
909    /// Returns all elements as a Vec.
910    pub fn to_vec(&self) -> Vec<&T> {
911        let mut v = vec![&self.head];
912        v.extend(self.tail.iter());
913        v
914    }
915}
916/// A pool of reusable string buffers.
917#[allow(dead_code)]
918pub struct StringPool {
919    free: Vec<String>,
920}
921#[allow(dead_code)]
922impl StringPool {
923    /// Creates a new empty string pool.
924    pub fn new() -> Self {
925        Self { free: Vec::new() }
926    }
927    /// Takes a string from the pool (may be empty).
928    pub fn take(&mut self) -> String {
929        self.free.pop().unwrap_or_default()
930    }
931    /// Returns a string to the pool.
932    pub fn give(&mut self, mut s: String) {
933        s.clear();
934        self.free.push(s);
935    }
936    /// Returns the number of free strings in the pool.
937    pub fn free_count(&self) -> usize {
938        self.free.len()
939    }
940}
941/// A generic counter that tracks min/max/sum for statistical summaries.
942#[allow(dead_code)]
943pub struct StatSummary {
944    count: u64,
945    sum: f64,
946    min: f64,
947    max: f64,
948}
949#[allow(dead_code)]
950impl StatSummary {
951    /// Creates an empty summary.
952    pub fn new() -> Self {
953        Self {
954            count: 0,
955            sum: 0.0,
956            min: f64::INFINITY,
957            max: f64::NEG_INFINITY,
958        }
959    }
960    /// Records a sample.
961    pub fn record(&mut self, val: f64) {
962        self.count += 1;
963        self.sum += val;
964        if val < self.min {
965            self.min = val;
966        }
967        if val > self.max {
968            self.max = val;
969        }
970    }
971    /// Returns the mean, or `None` if no samples.
972    pub fn mean(&self) -> Option<f64> {
973        if self.count == 0 {
974            None
975        } else {
976            Some(self.sum / self.count as f64)
977        }
978    }
979    /// Returns the minimum, or `None` if no samples.
980    pub fn min(&self) -> Option<f64> {
981        if self.count == 0 {
982            None
983        } else {
984            Some(self.min)
985        }
986    }
987    /// Returns the maximum, or `None` if no samples.
988    pub fn max(&self) -> Option<f64> {
989        if self.count == 0 {
990            None
991        } else {
992            Some(self.max)
993        }
994    }
995    /// Returns the count of recorded samples.
996    pub fn count(&self) -> u64 {
997        self.count
998    }
999}
1000/// A simple directed acyclic graph.
1001#[allow(dead_code)]
1002pub struct SimpleDag {
1003    /// `edges[i]` is the list of direct successors of node `i`.
1004    edges: Vec<Vec<usize>>,
1005}
1006#[allow(dead_code)]
1007impl SimpleDag {
1008    /// Creates a DAG with `n` nodes and no edges.
1009    pub fn new(n: usize) -> Self {
1010        Self {
1011            edges: vec![Vec::new(); n],
1012        }
1013    }
1014    /// Adds an edge from `from` to `to`.
1015    pub fn add_edge(&mut self, from: usize, to: usize) {
1016        if from < self.edges.len() {
1017            self.edges[from].push(to);
1018        }
1019    }
1020    /// Returns the successors of `node`.
1021    pub fn successors(&self, node: usize) -> &[usize] {
1022        self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
1023    }
1024    /// Returns `true` if `from` can reach `to` via DFS.
1025    pub fn can_reach(&self, from: usize, to: usize) -> bool {
1026        let mut visited = vec![false; self.edges.len()];
1027        self.dfs(from, to, &mut visited)
1028    }
1029    fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
1030        if cur == target {
1031            return true;
1032        }
1033        if cur >= visited.len() || visited[cur] {
1034            return false;
1035        }
1036        visited[cur] = true;
1037        for &next in self.successors(cur) {
1038            if self.dfs(next, target, visited) {
1039                return true;
1040            }
1041        }
1042        false
1043    }
1044    /// Returns the topological order of nodes, or `None` if a cycle is detected.
1045    pub fn topological_sort(&self) -> Option<Vec<usize>> {
1046        let n = self.edges.len();
1047        let mut in_degree = vec![0usize; n];
1048        for succs in &self.edges {
1049            for &s in succs {
1050                if s < n {
1051                    in_degree[s] += 1;
1052                }
1053            }
1054        }
1055        let mut queue: std::collections::VecDeque<usize> =
1056            (0..n).filter(|&i| in_degree[i] == 0).collect();
1057        let mut order = Vec::new();
1058        while let Some(node) = queue.pop_front() {
1059            order.push(node);
1060            for &s in self.successors(node) {
1061                if s < n {
1062                    in_degree[s] -= 1;
1063                    if in_degree[s] == 0 {
1064                        queue.push_back(s);
1065                    }
1066                }
1067            }
1068        }
1069        if order.len() == n {
1070            Some(order)
1071        } else {
1072            None
1073        }
1074    }
1075    /// Returns the number of nodes.
1076    pub fn num_nodes(&self) -> usize {
1077        self.edges.len()
1078    }
1079}
1080/// A universe level.
1081///
1082/// Levels form expressions over zero, successor, max, imax, parameters,
1083/// and metavariables.
1084#[derive(Clone, PartialEq, Eq, Hash, Debug)]
1085pub enum Level {
1086    /// Level 0 (Prop).
1087    Zero,
1088    /// Successor: u + 1.
1089    Succ(Box<Level>),
1090    /// Maximum of two levels: max(u, v).
1091    Max(Box<Level>, Box<Level>),
1092    /// Impredicative maximum: imax(u, v).
1093    ///
1094    /// Semantics: imax(u, v) = 0 if v = 0, else max(u, v).
1095    /// This ensures Prop -> Prop : Prop (impredicativity).
1096    IMax(Box<Level>, Box<Level>),
1097    /// Universe parameter (for polymorphism).
1098    Param(Name),
1099    /// Universe metavariable (for unification).
1100    MVar(LevelMVarId),
1101}
1102impl Level {
1103    /// Create Zero level.
1104    pub fn zero() -> Self {
1105        Level::Zero
1106    }
1107    /// Create a successor level.
1108    pub fn succ(l: Level) -> Self {
1109        Level::Succ(Box::new(l))
1110    }
1111    /// Create a max level.
1112    pub fn max(l1: Level, l2: Level) -> Self {
1113        Level::Max(Box::new(l1), Box::new(l2))
1114    }
1115    /// Create an imax level.
1116    pub fn imax(l1: Level, l2: Level) -> Self {
1117        Level::IMax(Box::new(l1), Box::new(l2))
1118    }
1119    /// Create a parameter level.
1120    pub fn param(name: Name) -> Self {
1121        Level::Param(name)
1122    }
1123    /// Create a level metavariable.
1124    pub fn mvar(id: LevelMVarId) -> Self {
1125        Level::MVar(id)
1126    }
1127    /// Check if this is Zero.
1128    pub fn is_zero(&self) -> bool {
1129        matches!(self, Level::Zero)
1130    }
1131    /// Check if this is a parameter.
1132    pub fn is_param(&self) -> bool {
1133        matches!(self, Level::Param(_))
1134    }
1135    /// Check if this is a metavariable.
1136    pub fn is_mvar(&self) -> bool {
1137        matches!(self, Level::MVar(_))
1138    }
1139    /// Check if this is a successor.
1140    pub fn is_succ(&self) -> bool {
1141        matches!(self, Level::Succ(_))
1142    }
1143    /// Check if this is a max.
1144    pub fn is_max(&self) -> bool {
1145        matches!(self, Level::Max(_, _))
1146    }
1147    /// Check if this is an imax.
1148    pub fn is_imax(&self) -> bool {
1149        matches!(self, Level::IMax(_, _))
1150    }
1151    /// Check if this level is definitely not zero.
1152    ///
1153    /// Returns true if we can statically determine this is >= 1.
1154    pub fn is_not_zero(&self) -> bool {
1155        match self {
1156            Level::Zero => false,
1157            Level::Succ(_) => true,
1158            Level::Max(l1, l2) => l1.is_not_zero() || l2.is_not_zero(),
1159            Level::IMax(_, l2) => l2.is_not_zero(),
1160            Level::Param(_) | Level::MVar(_) => false,
1161        }
1162    }
1163    /// Check if this level contains any metavariables.
1164    pub fn has_mvar(&self) -> bool {
1165        match self {
1166            Level::MVar(_) => true,
1167            Level::Succ(l) => l.has_mvar(),
1168            Level::Max(l1, l2) | Level::IMax(l1, l2) => l1.has_mvar() || l2.has_mvar(),
1169            Level::Zero | Level::Param(_) => false,
1170        }
1171    }
1172    /// Check if this level contains any parameters.
1173    pub fn has_param(&self) -> bool {
1174        match self {
1175            Level::Param(_) => true,
1176            Level::Succ(l) => l.has_param(),
1177            Level::Max(l1, l2) | Level::IMax(l1, l2) => l1.has_param() || l2.has_param(),
1178            Level::Zero | Level::MVar(_) => false,
1179        }
1180    }
1181    /// Get the depth (nesting) of this level expression.
1182    pub fn depth(&self) -> usize {
1183        match self {
1184            Level::Zero | Level::Param(_) | Level::MVar(_) => 0,
1185            Level::Succ(l) => 1 + l.depth(),
1186            Level::Max(l1, l2) | Level::IMax(l1, l2) => 1 + l1.depth().max(l2.depth()),
1187        }
1188    }
1189    /// Create a numeric level `succ^n(zero)`.
1190    pub fn from_nat(n: u32) -> Self {
1191        let mut l = Level::Zero;
1192        for _ in 0..n {
1193            l = Level::succ(l);
1194        }
1195        l
1196    }
1197    /// Try to convert to a numeric level.
1198    ///
1199    /// Returns `Some(n)` if this is `succ^n(zero)`, `None` otherwise.
1200    pub fn to_nat(&self) -> Option<u32> {
1201        match self {
1202            Level::Zero => Some(0),
1203            Level::Succ(l) => l.to_nat().map(|n| n + 1),
1204            _ => None,
1205        }
1206    }
1207}
1208/// A min-heap implemented as a binary heap.
1209#[allow(dead_code)]
1210pub struct MinHeap<T: Ord> {
1211    data: Vec<T>,
1212}
1213#[allow(dead_code)]
1214impl<T: Ord> MinHeap<T> {
1215    /// Creates a new empty min-heap.
1216    pub fn new() -> Self {
1217        Self { data: Vec::new() }
1218    }
1219    /// Inserts an element.
1220    pub fn push(&mut self, val: T) {
1221        self.data.push(val);
1222        self.sift_up(self.data.len() - 1);
1223    }
1224    /// Removes and returns the minimum element.
1225    pub fn pop(&mut self) -> Option<T> {
1226        if self.data.is_empty() {
1227            return None;
1228        }
1229        let n = self.data.len();
1230        self.data.swap(0, n - 1);
1231        let min = self.data.pop();
1232        if !self.data.is_empty() {
1233            self.sift_down(0);
1234        }
1235        min
1236    }
1237    /// Returns a reference to the minimum element.
1238    pub fn peek(&self) -> Option<&T> {
1239        self.data.first()
1240    }
1241    /// Returns the number of elements.
1242    pub fn len(&self) -> usize {
1243        self.data.len()
1244    }
1245    /// Returns `true` if empty.
1246    pub fn is_empty(&self) -> bool {
1247        self.data.is_empty()
1248    }
1249    fn sift_up(&mut self, mut i: usize) {
1250        while i > 0 {
1251            let parent = (i - 1) / 2;
1252            if self.data[i] < self.data[parent] {
1253                self.data.swap(i, parent);
1254                i = parent;
1255            } else {
1256                break;
1257            }
1258        }
1259    }
1260    fn sift_down(&mut self, mut i: usize) {
1261        let n = self.data.len();
1262        loop {
1263            let left = 2 * i + 1;
1264            let right = 2 * i + 2;
1265            let mut smallest = i;
1266            if left < n && self.data[left] < self.data[smallest] {
1267                smallest = left;
1268            }
1269            if right < n && self.data[right] < self.data[smallest] {
1270                smallest = right;
1271            }
1272            if smallest == i {
1273                break;
1274            }
1275            self.data.swap(i, smallest);
1276            i = smallest;
1277        }
1278    }
1279}
1280/// A pair of `StatSummary` values tracking before/after a transformation.
1281#[allow(dead_code)]
1282pub struct TransformStat {
1283    before: StatSummary,
1284    after: StatSummary,
1285}
1286#[allow(dead_code)]
1287impl TransformStat {
1288    /// Creates a new transform stat recorder.
1289    pub fn new() -> Self {
1290        Self {
1291            before: StatSummary::new(),
1292            after: StatSummary::new(),
1293        }
1294    }
1295    /// Records a before value.
1296    pub fn record_before(&mut self, v: f64) {
1297        self.before.record(v);
1298    }
1299    /// Records an after value.
1300    pub fn record_after(&mut self, v: f64) {
1301        self.after.record(v);
1302    }
1303    /// Returns the mean reduction ratio (after/before).
1304    pub fn mean_ratio(&self) -> Option<f64> {
1305        let b = self.before.mean()?;
1306        let a = self.after.mean()?;
1307        if b.abs() < f64::EPSILON {
1308            return None;
1309        }
1310        Some(a / b)
1311    }
1312}
1313/// Unique identifier for level metavariables.
1314#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1315pub struct LevelMVarId(pub u64);
1316/// A sparse vector: stores only non-default elements.
1317#[allow(dead_code)]
1318pub struct SparseVec<T: Default + Clone + PartialEq> {
1319    entries: std::collections::HashMap<usize, T>,
1320    default_: T,
1321    logical_len: usize,
1322}
1323#[allow(dead_code)]
1324impl<T: Default + Clone + PartialEq> SparseVec<T> {
1325    /// Creates a new sparse vector with logical length `len`.
1326    pub fn new(len: usize) -> Self {
1327        Self {
1328            entries: std::collections::HashMap::new(),
1329            default_: T::default(),
1330            logical_len: len,
1331        }
1332    }
1333    /// Sets element at `idx`.
1334    pub fn set(&mut self, idx: usize, val: T) {
1335        if val == self.default_ {
1336            self.entries.remove(&idx);
1337        } else {
1338            self.entries.insert(idx, val);
1339        }
1340    }
1341    /// Gets element at `idx`.
1342    pub fn get(&self, idx: usize) -> &T {
1343        self.entries.get(&idx).unwrap_or(&self.default_)
1344    }
1345    /// Returns the logical length.
1346    pub fn len(&self) -> usize {
1347        self.logical_len
1348    }
1349    /// Returns whether the collection is empty.
1350    pub fn is_empty(&self) -> bool {
1351        self.len() == 0
1352    }
1353    /// Returns the number of non-default elements.
1354    pub fn nnz(&self) -> usize {
1355        self.entries.len()
1356    }
1357}
1358/// A trie-based prefix counter.
1359#[allow(dead_code)]
1360pub struct PrefixCounter {
1361    children: std::collections::HashMap<char, PrefixCounter>,
1362    count: usize,
1363}
1364#[allow(dead_code)]
1365impl PrefixCounter {
1366    /// Creates an empty prefix counter.
1367    pub fn new() -> Self {
1368        Self {
1369            children: std::collections::HashMap::new(),
1370            count: 0,
1371        }
1372    }
1373    /// Records a string.
1374    pub fn record(&mut self, s: &str) {
1375        self.count += 1;
1376        let mut node = self;
1377        for c in s.chars() {
1378            node = node.children.entry(c).or_default();
1379            node.count += 1;
1380        }
1381    }
1382    /// Returns how many strings have been recorded that start with `prefix`.
1383    pub fn count_with_prefix(&self, prefix: &str) -> usize {
1384        let mut node = self;
1385        for c in prefix.chars() {
1386            match node.children.get(&c) {
1387                Some(n) => node = n,
1388                None => return 0,
1389            }
1390        }
1391        node.count
1392    }
1393}