Skip to main content

oxilean_kernel/typeclasses/
types.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use super::functions::*;
6use crate::{Expr, Name};
7use std::collections::HashMap;
8
9/// A pool of reusable string buffers.
10#[allow(dead_code)]
11pub struct StringPool {
12    free: Vec<String>,
13}
14#[allow(dead_code)]
15impl StringPool {
16    /// Creates a new empty string pool.
17    pub fn new() -> Self {
18        Self { free: Vec::new() }
19    }
20    /// Takes a string from the pool (may be empty).
21    pub fn take(&mut self) -> String {
22        self.free.pop().unwrap_or_default()
23    }
24    /// Returns a string to the pool.
25    pub fn give(&mut self, mut s: String) {
26        s.clear();
27        self.free.push(s);
28    }
29    /// Returns the number of free strings in the pool.
30    pub fn free_count(&self) -> usize {
31        self.free.len()
32    }
33}
34/// Priority levels for instance selection.
35#[allow(dead_code)]
36#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
37pub enum InstancePriority {
38    /// Low priority (fallback).
39    Low = 0,
40    /// Normal priority.
41    #[default]
42    Normal = 100,
43    /// High priority (preferred over Normal).
44    High = 200,
45    /// Forced priority (always chosen).
46    Forced = 1000,
47}
48impl InstancePriority {
49    /// Convert a numeric priority to an `InstancePriority`.
50    #[allow(dead_code)]
51    pub fn from_u32(n: u32) -> Self {
52        match n {
53            0..=50 => InstancePriority::Low,
54            51..=150 => InstancePriority::Normal,
55            151..=500 => InstancePriority::High,
56            _ => InstancePriority::Forced,
57        }
58    }
59    /// Numeric value.
60    #[allow(dead_code)]
61    pub fn value(self) -> u32 {
62        self as u32
63    }
64}
65/// A versioned record that stores a history of values.
66#[allow(dead_code)]
67pub struct VersionedRecord<T: Clone> {
68    history: Vec<T>,
69}
70#[allow(dead_code)]
71impl<T: Clone> VersionedRecord<T> {
72    /// Creates a new record with an initial value.
73    pub fn new(initial: T) -> Self {
74        Self {
75            history: vec![initial],
76        }
77    }
78    /// Updates the record with a new version.
79    pub fn update(&mut self, val: T) {
80        self.history.push(val);
81    }
82    /// Returns the current (latest) value.
83    pub fn current(&self) -> &T {
84        self.history
85            .last()
86            .expect("VersionedRecord history is always non-empty after construction")
87    }
88    /// Returns the value at version `n` (0-indexed), or `None`.
89    pub fn at_version(&self, n: usize) -> Option<&T> {
90        self.history.get(n)
91    }
92    /// Returns the version number of the current value.
93    pub fn version(&self) -> usize {
94        self.history.len() - 1
95    }
96    /// Returns `true` if more than one version exists.
97    pub fn has_history(&self) -> bool {
98        self.history.len() > 1
99    }
100}
101/// A simple decision tree node for rule dispatching.
102#[allow(dead_code)]
103#[allow(missing_docs)]
104pub enum DecisionNode {
105    /// A leaf with an action string.
106    Leaf(String),
107    /// An interior node: check `key` equals `val` → `yes_branch`, else `no_branch`.
108    Branch {
109        key: String,
110        val: String,
111        yes_branch: Box<DecisionNode>,
112        no_branch: Box<DecisionNode>,
113    },
114}
115#[allow(dead_code)]
116impl DecisionNode {
117    /// Evaluates the decision tree with the given context.
118    pub fn evaluate(&self, ctx: &std::collections::HashMap<String, String>) -> &str {
119        match self {
120            DecisionNode::Leaf(action) => action.as_str(),
121            DecisionNode::Branch {
122                key,
123                val,
124                yes_branch,
125                no_branch,
126            } => {
127                let actual = ctx.get(key).map(|s| s.as_str()).unwrap_or("");
128                if actual == val.as_str() {
129                    yes_branch.evaluate(ctx)
130                } else {
131                    no_branch.evaluate(ctx)
132                }
133            }
134        }
135    }
136    /// Returns the depth of the decision tree.
137    pub fn depth(&self) -> usize {
138        match self {
139            DecisionNode::Leaf(_) => 0,
140            DecisionNode::Branch {
141                yes_branch,
142                no_branch,
143                ..
144            } => 1 + yes_branch.depth().max(no_branch.depth()),
145        }
146    }
147}
148/// Represents a rewrite rule `lhs → rhs`.
149#[allow(dead_code)]
150#[allow(missing_docs)]
151pub struct RewriteRule {
152    /// The name of the rule.
153    pub name: String,
154    /// A string representation of the LHS pattern.
155    pub lhs: String,
156    /// A string representation of the RHS.
157    pub rhs: String,
158    /// Whether this is a conditional rule (has side conditions).
159    pub conditional: bool,
160}
161#[allow(dead_code)]
162impl RewriteRule {
163    /// Creates an unconditional rewrite rule.
164    pub fn unconditional(
165        name: impl Into<String>,
166        lhs: impl Into<String>,
167        rhs: impl Into<String>,
168    ) -> Self {
169        Self {
170            name: name.into(),
171            lhs: lhs.into(),
172            rhs: rhs.into(),
173            conditional: false,
174        }
175    }
176    /// Creates a conditional rewrite rule.
177    pub fn conditional(
178        name: impl Into<String>,
179        lhs: impl Into<String>,
180        rhs: impl Into<String>,
181    ) -> Self {
182        Self {
183            name: name.into(),
184            lhs: lhs.into(),
185            rhs: rhs.into(),
186            conditional: true,
187        }
188    }
189    /// Returns a textual representation.
190    pub fn display(&self) -> String {
191        format!("{}: {} → {}", self.name, self.lhs, self.rhs)
192    }
193}
194/// Statistics about typeclass resolution.
195#[allow(dead_code)]
196#[derive(Debug, Clone, Default)]
197pub struct TypeClassStats {
198    /// Number of successful instance lookups.
199    pub cache_hits: u64,
200    /// Number of failed instance lookups.
201    pub cache_misses: u64,
202    /// Total instance resolution calls.
203    pub total_lookups: u64,
204    /// Number of instances registered.
205    pub instances_registered: u64,
206    /// Number of classes registered.
207    pub classes_registered: u64,
208}
209impl TypeClassStats {
210    /// Create zeroed stats.
211    #[allow(dead_code)]
212    pub fn new() -> Self {
213        Self::default()
214    }
215    /// Hit rate for instance resolution (0.0–1.0).
216    #[allow(dead_code)]
217    pub fn hit_rate(&self) -> f64 {
218        if self.total_lookups == 0 {
219            1.0
220        } else {
221            self.cache_hits as f64 / self.total_lookups as f64
222        }
223    }
224    /// Merge another stats object.
225    #[allow(dead_code)]
226    pub fn merge(&mut self, other: &Self) {
227        self.cache_hits += other.cache_hits;
228        self.cache_misses += other.cache_misses;
229        self.total_lookups += other.total_lookups;
230        self.instances_registered += other.instances_registered;
231        self.classes_registered += other.classes_registered;
232    }
233}
234/// A type-erased function pointer with arity tracking.
235#[allow(dead_code)]
236pub struct RawFnPtr {
237    /// The raw function pointer (stored as usize for type erasure).
238    ptr: usize,
239    arity: usize,
240    name: String,
241}
242#[allow(dead_code)]
243impl RawFnPtr {
244    /// Creates a new raw function pointer descriptor.
245    pub fn new(ptr: usize, arity: usize, name: impl Into<String>) -> Self {
246        Self {
247            ptr,
248            arity,
249            name: name.into(),
250        }
251    }
252    /// Returns the arity.
253    pub fn arity(&self) -> usize {
254        self.arity
255    }
256    /// Returns the name.
257    pub fn name(&self) -> &str {
258        &self.name
259    }
260    /// Returns the raw pointer value.
261    pub fn raw(&self) -> usize {
262        self.ptr
263    }
264}
265/// A simple key-value store backed by a sorted Vec for small maps.
266#[allow(dead_code)]
267pub struct SmallMap<K: Ord + Clone, V: Clone> {
268    entries: Vec<(K, V)>,
269}
270#[allow(dead_code)]
271impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
272    /// Creates a new empty small map.
273    pub fn new() -> Self {
274        Self {
275            entries: Vec::new(),
276        }
277    }
278    /// Inserts or replaces the value for `key`.
279    pub fn insert(&mut self, key: K, val: V) {
280        match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
281            Ok(i) => self.entries[i].1 = val,
282            Err(i) => self.entries.insert(i, (key, val)),
283        }
284    }
285    /// Returns the value for `key`, or `None`.
286    pub fn get(&self, key: &K) -> Option<&V> {
287        self.entries
288            .binary_search_by_key(&key, |(k, _)| k)
289            .ok()
290            .map(|i| &self.entries[i].1)
291    }
292    /// Returns the number of entries.
293    pub fn len(&self) -> usize {
294        self.entries.len()
295    }
296    /// Returns `true` if empty.
297    pub fn is_empty(&self) -> bool {
298        self.entries.is_empty()
299    }
300    /// Returns all keys.
301    pub fn keys(&self) -> Vec<&K> {
302        self.entries.iter().map(|(k, _)| k).collect()
303    }
304    /// Returns all values.
305    pub fn values(&self) -> Vec<&V> {
306        self.entries.iter().map(|(_, v)| v).collect()
307    }
308}
309/// A layered typeclass registry that supports scoped instance introduction.
310///
311/// Useful for local `instance` declarations inside tactics or proofs.
312#[allow(dead_code)]
313#[derive(Debug, Default)]
314pub struct LayeredTypeClassRegistry {
315    /// Stack of local registries (outermost first).
316    layers: Vec<TypeClassRegistry>,
317    /// Global base registry.
318    global: TypeClassRegistry,
319}
320impl LayeredTypeClassRegistry {
321    /// Create a new empty layered registry.
322    #[allow(dead_code)]
323    pub fn new() -> Self {
324        Self {
325            layers: Vec::new(),
326            global: TypeClassRegistry::new(),
327        }
328    }
329    /// Push a new empty layer.
330    #[allow(dead_code)]
331    pub fn push_layer(&mut self) {
332        self.layers.push(TypeClassRegistry::new());
333    }
334    /// Pop the topmost layer.
335    #[allow(dead_code)]
336    pub fn pop_layer(&mut self) {
337        self.layers.pop();
338    }
339    /// Register an instance in the top layer (or global if no layers).
340    #[allow(dead_code)]
341    pub fn add_instance(&mut self, inst: Instance) {
342        if let Some(top) = self.layers.last_mut() {
343            top.register_instance(inst);
344        } else {
345            self.global.register_instance(inst);
346        }
347    }
348    /// Register a class in the global registry.
349    #[allow(dead_code)]
350    pub fn add_class(&mut self, class: TypeClass) {
351        self.global.register_class(class);
352    }
353    /// Find an instance by searching from the top layer to global.
354    #[allow(dead_code)]
355    pub fn find_instance(&self, class: &Name, ty: &Expr) -> Option<&Instance> {
356        for layer in self.layers.iter().rev() {
357            let found = layer.find_instances(class, ty);
358            if let Some(inst) = found.into_iter().next() {
359                return Some(inst);
360            }
361        }
362        self.global.find_instances(class, ty).into_iter().next()
363    }
364    /// Current number of layers.
365    #[allow(dead_code)]
366    pub fn depth(&self) -> usize {
367        self.layers.len()
368    }
369    /// Total instance count across all layers.
370    #[allow(dead_code)]
371    pub fn total_instances(&self) -> usize {
372        let layer_total: usize = self.layers.iter().map(|l| l.instances.len()).sum();
373        layer_total + self.global.instances.len()
374    }
375}
376/// A flat list of substitution pairs `(from, to)`.
377#[allow(dead_code)]
378pub struct FlatSubstitution {
379    pairs: Vec<(String, String)>,
380}
381#[allow(dead_code)]
382impl FlatSubstitution {
383    /// Creates an empty substitution.
384    pub fn new() -> Self {
385        Self { pairs: Vec::new() }
386    }
387    /// Adds a pair.
388    pub fn add(&mut self, from: impl Into<String>, to: impl Into<String>) {
389        self.pairs.push((from.into(), to.into()));
390    }
391    /// Applies all substitutions to `s` (leftmost-first order).
392    pub fn apply(&self, s: &str) -> String {
393        let mut result = s.to_string();
394        for (from, to) in &self.pairs {
395            result = result.replace(from.as_str(), to.as_str());
396        }
397        result
398    }
399    /// Returns the number of pairs.
400    pub fn len(&self) -> usize {
401        self.pairs.len()
402    }
403    /// Returns `true` if empty.
404    pub fn is_empty(&self) -> bool {
405        self.pairs.is_empty()
406    }
407}
408/// The registry that holds all type class and instance declarations.
409#[derive(Clone, Debug, Default)]
410pub struct TypeClassRegistry {
411    /// All registered classes, keyed by class name.
412    pub(super) classes: HashMap<String, TypeClass>,
413    /// All registered instances, in registration order.
414    pub(super) instances: Vec<Instance>,
415    /// Cache from (class, type-repr) → instance index.
416    instance_cache: HashMap<(String, String), usize>,
417}
418impl TypeClassRegistry {
419    /// Create an empty registry.
420    pub fn new() -> Self {
421        Self {
422            classes: HashMap::new(),
423            instances: Vec::new(),
424            instance_cache: HashMap::new(),
425        }
426    }
427    /// Register a type class.
428    pub fn register_class(&mut self, class: TypeClass) {
429        self.classes.insert(class.name.to_string(), class);
430    }
431    /// Look up a class by name.
432    pub fn get_class(&self, name: &Name) -> Option<&TypeClass> {
433        self.classes.get(&name.to_string())
434    }
435    /// Check whether a name refers to a registered class.
436    pub fn is_class(&self, name: &Name) -> bool {
437        self.classes.contains_key(&name.to_string())
438    }
439    /// Number of registered classes.
440    pub fn class_count(&self) -> usize {
441        self.classes.len()
442    }
443    /// Iterate over all class names.
444    pub fn class_names(&self) -> impl Iterator<Item = &String> {
445        self.classes.keys()
446    }
447    /// Get all classes that extend the given super-class.
448    pub fn subclasses_of(&self, super_name: &Name) -> Vec<&TypeClass> {
449        self.classes
450            .values()
451            .filter(|c| c.has_super(super_name))
452            .collect()
453    }
454    /// Register an instance.
455    pub fn register_instance(&mut self, instance: Instance) {
456        self.instance_cache
457            .remove(&(instance.class.to_string(), format!("{:?}", instance.ty)));
458        self.instances.push(instance);
459    }
460    /// Search for instances of the given class for the given type.
461    pub fn find_instances(&self, class: &Name, ty: &Expr) -> Vec<&Instance> {
462        self.instances
463            .iter()
464            .filter(|inst| &inst.class == class && instances_match(ty, &inst.ty))
465            .collect()
466    }
467    /// Find the best (highest priority, lowest number) instance.
468    pub fn find_best_instance(&self, class: &Name, ty: &Expr) -> InstanceSearchResult {
469        let mut candidates: Vec<&Instance> = self.find_instances(class, ty);
470        if candidates.is_empty() {
471            return InstanceSearchResult::NotFound;
472        }
473        candidates.sort_by_key(|i| i.priority);
474        let best_priority = candidates[0].priority;
475        let top: Vec<&Instance> = candidates
476            .iter()
477            .filter(|i| i.priority == best_priority)
478            .copied()
479            .collect();
480        if top.len() == 1 {
481            InstanceSearchResult::Found(top[0].clone())
482        } else {
483            InstanceSearchResult::Ambiguous(top.into_iter().cloned().collect())
484        }
485    }
486    /// Number of registered instances.
487    pub fn instance_count(&self) -> usize {
488        self.instances.len()
489    }
490    /// Remove all local instances.
491    pub fn clear_local_instances(&mut self) {
492        self.instances.retain(|i| !i.is_local);
493        self.instance_cache.clear();
494    }
495    /// Get all instances for a given class, sorted by priority.
496    pub fn instances_for_class(&self, class: &Name) -> Vec<&Instance> {
497        let mut result: Vec<&Instance> = self
498            .instances
499            .iter()
500            .filter(|i| &i.class == class)
501            .collect();
502        result.sort_by_key(|i| i.priority);
503        result
504    }
505    /// Get instances that match a given type predicate.
506    pub fn filter_instances<F>(&self, predicate: F) -> Vec<&Instance>
507    where
508        F: Fn(&Instance) -> bool,
509    {
510        self.instances.iter().filter(|i| predicate(i)).collect()
511    }
512    /// Get the projection expression for a method in a class (method index → projection).
513    pub fn method_projection(&self, class: &Name, method: &Name) -> Option<Expr> {
514        let cls = self.get_class(class)?;
515        let m = cls.find_method(method)?;
516        Some(build_method_projection(class, method, m.index))
517    }
518    /// Summarize the registry.
519    pub fn summary(&self) -> String {
520        format!(
521            "TypeClassRegistry {{ classes: {}, instances: {} }}",
522            self.classes.len(),
523            self.instances.len()
524        )
525    }
526}
527impl TypeClassRegistry {
528    /// Take a snapshot of the current instance count.
529    pub fn snapshot(&self) -> RegistrySnapshot {
530        RegistrySnapshot {
531            instance_count: self.instances.len(),
532        }
533    }
534    /// Restore the registry to a previously taken snapshot (removes instances added after).
535    pub fn restore(&mut self, snapshot: RegistrySnapshot) {
536        self.instances.truncate(snapshot.instance_count);
537        self.instance_cache.clear();
538    }
539}
540/// A pair of `StatSummary` values tracking before/after a transformation.
541#[allow(dead_code)]
542pub struct TransformStat {
543    before: StatSummary,
544    after: StatSummary,
545}
546#[allow(dead_code)]
547impl TransformStat {
548    /// Creates a new transform stat recorder.
549    pub fn new() -> Self {
550        Self {
551            before: StatSummary::new(),
552            after: StatSummary::new(),
553        }
554    }
555    /// Records a before value.
556    pub fn record_before(&mut self, v: f64) {
557        self.before.record(v);
558    }
559    /// Records an after value.
560    pub fn record_after(&mut self, v: f64) {
561        self.after.record(v);
562    }
563    /// Returns the mean reduction ratio (after/before).
564    pub fn mean_ratio(&self) -> Option<f64> {
565        let b = self.before.mean()?;
566        let a = self.after.mean()?;
567        if b.abs() < f64::EPSILON {
568            return None;
569        }
570        Some(a / b)
571    }
572}
573/// A reusable scratch buffer for path computations.
574#[allow(dead_code)]
575pub struct PathBuf {
576    components: Vec<String>,
577}
578#[allow(dead_code)]
579impl PathBuf {
580    /// Creates a new empty path buffer.
581    pub fn new() -> Self {
582        Self {
583            components: Vec::new(),
584        }
585    }
586    /// Pushes a component.
587    pub fn push(&mut self, comp: impl Into<String>) {
588        self.components.push(comp.into());
589    }
590    /// Pops the last component.
591    pub fn pop(&mut self) {
592        self.components.pop();
593    }
594    /// Returns the current path as a `/`-separated string.
595    pub fn as_str(&self) -> String {
596        self.components.join("/")
597    }
598    /// Returns the depth of the path.
599    pub fn depth(&self) -> usize {
600        self.components.len()
601    }
602    /// Clears the path.
603    pub fn clear(&mut self) {
604        self.components.clear();
605    }
606}
607/// A snapshot of a `TypeClassRegistry` for backtracking during elaboration.
608#[derive(Debug)]
609pub struct RegistrySnapshot {
610    instance_count: usize,
611}
612/// A set of rewrite rules.
613#[allow(dead_code)]
614pub struct RewriteRuleSet {
615    rules: Vec<RewriteRule>,
616}
617#[allow(dead_code)]
618impl RewriteRuleSet {
619    /// Creates an empty rule set.
620    pub fn new() -> Self {
621        Self { rules: Vec::new() }
622    }
623    /// Adds a rule.
624    pub fn add(&mut self, rule: RewriteRule) {
625        self.rules.push(rule);
626    }
627    /// Returns the number of rules.
628    pub fn len(&self) -> usize {
629        self.rules.len()
630    }
631    /// Returns `true` if the set is empty.
632    pub fn is_empty(&self) -> bool {
633        self.rules.is_empty()
634    }
635    /// Returns all conditional rules.
636    pub fn conditional_rules(&self) -> Vec<&RewriteRule> {
637        self.rules.iter().filter(|r| r.conditional).collect()
638    }
639    /// Returns all unconditional rules.
640    pub fn unconditional_rules(&self) -> Vec<&RewriteRule> {
641        self.rules.iter().filter(|r| !r.conditional).collect()
642    }
643    /// Looks up a rule by name.
644    pub fn get(&self, name: &str) -> Option<&RewriteRule> {
645        self.rules.iter().find(|r| r.name == name)
646    }
647}
648/// A sparse vector: stores only non-default elements.
649#[allow(dead_code)]
650pub struct SparseVec<T: Default + Clone + PartialEq> {
651    entries: std::collections::HashMap<usize, T>,
652    default_: T,
653    logical_len: usize,
654}
655#[allow(dead_code)]
656impl<T: Default + Clone + PartialEq> SparseVec<T> {
657    /// Creates a new sparse vector with logical length `len`.
658    pub fn new(len: usize) -> Self {
659        Self {
660            entries: std::collections::HashMap::new(),
661            default_: T::default(),
662            logical_len: len,
663        }
664    }
665    /// Sets element at `idx`.
666    pub fn set(&mut self, idx: usize, val: T) {
667        if val == self.default_ {
668            self.entries.remove(&idx);
669        } else {
670            self.entries.insert(idx, val);
671        }
672    }
673    /// Gets element at `idx`.
674    pub fn get(&self, idx: usize) -> &T {
675        self.entries.get(&idx).unwrap_or(&self.default_)
676    }
677    /// Returns the logical length.
678    pub fn len(&self) -> usize {
679        self.logical_len
680    }
681    /// Returns whether the collection is empty.
682    pub fn is_empty(&self) -> bool {
683        self.len() == 0
684    }
685    /// Returns the number of non-default elements.
686    pub fn nnz(&self) -> usize {
687        self.entries.len()
688    }
689}
690/// A non-empty list (at least one element guaranteed).
691#[allow(dead_code)]
692pub struct NonEmptyVec<T> {
693    head: T,
694    tail: Vec<T>,
695}
696#[allow(dead_code)]
697impl<T> NonEmptyVec<T> {
698    /// Creates a non-empty vec with a single element.
699    pub fn singleton(val: T) -> Self {
700        Self {
701            head: val,
702            tail: Vec::new(),
703        }
704    }
705    /// Pushes an element.
706    pub fn push(&mut self, val: T) {
707        self.tail.push(val);
708    }
709    /// Returns a reference to the first element.
710    pub fn first(&self) -> &T {
711        &self.head
712    }
713    /// Returns a reference to the last element.
714    pub fn last(&self) -> &T {
715        self.tail.last().unwrap_or(&self.head)
716    }
717    /// Returns the number of elements.
718    pub fn len(&self) -> usize {
719        1 + self.tail.len()
720    }
721    /// Returns whether the collection is empty.
722    pub fn is_empty(&self) -> bool {
723        self.len() == 0
724    }
725    /// Returns all elements as a Vec.
726    pub fn to_vec(&self) -> Vec<&T> {
727        let mut v = vec![&self.head];
728        v.extend(self.tail.iter());
729        v
730    }
731}
732/// A fixed-size sliding window that computes a running sum.
733#[allow(dead_code)]
734pub struct SlidingSum {
735    window: Vec<f64>,
736    capacity: usize,
737    pos: usize,
738    sum: f64,
739    count: usize,
740}
741#[allow(dead_code)]
742impl SlidingSum {
743    /// Creates a sliding sum with the given window size.
744    pub fn new(capacity: usize) -> Self {
745        Self {
746            window: vec![0.0; capacity],
747            capacity,
748            pos: 0,
749            sum: 0.0,
750            count: 0,
751        }
752    }
753    /// Adds a value to the window, removing the oldest if full.
754    pub fn push(&mut self, val: f64) {
755        let oldest = self.window[self.pos];
756        self.sum -= oldest;
757        self.sum += val;
758        self.window[self.pos] = val;
759        self.pos = (self.pos + 1) % self.capacity;
760        if self.count < self.capacity {
761            self.count += 1;
762        }
763    }
764    /// Returns the current window sum.
765    pub fn sum(&self) -> f64 {
766        self.sum
767    }
768    /// Returns the window mean, or `None` if empty.
769    pub fn mean(&self) -> Option<f64> {
770        if self.count == 0 {
771            None
772        } else {
773            Some(self.sum / self.count as f64)
774        }
775    }
776    /// Returns the current window size (number of valid elements).
777    pub fn count(&self) -> usize {
778        self.count
779    }
780}
781/// A write-once cell.
782#[allow(dead_code)]
783pub struct WriteOnce<T> {
784    value: std::cell::Cell<Option<T>>,
785}
786#[allow(dead_code)]
787impl<T: Copy> WriteOnce<T> {
788    /// Creates an empty write-once cell.
789    pub fn new() -> Self {
790        Self {
791            value: std::cell::Cell::new(None),
792        }
793    }
794    /// Writes a value.  Returns `false` if already written.
795    pub fn write(&self, val: T) -> bool {
796        if self.value.get().is_some() {
797            return false;
798        }
799        self.value.set(Some(val));
800        true
801    }
802    /// Returns the value if written.
803    pub fn read(&self) -> Option<T> {
804        self.value.get()
805    }
806    /// Returns `true` if the value has been written.
807    pub fn is_written(&self) -> bool {
808        self.value.get().is_some()
809    }
810}
811/// A simple stack-based calculator for arithmetic expressions.
812#[allow(dead_code)]
813pub struct StackCalc {
814    stack: Vec<i64>,
815}
816#[allow(dead_code)]
817impl StackCalc {
818    /// Creates a new empty calculator.
819    pub fn new() -> Self {
820        Self { stack: Vec::new() }
821    }
822    /// Pushes an integer literal.
823    pub fn push(&mut self, n: i64) {
824        self.stack.push(n);
825    }
826    /// Adds the top two values.  Panics if fewer than two values.
827    pub fn add(&mut self) {
828        let b = self
829            .stack
830            .pop()
831            .expect("stack must have at least two values for add");
832        let a = self
833            .stack
834            .pop()
835            .expect("stack must have at least two values for add");
836        self.stack.push(a + b);
837    }
838    /// Subtracts top from second.
839    pub fn sub(&mut self) {
840        let b = self
841            .stack
842            .pop()
843            .expect("stack must have at least two values for sub");
844        let a = self
845            .stack
846            .pop()
847            .expect("stack must have at least two values for sub");
848        self.stack.push(a - b);
849    }
850    /// Multiplies the top two values.
851    pub fn mul(&mut self) {
852        let b = self
853            .stack
854            .pop()
855            .expect("stack must have at least two values for mul");
856        let a = self
857            .stack
858            .pop()
859            .expect("stack must have at least two values for mul");
860        self.stack.push(a * b);
861    }
862    /// Peeks the top value.
863    pub fn peek(&self) -> Option<i64> {
864        self.stack.last().copied()
865    }
866    /// Returns the stack depth.
867    pub fn depth(&self) -> usize {
868        self.stack.len()
869    }
870}
871/// A counter that can measure elapsed time between snapshots.
872#[allow(dead_code)]
873pub struct Stopwatch {
874    start: std::time::Instant,
875    splits: Vec<f64>,
876}
877#[allow(dead_code)]
878impl Stopwatch {
879    /// Creates and starts a new stopwatch.
880    pub fn start() -> Self {
881        Self {
882            start: std::time::Instant::now(),
883            splits: Vec::new(),
884        }
885    }
886    /// Records a split time (elapsed since start).
887    pub fn split(&mut self) {
888        self.splits.push(self.elapsed_ms());
889    }
890    /// Returns total elapsed milliseconds since start.
891    pub fn elapsed_ms(&self) -> f64 {
892        self.start.elapsed().as_secs_f64() * 1000.0
893    }
894    /// Returns all recorded split times.
895    pub fn splits(&self) -> &[f64] {
896        &self.splits
897    }
898    /// Returns the number of splits.
899    pub fn num_splits(&self) -> usize {
900        self.splits.len()
901    }
902}
903/// A tagged union for representing a simple two-case discriminated union.
904#[allow(dead_code)]
905pub enum Either2<A, B> {
906    /// The first alternative.
907    First(A),
908    /// The second alternative.
909    Second(B),
910}
911#[allow(dead_code)]
912impl<A, B> Either2<A, B> {
913    /// Returns `true` if this is the first alternative.
914    pub fn is_first(&self) -> bool {
915        matches!(self, Either2::First(_))
916    }
917    /// Returns `true` if this is the second alternative.
918    pub fn is_second(&self) -> bool {
919        matches!(self, Either2::Second(_))
920    }
921    /// Returns the first value if present.
922    pub fn first(self) -> Option<A> {
923        match self {
924            Either2::First(a) => Some(a),
925            _ => None,
926        }
927    }
928    /// Returns the second value if present.
929    pub fn second(self) -> Option<B> {
930        match self {
931            Either2::Second(b) => Some(b),
932            _ => None,
933        }
934    }
935    /// Maps over the first alternative.
936    pub fn map_first<C, F: FnOnce(A) -> C>(self, f: F) -> Either2<C, B> {
937        match self {
938            Either2::First(a) => Either2::First(f(a)),
939            Either2::Second(b) => Either2::Second(b),
940        }
941    }
942}
943/// A hierarchical configuration tree.
944#[allow(dead_code)]
945pub struct ConfigNode {
946    key: String,
947    value: Option<String>,
948    children: Vec<ConfigNode>,
949}
950#[allow(dead_code)]
951impl ConfigNode {
952    /// Creates a leaf config node with a value.
953    pub fn leaf(key: impl Into<String>, value: impl Into<String>) -> Self {
954        Self {
955            key: key.into(),
956            value: Some(value.into()),
957            children: Vec::new(),
958        }
959    }
960    /// Creates a section node with children.
961    pub fn section(key: impl Into<String>) -> Self {
962        Self {
963            key: key.into(),
964            value: None,
965            children: Vec::new(),
966        }
967    }
968    /// Adds a child node.
969    pub fn add_child(&mut self, child: ConfigNode) {
970        self.children.push(child);
971    }
972    /// Returns the key.
973    pub fn key(&self) -> &str {
974        &self.key
975    }
976    /// Returns the value, or `None` for section nodes.
977    pub fn value(&self) -> Option<&str> {
978        self.value.as_deref()
979    }
980    /// Returns the number of children.
981    pub fn num_children(&self) -> usize {
982        self.children.len()
983    }
984    /// Looks up a dot-separated path.
985    pub fn lookup(&self, path: &str) -> Option<&str> {
986        let mut parts = path.splitn(2, '.');
987        let head = parts.next()?;
988        let tail = parts.next();
989        if head != self.key {
990            return None;
991        }
992        match tail {
993            None => self.value.as_deref(),
994            Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
995        }
996    }
997    fn lookup_relative(&self, path: &str) -> Option<&str> {
998        let mut parts = path.splitn(2, '.');
999        let head = parts.next()?;
1000        let tail = parts.next();
1001        if head != self.key {
1002            return None;
1003        }
1004        match tail {
1005            None => self.value.as_deref(),
1006            Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
1007        }
1008    }
1009}
1010/// An instance resolver that always returns `None`.
1011#[derive(Debug)]
1012pub struct NullResolver;
1013/// A window iterator that yields overlapping windows of size `n`.
1014#[allow(dead_code)]
1015pub struct WindowIterator<'a, T> {
1016    pub(super) data: &'a [T],
1017    pub(super) pos: usize,
1018    pub(super) window: usize,
1019}
1020#[allow(dead_code)]
1021impl<'a, T> WindowIterator<'a, T> {
1022    /// Creates a new window iterator.
1023    pub fn new(data: &'a [T], window: usize) -> Self {
1024        Self {
1025            data,
1026            pos: 0,
1027            window,
1028        }
1029    }
1030}
1031/// A generic counter that tracks min/max/sum for statistical summaries.
1032#[allow(dead_code)]
1033pub struct StatSummary {
1034    count: u64,
1035    sum: f64,
1036    min: f64,
1037    max: f64,
1038}
1039#[allow(dead_code)]
1040impl StatSummary {
1041    /// Creates an empty summary.
1042    pub fn new() -> Self {
1043        Self {
1044            count: 0,
1045            sum: 0.0,
1046            min: f64::INFINITY,
1047            max: f64::NEG_INFINITY,
1048        }
1049    }
1050    /// Records a sample.
1051    pub fn record(&mut self, val: f64) {
1052        self.count += 1;
1053        self.sum += val;
1054        if val < self.min {
1055            self.min = val;
1056        }
1057        if val > self.max {
1058            self.max = val;
1059        }
1060    }
1061    /// Returns the mean, or `None` if no samples.
1062    pub fn mean(&self) -> Option<f64> {
1063        if self.count == 0 {
1064            None
1065        } else {
1066            Some(self.sum / self.count as f64)
1067        }
1068    }
1069    /// Returns the minimum, or `None` if no samples.
1070    pub fn min(&self) -> Option<f64> {
1071        if self.count == 0 {
1072            None
1073        } else {
1074            Some(self.min)
1075        }
1076    }
1077    /// Returns the maximum, or `None` if no samples.
1078    pub fn max(&self) -> Option<f64> {
1079        if self.count == 0 {
1080            None
1081        } else {
1082            Some(self.max)
1083        }
1084    }
1085    /// Returns the count of recorded samples.
1086    pub fn count(&self) -> u64 {
1087        self.count
1088    }
1089}
1090/// A mutable reference stack for tracking the current "focus" in a tree traversal.
1091#[allow(dead_code)]
1092pub struct FocusStack<T> {
1093    items: Vec<T>,
1094}
1095#[allow(dead_code)]
1096impl<T> FocusStack<T> {
1097    /// Creates an empty focus stack.
1098    pub fn new() -> Self {
1099        Self { items: Vec::new() }
1100    }
1101    /// Focuses on `item`.
1102    pub fn focus(&mut self, item: T) {
1103        self.items.push(item);
1104    }
1105    /// Blurs (pops) the current focus.
1106    pub fn blur(&mut self) -> Option<T> {
1107        self.items.pop()
1108    }
1109    /// Returns the current focus, or `None`.
1110    pub fn current(&self) -> Option<&T> {
1111        self.items.last()
1112    }
1113    /// Returns the focus depth.
1114    pub fn depth(&self) -> usize {
1115        self.items.len()
1116    }
1117    /// Returns `true` if there is no current focus.
1118    pub fn is_empty(&self) -> bool {
1119        self.items.is_empty()
1120    }
1121}
1122/// A token bucket rate limiter.
1123#[allow(dead_code)]
1124pub struct TokenBucket {
1125    capacity: u64,
1126    tokens: u64,
1127    refill_per_ms: u64,
1128    last_refill: std::time::Instant,
1129}
1130#[allow(dead_code)]
1131impl TokenBucket {
1132    /// Creates a new token bucket.
1133    pub fn new(capacity: u64, refill_per_ms: u64) -> Self {
1134        Self {
1135            capacity,
1136            tokens: capacity,
1137            refill_per_ms,
1138            last_refill: std::time::Instant::now(),
1139        }
1140    }
1141    /// Attempts to consume `n` tokens.  Returns `true` on success.
1142    pub fn try_consume(&mut self, n: u64) -> bool {
1143        self.refill();
1144        if self.tokens >= n {
1145            self.tokens -= n;
1146            true
1147        } else {
1148            false
1149        }
1150    }
1151    fn refill(&mut self) {
1152        let now = std::time::Instant::now();
1153        let elapsed_ms = now.duration_since(self.last_refill).as_millis() as u64;
1154        if elapsed_ms > 0 {
1155            let new_tokens = elapsed_ms * self.refill_per_ms;
1156            self.tokens = (self.tokens + new_tokens).min(self.capacity);
1157            self.last_refill = now;
1158        }
1159    }
1160    /// Returns the number of currently available tokens.
1161    pub fn available(&self) -> u64 {
1162        self.tokens
1163    }
1164    /// Returns the bucket capacity.
1165    pub fn capacity(&self) -> u64 {
1166        self.capacity
1167    }
1168}
1169/// A complete set of method implementations for an instance.
1170#[allow(dead_code)]
1171#[derive(Clone, Debug, Default)]
1172pub struct InstanceImpl {
1173    /// Map from method name to implementation.
1174    impls: Vec<MethodImpl>,
1175}
1176impl InstanceImpl {
1177    /// Create an empty implementation set.
1178    #[allow(dead_code)]
1179    pub fn new() -> Self {
1180        Self::default()
1181    }
1182    /// Add a method implementation.
1183    #[allow(dead_code)]
1184    pub fn add(&mut self, impl_: MethodImpl) {
1185        self.impls.push(impl_);
1186    }
1187    /// Get the implementation for a method.
1188    #[allow(dead_code)]
1189    pub fn get(&self, method: &Name) -> Option<&MethodImpl> {
1190        self.impls.iter().find(|m| &m.method_name == method)
1191    }
1192    /// Number of implemented methods.
1193    #[allow(dead_code)]
1194    pub fn len(&self) -> usize {
1195        self.impls.len()
1196    }
1197    /// Check if empty.
1198    #[allow(dead_code)]
1199    pub fn is_empty(&self) -> bool {
1200        self.impls.is_empty()
1201    }
1202    /// Count default implementations.
1203    #[allow(dead_code)]
1204    pub fn count_defaults(&self) -> usize {
1205        self.impls.iter().filter(|m| m.is_default).count()
1206    }
1207    /// All method names.
1208    #[allow(dead_code)]
1209    pub fn method_names(&self) -> Vec<&Name> {
1210        self.impls.iter().map(|m| &m.method_name).collect()
1211    }
1212}
1213/// A dependency closure builder (transitive closure via BFS).
1214#[allow(dead_code)]
1215pub struct TransitiveClosure {
1216    adj: Vec<Vec<usize>>,
1217    n: usize,
1218}
1219#[allow(dead_code)]
1220impl TransitiveClosure {
1221    /// Creates a transitive closure builder for `n` nodes.
1222    pub fn new(n: usize) -> Self {
1223        Self {
1224            adj: vec![Vec::new(); n],
1225            n,
1226        }
1227    }
1228    /// Adds a direct edge.
1229    pub fn add_edge(&mut self, from: usize, to: usize) {
1230        if from < self.n {
1231            self.adj[from].push(to);
1232        }
1233    }
1234    /// Computes all nodes reachable from `start` (including `start`).
1235    pub fn reachable_from(&self, start: usize) -> Vec<usize> {
1236        let mut visited = vec![false; self.n];
1237        let mut queue = std::collections::VecDeque::new();
1238        queue.push_back(start);
1239        while let Some(node) = queue.pop_front() {
1240            if node >= self.n || visited[node] {
1241                continue;
1242            }
1243            visited[node] = true;
1244            for &next in &self.adj[node] {
1245                queue.push_back(next);
1246            }
1247        }
1248        (0..self.n).filter(|&i| visited[i]).collect()
1249    }
1250    /// Returns `true` if `from` can transitively reach `to`.
1251    pub fn can_reach(&self, from: usize, to: usize) -> bool {
1252        self.reachable_from(from).contains(&to)
1253    }
1254}
1255/// A simple directed acyclic graph.
1256#[allow(dead_code)]
1257pub struct SimpleDag {
1258    /// `edges[i]` is the list of direct successors of node `i`.
1259    edges: Vec<Vec<usize>>,
1260}
1261#[allow(dead_code)]
1262impl SimpleDag {
1263    /// Creates a DAG with `n` nodes and no edges.
1264    pub fn new(n: usize) -> Self {
1265        Self {
1266            edges: vec![Vec::new(); n],
1267        }
1268    }
1269    /// Adds an edge from `from` to `to`.
1270    pub fn add_edge(&mut self, from: usize, to: usize) {
1271        if from < self.edges.len() {
1272            self.edges[from].push(to);
1273        }
1274    }
1275    /// Returns the successors of `node`.
1276    pub fn successors(&self, node: usize) -> &[usize] {
1277        self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
1278    }
1279    /// Returns `true` if `from` can reach `to` via DFS.
1280    pub fn can_reach(&self, from: usize, to: usize) -> bool {
1281        let mut visited = vec![false; self.edges.len()];
1282        self.dfs(from, to, &mut visited)
1283    }
1284    fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
1285        if cur == target {
1286            return true;
1287        }
1288        if cur >= visited.len() || visited[cur] {
1289            return false;
1290        }
1291        visited[cur] = true;
1292        for &next in self.successors(cur) {
1293            if self.dfs(next, target, visited) {
1294                return true;
1295            }
1296        }
1297        false
1298    }
1299    /// Returns the topological order of nodes, or `None` if a cycle is detected.
1300    pub fn topological_sort(&self) -> Option<Vec<usize>> {
1301        let n = self.edges.len();
1302        let mut in_degree = vec![0usize; n];
1303        for succs in &self.edges {
1304            for &s in succs {
1305                if s < n {
1306                    in_degree[s] += 1;
1307                }
1308            }
1309        }
1310        let mut queue: std::collections::VecDeque<usize> =
1311            (0..n).filter(|&i| in_degree[i] == 0).collect();
1312        let mut order = Vec::new();
1313        while let Some(node) = queue.pop_front() {
1314            order.push(node);
1315            for &s in self.successors(node) {
1316                if s < n {
1317                    in_degree[s] -= 1;
1318                    if in_degree[s] == 0 {
1319                        queue.push_back(s);
1320                    }
1321                }
1322            }
1323        }
1324        if order.len() == n {
1325            Some(order)
1326        } else {
1327            None
1328        }
1329    }
1330    /// Returns the number of nodes.
1331    pub fn num_nodes(&self) -> usize {
1332        self.edges.len()
1333    }
1334}
1335/// A type class declaration.
1336///
1337/// For example, `class Add (α : Type)` declares a type class named `Add` with
1338/// one type parameter and one method `add : α → α → α`.
1339#[derive(Clone, Debug)]
1340pub struct TypeClass {
1341    /// Name of the class (e.g., `Add`, `Mul`, `Inhabited`).
1342    pub name: Name,
1343    /// Names of the type parameters.
1344    pub params: Vec<Name>,
1345    /// The full type of the class (as a Pi-type).
1346    pub ty: Expr,
1347    /// Methods declared in the class, in declaration order.
1348    pub methods: Vec<Method>,
1349    /// Names of super-classes that instances must also implement.
1350    pub super_classes: Vec<Name>,
1351    /// Whether this class is in Prop (proof-irrelevant).
1352    pub is_prop: bool,
1353}
1354impl TypeClass {
1355    /// Create a new type class with no methods or super-classes.
1356    pub fn new(name: Name, params: Vec<Name>, ty: Expr) -> Self {
1357        Self {
1358            name,
1359            params,
1360            ty,
1361            methods: Vec::new(),
1362            super_classes: Vec::new(),
1363            is_prop: false,
1364        }
1365    }
1366    /// Add a method to the class.
1367    pub fn add_method(&mut self, method: Method) {
1368        self.methods.push(method);
1369    }
1370    /// Add a super-class dependency.
1371    pub fn add_super(&mut self, super_name: Name) {
1372        self.super_classes.push(super_name);
1373    }
1374    /// Mark this class as living in Prop.
1375    pub fn mark_prop(mut self) -> Self {
1376        self.is_prop = true;
1377        self
1378    }
1379    /// Look up a method by name.
1380    pub fn find_method(&self, name: &Name) -> Option<&Method> {
1381        self.methods.iter().find(|m| &m.name == name)
1382    }
1383    /// Check whether the class has a super-class with the given name.
1384    pub fn has_super(&self, name: &Name) -> bool {
1385        self.super_classes.contains(name)
1386    }
1387    /// Count methods in the class.
1388    pub fn method_count(&self) -> usize {
1389        self.methods.len()
1390    }
1391    /// Check whether the class has any methods.
1392    pub fn is_empty(&self) -> bool {
1393        self.methods.is_empty()
1394    }
1395    /// Iterate over all method names.
1396    pub fn method_names(&self) -> impl Iterator<Item = &Name> {
1397        self.methods.iter().map(|m| &m.name)
1398    }
1399    /// Check whether the class has any super-classes.
1400    pub fn has_super_classes(&self) -> bool {
1401        !self.super_classes.is_empty()
1402    }
1403    /// Number of type parameters.
1404    pub fn arity(&self) -> usize {
1405        self.params.len()
1406    }
1407}
1408/// An instance of a type class.
1409///
1410/// For example, `instance : Add Nat` is an instance of `Add` for the type `Nat`.
1411#[derive(Clone, Debug)]
1412pub struct Instance {
1413    /// The class this is an instance of.
1414    pub class: Name,
1415    /// The type argument(s) for this instance.
1416    pub ty: Expr,
1417    /// Search priority (lower number = searched first).
1418    pub priority: i32,
1419    /// Implementations of each method (method name → expression).
1420    pub methods: HashMap<String, Expr>,
1421    /// Optional name for the instance declaration.
1422    pub instance_name: Option<Name>,
1423    /// Whether this is a local (hypothetical) instance.
1424    pub is_local: bool,
1425}
1426impl Instance {
1427    /// Create a new anonymous instance with default priority.
1428    pub fn new(class: Name, ty: Expr) -> Self {
1429        Self {
1430            class,
1431            ty,
1432            priority: 100,
1433            methods: HashMap::new(),
1434            instance_name: None,
1435            is_local: false,
1436        }
1437    }
1438    /// Create a named instance.
1439    pub fn named(class: Name, ty: Expr, name: Name) -> Self {
1440        Self {
1441            class,
1442            ty,
1443            priority: 100,
1444            methods: HashMap::new(),
1445            instance_name: Some(name),
1446            is_local: false,
1447        }
1448    }
1449    /// Set the priority.
1450    pub fn with_priority(mut self, priority: i32) -> Self {
1451        self.priority = priority;
1452        self
1453    }
1454    /// Mark as a local instance.
1455    pub fn as_local(mut self) -> Self {
1456        self.is_local = true;
1457        self
1458    }
1459    /// Add an implementation for a method.
1460    pub fn add_method_impl(&mut self, method_name: impl Into<String>, impl_expr: Expr) {
1461        self.methods.insert(method_name.into(), impl_expr);
1462    }
1463    /// Look up the implementation of a method.
1464    pub fn get_method_impl(&self, method_name: &str) -> Option<&Expr> {
1465        self.methods.get(method_name)
1466    }
1467    /// Check whether all methods of the given class are implemented.
1468    pub fn implements_all(&self, class: &TypeClass) -> bool {
1469        class
1470            .methods
1471            .iter()
1472            .all(|m| self.methods.contains_key(&m.name.to_string()))
1473    }
1474    /// Number of implemented methods.
1475    pub fn implemented_count(&self) -> usize {
1476        self.methods.len()
1477    }
1478    /// Check whether this instance has a name.
1479    pub fn is_named(&self) -> bool {
1480        self.instance_name.is_some()
1481    }
1482}
1483/// A single method belonging to a type class.
1484#[derive(Clone, Debug)]
1485pub struct Method {
1486    /// Name of the method.
1487    pub name: Name,
1488    /// Type signature of the method (as a kernel expression).
1489    pub ty: Expr,
1490    /// Whether the method has a default implementation.
1491    pub has_default: bool,
1492    /// Index of this method in the class declaration (0-based).
1493    pub index: usize,
1494}
1495impl Method {
1496    /// Create a new method without a default implementation.
1497    pub fn new(name: Name, ty: Expr, index: usize) -> Self {
1498        Self {
1499            name,
1500            ty,
1501            has_default: false,
1502            index,
1503        }
1504    }
1505    /// Create a method that has a default implementation.
1506    pub fn with_default(name: Name, ty: Expr, index: usize) -> Self {
1507        Self {
1508            name,
1509            ty,
1510            has_default: true,
1511            index,
1512        }
1513    }
1514    /// Return a copy marked as having a default.
1515    pub fn set_default(mut self) -> Self {
1516        self.has_default = true;
1517        self
1518    }
1519}
1520/// Represents a class hierarchy edge (parent → child relationship).
1521#[derive(Clone, Debug, PartialEq, Eq)]
1522pub struct ClassEdge {
1523    /// The parent class.
1524    pub parent: Name,
1525    /// The child class that extends the parent.
1526    pub child: Name,
1527}
1528impl ClassEdge {
1529    /// Create a new class hierarchy edge.
1530    pub fn new(parent: Name, child: Name) -> Self {
1531        Self { parent, child }
1532    }
1533}
1534/// A label set for a graph node.
1535#[allow(dead_code)]
1536pub struct LabelSet {
1537    labels: Vec<String>,
1538}
1539#[allow(dead_code)]
1540impl LabelSet {
1541    /// Creates a new empty label set.
1542    pub fn new() -> Self {
1543        Self { labels: Vec::new() }
1544    }
1545    /// Adds a label (deduplicates).
1546    pub fn add(&mut self, label: impl Into<String>) {
1547        let s = label.into();
1548        if !self.labels.contains(&s) {
1549            self.labels.push(s);
1550        }
1551    }
1552    /// Returns `true` if `label` is present.
1553    pub fn has(&self, label: &str) -> bool {
1554        self.labels.iter().any(|l| l == label)
1555    }
1556    /// Returns the count of labels.
1557    pub fn count(&self) -> usize {
1558        self.labels.len()
1559    }
1560    /// Returns all labels.
1561    pub fn all(&self) -> &[String] {
1562        &self.labels
1563    }
1564}
1565/// A method implementation override for derived instances.
1566#[allow(dead_code)]
1567#[derive(Clone, Debug)]
1568pub struct MethodImpl {
1569    /// Method name.
1570    pub method_name: Name,
1571    /// Implementation expression.
1572    pub impl_expr: Expr,
1573    /// Whether this uses a default implementation.
1574    pub is_default: bool,
1575}
1576impl MethodImpl {
1577    /// Create a custom method implementation.
1578    #[allow(dead_code)]
1579    pub fn custom(method: Name, expr: Expr) -> Self {
1580        Self {
1581            method_name: method,
1582            impl_expr: expr,
1583            is_default: false,
1584        }
1585    }
1586    /// Create a default method implementation.
1587    #[allow(dead_code)]
1588    pub fn default_impl(method: Name, expr: Expr) -> Self {
1589        Self {
1590            method_name: method,
1591            impl_expr: expr,
1592            is_default: true,
1593        }
1594    }
1595}
1596/// Result of a type class search.
1597#[derive(Clone, Debug)]
1598pub enum InstanceSearchResult {
1599    /// A unique instance was found.
1600    Found(Instance),
1601    /// Multiple instances matched (ambiguity).
1602    Ambiguous(Vec<Instance>),
1603    /// No instance was found.
1604    NotFound,
1605}
1606impl InstanceSearchResult {
1607    /// Returns `true` if a unique instance was found.
1608    pub fn is_found(&self) -> bool {
1609        matches!(self, InstanceSearchResult::Found(_))
1610    }
1611    /// Returns `true` if the search was ambiguous.
1612    pub fn is_ambiguous(&self) -> bool {
1613        matches!(self, InstanceSearchResult::Ambiguous(_))
1614    }
1615    /// Extract the unique instance, if any.
1616    pub fn into_instance(self) -> Option<Instance> {
1617        match self {
1618            InstanceSearchResult::Found(inst) => Some(inst),
1619            _ => None,
1620        }
1621    }
1622}