Skip to main content

oxilean_kernel/instantiate/
types.rs

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