Skip to main content

oxilean_kernel/env/
types.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use crate::declaration::{ConstantInfo, ConstantVal, DefinitionSafety, DefinitionVal};
6use crate::reduce::ReducibilityHint;
7use crate::{Expr, Level, Name};
8use std::collections::HashMap;
9
10/// Represents a rewrite rule `lhs → rhs`.
11#[allow(dead_code)]
12#[allow(missing_docs)]
13pub struct RewriteRule {
14    /// The name of the rule.
15    pub name: String,
16    /// A string representation of the LHS pattern.
17    pub lhs: String,
18    /// A string representation of the RHS.
19    pub rhs: String,
20    /// Whether this is a conditional rule (has side conditions).
21    pub conditional: bool,
22}
23#[allow(dead_code)]
24impl RewriteRule {
25    /// Creates an unconditional rewrite rule.
26    pub fn unconditional(
27        name: impl Into<String>,
28        lhs: impl Into<String>,
29        rhs: impl Into<String>,
30    ) -> Self {
31        Self {
32            name: name.into(),
33            lhs: lhs.into(),
34            rhs: rhs.into(),
35            conditional: false,
36        }
37    }
38    /// Creates a conditional rewrite rule.
39    pub fn conditional(
40        name: impl Into<String>,
41        lhs: impl Into<String>,
42        rhs: impl Into<String>,
43    ) -> Self {
44        Self {
45            name: name.into(),
46            lhs: lhs.into(),
47            rhs: rhs.into(),
48            conditional: true,
49        }
50    }
51    /// Returns a textual representation.
52    pub fn display(&self) -> String {
53        format!("{}: {} → {}", self.name, self.lhs, self.rhs)
54    }
55}
56/// A set of rewrite rules.
57#[allow(dead_code)]
58pub struct RewriteRuleSet {
59    rules: Vec<RewriteRule>,
60}
61#[allow(dead_code)]
62impl RewriteRuleSet {
63    /// Creates an empty rule set.
64    pub fn new() -> Self {
65        Self { rules: Vec::new() }
66    }
67    /// Adds a rule.
68    pub fn add(&mut self, rule: RewriteRule) {
69        self.rules.push(rule);
70    }
71    /// Returns the number of rules.
72    pub fn len(&self) -> usize {
73        self.rules.len()
74    }
75    /// Returns `true` if the set is empty.
76    pub fn is_empty(&self) -> bool {
77        self.rules.is_empty()
78    }
79    /// Returns all conditional rules.
80    pub fn conditional_rules(&self) -> Vec<&RewriteRule> {
81        self.rules.iter().filter(|r| r.conditional).collect()
82    }
83    /// Returns all unconditional rules.
84    pub fn unconditional_rules(&self) -> Vec<&RewriteRule> {
85        self.rules.iter().filter(|r| !r.conditional).collect()
86    }
87    /// Looks up a rule by name.
88    pub fn get(&self, name: &str) -> Option<&RewriteRule> {
89        self.rules.iter().find(|r| r.name == name)
90    }
91}
92/// A versioned record that stores a history of values.
93#[allow(dead_code)]
94pub struct VersionedRecord<T: Clone> {
95    /// Every earlier value, oldest first: version `n` is `earlier[n]`.
96    earlier: Vec<T>,
97    /// The latest value (version `earlier.len()`), declared last so it drops last.
98    current: T,
99}
100#[allow(dead_code)]
101impl<T: Clone> VersionedRecord<T> {
102    /// Creates a new record with an initial value.
103    pub fn new(initial: T) -> Self {
104        Self {
105            earlier: Vec::new(),
106            current: initial,
107        }
108    }
109    /// Updates the record with a new version.
110    pub fn update(&mut self, val: T) {
111        let previous = std::mem::replace(&mut self.current, val);
112        self.earlier.push(previous);
113    }
114    /// Returns the current (latest) value.
115    pub fn current(&self) -> &T {
116        &self.current
117    }
118    /// Returns the value at version `n` (0-indexed), or `None`.
119    pub fn at_version(&self, n: usize) -> Option<&T> {
120        match self.earlier.get(n) {
121            Some(value) => Some(value),
122            None if n == self.earlier.len() => Some(&self.current),
123            None => None,
124        }
125    }
126    /// Returns the version number of the current value.
127    pub fn version(&self) -> usize {
128        self.earlier.len()
129    }
130    /// Returns `true` if more than one version exists.
131    pub fn has_history(&self) -> bool {
132        !self.earlier.is_empty()
133    }
134}
135/// A mutable reference stack for tracking the current "focus" in a tree traversal.
136#[allow(dead_code)]
137pub struct FocusStack<T> {
138    items: Vec<T>,
139}
140#[allow(dead_code)]
141impl<T> FocusStack<T> {
142    /// Creates an empty focus stack.
143    pub fn new() -> Self {
144        Self { items: Vec::new() }
145    }
146    /// Focuses on `item`.
147    pub fn focus(&mut self, item: T) {
148        self.items.push(item);
149    }
150    /// Blurs (pops) the current focus.
151    pub fn blur(&mut self) -> Option<T> {
152        self.items.pop()
153    }
154    /// Returns the current focus, or `None`.
155    pub fn current(&self) -> Option<&T> {
156        self.items.last()
157    }
158    /// Returns the focus depth.
159    pub fn depth(&self) -> usize {
160        self.items.len()
161    }
162    /// Returns `true` if there is no current focus.
163    pub fn is_empty(&self) -> bool {
164        self.items.is_empty()
165    }
166}
167/// A sparse vector: stores only non-default elements.
168#[allow(dead_code)]
169pub struct SparseVec<T: Default + Clone + PartialEq> {
170    entries: std::collections::HashMap<usize, T>,
171    default_: T,
172    logical_len: usize,
173}
174#[allow(dead_code)]
175impl<T: Default + Clone + PartialEq> SparseVec<T> {
176    /// Creates a new sparse vector with logical length `len`.
177    pub fn new(len: usize) -> Self {
178        Self {
179            entries: std::collections::HashMap::new(),
180            default_: T::default(),
181            logical_len: len,
182        }
183    }
184    /// Sets element at `idx`.
185    pub fn set(&mut self, idx: usize, val: T) {
186        if val == self.default_ {
187            self.entries.remove(&idx);
188        } else {
189            self.entries.insert(idx, val);
190        }
191    }
192    /// Gets element at `idx`.
193    pub fn get(&self, idx: usize) -> &T {
194        self.entries.get(&idx).unwrap_or(&self.default_)
195    }
196    /// Returns the logical length.
197    pub fn len(&self) -> usize {
198        self.logical_len
199    }
200    /// Returns whether the collection is empty.
201    pub fn is_empty(&self) -> bool {
202        self.len() == 0
203    }
204    /// Returns the number of non-default elements.
205    pub fn nnz(&self) -> usize {
206        self.entries.len()
207    }
208}
209/// A window iterator that yields overlapping windows of size `n`.
210#[allow(dead_code)]
211pub struct WindowIterator<'a, T> {
212    pub(super) data: &'a [T],
213    pub(super) pos: usize,
214    pub(super) window: usize,
215}
216#[allow(dead_code)]
217impl<'a, T> WindowIterator<'a, T> {
218    /// Creates a new window iterator.
219    pub fn new(data: &'a [T], window: usize) -> Self {
220        Self {
221            data,
222            pos: 0,
223            window,
224        }
225    }
226}
227/// The global environment containing all checked declarations.
228#[derive(Clone, Debug, Default)]
229pub struct Environment {
230    /// All declarations indexed by name (legacy format).
231    declarations: HashMap<Name, Declaration>,
232    /// All constants indexed by name (new LEAN 4-style format).
233    constants: HashMap<Name, ConstantInfo>,
234    /// Whether the four `#QUOT` primitives have been installed via
235    /// [`Environment::add_quot`]. Quotient constants may only be added through
236    /// that once-only entry point (mirroring Lean's `environment::quot_initialized`).
237    quot_initialized: bool,
238    /// Whether this environment declares the kernel's own literal
239    /// primitives (see [`Environment::has_literal_primitives`]).
240    literal_primitives: bool,
241}
242impl Environment {
243    /// Create a new empty environment.
244    pub fn new() -> Self {
245        Self {
246            declarations: HashMap::new(),
247            constants: HashMap::new(),
248            quot_initialized: false,
249            literal_primitives: false,
250        }
251    }
252    /// Add a legacy declaration to the environment.
253    ///
254    /// Returns an error if a declaration with the same name already exists.
255    pub fn add(&mut self, decl: Declaration) -> Result<(), EnvError> {
256        let name = decl.name().clone();
257        if self.declarations.contains_key(&name) || self.constants.contains_key(&name) {
258            return Err(EnvError::DuplicateDeclaration(name));
259        }
260        let ci = decl.to_constant_info();
261        self.constants.insert(name.clone(), ci);
262        self.declarations.insert(name, decl);
263        Ok(())
264    }
265    /// Add a ConstantInfo to the environment.
266    ///
267    /// Quotient constants (`ConstantInfo::Quotient`) are rejected here: the four
268    /// `#QUOT` primitives may only be installed atomically through
269    /// [`Environment::add_quot`], which constructs their canonical types
270    /// in-kernel. This prevents a caller from smuggling a `Quotient` entry with
271    /// an arbitrary (possibly unsound) type past the checker.
272    pub fn add_constant(&mut self, ci: ConstantInfo) -> Result<(), EnvError> {
273        if ci.is_quotient() {
274            return Err(EnvError::InvalidQuotient(
275                "quotient constants may only be added via Environment::add_quot".to_string(),
276            ));
277        }
278        let name = ci.name().clone();
279        if self.declarations.contains_key(&name) || self.constants.contains_key(&name) {
280            return Err(EnvError::DuplicateDeclaration(name));
281        }
282        self.constants.insert(name, ci);
283        Ok(())
284    }
285    /// Add a group of constants as a unit: every one of them, or none.
286    ///
287    /// The whole group is looked at before anything is inserted. When one of
288    /// its names is already declared, occurs twice in the group, or belongs
289    /// to a quotient constant (see [`Environment::add_constant`]), the error
290    /// is returned and the environment is exactly what it was. This is how a
291    /// declaration that consists of several constants — an inductive family
292    /// with its constructors and recursors — is installed: a caller that
293    /// added them one by one would leave the first ones behind when a later
294    /// one is refused.
295    pub fn add_constants(&mut self, cis: Vec<ConstantInfo>) -> Result<(), EnvError> {
296        for (i, ci) in cis.iter().enumerate() {
297            if ci.is_quotient() {
298                return Err(EnvError::InvalidQuotient(
299                    "quotient constants may only be added via Environment::add_quot".to_string(),
300                ));
301            }
302            let name = ci.name();
303            if self.contains(name) || cis[..i].iter().any(|earlier| earlier.name() == name) {
304                return Err(EnvError::DuplicateDeclaration(name.clone()));
305            }
306        }
307        for ci in cis {
308            self.constants.insert(ci.name().clone(), ci);
309        }
310        Ok(())
311    }
312    /// Take constants out again. Only for undoing, within one kernel call,
313    /// what that same call added through [`Environment::add_constant`] (see
314    /// `check::check_constant_infos_atomic`): a name added that way was
315    /// free before, so removing it restores the environment exactly. It is
316    /// not public — removing a constant that other constants were checked
317    /// against would leave them unchecked.
318    pub(crate) fn remove_constants(&mut self, names: &[Name]) {
319        for name in names {
320            self.constants.remove(name);
321        }
322    }
323    /// Whether the four `#QUOT` primitives have been installed.
324    pub fn quot_initialized(&self) -> bool {
325        self.quot_initialized
326    }
327    /// Whether this environment declares the kernel's own literal
328    /// primitives — `Nat.pred`, `Nat.blt`, `Nat.log2`, `String.length`,
329    /// `String.append`, `String.beq` — as operations without a definition,
330    /// computed on literals by the reducer.
331    ///
332    /// `false` for an empty environment, and so for every environment
333    /// replayed from an export: there a constant of one of these names is
334    /// whatever the file declared, and it reduces by that declaration. Lean
335    /// 4's kernel computes none of the six by name; only the operations it
336    /// does compute by name (`Nat.add`, `Nat.sub`, ...) are computed
337    /// regardless of this flag. See `reduce::lit_op_arity`.
338    pub fn has_literal_primitives(&self) -> bool {
339        self.literal_primitives
340    }
341    /// Say that this environment declares the kernel's own literal
342    /// primitives (see [`Environment::has_literal_primitives`]). Called by
343    /// the builtin environment, which declares them without a definition;
344    /// it is not public, so that an environment built from declarations of
345    /// someone else's cannot turn the reduction rules on for them.
346    pub(crate) fn declare_literal_primitives(&mut self) {
347        self.literal_primitives = true;
348    }
349    /// Insert a pre-validated quotient constant.
350    ///
351    /// This bypasses the `add_constant` quotient guard and is used *only* by
352    /// [`Environment::add_quot`], which owns the canonical types and enforces
353    /// the once-only / atomicity invariants. It must never be exposed publicly.
354    pub(crate) fn insert_quotient(&mut self, ci: ConstantInfo) {
355        debug_assert!(ci.is_quotient());
356        let name = ci.name().clone();
357        self.constants.insert(name, ci);
358    }
359    /// Mark the quotient primitives as installed (used only by `add_quot`).
360    pub(crate) fn set_quot_initialized(&mut self) {
361        self.quot_initialized = true;
362    }
363    /// Look up a legacy declaration by name.
364    pub fn get(&self, name: &Name) -> Option<&Declaration> {
365        self.declarations.get(name)
366    }
367    /// Look up a constant info by name.
368    pub fn find(&self, name: &Name) -> Option<&ConstantInfo> {
369        self.constants.get(name)
370    }
371    /// Check if a declaration exists.
372    pub fn contains(&self, name: &Name) -> bool {
373        self.declarations.contains_key(name) || self.constants.contains_key(name)
374    }
375    /// Get the number of declarations.
376    pub fn len(&self) -> usize {
377        self.constants.len().max(self.declarations.len())
378    }
379    /// Check if the environment is empty.
380    pub fn is_empty(&self) -> bool {
381        self.declarations.is_empty() && self.constants.is_empty()
382    }
383    /// Get a definition's value and hint (for reduction).
384    pub fn get_defn(&self, name: &Name) -> Option<(Expr, ReducibilityHint)> {
385        if let Some(ci) = self.constants.get(name) {
386            if let Some(val) = ci.value() {
387                return Some((val.clone(), ci.reducibility_hint()));
388            }
389        }
390        self.declarations.get(name).and_then(|decl| {
391            decl.value()
392                .map(|val| (val.clone(), decl.reducibility_hint()))
393        })
394    }
395    /// Check if a name refers to an inductive type.
396    pub fn is_inductive(&self, name: &Name) -> bool {
397        self.constants.get(name).is_some_and(|ci| ci.is_inductive())
398    }
399    /// Check if a name refers to a constructor.
400    pub fn is_constructor(&self, name: &Name) -> bool {
401        self.constants
402            .get(name)
403            .is_some_and(|ci| ci.is_constructor())
404    }
405    /// Check if a name refers to a recursor.
406    pub fn is_recursor(&self, name: &Name) -> bool {
407        self.constants.get(name).is_some_and(|ci| ci.is_recursor())
408    }
409    /// Check if a name refers to a quotient.
410    pub fn is_quotient(&self, name: &Name) -> bool {
411        self.constants.get(name).is_some_and(|ci| ci.is_quotient())
412    }
413    /// Check if a name refers to a structure-like inductive.
414    pub fn is_structure_like(&self, name: &Name) -> bool {
415        self.constants
416            .get(name)
417            .is_some_and(|ci| ci.is_structure_like())
418    }
419    /// Get the inductive type info for a name.
420    pub fn get_inductive_val(&self, name: &Name) -> Option<&crate::declaration::InductiveVal> {
421        self.constants
422            .get(name)
423            .and_then(|ci| ci.to_inductive_val())
424    }
425    /// Get the constructor info for a name.
426    pub fn get_constructor_val(&self, name: &Name) -> Option<&crate::declaration::ConstructorVal> {
427        self.constants
428            .get(name)
429            .and_then(|ci| ci.to_constructor_val())
430    }
431    /// Get the recursor info for a name.
432    pub fn get_recursor_val(&self, name: &Name) -> Option<&crate::declaration::RecursorVal> {
433        self.constants.get(name).and_then(|ci| ci.to_recursor_val())
434    }
435    /// Get the quotient info for a name.
436    pub fn get_quotient_val(&self, name: &Name) -> Option<&crate::declaration::QuotVal> {
437        self.constants.get(name).and_then(|ci| ci.to_quotient_val())
438    }
439    /// Get the type of a constant (from ConstantInfo).
440    pub fn get_type(&self, name: &Name) -> Option<&Expr> {
441        self.constants.get(name).map(|ci| ci.ty())
442    }
443    /// Get the universe level parameters for a constant.
444    pub fn get_level_params(&self, name: &Name) -> Option<&[Name]> {
445        self.constants.get(name).map(|ci| ci.level_params())
446    }
447    /// Instantiate a constant's type with universe levels.
448    pub fn instantiate_const_type(&self, name: &Name, levels: &[Level]) -> Option<Expr> {
449        let ci = self.constants.get(name)?;
450        let params = ci.level_params();
451        if params.is_empty() || levels.is_empty() {
452            return Some(ci.ty().clone());
453        }
454        Some(crate::declaration::instantiate_level_params(
455            ci.ty(),
456            params,
457            levels,
458        ))
459    }
460    /// Iterate over all constant names.
461    pub fn constant_names(&self) -> impl Iterator<Item = &Name> {
462        self.constants.keys()
463    }
464    /// Iterate over all constant infos.
465    pub fn constant_infos(&self) -> impl Iterator<Item = (&Name, &ConstantInfo)> {
466        self.constants.iter()
467    }
468}
469/// Counts of declaration kinds in an environment.
470#[allow(dead_code)]
471#[derive(Debug, Clone, Default)]
472pub struct EnvKindCounts {
473    /// Number of axioms.
474    pub axioms: usize,
475    /// Number of inductive type definitions.
476    pub inductives: usize,
477    /// Number of constructors.
478    pub constructors: usize,
479    /// Number of recursors.
480    pub recursors: usize,
481    /// Number of definitions.
482    pub definitions: usize,
483    /// Number of theorems.
484    pub theorems: usize,
485    /// Other (quotients, etc.).
486    pub other: usize,
487}
488impl EnvKindCounts {
489    /// Total number of declarations.
490    #[allow(dead_code)]
491    pub fn total(&self) -> usize {
492        self.axioms
493            + self.inductives
494            + self.constructors
495            + self.recursors
496            + self.definitions
497            + self.theorems
498            + self.other
499    }
500}
501/// A declaration in the global environment (legacy format).
502#[derive(Clone, Debug)]
503pub enum Declaration {
504    /// Axiom: postulated type without proof
505    Axiom {
506        /// Name of the axiom
507        name: Name,
508        /// Universe parameters
509        univ_params: Vec<Name>,
510        /// Type of the axiom
511        ty: Expr,
512    },
513    /// Definition: has a computational value
514    Definition {
515        /// Name of the definition
516        name: Name,
517        /// Universe parameters
518        univ_params: Vec<Name>,
519        /// Type of the definition
520        ty: Expr,
521        /// Value/body of the definition
522        val: Expr,
523        /// Reducibility hint
524        hint: ReducibilityHint,
525    },
526    /// Theorem: like definition but value is a proof (typically opaque)
527    Theorem {
528        /// Name of the theorem
529        name: Name,
530        /// Universe parameters
531        univ_params: Vec<Name>,
532        /// Type of the theorem (the proposition)
533        ty: Expr,
534        /// Proof of the theorem
535        val: Expr,
536    },
537    /// Opaque: definition that should never be unfolded
538    Opaque {
539        /// Name of the opaque definition
540        name: Name,
541        /// Universe parameters
542        univ_params: Vec<Name>,
543        /// Type of the definition
544        ty: Expr,
545        /// Value of the definition (hidden)
546        val: Expr,
547    },
548}
549impl Declaration {
550    /// Get the name of this declaration.
551    pub fn name(&self) -> &Name {
552        match self {
553            Declaration::Axiom { name, .. }
554            | Declaration::Definition { name, .. }
555            | Declaration::Theorem { name, .. }
556            | Declaration::Opaque { name, .. } => name,
557        }
558    }
559    /// Get the type of this declaration.
560    pub fn ty(&self) -> &Expr {
561        match self {
562            Declaration::Axiom { ty, .. }
563            | Declaration::Definition { ty, .. }
564            | Declaration::Theorem { ty, .. }
565            | Declaration::Opaque { ty, .. } => ty,
566        }
567    }
568    /// Get the universe parameters.
569    pub fn univ_params(&self) -> &[Name] {
570        match self {
571            Declaration::Axiom { univ_params, .. }
572            | Declaration::Definition { univ_params, .. }
573            | Declaration::Theorem { univ_params, .. }
574            | Declaration::Opaque { univ_params, .. } => univ_params,
575        }
576    }
577    /// Get the value (if this is a definition/theorem/opaque).
578    pub fn value(&self) -> Option<&Expr> {
579        match self {
580            Declaration::Axiom { .. } => None,
581            Declaration::Definition { val, .. }
582            | Declaration::Theorem { val, .. }
583            | Declaration::Opaque { val, .. } => Some(val),
584        }
585    }
586    /// Get the reducibility hint.
587    pub fn reducibility_hint(&self) -> ReducibilityHint {
588        match self {
589            Declaration::Axiom { .. } => ReducibilityHint::Opaque,
590            Declaration::Definition { hint, .. } => *hint,
591            Declaration::Theorem { .. } | Declaration::Opaque { .. } => ReducibilityHint::Opaque,
592        }
593    }
594    /// Convert a legacy Declaration to ConstantInfo.
595    pub fn to_constant_info(&self) -> ConstantInfo {
596        match self {
597            Declaration::Axiom {
598                name,
599                univ_params,
600                ty,
601            } => ConstantInfo::Axiom(crate::declaration::AxiomVal {
602                common: ConstantVal {
603                    name: name.clone(),
604                    level_params: univ_params.clone(),
605                    ty: ty.clone(),
606                },
607                is_unsafe: false,
608            }),
609            Declaration::Definition {
610                name,
611                univ_params,
612                ty,
613                val,
614                hint,
615            } => ConstantInfo::Definition(DefinitionVal {
616                common: ConstantVal {
617                    name: name.clone(),
618                    level_params: univ_params.clone(),
619                    ty: ty.clone(),
620                },
621                value: val.clone(),
622                hints: *hint,
623                safety: DefinitionSafety::Safe,
624                all: vec![name.clone()],
625            }),
626            Declaration::Theorem {
627                name,
628                univ_params,
629                ty,
630                val,
631            } => ConstantInfo::Theorem(crate::declaration::TheoremVal {
632                common: ConstantVal {
633                    name: name.clone(),
634                    level_params: univ_params.clone(),
635                    ty: ty.clone(),
636                },
637                value: val.clone(),
638                all: vec![name.clone()],
639            }),
640            Declaration::Opaque {
641                name,
642                univ_params,
643                ty,
644                val,
645            } => ConstantInfo::Opaque(crate::declaration::OpaqueVal {
646                common: ConstantVal {
647                    name: name.clone(),
648                    level_params: univ_params.clone(),
649                    ty: ty.clone(),
650                },
651                value: val.clone(),
652                is_unsafe: false,
653                all: vec![name.clone()],
654            }),
655        }
656    }
657}
658/// A type-erased function pointer with arity tracking.
659#[allow(dead_code)]
660pub struct RawFnPtr {
661    /// The raw function pointer (stored as usize for type erasure).
662    ptr: usize,
663    arity: usize,
664    name: String,
665}
666#[allow(dead_code)]
667impl RawFnPtr {
668    /// Creates a new raw function pointer descriptor.
669    pub fn new(ptr: usize, arity: usize, name: impl Into<String>) -> Self {
670        Self {
671            ptr,
672            arity,
673            name: name.into(),
674        }
675    }
676    /// Returns the arity.
677    pub fn arity(&self) -> usize {
678        self.arity
679    }
680    /// Returns the name.
681    pub fn name(&self) -> &str {
682        &self.name
683    }
684    /// Returns the raw pointer value.
685    pub fn raw(&self) -> usize {
686        self.ptr
687    }
688}
689/// A trie-based prefix counter.
690#[allow(dead_code)]
691pub struct PrefixCounter {
692    children: std::collections::HashMap<char, PrefixCounter>,
693    count: usize,
694}
695#[allow(dead_code)]
696impl PrefixCounter {
697    /// Creates an empty prefix counter.
698    pub fn new() -> Self {
699        Self {
700            children: std::collections::HashMap::new(),
701            count: 0,
702        }
703    }
704    /// Records a string.
705    pub fn record(&mut self, s: &str) {
706        self.count += 1;
707        let mut node = self;
708        for c in s.chars() {
709            node = node.children.entry(c).or_default();
710            node.count += 1;
711        }
712    }
713    /// Returns how many strings have been recorded that start with `prefix`.
714    pub fn count_with_prefix(&self, prefix: &str) -> usize {
715        let mut node = self;
716        for c in prefix.chars() {
717            match node.children.get(&c) {
718                Some(n) => node = n,
719                None => return 0,
720            }
721        }
722        node.count
723    }
724}
725/// A simple mutable key-value store for test fixtures.
726#[allow(dead_code)]
727pub struct Fixture {
728    data: std::collections::HashMap<String, String>,
729}
730#[allow(dead_code)]
731impl Fixture {
732    /// Creates an empty fixture.
733    pub fn new() -> Self {
734        Self {
735            data: std::collections::HashMap::new(),
736        }
737    }
738    /// Sets a key.
739    pub fn set(&mut self, key: impl Into<String>, val: impl Into<String>) {
740        self.data.insert(key.into(), val.into());
741    }
742    /// Gets a value.
743    pub fn get(&self, key: &str) -> Option<&str> {
744        self.data.get(key).map(|s| s.as_str())
745    }
746    /// Returns the number of entries.
747    pub fn len(&self) -> usize {
748        self.data.len()
749    }
750    /// Returns whether the collection is empty.
751    pub fn is_empty(&self) -> bool {
752        self.len() == 0
753    }
754}
755/// A read-only view of the environment with aggregated queries.
756#[allow(dead_code)]
757pub struct EnvironmentView<'a> {
758    env: &'a Environment,
759}
760impl<'a> EnvironmentView<'a> {
761    /// Create a view over an environment.
762    #[allow(dead_code)]
763    pub fn new(env: &'a Environment) -> Self {
764        Self { env }
765    }
766    /// Get all axiom names.
767    #[allow(dead_code)]
768    pub fn axiom_names(&self) -> Vec<&Name> {
769        self.env
770            .constant_infos()
771            .filter_map(|(name, ci)| if ci.is_axiom() { Some(name) } else { None })
772            .collect()
773    }
774    /// Get all inductive type names.
775    #[allow(dead_code)]
776    pub fn inductive_names(&self) -> Vec<&Name> {
777        self.env
778            .constant_infos()
779            .filter_map(|(name, ci)| if ci.is_inductive() { Some(name) } else { None })
780            .collect()
781    }
782    /// Get all constructor names.
783    #[allow(dead_code)]
784    pub fn constructor_names(&self) -> Vec<&Name> {
785        self.env
786            .constant_infos()
787            .filter_map(|(name, ci)| {
788                if ci.is_constructor() {
789                    Some(name)
790                } else {
791                    None
792                }
793            })
794            .collect()
795    }
796    /// Get all definition names.
797    #[allow(dead_code)]
798    pub fn definition_names(&self) -> Vec<&Name> {
799        self.env
800            .constant_infos()
801            .filter_map(|(name, ci)| if ci.is_definition() { Some(name) } else { None })
802            .collect()
803    }
804    /// Count declarations by kind.
805    #[allow(dead_code)]
806    pub fn count_by_kind(&self) -> EnvKindCounts {
807        let mut counts = EnvKindCounts::default();
808        for (_, ci) in self.env.constant_infos() {
809            if ci.is_axiom() {
810                counts.axioms += 1;
811            } else if ci.is_inductive() {
812                counts.inductives += 1;
813            } else if ci.is_constructor() {
814                counts.constructors += 1;
815            } else if ci.is_recursor() {
816                counts.recursors += 1;
817            } else if ci.is_definition() {
818                counts.definitions += 1;
819            } else if ci.is_theorem() {
820                counts.theorems += 1;
821            } else {
822                counts.other += 1;
823            }
824        }
825        counts
826    }
827}
828/// A label set for a graph node.
829#[allow(dead_code)]
830pub struct LabelSet {
831    labels: Vec<String>,
832}
833#[allow(dead_code)]
834impl LabelSet {
835    /// Creates a new empty label set.
836    pub fn new() -> Self {
837        Self { labels: Vec::new() }
838    }
839    /// Adds a label (deduplicates).
840    pub fn add(&mut self, label: impl Into<String>) {
841        let s = label.into();
842        if !self.labels.contains(&s) {
843            self.labels.push(s);
844        }
845    }
846    /// Returns `true` if `label` is present.
847    pub fn has(&self, label: &str) -> bool {
848        self.labels.iter().any(|l| l == label)
849    }
850    /// Returns the count of labels.
851    pub fn count(&self) -> usize {
852        self.labels.len()
853    }
854    /// Returns all labels.
855    pub fn all(&self) -> &[String] {
856        &self.labels
857    }
858}
859/// Environment statistics summary.
860#[derive(Clone, Debug, Default)]
861pub struct EnvStats {
862    /// Total constants.
863    pub total: usize,
864    /// Axioms.
865    pub axioms: usize,
866    /// Definitions.
867    pub definitions: usize,
868    /// Theorems.
869    pub theorems: usize,
870    /// Inductive types.
871    pub inductives: usize,
872    /// Constructors.
873    pub constructors: usize,
874    /// Recursors.
875    pub recursors: usize,
876}
877/// A generic counter that tracks min/max/sum for statistical summaries.
878#[allow(dead_code)]
879pub struct StatSummary {
880    count: u64,
881    sum: f64,
882    min: f64,
883    max: f64,
884}
885#[allow(dead_code)]
886impl StatSummary {
887    /// Creates an empty summary.
888    pub fn new() -> Self {
889        Self {
890            count: 0,
891            sum: 0.0,
892            min: f64::INFINITY,
893            max: f64::NEG_INFINITY,
894        }
895    }
896    /// Records a sample.
897    pub fn record(&mut self, val: f64) {
898        self.count += 1;
899        self.sum += val;
900        if val < self.min {
901            self.min = val;
902        }
903        if val > self.max {
904            self.max = val;
905        }
906    }
907    /// Returns the mean, or `None` if no samples.
908    pub fn mean(&self) -> Option<f64> {
909        if self.count == 0 {
910            None
911        } else {
912            Some(self.sum / self.count as f64)
913        }
914    }
915    /// Returns the minimum, or `None` if no samples.
916    pub fn min(&self) -> Option<f64> {
917        if self.count == 0 {
918            None
919        } else {
920            Some(self.min)
921        }
922    }
923    /// Returns the maximum, or `None` if no samples.
924    pub fn max(&self) -> Option<f64> {
925        if self.count == 0 {
926            None
927        } else {
928            Some(self.max)
929        }
930    }
931    /// Returns the count of recorded samples.
932    pub fn count(&self) -> u64 {
933        self.count
934    }
935}
936/// A non-empty list (at least one element guaranteed).
937#[allow(dead_code)]
938pub struct NonEmptyVec<T> {
939    head: T,
940    tail: Vec<T>,
941}
942#[allow(dead_code)]
943impl<T> NonEmptyVec<T> {
944    /// Creates a non-empty vec with a single element.
945    pub fn singleton(val: T) -> Self {
946        Self {
947            head: val,
948            tail: Vec::new(),
949        }
950    }
951    /// Pushes an element.
952    pub fn push(&mut self, val: T) {
953        self.tail.push(val);
954    }
955    /// Returns a reference to the first element.
956    pub fn first(&self) -> &T {
957        &self.head
958    }
959    /// Returns a reference to the last element.
960    pub fn last(&self) -> &T {
961        self.tail.last().unwrap_or(&self.head)
962    }
963    /// Returns the number of elements.
964    pub fn len(&self) -> usize {
965        1 + self.tail.len()
966    }
967    /// Returns whether the collection is empty.
968    pub fn is_empty(&self) -> bool {
969        self.len() == 0
970    }
971    /// Returns all elements as a Vec.
972    pub fn to_vec(&self) -> Vec<&T> {
973        let mut v = vec![&self.head];
974        v.extend(self.tail.iter());
975        v
976    }
977}
978/// A counter that can measure elapsed time between snapshots.
979#[allow(dead_code)]
980pub struct Stopwatch {
981    start: crate::wall_clock::Instant,
982    splits: Vec<f64>,
983}
984#[allow(dead_code)]
985impl Stopwatch {
986    /// Creates and starts a new stopwatch.
987    pub fn start() -> Self {
988        Self {
989            start: crate::wall_clock::Instant::now(),
990            splits: Vec::new(),
991        }
992    }
993    /// Records a split time (elapsed since start).
994    pub fn split(&mut self) {
995        self.splits.push(self.elapsed_ms());
996    }
997    /// Returns total elapsed milliseconds since start.
998    pub fn elapsed_ms(&self) -> f64 {
999        self.start.elapsed().as_secs_f64() * 1000.0
1000    }
1001    /// Returns all recorded split times.
1002    pub fn splits(&self) -> &[f64] {
1003        &self.splits
1004    }
1005    /// Returns the number of splits.
1006    pub fn num_splits(&self) -> usize {
1007        self.splits.len()
1008    }
1009}
1010/// A token bucket rate limiter.
1011#[allow(dead_code)]
1012pub struct TokenBucket {
1013    capacity: u64,
1014    tokens: u64,
1015    refill_per_ms: u64,
1016    last_refill: crate::wall_clock::Instant,
1017}
1018#[allow(dead_code)]
1019impl TokenBucket {
1020    /// Creates a new token bucket.
1021    pub fn new(capacity: u64, refill_per_ms: u64) -> Self {
1022        Self {
1023            capacity,
1024            tokens: capacity,
1025            refill_per_ms,
1026            last_refill: crate::wall_clock::Instant::now(),
1027        }
1028    }
1029    /// Attempts to consume `n` tokens.  Returns `true` on success.
1030    pub fn try_consume(&mut self, n: u64) -> bool {
1031        self.refill();
1032        if self.tokens >= n {
1033            self.tokens -= n;
1034            true
1035        } else {
1036            false
1037        }
1038    }
1039    fn refill(&mut self) {
1040        let now = crate::wall_clock::Instant::now();
1041        let elapsed_ms = now.duration_since(self.last_refill).as_millis() as u64;
1042        if elapsed_ms > 0 {
1043            let new_tokens = elapsed_ms * self.refill_per_ms;
1044            self.tokens = (self.tokens + new_tokens).min(self.capacity);
1045            self.last_refill = now;
1046        }
1047    }
1048    /// Returns the number of currently available tokens.
1049    pub fn available(&self) -> u64 {
1050        self.tokens
1051    }
1052    /// Returns the bucket capacity.
1053    pub fn capacity(&self) -> u64 {
1054        self.capacity
1055    }
1056}
1057/// A builder for incrementally constructing an `Environment`.
1058#[allow(dead_code)]
1059#[derive(Default)]
1060pub struct EnvironmentBuilder {
1061    declarations: Vec<Declaration>,
1062    constants: Vec<crate::declaration::ConstantInfo>,
1063}
1064impl EnvironmentBuilder {
1065    /// Create a new empty builder.
1066    #[allow(dead_code)]
1067    pub fn new() -> Self {
1068        Self::default()
1069    }
1070    /// Queue a legacy declaration for addition.
1071    #[allow(dead_code)]
1072    pub fn add_decl(mut self, decl: Declaration) -> Self {
1073        self.declarations.push(decl);
1074        self
1075    }
1076    /// Queue a ConstantInfo for addition.
1077    #[allow(dead_code)]
1078    pub fn add_constant(mut self, ci: crate::declaration::ConstantInfo) -> Self {
1079        self.constants.push(ci);
1080        self
1081    }
1082    /// Build the environment.
1083    #[allow(dead_code)]
1084    pub fn build(self) -> Result<Environment, EnvError> {
1085        let mut env = Environment::new();
1086        for decl in self.declarations {
1087            env.add(decl)?;
1088        }
1089        for ci in self.constants {
1090            env.add_constant(ci)?;
1091        }
1092        Ok(env)
1093    }
1094    /// Return the number of queued items.
1095    #[allow(dead_code)]
1096    pub fn len(&self) -> usize {
1097        self.declarations.len() + self.constants.len()
1098    }
1099    /// Check if the builder has nothing queued.
1100    #[allow(dead_code)]
1101    pub fn is_empty(&self) -> bool {
1102        self.declarations.is_empty() && self.constants.is_empty()
1103    }
1104}
1105/// A simple decision tree node for rule dispatching.
1106#[allow(dead_code)]
1107#[allow(missing_docs)]
1108pub enum DecisionNode {
1109    /// A leaf with an action string.
1110    Leaf(String),
1111    /// An interior node: check `key` equals `val` → `yes_branch`, else `no_branch`.
1112    Branch {
1113        key: String,
1114        val: String,
1115        yes_branch: Box<DecisionNode>,
1116        no_branch: Box<DecisionNode>,
1117    },
1118}
1119#[allow(dead_code)]
1120impl DecisionNode {
1121    /// Evaluates the decision tree with the given context.
1122    pub fn evaluate(&self, ctx: &std::collections::HashMap<String, String>) -> &str {
1123        match self {
1124            DecisionNode::Leaf(action) => action.as_str(),
1125            DecisionNode::Branch {
1126                key,
1127                val,
1128                yes_branch,
1129                no_branch,
1130            } => {
1131                let actual = ctx.get(key).map(|s| s.as_str()).unwrap_or("");
1132                if actual == val.as_str() {
1133                    yes_branch.evaluate(ctx)
1134                } else {
1135                    no_branch.evaluate(ctx)
1136                }
1137            }
1138        }
1139    }
1140    /// Returns the depth of the decision tree.
1141    pub fn depth(&self) -> usize {
1142        match self {
1143            DecisionNode::Leaf(_) => 0,
1144            DecisionNode::Branch {
1145                yes_branch,
1146                no_branch,
1147                ..
1148            } => 1 + yes_branch.depth().max(no_branch.depth()),
1149        }
1150    }
1151}
1152/// A pool of reusable string buffers.
1153#[allow(dead_code)]
1154pub struct StringPool {
1155    free: Vec<String>,
1156}
1157#[allow(dead_code)]
1158impl StringPool {
1159    /// Creates a new empty string pool.
1160    pub fn new() -> Self {
1161        Self { free: Vec::new() }
1162    }
1163    /// Takes a string from the pool (may be empty).
1164    pub fn take(&mut self) -> String {
1165        self.free.pop().unwrap_or_default()
1166    }
1167    /// Returns a string to the pool.
1168    pub fn give(&mut self, mut s: String) {
1169        s.clear();
1170        self.free.push(s);
1171    }
1172    /// Returns the number of free strings in the pool.
1173    pub fn free_count(&self) -> usize {
1174        self.free.len()
1175    }
1176}
1177/// A tagged union for representing a simple two-case discriminated union.
1178#[allow(dead_code)]
1179pub enum Either2<A, B> {
1180    /// The first alternative.
1181    First(A),
1182    /// The second alternative.
1183    Second(B),
1184}
1185#[allow(dead_code)]
1186impl<A, B> Either2<A, B> {
1187    /// Returns `true` if this is the first alternative.
1188    pub fn is_first(&self) -> bool {
1189        matches!(self, Either2::First(_))
1190    }
1191    /// Returns `true` if this is the second alternative.
1192    pub fn is_second(&self) -> bool {
1193        matches!(self, Either2::Second(_))
1194    }
1195    /// Returns the first value if present.
1196    pub fn first(self) -> Option<A> {
1197        match self {
1198            Either2::First(a) => Some(a),
1199            _ => None,
1200        }
1201    }
1202    /// Returns the second value if present.
1203    pub fn second(self) -> Option<B> {
1204        match self {
1205            Either2::Second(b) => Some(b),
1206            _ => None,
1207        }
1208    }
1209    /// Maps over the first alternative.
1210    pub fn map_first<C, F: FnOnce(A) -> C>(self, f: F) -> Either2<C, B> {
1211        match self {
1212            Either2::First(a) => Either2::First(f(a)),
1213            Either2::Second(b) => Either2::Second(b),
1214        }
1215    }
1216}
1217/// A simple stack-based calculator for arithmetic expressions.
1218#[allow(dead_code)]
1219pub struct StackCalc {
1220    stack: Vec<i64>,
1221}
1222#[allow(dead_code)]
1223impl StackCalc {
1224    /// Creates a new empty calculator.
1225    pub fn new() -> Self {
1226        Self { stack: Vec::new() }
1227    }
1228    /// Pushes an integer literal.
1229    pub fn push(&mut self, n: i64) {
1230        self.stack.push(n);
1231    }
1232    /// Replaces the top two values, `b` on top of `a`, with `op(a, b)` and
1233    /// returns it.  Returns `None`, leaving the stack unchanged, if it holds
1234    /// fewer than two values.
1235    fn apply_binary(&mut self, op: impl FnOnce(i64, i64) -> i64) -> Option<i64> {
1236        let (rest_len, a, b) = match self.stack[..] {
1237            [ref rest @ .., a, b] => (rest.len(), a, b),
1238            _ => return None,
1239        };
1240        let value = op(a, b);
1241        self.stack.truncate(rest_len);
1242        self.stack.push(value);
1243        Some(value)
1244    }
1245    /// Adds the top two values and returns the sum, which replaces them.
1246    /// Returns `None`, leaving the stack unchanged, if it holds fewer than
1247    /// two values.
1248    pub fn add(&mut self) -> Option<i64> {
1249        self.apply_binary(|a, b| a + b)
1250    }
1251    /// Subtracts top from second and returns the difference, which replaces
1252    /// them.  Returns `None`, leaving the stack unchanged, if it holds fewer
1253    /// than two values.
1254    pub fn sub(&mut self) -> Option<i64> {
1255        self.apply_binary(|a, b| a - b)
1256    }
1257    /// Multiplies the top two values and returns the product, which replaces
1258    /// them.  Returns `None`, leaving the stack unchanged, if it holds fewer
1259    /// than two values.
1260    pub fn mul(&mut self) -> Option<i64> {
1261        self.apply_binary(|a, b| a * b)
1262    }
1263    /// Peeks the top value.
1264    pub fn peek(&self) -> Option<i64> {
1265        self.stack.last().copied()
1266    }
1267    /// Returns the stack depth.
1268    pub fn depth(&self) -> usize {
1269        self.stack.len()
1270    }
1271}
1272/// A fixed-size sliding window that computes a running sum.
1273#[allow(dead_code)]
1274pub struct SlidingSum {
1275    window: Vec<f64>,
1276    capacity: usize,
1277    pos: usize,
1278    sum: f64,
1279    count: usize,
1280}
1281#[allow(dead_code)]
1282impl SlidingSum {
1283    /// Creates a sliding sum with the given window size.
1284    pub fn new(capacity: usize) -> Self {
1285        Self {
1286            window: vec![0.0; capacity],
1287            capacity,
1288            pos: 0,
1289            sum: 0.0,
1290            count: 0,
1291        }
1292    }
1293    /// Adds a value to the window, removing the oldest if full.
1294    pub fn push(&mut self, val: f64) {
1295        let oldest = self.window[self.pos];
1296        self.sum -= oldest;
1297        self.sum += val;
1298        self.window[self.pos] = val;
1299        self.pos = (self.pos + 1) % self.capacity;
1300        if self.count < self.capacity {
1301            self.count += 1;
1302        }
1303    }
1304    /// Returns the current window sum.
1305    pub fn sum(&self) -> f64 {
1306        self.sum
1307    }
1308    /// Returns the window mean, or `None` if empty.
1309    pub fn mean(&self) -> Option<f64> {
1310        if self.count == 0 {
1311            None
1312        } else {
1313            Some(self.sum / self.count as f64)
1314        }
1315    }
1316    /// Returns the current window size (number of valid elements).
1317    pub fn count(&self) -> usize {
1318        self.count
1319    }
1320}
1321/// A reusable scratch buffer for path computations.
1322#[allow(dead_code)]
1323pub struct PathBuf {
1324    components: Vec<String>,
1325}
1326#[allow(dead_code)]
1327impl PathBuf {
1328    /// Creates a new empty path buffer.
1329    pub fn new() -> Self {
1330        Self {
1331            components: Vec::new(),
1332        }
1333    }
1334    /// Pushes a component.
1335    pub fn push(&mut self, comp: impl Into<String>) {
1336        self.components.push(comp.into());
1337    }
1338    /// Pops the last component.
1339    pub fn pop(&mut self) {
1340        self.components.pop();
1341    }
1342    /// Returns the current path as a `/`-separated string.
1343    pub fn as_str(&self) -> String {
1344        self.components.join("/")
1345    }
1346    /// Returns the depth of the path.
1347    pub fn depth(&self) -> usize {
1348        self.components.len()
1349    }
1350    /// Clears the path.
1351    pub fn clear(&mut self) {
1352        self.components.clear();
1353    }
1354}
1355/// A flat list of substitution pairs `(from, to)`.
1356#[allow(dead_code)]
1357pub struct FlatSubstitution {
1358    pairs: Vec<(String, String)>,
1359}
1360#[allow(dead_code)]
1361impl FlatSubstitution {
1362    /// Creates an empty substitution.
1363    pub fn new() -> Self {
1364        Self { pairs: Vec::new() }
1365    }
1366    /// Adds a pair.
1367    pub fn add(&mut self, from: impl Into<String>, to: impl Into<String>) {
1368        self.pairs.push((from.into(), to.into()));
1369    }
1370    /// Applies all substitutions to `s` (leftmost-first order).
1371    pub fn apply(&self, s: &str) -> String {
1372        let mut result = s.to_string();
1373        for (from, to) in &self.pairs {
1374            result = result.replace(from.as_str(), to.as_str());
1375        }
1376        result
1377    }
1378    /// Returns the number of pairs.
1379    pub fn len(&self) -> usize {
1380        self.pairs.len()
1381    }
1382    /// Returns `true` if empty.
1383    pub fn is_empty(&self) -> bool {
1384        self.pairs.is_empty()
1385    }
1386}
1387/// Errors that can occur when working with the environment.
1388#[derive(Clone, Debug)]
1389pub enum EnvError {
1390    /// A declaration with this name already exists
1391    DuplicateDeclaration(Name),
1392    /// The declaration was not found
1393    NotFound(Name),
1394    /// A quotient-related precondition failed (e.g. quotients already
1395    /// initialized, `Eq` missing or malformed, or an attempt to add a
1396    /// `ConstantInfo::Quotient` outside of [`Environment::add_quot`]).
1397    InvalidQuotient(String),
1398}
1399/// A pair of `StatSummary` values tracking before/after a transformation.
1400#[allow(dead_code)]
1401pub struct TransformStat {
1402    before: StatSummary,
1403    after: StatSummary,
1404}
1405#[allow(dead_code)]
1406impl TransformStat {
1407    /// Creates a new transform stat recorder.
1408    pub fn new() -> Self {
1409        Self {
1410            before: StatSummary::new(),
1411            after: StatSummary::new(),
1412        }
1413    }
1414    /// Records a before value.
1415    pub fn record_before(&mut self, v: f64) {
1416        self.before.record(v);
1417    }
1418    /// Records an after value.
1419    pub fn record_after(&mut self, v: f64) {
1420        self.after.record(v);
1421    }
1422    /// Returns the mean reduction ratio (after/before).
1423    pub fn mean_ratio(&self) -> Option<f64> {
1424        let b = self.before.mean()?;
1425        let a = self.after.mean()?;
1426        if b.abs() < f64::EPSILON {
1427            return None;
1428        }
1429        Some(a / b)
1430    }
1431}
1432/// A dependency closure builder (transitive closure via BFS).
1433#[allow(dead_code)]
1434pub struct TransitiveClosure {
1435    adj: Vec<Vec<usize>>,
1436    n: usize,
1437}
1438#[allow(dead_code)]
1439impl TransitiveClosure {
1440    /// Creates a transitive closure builder for `n` nodes.
1441    pub fn new(n: usize) -> Self {
1442        Self {
1443            adj: vec![Vec::new(); n],
1444            n,
1445        }
1446    }
1447    /// Adds a direct edge.
1448    pub fn add_edge(&mut self, from: usize, to: usize) {
1449        if from < self.n {
1450            self.adj[from].push(to);
1451        }
1452    }
1453    /// Computes all nodes reachable from `start` (including `start`).
1454    pub fn reachable_from(&self, start: usize) -> Vec<usize> {
1455        let mut visited = vec![false; self.n];
1456        let mut queue = std::collections::VecDeque::new();
1457        queue.push_back(start);
1458        while let Some(node) = queue.pop_front() {
1459            if node >= self.n || visited[node] {
1460                continue;
1461            }
1462            visited[node] = true;
1463            for &next in &self.adj[node] {
1464                queue.push_back(next);
1465            }
1466        }
1467        (0..self.n).filter(|&i| visited[i]).collect()
1468    }
1469    /// Returns `true` if `from` can transitively reach `to`.
1470    pub fn can_reach(&self, from: usize, to: usize) -> bool {
1471        self.reachable_from(from).contains(&to)
1472    }
1473}
1474/// A min-heap implemented as a binary heap.
1475#[allow(dead_code)]
1476pub struct MinHeap<T: Ord> {
1477    data: Vec<T>,
1478}
1479#[allow(dead_code)]
1480impl<T: Ord> MinHeap<T> {
1481    /// Creates a new empty min-heap.
1482    pub fn new() -> Self {
1483        Self { data: Vec::new() }
1484    }
1485    /// Inserts an element.
1486    pub fn push(&mut self, val: T) {
1487        self.data.push(val);
1488        self.sift_up(self.data.len() - 1);
1489    }
1490    /// Removes and returns the minimum element.
1491    pub fn pop(&mut self) -> Option<T> {
1492        if self.data.is_empty() {
1493            return None;
1494        }
1495        let n = self.data.len();
1496        self.data.swap(0, n - 1);
1497        let min = self.data.pop();
1498        if !self.data.is_empty() {
1499            self.sift_down(0);
1500        }
1501        min
1502    }
1503    /// Returns a reference to the minimum element.
1504    pub fn peek(&self) -> Option<&T> {
1505        self.data.first()
1506    }
1507    /// Returns the number of elements.
1508    pub fn len(&self) -> usize {
1509        self.data.len()
1510    }
1511    /// Returns `true` if empty.
1512    pub fn is_empty(&self) -> bool {
1513        self.data.is_empty()
1514    }
1515    fn sift_up(&mut self, mut i: usize) {
1516        while i > 0 {
1517            let parent = (i - 1) / 2;
1518            if self.data[i] < self.data[parent] {
1519                self.data.swap(i, parent);
1520                i = parent;
1521            } else {
1522                break;
1523            }
1524        }
1525    }
1526    fn sift_down(&mut self, mut i: usize) {
1527        let n = self.data.len();
1528        loop {
1529            let left = 2 * i + 1;
1530            let right = 2 * i + 2;
1531            let mut smallest = i;
1532            if left < n && self.data[left] < self.data[smallest] {
1533                smallest = left;
1534            }
1535            if right < n && self.data[right] < self.data[smallest] {
1536                smallest = right;
1537            }
1538            if smallest == i {
1539                break;
1540            }
1541            self.data.swap(i, smallest);
1542            i = smallest;
1543        }
1544    }
1545}
1546/// A hierarchical configuration tree.
1547#[allow(dead_code)]
1548pub struct ConfigNode {
1549    key: String,
1550    value: Option<String>,
1551    children: Vec<ConfigNode>,
1552}
1553#[allow(dead_code)]
1554impl ConfigNode {
1555    /// Creates a leaf config node with a value.
1556    pub fn leaf(key: impl Into<String>, value: impl Into<String>) -> Self {
1557        Self {
1558            key: key.into(),
1559            value: Some(value.into()),
1560            children: Vec::new(),
1561        }
1562    }
1563    /// Creates a section node with children.
1564    pub fn section(key: impl Into<String>) -> Self {
1565        Self {
1566            key: key.into(),
1567            value: None,
1568            children: Vec::new(),
1569        }
1570    }
1571    /// Adds a child node.
1572    pub fn add_child(&mut self, child: ConfigNode) {
1573        self.children.push(child);
1574    }
1575    /// Returns the key.
1576    pub fn key(&self) -> &str {
1577        &self.key
1578    }
1579    /// Returns the value, or `None` for section nodes.
1580    pub fn value(&self) -> Option<&str> {
1581        self.value.as_deref()
1582    }
1583    /// Returns the number of children.
1584    pub fn num_children(&self) -> usize {
1585        self.children.len()
1586    }
1587    /// Looks up a dot-separated path.
1588    pub fn lookup(&self, path: &str) -> Option<&str> {
1589        let mut parts = path.splitn(2, '.');
1590        let head = parts.next()?;
1591        let tail = parts.next();
1592        if head != self.key {
1593            return None;
1594        }
1595        match tail {
1596            None => self.value.as_deref(),
1597            Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
1598        }
1599    }
1600    fn lookup_relative(&self, path: &str) -> Option<&str> {
1601        let mut parts = path.splitn(2, '.');
1602        let head = parts.next()?;
1603        let tail = parts.next();
1604        if head != self.key {
1605            return None;
1606        }
1607        match tail {
1608            None => self.value.as_deref(),
1609            Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
1610        }
1611    }
1612}
1613/// A snapshot of an `Environment` at a point in time.
1614///
1615/// Snapshots are useful for implementing undo/redo in interactive mode.
1616#[derive(Clone, Debug)]
1617pub struct EnvironmentSnapshot {
1618    /// Names present at snapshot time, in insertion order.
1619    pub names: Vec<Name>,
1620}
1621impl EnvironmentSnapshot {
1622    /// Create a snapshot from an environment.
1623    pub fn from_env(env: &Environment) -> Self {
1624        let names: Vec<Name> = env.constant_names().cloned().collect();
1625        Self { names }
1626    }
1627    /// Number of constants in the snapshot.
1628    pub fn len(&self) -> usize {
1629        self.names.len()
1630    }
1631    /// Check if empty.
1632    pub fn is_empty(&self) -> bool {
1633        self.names.is_empty()
1634    }
1635    /// Return the names added in `new` that were not in `self`.
1636    pub fn diff<'a>(&self, new: &'a EnvironmentSnapshot) -> Vec<&'a Name> {
1637        new.names
1638            .iter()
1639            .filter(|n| !self.names.contains(n))
1640            .collect()
1641    }
1642}
1643/// A simple key-value store backed by a sorted Vec for small maps.
1644#[allow(dead_code)]
1645pub struct SmallMap<K: Ord + Clone, V: Clone> {
1646    entries: Vec<(K, V)>,
1647}
1648#[allow(dead_code)]
1649impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
1650    /// Creates a new empty small map.
1651    pub fn new() -> Self {
1652        Self {
1653            entries: Vec::new(),
1654        }
1655    }
1656    /// Inserts or replaces the value for `key`.
1657    pub fn insert(&mut self, key: K, val: V) {
1658        match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
1659            Ok(i) => self.entries[i].1 = val,
1660            Err(i) => self.entries.insert(i, (key, val)),
1661        }
1662    }
1663    /// Returns the value for `key`, or `None`.
1664    pub fn get(&self, key: &K) -> Option<&V> {
1665        self.entries
1666            .binary_search_by_key(&key, |(k, _)| k)
1667            .ok()
1668            .map(|i| &self.entries[i].1)
1669    }
1670    /// Returns the number of entries.
1671    pub fn len(&self) -> usize {
1672        self.entries.len()
1673    }
1674    /// Returns `true` if empty.
1675    pub fn is_empty(&self) -> bool {
1676        self.entries.is_empty()
1677    }
1678    /// Returns all keys.
1679    pub fn keys(&self) -> Vec<&K> {
1680        self.entries.iter().map(|(k, _)| k).collect()
1681    }
1682    /// Returns all values.
1683    pub fn values(&self) -> Vec<&V> {
1684        self.entries.iter().map(|(_, v)| v).collect()
1685    }
1686}
1687/// A simple directed acyclic graph.
1688#[allow(dead_code)]
1689pub struct SimpleDag {
1690    /// `edges[i]` is the list of direct successors of node `i`.
1691    edges: Vec<Vec<usize>>,
1692}
1693#[allow(dead_code)]
1694impl SimpleDag {
1695    /// Creates a DAG with `n` nodes and no edges.
1696    pub fn new(n: usize) -> Self {
1697        Self {
1698            edges: vec![Vec::new(); n],
1699        }
1700    }
1701    /// Adds an edge from `from` to `to`.
1702    pub fn add_edge(&mut self, from: usize, to: usize) {
1703        if from < self.edges.len() {
1704            self.edges[from].push(to);
1705        }
1706    }
1707    /// Returns the successors of `node`.
1708    pub fn successors(&self, node: usize) -> &[usize] {
1709        self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
1710    }
1711    /// Returns `true` if `from` can reach `to` via DFS.
1712    pub fn can_reach(&self, from: usize, to: usize) -> bool {
1713        let mut visited = vec![false; self.edges.len()];
1714        self.dfs(from, to, &mut visited)
1715    }
1716    fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
1717        if cur == target {
1718            return true;
1719        }
1720        if cur >= visited.len() || visited[cur] {
1721            return false;
1722        }
1723        visited[cur] = true;
1724        for &next in self.successors(cur) {
1725            if self.dfs(next, target, visited) {
1726                return true;
1727            }
1728        }
1729        false
1730    }
1731    /// Returns the topological order of nodes, or `None` if a cycle is detected.
1732    pub fn topological_sort(&self) -> Option<Vec<usize>> {
1733        let n = self.edges.len();
1734        let mut in_degree = vec![0usize; n];
1735        for succs in &self.edges {
1736            for &s in succs {
1737                if s < n {
1738                    in_degree[s] += 1;
1739                }
1740            }
1741        }
1742        let mut queue: std::collections::VecDeque<usize> =
1743            (0..n).filter(|&i| in_degree[i] == 0).collect();
1744        let mut order = Vec::new();
1745        while let Some(node) = queue.pop_front() {
1746            order.push(node);
1747            for &s in self.successors(node) {
1748                if s < n {
1749                    in_degree[s] -= 1;
1750                    if in_degree[s] == 0 {
1751                        queue.push_back(s);
1752                    }
1753                }
1754            }
1755        }
1756        if order.len() == n {
1757            Some(order)
1758        } else {
1759            None
1760        }
1761    }
1762    /// Returns the number of nodes.
1763    pub fn num_nodes(&self) -> usize {
1764        self.edges.len()
1765    }
1766}
1767/// A write-once cell.
1768#[allow(dead_code)]
1769pub struct WriteOnce<T> {
1770    value: std::cell::Cell<Option<T>>,
1771}
1772#[allow(dead_code)]
1773impl<T: Copy> WriteOnce<T> {
1774    /// Creates an empty write-once cell.
1775    pub fn new() -> Self {
1776        Self {
1777            value: std::cell::Cell::new(None),
1778        }
1779    }
1780    /// Writes a value.  Returns `false` if already written.
1781    pub fn write(&self, val: T) -> bool {
1782        if self.value.get().is_some() {
1783            return false;
1784        }
1785        self.value.set(Some(val));
1786        true
1787    }
1788    /// Returns the value if written.
1789    pub fn read(&self) -> Option<T> {
1790        self.value.get()
1791    }
1792    /// Returns `true` if the value has been written.
1793    pub fn is_written(&self) -> bool {
1794        self.value.get().is_some()
1795    }
1796}