Skip to main content

oxilean_std/
lib.rs

1//! # OxiLean Standard Library — Core Data Types & Theorems
2//!
3//! The standard library provides essential types, type classes, and theorems for OxiLean programs.
4//! It is written in OxiLean itself and loaded into the kernel environment at startup.
5//!
6//! ## Quick Start
7//!
8//! ### Using Standard Types
9//!
10//! ```ignore
11//! theorem two_plus_three : 2 + 3 = 5 := by
12//!   norm_num
13//!
14//! def my_list : List Nat := [1, 2, 3]
15//!
16//! instance : Eq Nat := { ... }
17//! ```
18//!
19//! ## Architecture Overview
20//!
21//! The standard library is organized into logical categories:
22//!
23//! ```text
24//! Standard Library Organization
25//! ├─ Primitive Types
26//! │  ├─ nat, bool, char, int
27//! │  ├─ string, list, array
28//! │  ├─ option, result, sum
29//! │  └─ prod, sigma
30//! │
31//! ├─ Type Classes & Traits
32//! │  ├─ Eq, Ord, Show, Repr
33//! │  ├─ Functor, Monad, Applicative
34//! │  ├─ Monoid, Semigroup
35//! │  └─ Decidable
36//! │
37//! ├─ Core Theorems & Lemmas
38//! │  ├─ Equality (eq.rs)
39//! │  ├─ Logic (logic.rs, prop.rs)
40//! │  ├─ Arithmetic (nat.rs, int.rs)
41//! │  └─ Order (ord.rs, order.rs)
42//! │
43//! └─ Utilities & Automation
44//!    ├─ Tactic lemmas
45//!    ├─ Decision procedures
46//!    └─ Parsing combinators
47//! ```
48//!
49//! ## Key Concepts & Terminology
50//!
51//! ### Inductive Types
52//!
53//! Core types are defined inductively:
54//!
55//! ```text
56//! Nat : Type 0
57//!   | zero : Nat
58//!   | succ : Nat → Nat
59//!
60//! Bool : Prop
61//!   | true : Bool
62//!   | false : Bool
63//!
64//! List α : Type 0
65//!   | nil : List α
66//!   | cons : α → List α → List α
67//! ```
68//!
69//! Each inductive type comes with:
70//! - **Constructors**: Ways to create values
71//! - **Recursor**: Principle for inductive recursion
72//! - **Induction principle**: Structural induction proof technique
73//!
74//! ### Type Classes
75//!
76//! Type classes enable ad-hoc polymorphism:
77//!
78//! ```text
79//! class Eq (α : Type u) : Prop where
80//!   eq : α → α → Prop
81//!   refl : ∀ x, eq x x
82//!   symm : ∀ x y, eq x y → eq y x
83//!   trans : ∀ x y z, eq x y → eq y z → eq x z
84//! ```
85//!
86//! Instances provide implementations for specific types:
87//!
88//! ```text
89//! instance Eq Nat : Eq Nat where
90//!   eq := Nat.eq
91//!   refl := Nat.eq_refl
92//!   ...
93//! ```
94//!
95//! ### Recursion Schemes
96//!
97//! Each inductive type gets a **recursor** for primitive recursion:
98//!
99//! ```text
100//! Nat.rec :
101//!   {motive : Nat → Sort u}
102//! → motive 0
103//! → (∀ n, motive n → motive (n + 1))
104//! → ∀ n, motive n
105//! ```
106//!
107//! Higher-order recursion patterns (fold, map, etc.) are defined in terms of recs.
108//!
109//! ### Decidability
110//!
111//! For computable propositions, we can decide them algorithmically:
112//!
113//! ```text
114//! class Decidable (p : Prop) : Type 0 where
115//!   decide : Bool
116//!   correct : decide = true ↔ p
117//! ```
118//!
119//! Examples: `2 + 3 = 5` is decidable (computable), but `∀ n, P n` usually isn't.
120//!
121//! ## Module Organization
122//!
123//! ### Primitive Types & Constructors
124//!
125//! | Module | Types | Purpose |
126//! |--------|-------|---------|
127//! | `nat` | `Nat` | Natural numbers (zero, successor) |
128//! | `bool` | `Bool` | Booleans (true, false) |
129//! | `int` | `Int` | Signed integers |
130//! | `char` | `Char` | Unicode characters |
131//! | `string` | `String` | Text strings |
132//!
133//! ### Collection Types
134//!
135//! | Module | Types | Purpose |
136//! |--------|-------|---------|
137//! | `list` | `List α` | Linked lists |
138//! | `array` | `Array α` | Fixed-size arrays |
139//! | `vec` | `Vec α` | Dynamic vectors (like Lean 4) |
140//! | `set` | `Set α` | Mathematical sets |
141//! | `fin` | `Fin n` | Finite sets (0..n-1) |
142//!
143//! ### Option & Alternative Types
144//!
145//! | Module | Types | Purpose |
146//! |--------|-------|---------|
147//! | `option` | `Option α` | Nullable value |
148//! | `result` | `Result α ε` | Value or error |
149//! | `sum` | `α ⊕ β` | Tagged union |
150//! | `either` | `Either α β` | Alternative representation |
151//! | `prod` | `α × β` | Pairs/products |
152//! | `sigma` | `Σ x, P x` | Dependent pairs |
153//!
154//! ### Type Classes
155//!
156//! | Module | Classes | Purpose |
157//! |--------|---------|---------|
158//! | `eq` | `Eq` | Equality relation |
159//! | `ord` | `Ord` | Total ordering |
160//! | `show` | `Show` | String representation |
161//! | `repr` | `Repr` | Debug representation |
162//! | `decidable` | `Decidable` | Computable propositions |
163//!
164//! ### Higher-Order Abstractions
165//!
166//! | Module | Classes | Purpose |
167//! |--------|---------|---------|
168//! | `functor` | `Functor` | Map over container |
169//! | `applicative` | `Applicative` | Apply pure functions |
170//! | `monad` | `Monad` | Sequencing computations |
171//! | `algebra` | `Monoid`, `Semigroup` | Algebraic structures |
172//!
173//! ### Logic & Propositions
174//!
175//! | Module | Purpose |
176//! |--------|---------|
177//! | `logic` | Classical logic (excluded middle, etc.) |
178//! | `prop` | Propositional theorems |
179//! | `eq` | Equality and substitution |
180//!
181//! ### Arithmetic & Order
182//!
183//! | Module | Purpose |
184//! |--------|---------|
185//! | `nat` | Natural number theorems |
186//! | `int` | Integer theorems |
187//! | `order` | Partial orders |
188//! | `ordering` | Compare result type |
189//! | `range` | Integer ranges |
190//!
191//! ### Advanced Structures
192//!
193//! | Module | Purpose |
194//! |--------|---------|
195//! | `rbtree` | Red-black trees (sorted maps) |
196//! | `hashmap` | Hash maps |
197//! | `hashset` | Hash sets |
198//! | `stream` | Lazy sequences |
199//! | `thunk` | Delayed computation |
200//! | `lazy` | Lazy values |
201//!
202//! ### Utilities
203//!
204//! | Module | Purpose |
205//! |--------|---------|
206//! | `wellfounded` | Well-founded relations |
207//! | `quotient_types` | Quotient type operations |
208//! | `tactic_lemmas` | Lemmas useful for automation |
209//! | `parsec` | Parsing combinators |
210//! | `io` | I/O operations |
211//!
212//! ## Type Hierarchy
213//!
214//! The standard library respects the universe hierarchy:
215//!
216//! ```text
217//! Data types (Nat, Bool, List) : Type 0
218//! Type classes (Eq, Show) : Type 0 → Prop or Type 1
219//! Propositions (Nat.add_comm) : Prop
220//! Proofs (rfl, trans) : Prop
221//! ```
222//!
223//! ## Usage Examples
224//!
225//! ### Example 1: Working with Natural Numbers
226//!
227//! ```ignore
228//! theorem add_comm : ∀ n m : Nat, n + m = m + n := by
229//!   intro n m
230//!   induction n with
231//!   | zero => simp
232//!   | succ n ih => simp [ih]
233//! ```
234//!
235//! ### Example 2: List Operations
236//!
237//! ```ignore
238//! def append {α : Type u} : List α → List α → List α
239//!   | [], ys => ys
240//!   | x :: xs, ys => x :: append xs ys
241//!
242//! theorem append_nil : ∀ xs : List α, append xs [] = xs := by
243//!   intro xs
244//!   induction xs with
245//!   | nil => rfl
246//!   | cons x xs ih => simp [ih]
247//! ```
248//!
249//! ### Example 3: Type Class Instance
250//!
251//! ```ignore
252//! instance : Eq (List Nat) where
253//!   eq xs ys := (append xs [] = append ys [])
254//!   refl xs := rfl
255//!   ...
256//! ```
257//!
258//! ### Example 4: Pattern Matching
259//!
260//! ```ignore
261//! def is_zero : Nat → Bool
262//!   | 0 => true
263//!   | _ + 1 => false
264//!
265//! def head {α : Type u} : List α → Option α
266//!   | [] => none
267//!   | x :: _ => some x
268//! ```
269//!
270//! ## Environment Building
271//!
272//! The standard library is built in phases:
273//!
274//! 1. **Phase 1: Primitives** — Nat, Bool, basic operations
275//! 2. **Phase 2: Collections** — List, Array, Set
276//! 3. **Phase 3: Type Classes** — Eq, Show, etc.
277//! 4. **Phase 4: Theorems** — Induction principles, lemmas
278//! 5. **Phase 5: Automation** — Tactic lemmas, decision procedures
279//!
280//! Loading happens in `oxilean-std` via `build_*_env` functions:
281//!
282//! ```ignore
283//! let env = Environment::new();
284//! let env = build_nat_env(env)?;
285//! let env = build_list_env(env)?;
286//! let env = build_eq_env(env)?;
287//! // etc...
288//! ```
289//!
290//! ## Integration with Elaborator & Tactics
291//!
292//! ### Decidability
293//!
294//! The `norm_num` and `decide` tactics use decidable instances:
295//! - `2 + 3 = 5` via `Decidable` instance on Nat equality
296//! - `decide` extracts this decision to reduce proofs automatically
297//!
298//! ### Simplification
299//!
300//! The `simp` tactic uses lemmas from the standard library:
301//! - Reflexivity: `x = x`
302//! - Commutativity: `x + y = y + x`
303//! - Associativity: `(x + y) + z = x + (y + z)`
304//!
305//! ### Induction
306//!
307//! The `induction` tactic uses recursors and induction principles:
308//! - For `Nat`: Decompose into zero/successor cases
309//! - For `List`: Decompose into nil/cons cases
310//!
311//! ## Performance & Memory
312//!
313//! - **Lazy evaluation**: Some computations deferred via `Thunk`
314//! - **Persistent data structures**: Lists/sets use structural sharing
315//! - **Universe polymorphism**: Generic types work across universe levels
316//!
317//! ## Further Reading
318//!
319//! - [ARCHITECTURE.md](../../ARCHITECTURE.md) — System architecture
320//! - [BLUEPRINT.md](../../BLUEPRINT.md) — Formal specifications
321//! - Module documentation for specific type definitions
322
323#![allow(missing_docs)]
324#![warn(clippy::all)]
325#![allow(mixed_script_confusables)]
326#![allow(clippy::type_complexity)]
327#![allow(clippy::needless_range_loop)]
328#![allow(clippy::map_unwrap_or)]
329#![allow(clippy::collapsible_if)]
330#![allow(clippy::collapsible_else_if)]
331#![allow(clippy::should_implement_trait)]
332#![allow(clippy::vec_box)]
333#![allow(clippy::ptr_arg)]
334#![allow(clippy::redundant_field_names)]
335#![allow(clippy::redundant_closure)]
336#![allow(clippy::int_plus_one)]
337#![allow(clippy::implicit_saturating_sub)]
338#![allow(clippy::assign_op_pattern)]
339#![allow(clippy::clone_on_copy)]
340#![allow(clippy::map_unwrap_or)]
341#![allow(clippy::map_unwrap_or)]
342#![allow(clippy::useless_let_if_seq)]
343#![allow(clippy::identity_op)]
344#![allow(clippy::if_same_then_else)]
345#![allow(clippy::doc_lazy_continuation)]
346#![allow(clippy::cast_lossless)]
347#![allow(clippy::manual_range_contains)]
348#![allow(clippy::option_if_let_else)]
349#![allow(clippy::unnecessary_unwrap)]
350#![allow(clippy::missing_panics_doc)]
351#![allow(clippy::missing_errors_doc)]
352#![allow(clippy::must_use_candidate)]
353#![allow(clippy::return_self_not_must_use)]
354#![allow(clippy::items_after_statements)]
355#![allow(clippy::too_many_lines)]
356#![allow(clippy::similar_names)]
357#![allow(clippy::cast_possible_truncation)]
358#![allow(clippy::cast_sign_loss)]
359#![allow(clippy::cast_precision_loss)]
360#![allow(clippy::float_cmp)]
361#![allow(clippy::match_same_arms)]
362#![allow(clippy::single_match_else)]
363#![allow(clippy::wildcard_imports)]
364#![allow(clippy::struct_excessive_bools)]
365#![allow(clippy::module_name_repetitions)]
366#![allow(clippy::unused_self)]
367#![allow(clippy::unnecessary_wraps)]
368#![allow(clippy::use_self)]
369#![allow(clippy::default_trait_access)]
370#![allow(clippy::uninlined_format_args)]
371#![allow(clippy::vec_init_then_push)]
372#![allow(clippy::box_collection)]
373#![allow(clippy::iter_nth_zero)]
374#![allow(clippy::new_without_default)]
375#![allow(clippy::useless_conversion)]
376#![allow(suspicious_double_ref_op)]
377#![allow(clippy::needless_pass_by_value)]
378#![allow(clippy::inline_always)]
379#![allow(dead_code)]
380#![allow(unused_assignments)]
381#![allow(clippy::unnecessary_map_or)]
382#![allow(clippy::extra_unused_lifetimes)]
383#![allow(clippy::needless_lifetimes)]
384#![allow(clippy::borrow_as_ptr)]
385#![allow(clippy::used_underscore_binding)]
386#![allow(clippy::manual_let_else)]
387#![allow(clippy::empty_line_after_doc_comments)]
388#![allow(clippy::useless_format)]
389#![allow(clippy::option_option)]
390#![allow(clippy::large_enum_variant)]
391#![allow(clippy::enum_variant_names)]
392#![allow(clippy::single_char_lifetime_names)]
393#![allow(clippy::needless_update)]
394#![allow(clippy::match_wildcard_for_single_variants)]
395#![allow(clippy::missing_fields_in_debug)]
396#![allow(clippy::expect_used)]
397#![allow(clippy::panic)]
398#![allow(clippy::unwrap_used)]
399#![allow(clippy::explicit_deref_methods)]
400#![allow(clippy::suspicious_arithmetic_impl)]
401#![allow(clippy::suspicious_op_assign_impl)]
402#![allow(clippy::doc_lazy_continuation)]
403#![allow(clippy::empty_line_after_doc_comments)]
404#![allow(clippy::duplicated_attributes)]
405#![allow(clippy::match_like_matches_macro)]
406#![allow(clippy::manual_clamp)]
407#![allow(clippy::too_many_arguments)]
408#![allow(clippy::borrowed_box)]
409#![allow(clippy::nonminimal_bool)]
410#![allow(clippy::manual_range_contains)]
411#![allow(clippy::if_same_then_else)]
412#![allow(clippy::option_map_or_none)]
413#![allow(clippy::collapsible_match)]
414#![allow(clippy::map_clone)]
415#![allow(clippy::unnecessary_cast)]
416#![allow(unused_imports)]
417#![allow(dead_code)]
418#![allow(clippy::unnecessary_map_or)]
419#![allow(clippy::extra_unused_lifetimes)]
420#![allow(clippy::needless_lifetimes)]
421#![allow(clippy::borrow_as_ptr)]
422#![allow(clippy::used_underscore_binding)]
423#![allow(clippy::manual_let_else)]
424#![allow(clippy::empty_line_after_doc_comments)]
425#![allow(clippy::useless_format)]
426#![allow(clippy::option_option)]
427#![allow(clippy::large_enum_variant)]
428#![allow(clippy::enum_variant_names)]
429#![allow(clippy::single_char_lifetime_names)]
430#![allow(clippy::needless_update)]
431#![allow(clippy::match_wildcard_for_single_variants)]
432#![allow(clippy::missing_fields_in_debug)]
433#![allow(clippy::expect_used)]
434#![allow(clippy::panic)]
435#![allow(clippy::unwrap_used)]
436#![allow(clippy::explicit_deref_methods)]
437#![allow(clippy::suspicious_arithmetic_impl)]
438#![allow(clippy::suspicious_op_assign_impl)]
439
440pub mod abstract_algebra_adv;
441pub mod abstract_interpretation;
442pub mod algebra;
443pub mod algebraic_combinatorics;
444pub mod algebraic_effects;
445pub mod algebraic_geometry;
446pub mod algebraic_number_theory;
447pub mod algebraic_topology;
448pub mod analytic_number_theory;
449pub mod arithmetic_geometry;
450pub mod array;
451pub mod automata_theory;
452pub mod bitvec;
453pub mod bool;
454pub mod category_theory;
455pub mod category_theory_ext;
456pub mod certified_algorithms;
457pub mod chaos_theory;
458pub mod char;
459pub mod chromatic_homotopy;
460pub mod coding_theory;
461pub mod combinatorial_game_theory;
462pub mod combinatorial_optimization;
463pub mod combinatorics;
464pub mod complex;
465pub mod complexity;
466pub mod computational_geometry;
467pub mod concurrency_theory;
468pub mod constructive_mathematics;
469pub mod control_theory;
470pub mod convex_geometry;
471pub mod convex_optimization;
472pub mod cryptographic_protocols;
473pub mod cryptography;
474pub mod data_structures;
475pub mod decidable;
476pub mod denotational_semantics;
477pub mod derived_algebraic_geometry;
478pub mod descriptive_set_theory;
479pub mod differential_equations;
480pub mod differential_geometry;
481pub mod diophantine_geometry;
482pub mod domain_theory;
483pub mod either;
484pub mod elliptic_curves;
485pub mod env_builder;
486pub mod eq;
487pub mod ergodic_theory;
488pub mod fin;
489pub mod forcing_theory;
490pub mod formal_languages;
491pub mod formal_verification;
492pub mod functional_analysis;
493pub mod functional_calculus;
494pub mod functional_programming;
495pub mod functor;
496pub mod fuzzy_logic;
497pub mod game_theory;
498pub mod game_theory_ext;
499pub mod geometric_group_theory;
500pub mod graph;
501pub mod groebner_bases;
502pub mod group_theory;
503pub mod hashmap;
504pub mod hashset;
505pub mod higher_category_theory;
506pub mod homological_algebra;
507pub mod homological_computations;
508pub mod homotopy_theory;
509pub mod homotopy_type_theory;
510pub mod information_geometry;
511pub mod information_theory;
512pub mod information_theory_ext;
513pub mod int;
514pub mod io;
515pub mod iwasawa_theory;
516pub mod k_theory;
517pub mod lattice_theory;
518pub mod lazy;
519pub mod lie_theory;
520pub mod linear_algebra;
521pub mod linear_logic;
522pub mod linear_programming;
523pub mod list;
524pub mod logic;
525pub mod machine_learning;
526pub mod mathematical_physics;
527pub mod measure_theory;
528pub mod model_checking;
529pub mod model_theory;
530pub mod monad;
531pub mod motivic_cohomology;
532pub mod nat;
533pub mod noncommutative_geometry;
534pub mod number_theory;
535pub mod numerical_analysis;
536pub mod numerical_linear_algebra;
537pub mod operations_research;
538pub mod operator_algebras;
539pub mod option;
540pub mod ord;
541pub mod order;
542pub mod order_topology;
543pub mod ordering;
544pub mod padic_analysis;
545pub mod padic_hodge_theory;
546pub mod parametricity;
547pub mod parsec;
548pub mod pde_theory;
549pub mod point_set_topology;
550pub mod probability;
551pub mod prod;
552pub mod proof_mining;
553pub mod proof_theory;
554pub mod prop;
555pub mod quantum_computing;
556pub mod quantum_field_theory;
557pub mod quantum_information;
558pub mod quotient_types;
559pub mod random_matrix_theory;
560pub mod range;
561pub mod rbtree;
562pub mod real;
563pub mod repr;
564pub mod representation_theory;
565pub mod result;
566pub mod reverse_mathematics;
567pub mod set;
568pub mod set_theory_zfc;
569pub mod show;
570pub mod sigma;
571pub mod social_choice_theory;
572pub mod spectral_theory;
573pub mod statistical_learning;
574pub mod statistical_mechanics;
575pub mod stochastic_control;
576pub mod stochastic_processes;
577pub mod stream;
578pub mod string;
579pub mod sum;
580pub mod symplectic_geometry;
581pub mod tactic_lemmas;
582pub mod tauberian_theory;
583pub mod term_rewriting;
584pub mod thunk;
585pub mod topological_data_analysis;
586pub mod topology;
587pub mod topology_ext;
588pub mod topos_theory;
589pub mod tropical_geometry;
590pub mod type_theory;
591pub mod universal_algebra;
592pub mod variational_calculus;
593pub mod vec;
594pub mod wellfounded;
595
596pub use algebra::build_algebra_env;
597pub use array::build_array_env;
598pub use bitvec::build_bitvec_env;
599pub use bool::build_bool_env;
600pub use category_theory::build_category_theory_env;
601pub use char::build_char_env;
602pub use decidable::build_decidable_env;
603pub use either::build_either_env;
604pub use eq::build_eq_env;
605pub use fin::build_fin_env;
606pub use functor::build_functor_env;
607pub use group_theory::build_group_theory_env;
608pub use hashmap::build_hashmap_env;
609pub use hashset::build_hashset_env;
610pub use int::build_int_env;
611pub use io::build_io_env;
612pub use lazy::build_lazy_env;
613pub use list::build_list_env;
614pub use logic::build_logic_env;
615pub use monad::build_monad_env;
616pub use nat::build_nat_env;
617pub use option::build_option_env;
618pub use ord::build_ord_env;
619pub use order::build_order_env;
620pub use ordering::build_ordering_env;
621pub use parsec::build_parsec_env;
622pub use prod::build_prod_env;
623pub use prop::build_prop_env;
624pub use quotient_types::build_quotient_types_env;
625pub use range::build_range_env;
626pub use rbtree::build_rbtree_env;
627pub use real::build_real_env;
628pub use repr::build_repr_env;
629pub use result::build_result_env;
630pub use set::build_set_env;
631pub use show::build_show_env;
632pub use sigma::build_sigma_env;
633pub use stream::build_stream_env;
634pub use string::build_string_env;
635pub use sum::build_sum_env;
636pub use tactic_lemmas::build_tactic_lemmas_env;
637pub use thunk::build_thunk_env;
638pub use topology::build_topology_env;
639pub use vec::build_vec_env;
640pub use wellfounded::build_wellfounded_env;
641
642// ============================================================================
643// Environment Builder Registry & Orchestration
644// ============================================================================
645
646/// Represents a phase in the standard library build process.
647#[allow(dead_code)]
648#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
649pub enum BuildPhase {
650    /// Phase 1: Primitive types (Nat, Bool, Char, etc.)
651    Primitives,
652    /// Phase 2: Collection types (List, Array, Set, etc.)
653    Collections,
654    /// Phase 3: Type class definitions (Eq, Ord, Show, etc.)
655    TypeClasses,
656    /// Phase 4: Core theorems and lemmas.
657    Theorems,
658    /// Phase 5: Automation (tactic lemmas, decision procedures).
659    Automation,
660}
661
662impl BuildPhase {
663    /// Returns all phases in build order.
664    #[allow(dead_code)]
665    pub fn all_in_order() -> &'static [BuildPhase] {
666        &[
667            BuildPhase::Primitives,
668            BuildPhase::Collections,
669            BuildPhase::TypeClasses,
670            BuildPhase::Theorems,
671            BuildPhase::Automation,
672        ]
673    }
674
675    /// Returns a human-readable name for this phase.
676    #[allow(dead_code)]
677    pub fn name(&self) -> &'static str {
678        match self {
679            BuildPhase::Primitives => "primitives",
680            BuildPhase::Collections => "collections",
681            BuildPhase::TypeClasses => "type_classes",
682            BuildPhase::Theorems => "theorems",
683            BuildPhase::Automation => "automation",
684        }
685    }
686}
687
688/// A registry entry describing one standard library module.
689#[allow(dead_code)]
690#[derive(Debug, Clone)]
691pub struct StdModuleEntry {
692    /// Fully qualified module name.
693    pub qualified_name: &'static str,
694    /// Build phase this module belongs to.
695    pub phase: BuildPhase,
696    /// Whether this module is loaded by default.
697    pub default_load: bool,
698    /// Brief description of module purpose.
699    pub description: &'static str,
700}
701
702/// Inventory of all standard library modules.
703#[allow(dead_code)]
704pub static STD_MODULE_REGISTRY: &[StdModuleEntry] = &[
705    StdModuleEntry {
706        qualified_name: "Std.Nat",
707        phase: BuildPhase::Primitives,
708        default_load: true,
709        description: "Natural number type",
710    },
711    StdModuleEntry {
712        qualified_name: "Std.Bool",
713        phase: BuildPhase::Primitives,
714        default_load: true,
715        description: "Boolean type",
716    },
717    StdModuleEntry {
718        qualified_name: "Std.Char",
719        phase: BuildPhase::Primitives,
720        default_load: true,
721        description: "Unicode character type",
722    },
723    StdModuleEntry {
724        qualified_name: "Std.Int",
725        phase: BuildPhase::Primitives,
726        default_load: true,
727        description: "Signed integer type",
728    },
729    StdModuleEntry {
730        qualified_name: "Std.String",
731        phase: BuildPhase::Primitives,
732        default_load: true,
733        description: "Immutable string type",
734    },
735    StdModuleEntry {
736        qualified_name: "Std.List",
737        phase: BuildPhase::Collections,
738        default_load: true,
739        description: "Linked list type",
740    },
741    StdModuleEntry {
742        qualified_name: "Std.Array",
743        phase: BuildPhase::Collections,
744        default_load: true,
745        description: "Fixed-size arrays",
746    },
747    StdModuleEntry {
748        qualified_name: "Std.Set",
749        phase: BuildPhase::Collections,
750        default_load: false,
751        description: "Mathematical sets",
752    },
753    StdModuleEntry {
754        qualified_name: "Std.Fin",
755        phase: BuildPhase::Collections,
756        default_load: true,
757        description: "Finite sets",
758    },
759    StdModuleEntry {
760        qualified_name: "Std.Vec",
761        phase: BuildPhase::Collections,
762        default_load: false,
763        description: "Length-indexed vectors",
764    },
765    StdModuleEntry {
766        qualified_name: "Std.Option",
767        phase: BuildPhase::Collections,
768        default_load: true,
769        description: "Optional value type",
770    },
771    StdModuleEntry {
772        qualified_name: "Std.Result",
773        phase: BuildPhase::Collections,
774        default_load: true,
775        description: "Result type",
776    },
777    StdModuleEntry {
778        qualified_name: "Std.Prod",
779        phase: BuildPhase::Collections,
780        default_load: true,
781        description: "Product type",
782    },
783    StdModuleEntry {
784        qualified_name: "Std.Sum",
785        phase: BuildPhase::Collections,
786        default_load: true,
787        description: "Sum type",
788    },
789    StdModuleEntry {
790        qualified_name: "Std.Sigma",
791        phase: BuildPhase::Collections,
792        default_load: false,
793        description: "Dependent pair type",
794    },
795    StdModuleEntry {
796        qualified_name: "Std.Eq",
797        phase: BuildPhase::TypeClasses,
798        default_load: true,
799        description: "Equality type class",
800    },
801    StdModuleEntry {
802        qualified_name: "Std.Ord",
803        phase: BuildPhase::TypeClasses,
804        default_load: true,
805        description: "Total ordering type class",
806    },
807    StdModuleEntry {
808        qualified_name: "Std.Show",
809        phase: BuildPhase::TypeClasses,
810        default_load: false,
811        description: "String representation",
812    },
813    StdModuleEntry {
814        qualified_name: "Std.Functor",
815        phase: BuildPhase::TypeClasses,
816        default_load: true,
817        description: "Functor type class",
818    },
819    StdModuleEntry {
820        qualified_name: "Std.Monad",
821        phase: BuildPhase::TypeClasses,
822        default_load: false,
823        description: "Monad type class",
824    },
825    StdModuleEntry {
826        qualified_name: "Std.Decidable",
827        phase: BuildPhase::TypeClasses,
828        default_load: true,
829        description: "Decidable propositions",
830    },
831    StdModuleEntry {
832        qualified_name: "Std.Algebra",
833        phase: BuildPhase::TypeClasses,
834        default_load: false,
835        description: "Algebraic structures",
836    },
837    StdModuleEntry {
838        qualified_name: "Std.Logic",
839        phase: BuildPhase::Theorems,
840        default_load: true,
841        description: "Classical logic",
842    },
843    StdModuleEntry {
844        qualified_name: "Std.Prop",
845        phase: BuildPhase::Theorems,
846        default_load: true,
847        description: "Propositional theorems",
848    },
849    StdModuleEntry {
850        qualified_name: "Std.Order",
851        phase: BuildPhase::Theorems,
852        default_load: false,
853        description: "Order theorems",
854    },
855    StdModuleEntry {
856        qualified_name: "Std.TacticLemmas",
857        phase: BuildPhase::Automation,
858        default_load: true,
859        description: "Tactic lemmas",
860    },
861    StdModuleEntry {
862        qualified_name: "Std.WellFounded",
863        phase: BuildPhase::Automation,
864        default_load: false,
865        description: "Well-founded relations",
866    },
867];
868
869/// Get all module entries for a specific build phase.
870#[allow(dead_code)]
871pub fn modules_for_phase(phase: BuildPhase) -> Vec<&'static StdModuleEntry> {
872    STD_MODULE_REGISTRY
873        .iter()
874        .filter(|e| e.phase == phase)
875        .collect()
876}
877
878/// Get all default-loaded modules.
879#[allow(dead_code)]
880pub fn default_modules() -> Vec<&'static StdModuleEntry> {
881    STD_MODULE_REGISTRY
882        .iter()
883        .filter(|e| e.default_load)
884        .collect()
885}
886
887/// Get all modules.
888#[allow(dead_code)]
889pub fn all_modules() -> &'static [StdModuleEntry] {
890    STD_MODULE_REGISTRY
891}
892
893/// Count how many modules are loaded by default.
894#[allow(dead_code)]
895pub fn count_default_modules() -> usize {
896    STD_MODULE_REGISTRY
897        .iter()
898        .filter(|e| e.default_load)
899        .count()
900}
901
902/// Count total number of registered standard library modules.
903#[allow(dead_code)]
904pub fn count_total_modules() -> usize {
905    STD_MODULE_REGISTRY.len()
906}
907
908/// Look up a module entry by its qualified name.
909#[allow(dead_code)]
910pub fn find_module(qualified_name: &str) -> Option<&'static StdModuleEntry> {
911    STD_MODULE_REGISTRY
912        .iter()
913        .find(|e| e.qualified_name == qualified_name)
914}
915
916/// A dependency pair: (dependent, dependency).
917#[allow(dead_code)]
918#[derive(Debug, Clone, Copy)]
919pub struct ModuleDep {
920    /// The module that depends on another.
921    pub dependent: &'static str,
922    /// The module that must be built first.
923    pub dependency: &'static str,
924}
925
926/// Minimal dependency graph for core standard library modules.
927#[allow(dead_code)]
928pub static CORE_DEPS: &[ModuleDep] = &[
929    ModuleDep {
930        dependent: "Std.List",
931        dependency: "Std.Nat",
932    },
933    ModuleDep {
934        dependent: "Std.Array",
935        dependency: "Std.Nat",
936    },
937    ModuleDep {
938        dependent: "Std.Fin",
939        dependency: "Std.Nat",
940    },
941    ModuleDep {
942        dependent: "Std.Vec",
943        dependency: "Std.List",
944    },
945    ModuleDep {
946        dependent: "Std.Set",
947        dependency: "Std.List",
948    },
949    ModuleDep {
950        dependent: "Std.Ord",
951        dependency: "Std.Eq",
952    },
953    ModuleDep {
954        dependent: "Std.Functor",
955        dependency: "Std.Eq",
956    },
957    ModuleDep {
958        dependent: "Std.Monad",
959        dependency: "Std.Functor",
960    },
961    ModuleDep {
962        dependent: "Std.Algebra",
963        dependency: "Std.Eq",
964    },
965    ModuleDep {
966        dependent: "Std.Logic",
967        dependency: "Std.Bool",
968    },
969    ModuleDep {
970        dependent: "Std.Prop",
971        dependency: "Std.Logic",
972    },
973    ModuleDep {
974        dependent: "Std.Order",
975        dependency: "Std.Ord",
976    },
977    ModuleDep {
978        dependent: "Std.TacticLemmas",
979        dependency: "Std.Nat",
980    },
981    ModuleDep {
982        dependent: "Std.WellFounded",
983        dependency: "Std.Nat",
984    },
985];
986
987/// Get all dependencies of a named module (direct only).
988#[allow(dead_code)]
989pub fn direct_deps(module: &str) -> Vec<&'static str> {
990    CORE_DEPS
991        .iter()
992        .filter(|d| d.dependent == module)
993        .map(|d| d.dependency)
994        .collect()
995}
996
997/// Get all modules that depend on the given module.
998#[allow(dead_code)]
999pub fn dependents_of(module: &str) -> Vec<&'static str> {
1000    CORE_DEPS
1001        .iter()
1002        .filter(|d| d.dependency == module)
1003        .map(|d| d.dependent)
1004        .collect()
1005}
1006
1007/// OxiLean standard library version string.
1008#[allow(dead_code)]
1009pub const STD_VERSION: &str = "0.1.1";
1010
1011/// Feature flags for optional standard library components.
1012#[allow(dead_code)]
1013#[derive(Debug, Clone, Default)]
1014pub struct StdFeatures {
1015    /// Enable classical logic axioms (excluded middle, choice).
1016    pub classical: bool,
1017    /// Enable propext (propositional extensionality).
1018    pub propext: bool,
1019    /// Enable funext (function extensionality).
1020    pub funext: bool,
1021    /// Enable quotient types.
1022    pub quotient: bool,
1023    /// Enable experimental category theory module.
1024    pub category_theory: bool,
1025    /// Enable topology module.
1026    pub topology: bool,
1027    /// Enable real number support.
1028    pub reals: bool,
1029}
1030
1031impl StdFeatures {
1032    /// Create the default feature set (classical logic enabled by default).
1033    #[allow(dead_code)]
1034    pub fn default_features() -> Self {
1035        Self {
1036            classical: true,
1037            propext: true,
1038            funext: true,
1039            quotient: false,
1040            category_theory: false,
1041            topology: false,
1042            reals: false,
1043        }
1044    }
1045
1046    /// Create the full feature set.
1047    #[allow(dead_code)]
1048    pub fn full() -> Self {
1049        Self {
1050            classical: true,
1051            propext: true,
1052            funext: true,
1053            quotient: true,
1054            category_theory: true,
1055            topology: true,
1056            reals: true,
1057        }
1058    }
1059
1060    /// Count how many features are enabled.
1061    #[allow(dead_code)]
1062    pub fn count_enabled(&self) -> usize {
1063        [
1064            self.classical,
1065            self.propext,
1066            self.funext,
1067            self.quotient,
1068            self.category_theory,
1069            self.topology,
1070            self.reals,
1071        ]
1072        .iter()
1073        .filter(|&&v| v)
1074        .count()
1075    }
1076}
1077
1078/// Standard library module statistics.
1079#[allow(dead_code)]
1080#[derive(Debug, Clone, Default)]
1081pub struct StdLibStats {
1082    /// Total modules registered.
1083    pub total_modules: usize,
1084    /// Modules enabled by default.
1085    pub default_modules: usize,
1086    /// Modules per build phase.
1087    pub per_phase: [usize; 5],
1088}
1089
1090impl StdLibStats {
1091    /// Compute statistics from the registry.
1092    #[allow(dead_code)]
1093    pub fn compute() -> Self {
1094        let total = count_total_modules();
1095        let defaults = count_default_modules();
1096        let phases = [
1097            modules_for_phase(BuildPhase::Primitives).len(),
1098            modules_for_phase(BuildPhase::Collections).len(),
1099            modules_for_phase(BuildPhase::TypeClasses).len(),
1100            modules_for_phase(BuildPhase::Theorems).len(),
1101            modules_for_phase(BuildPhase::Automation).len(),
1102        ];
1103        Self {
1104            total_modules: total,
1105            default_modules: defaults,
1106            per_phase: phases,
1107        }
1108    }
1109
1110    /// Check if all phases have at least one module.
1111    #[allow(dead_code)]
1112    pub fn all_phases_populated(&self) -> bool {
1113        self.per_phase.iter().all(|&n| n > 0)
1114    }
1115
1116    /// Get total modules across all phases.
1117    #[allow(dead_code)]
1118    pub fn phase_total(&self) -> usize {
1119        self.per_phase.iter().sum()
1120    }
1121}
1122
1123#[cfg(test)]
1124mod std_lib_tests {
1125    use super::*;
1126
1127    #[test]
1128    fn test_module_registry_not_empty() {
1129        assert!(!STD_MODULE_REGISTRY.is_empty());
1130        assert!(count_total_modules() > 10);
1131    }
1132
1133    #[test]
1134    fn test_default_modules_subset() {
1135        let defaults = default_modules();
1136        assert!(!defaults.is_empty());
1137        assert!(defaults.len() <= count_total_modules());
1138    }
1139
1140    #[test]
1141    fn test_modules_for_phase() {
1142        let primitives = modules_for_phase(BuildPhase::Primitives);
1143        assert!(!primitives.is_empty());
1144        for m in &primitives {
1145            assert_eq!(m.phase, BuildPhase::Primitives);
1146        }
1147    }
1148
1149    #[test]
1150    fn test_find_module_existing() {
1151        let m = find_module("Std.Nat");
1152        assert!(m.is_some());
1153        assert_eq!(m.expect("m should be valid").phase, BuildPhase::Primitives);
1154    }
1155
1156    #[test]
1157    fn test_find_module_nonexistent() {
1158        assert!(find_module("Std.DoesNotExist").is_none());
1159    }
1160
1161    #[test]
1162    fn test_direct_deps() {
1163        let deps = direct_deps("Std.List");
1164        assert!(deps.contains(&"Std.Nat"));
1165    }
1166
1167    #[test]
1168    fn test_dependents_of() {
1169        let deps = dependents_of("Std.Nat");
1170        assert!(deps.contains(&"Std.List"));
1171    }
1172
1173    #[test]
1174    fn test_build_phase_order() {
1175        let phases = BuildPhase::all_in_order();
1176        assert_eq!(phases.len(), 5);
1177        assert_eq!(phases[0], BuildPhase::Primitives);
1178        assert_eq!(phases[4], BuildPhase::Automation);
1179    }
1180
1181    #[test]
1182    fn test_std_features_default() {
1183        let f = StdFeatures::default_features();
1184        assert!(f.classical);
1185        assert!(f.propext);
1186        assert!(!f.topology);
1187    }
1188
1189    #[test]
1190    fn test_std_features_full() {
1191        let f = StdFeatures::full();
1192        assert!(f.classical && f.topology && f.reals && f.quotient);
1193        assert_eq!(f.count_enabled(), 7);
1194    }
1195
1196    #[test]
1197    fn test_build_phase_names() {
1198        assert_eq!(BuildPhase::Primitives.name(), "primitives");
1199        assert_eq!(BuildPhase::Automation.name(), "automation");
1200    }
1201
1202    #[test]
1203    fn test_count_default_modules() {
1204        let count = count_default_modules();
1205        assert!(count > 0);
1206        assert!(count <= count_total_modules());
1207    }
1208
1209    #[test]
1210    fn test_std_lib_stats() {
1211        let stats = StdLibStats::compute();
1212        assert!(stats.total_modules > 0);
1213        assert!(stats.all_phases_populated());
1214    }
1215
1216    #[test]
1217    fn test_all_modules_count() {
1218        assert_eq!(all_modules().len(), STD_MODULE_REGISTRY.len());
1219    }
1220
1221    #[test]
1222    fn test_std_version_nonempty() {
1223        assert!(!STD_VERSION.is_empty());
1224    }
1225}
1226
1227#[cfg(test)]
1228mod std_stats_tests {
1229    use super::*;
1230
1231    #[test]
1232    fn test_std_lib_stats_compute() {
1233        let s = StdLibStats::compute();
1234        assert_eq!(s.total_modules, count_total_modules());
1235        assert!(s.all_phases_populated());
1236        assert!(s.phase_total() > 0);
1237    }
1238
1239    #[test]
1240    fn test_std_lib_stats_phase_total() {
1241        let s = StdLibStats::compute();
1242        assert_eq!(s.phase_total(), s.total_modules);
1243    }
1244
1245    #[test]
1246    fn test_module_descriptions_not_empty() {
1247        for m in STD_MODULE_REGISTRY {
1248            assert!(
1249                !m.description.is_empty(),
1250                "Module {} has empty description",
1251                m.qualified_name
1252            );
1253        }
1254    }
1255}
1256
1257// ============================================================
1258// Topological sort for module dependency resolution
1259// ============================================================
1260
1261/// Compute a topological ordering of modules based on `CORE_DEPS`.
1262///
1263/// Returns `None` if there is a cycle.
1264#[allow(dead_code)]
1265pub fn topological_sort_modules() -> Option<Vec<&'static str>> {
1266    let mut in_degree: std::collections::HashMap<&'static str, usize> =
1267        std::collections::HashMap::new();
1268    let mut adjacency: std::collections::HashMap<&'static str, Vec<&'static str>> =
1269        std::collections::HashMap::new();
1270
1271    // Initialize all modules
1272    for entry in STD_MODULE_REGISTRY {
1273        in_degree.entry(entry.qualified_name).or_insert(0);
1274        adjacency.entry(entry.qualified_name).or_default();
1275    }
1276
1277    // Build graph from dependencies
1278    for dep in CORE_DEPS {
1279        *in_degree.entry(dep.dependent).or_insert(0) += 1;
1280        adjacency
1281            .entry(dep.dependency)
1282            .or_default()
1283            .push(dep.dependent);
1284    }
1285
1286    // Kahn's algorithm
1287    let mut queue: std::collections::VecDeque<&'static str> = in_degree
1288        .iter()
1289        .filter(|(_, &d)| d == 0)
1290        .map(|(&n, _)| n)
1291        .collect();
1292
1293    let mut sorted = Vec::new();
1294    while let Some(node) = queue.pop_front() {
1295        sorted.push(node);
1296        if let Some(neighbors) = adjacency.get(node) {
1297            for &neighbor in neighbors {
1298                let deg = in_degree.entry(neighbor).or_insert(0);
1299                *deg -= 1;
1300                if *deg == 0 {
1301                    queue.push_back(neighbor);
1302                }
1303            }
1304        }
1305    }
1306
1307    if sorted.len() == in_degree.len() {
1308        Some(sorted)
1309    } else {
1310        None // cycle detected
1311    }
1312}
1313
1314#[cfg(test)]
1315mod topo_sort_tests {
1316    use super::*;
1317
1318    #[test]
1319    fn test_topological_sort_acyclic() {
1320        let result = topological_sort_modules();
1321        assert!(result.is_some(), "Dependency graph should have no cycles");
1322        let sorted = result.expect("result should be valid");
1323        assert!(!sorted.is_empty());
1324    }
1325
1326    #[test]
1327    fn test_nat_before_list() {
1328        let sorted = topological_sort_modules().expect("operation should succeed");
1329        let nat_pos = sorted.iter().position(|&s| s == "Std.Nat");
1330        let list_pos = sorted.iter().position(|&s| s == "Std.List");
1331        if let (Some(np), Some(lp)) = (nat_pos, list_pos) {
1332            assert!(np < lp, "Nat must appear before List");
1333        }
1334    }
1335
1336    #[test]
1337    fn test_nat_before_array() {
1338        let sorted = topological_sort_modules().expect("operation should succeed");
1339        let nat_pos = sorted.iter().position(|&s| s == "Std.Nat");
1340        let arr_pos = sorted.iter().position(|&s| s == "Std.Array");
1341        if let (Some(np), Some(ap)) = (nat_pos, arr_pos) {
1342            assert!(np < ap);
1343        }
1344    }
1345
1346    #[test]
1347    fn test_all_modules_in_sorted() {
1348        let sorted = topological_sort_modules().expect("operation should succeed");
1349        for entry in STD_MODULE_REGISTRY {
1350            assert!(
1351                sorted.contains(&entry.qualified_name),
1352                "Module {} missing from topological sort",
1353                entry.qualified_name
1354            );
1355        }
1356    }
1357
1358    #[test]
1359    fn test_std_features_default_count() {
1360        let f = StdFeatures::default_features();
1361        // classical, propext, funext are true → 3 enabled
1362        assert_eq!(f.count_enabled(), 3);
1363    }
1364
1365    #[test]
1366    fn test_module_dep_dependent_in_registry() {
1367        // Every dependent in CORE_DEPS should be in the registry
1368        let names: Vec<_> = STD_MODULE_REGISTRY
1369            .iter()
1370            .map(|e| e.qualified_name)
1371            .collect();
1372        for dep in CORE_DEPS {
1373            assert!(
1374                names.contains(&dep.dependent),
1375                "Dependent {} not in registry",
1376                dep.dependent
1377            );
1378        }
1379    }
1380
1381    #[test]
1382    fn test_module_dep_dependency_in_registry() {
1383        let names: Vec<_> = STD_MODULE_REGISTRY
1384            .iter()
1385            .map(|e| e.qualified_name)
1386            .collect();
1387        for dep in CORE_DEPS {
1388            assert!(
1389                names.contains(&dep.dependency),
1390                "Dependency {} not in registry",
1391                dep.dependency
1392            );
1393        }
1394    }
1395
1396    #[test]
1397    fn test_std_lib_stats_phase_count() {
1398        let s = StdLibStats::compute();
1399        assert_eq!(s.per_phase.len(), 5);
1400    }
1401
1402    #[test]
1403    fn test_direct_deps_non_empty() {
1404        let deps = direct_deps("Std.Monad");
1405        assert!(!deps.is_empty());
1406    }
1407}
1408
1409// ============================================================
1410// Extended standard library utilities
1411// ============================================================
1412
1413/// A record of a single OxiLean standard library theorem or definition
1414/// that the elaborator knows about.
1415#[allow(dead_code)]
1416#[derive(Debug, Clone)]
1417pub struct StdEntry {
1418    /// Qualified name (e.g., `Nat.add_comm`).
1419    pub name: &'static str,
1420    /// Which module this entry belongs to.
1421    pub module: &'static str,
1422    /// Human-readable description.
1423    pub description: &'static str,
1424    /// Whether this is a theorem (vs. a definition).
1425    pub is_theorem: bool,
1426}
1427
1428/// A representative sample of well-known standard library entries.
1429#[allow(dead_code)]
1430pub const STD_KNOWN_ENTRIES: &[StdEntry] = &[
1431    StdEntry {
1432        name: "Nat.zero_add",
1433        module: "Std.Nat",
1434        description: "0 + n = n",
1435        is_theorem: true,
1436    },
1437    StdEntry {
1438        name: "Nat.add_zero",
1439        module: "Std.Nat",
1440        description: "n + 0 = n",
1441        is_theorem: true,
1442    },
1443    StdEntry {
1444        name: "Nat.add_comm",
1445        module: "Std.Nat",
1446        description: "Commutativity of natural number addition",
1447        is_theorem: true,
1448    },
1449    StdEntry {
1450        name: "Nat.add_assoc",
1451        module: "Std.Nat",
1452        description: "Associativity of natural number addition",
1453        is_theorem: true,
1454    },
1455    StdEntry {
1456        name: "Nat.mul_comm",
1457        module: "Std.Nat",
1458        description: "Commutativity of natural number multiplication",
1459        is_theorem: true,
1460    },
1461    StdEntry {
1462        name: "List.length_nil",
1463        module: "Std.List",
1464        description: "Length of the empty list is 0",
1465        is_theorem: true,
1466    },
1467    StdEntry {
1468        name: "List.length_cons",
1469        module: "Std.List",
1470        description: "Length of cons is 1 + length of tail",
1471        is_theorem: true,
1472    },
1473    StdEntry {
1474        name: "Bool.not_not",
1475        module: "Std.Bool",
1476        description: "Double negation elimination for Bool",
1477        is_theorem: true,
1478    },
1479    StdEntry {
1480        name: "Bool.and_comm",
1481        module: "Std.Bool",
1482        description: "Commutativity of boolean and",
1483        is_theorem: true,
1484    },
1485    StdEntry {
1486        name: "Option.some_ne_none",
1487        module: "Std.Option",
1488        description: "Some x is never None",
1489        is_theorem: true,
1490    },
1491];
1492
1493/// Look up a standard library entry by its qualified name.
1494#[allow(dead_code)]
1495pub fn lookup_std_entry(name: &str) -> Option<&'static StdEntry> {
1496    STD_KNOWN_ENTRIES.iter().find(|e| e.name == name)
1497}
1498
1499/// Return all entries from a given module.
1500#[allow(dead_code)]
1501pub fn entries_in_module(module: &str) -> Vec<&'static StdEntry> {
1502    STD_KNOWN_ENTRIES
1503        .iter()
1504        .filter(|e| e.module == module)
1505        .collect()
1506}
1507
1508/// Return all theorems (non-definitions) in the standard library sample.
1509#[allow(dead_code)]
1510pub fn all_theorems() -> Vec<&'static StdEntry> {
1511    STD_KNOWN_ENTRIES.iter().filter(|e| e.is_theorem).collect()
1512}
1513
1514/// A category tag for standard library modules.
1515#[allow(dead_code)]
1516#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1517pub enum StdCategory {
1518    /// Core arithmetic (Nat, Int).
1519    Arithmetic,
1520    /// Logic (Prop, And, Or, Not, Iff).
1521    Logic,
1522    /// Data structures (List, Array, Option, etc.).
1523    Data,
1524    /// Type classes (Eq, Ord, Functor, etc.).
1525    TypeClass,
1526    /// IO and system operations.
1527    IO,
1528    /// String operations.
1529    String,
1530    /// Tactics and proof automation.
1531    Tactic,
1532    /// Universe polymorphism.
1533    Universe,
1534}
1535
1536impl StdCategory {
1537    /// Human-readable label.
1538    #[allow(dead_code)]
1539    pub fn label(self) -> &'static str {
1540        match self {
1541            Self::Arithmetic => "Arithmetic",
1542            Self::Logic => "Logic",
1543            Self::Data => "Data",
1544            Self::TypeClass => "TypeClass",
1545            Self::IO => "IO",
1546            Self::String => "String",
1547            Self::Tactic => "Tactic",
1548            Self::Universe => "Universe",
1549        }
1550    }
1551}
1552
1553/// Map a module name to its `StdCategory`.
1554#[allow(dead_code)]
1555pub fn module_category(module: &str) -> StdCategory {
1556    if module.contains("Nat") || module.contains("Int") {
1557        StdCategory::Arithmetic
1558    } else if module.contains("Logic") || module.contains("Prop") {
1559        StdCategory::Logic
1560    } else if module.contains("List") || module.contains("Option") || module.contains("Array") {
1561        StdCategory::Data
1562    } else if module.contains("Functor") || module.contains("Monad") || module.contains("Eq") {
1563        StdCategory::TypeClass
1564    } else if module.contains("IO") {
1565        StdCategory::IO
1566    } else if module.contains("String") || module.contains("Char") {
1567        StdCategory::String
1568    } else if module.contains("Tactic") {
1569        StdCategory::Tactic
1570    } else {
1571        StdCategory::Universe
1572    }
1573}
1574
1575/// Version information for the OxiLean standard library.
1576#[allow(dead_code)]
1577pub struct StdVersion {
1578    /// Major version number.
1579    pub major: u32,
1580    /// Minor version number.
1581    pub minor: u32,
1582    /// Patch version number.
1583    pub patch: u32,
1584    /// Pre-release label (empty for stable).
1585    pub pre: &'static str,
1586}
1587
1588impl StdVersion {
1589    /// The current standard library version.
1590    #[allow(dead_code)]
1591    pub const CURRENT: StdVersion = StdVersion {
1592        major: 0,
1593        minor: 1,
1594        patch: 0,
1595        pre: "alpha",
1596    };
1597
1598    /// Format as a semver string.
1599    #[allow(dead_code)]
1600    pub fn format_version(&self) -> String {
1601        self.to_string()
1602    }
1603
1604    /// Check if this is a stable release.
1605    #[allow(dead_code)]
1606    pub fn is_stable(&self) -> bool {
1607        self.pre.is_empty()
1608    }
1609}
1610impl std::fmt::Display for StdVersion {
1611    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1612        if self.pre.is_empty() {
1613            write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
1614        } else {
1615            write!(
1616                f,
1617                "{}.{}.{}-{}",
1618                self.major, self.minor, self.patch, self.pre
1619            )
1620        }
1621    }
1622}
1623
1624#[cfg(test)]
1625mod extra_std_tests {
1626    use super::*;
1627
1628    #[test]
1629    fn test_lookup_std_entry_found() {
1630        let e = lookup_std_entry("Nat.add_comm");
1631        assert!(e.is_some());
1632        assert!(e.expect("e should be valid").is_theorem);
1633    }
1634
1635    #[test]
1636    fn test_lookup_std_entry_not_found() {
1637        assert!(lookup_std_entry("Nonexistent.theorem").is_none());
1638    }
1639
1640    #[test]
1641    fn test_entries_in_module() {
1642        let nat_entries = entries_in_module("Std.Nat");
1643        assert!(!nat_entries.is_empty());
1644        assert!(nat_entries.iter().all(|e| e.module == "Std.Nat"));
1645    }
1646
1647    #[test]
1648    fn test_all_theorems_nonempty() {
1649        let thms = all_theorems();
1650        assert!(!thms.is_empty());
1651        assert!(thms.iter().all(|e| e.is_theorem));
1652    }
1653
1654    #[test]
1655    fn test_module_category_nat() {
1656        assert_eq!(module_category("Std.Nat"), StdCategory::Arithmetic);
1657    }
1658
1659    #[test]
1660    fn test_module_category_list() {
1661        assert_eq!(module_category("Std.List"), StdCategory::Data);
1662    }
1663
1664    #[test]
1665    fn test_module_category_io() {
1666        assert_eq!(module_category("Std.IO"), StdCategory::IO);
1667    }
1668
1669    #[test]
1670    fn test_std_version_to_string() {
1671        let v = StdVersion {
1672            major: 1,
1673            minor: 2,
1674            patch: 3,
1675            pre: "",
1676        };
1677        assert_eq!(v.to_string(), "1.2.3");
1678    }
1679
1680    #[test]
1681    fn test_std_version_prerelease_to_string() {
1682        let v = StdVersion {
1683            major: 0,
1684            minor: 1,
1685            patch: 0,
1686            pre: "alpha",
1687        };
1688        assert_eq!(v.to_string(), "0.1.0-alpha");
1689    }
1690
1691    #[test]
1692    fn test_std_version_is_stable_false() {
1693        assert!(!StdVersion::CURRENT.is_stable());
1694    }
1695
1696    #[test]
1697    fn test_std_category_label() {
1698        assert_eq!(StdCategory::Arithmetic.label(), "Arithmetic");
1699        assert_eq!(StdCategory::Logic.label(), "Logic");
1700        assert_eq!(StdCategory::Data.label(), "Data");
1701    }
1702
1703    #[test]
1704    fn test_std_known_entries_nonempty() {
1705        assert!(!STD_KNOWN_ENTRIES.is_empty());
1706    }
1707
1708    #[test]
1709    fn test_all_entries_have_module() {
1710        for e in STD_KNOWN_ENTRIES {
1711            assert!(!e.module.is_empty(), "Entry {} has empty module", e.name);
1712        }
1713    }
1714}
1715pub mod abstract_algebra_advanced;
1716pub mod approximation_algorithms;
1717pub mod bayesian_networks;
1718pub mod bioinformatics;
1719pub mod birational_geometry;
1720pub mod coalgebra_theory;
1721pub mod compiler_theory;
1722pub mod convex_analysis;
1723pub mod cubical_type_theory;
1724pub mod differential_privacy;
1725pub mod distributed_systems_theory;
1726pub mod finite_element_method;
1727pub mod geometric_measure_theory;
1728pub mod harmonic_analysis;
1729pub mod information_theoretic_security;
1730pub mod intersection_theory;
1731pub mod knot_theory;
1732pub mod lambda_calculus;
1733pub mod low_dimensional_topology;
1734pub mod mathematical_ecology;
1735pub mod mechanism_design;
1736pub mod modal_logic;
1737pub mod modular_forms;
1738pub mod network_theory;
1739pub mod nonstandard_analysis;
1740pub mod observational_type_theory;
1741pub mod optimization_theory;
1742pub mod parameterized_complexity;
1743pub mod point_free_topology;
1744pub mod post_quantum_crypto;
1745pub mod probabilistic_programming;
1746pub mod program_logics;
1747pub mod program_synthesis;
1748pub mod quantum_error_correction;
1749pub mod rough_set_theory;
1750pub mod session_types;
1751pub mod sheaf_theory;
1752pub mod spectral_methods;
1753pub mod static_analysis;
1754pub mod string_theory_basics;
1755pub mod surreal_numbers;
1756pub mod systems_biology;
1757pub mod temporal_logic;
1758pub mod topological_quantum_computation;
1759pub mod type_inference_algorithms;
1760pub mod variational_analysis;
1761
1762pub mod categorical_logic;
1763pub mod type_theory_advanced;
1764
1765// ── Extended standard library utilities ──────────────────────────────────────
1766
1767/// Utility type for carrying source-location metadata.
1768#[allow(dead_code)]
1769#[derive(Debug, Clone, PartialEq, Eq)]
1770pub struct Span {
1771    /// Byte offset of the first character.
1772    pub start: usize,
1773    /// Byte offset one past the last character.
1774    pub end: usize,
1775    /// 1-based line number of the start.
1776    pub line: u32,
1777    /// 1-based column number of the start.
1778    pub column: u32,
1779}
1780
1781impl Span {
1782    /// Create a new span.
1783    #[allow(dead_code)]
1784    pub fn new(start: usize, end: usize, line: u32, column: u32) -> Self {
1785        Self {
1786            start,
1787            end,
1788            line,
1789            column,
1790        }
1791    }
1792
1793    /// Create a dummy span (all zeros).
1794    #[allow(dead_code)]
1795    pub fn dummy() -> Self {
1796        Self {
1797            start: 0,
1798            end: 0,
1799            line: 0,
1800            column: 0,
1801        }
1802    }
1803
1804    /// Return the length in bytes.
1805    #[allow(dead_code)]
1806    pub fn len(&self) -> usize {
1807        self.end.saturating_sub(self.start)
1808    }
1809
1810    /// Return `true` if the span covers zero bytes.
1811    #[allow(dead_code)]
1812    pub fn is_empty(&self) -> bool {
1813        self.start >= self.end
1814    }
1815
1816    /// Merge two spans: from the earlier start to the later end.
1817    #[allow(dead_code)]
1818    pub fn merge(&self, other: &Span) -> Span {
1819        Span {
1820            start: self.start.min(other.start),
1821            end: self.end.max(other.end),
1822            line: self.line.min(other.line),
1823            column: self.column,
1824        }
1825    }
1826}
1827
1828/// A value annotated with a `Span`.
1829#[allow(dead_code)]
1830#[derive(Debug, Clone)]
1831pub struct Located<T> {
1832    /// The wrapped value.
1833    pub value: T,
1834    /// The source span.
1835    pub span: Span,
1836}
1837
1838impl<T> Located<T> {
1839    /// Wrap `value` with a `span`.
1840    #[allow(dead_code)]
1841    pub fn new(value: T, span: Span) -> Self {
1842        Self { value, span }
1843    }
1844
1845    /// Wrap `value` with a dummy span.
1846    #[allow(dead_code)]
1847    pub fn dummy(value: T) -> Self {
1848        Self {
1849            value,
1850            span: Span::dummy(),
1851        }
1852    }
1853
1854    /// Map over the inner value.
1855    #[allow(dead_code)]
1856    pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Located<U> {
1857        Located {
1858            value: f(self.value),
1859            span: self.span,
1860        }
1861    }
1862
1863    /// Return a reference to the inner value.
1864    #[allow(dead_code)]
1865    pub fn as_ref(&self) -> Located<&T> {
1866        Located {
1867            value: &self.value,
1868            span: self.span.clone(),
1869        }
1870    }
1871}
1872
1873// ── Simple name-interning table ───────────────────────────────────────────────
1874
1875/// A simple string-interning table backed by a `Vec`.
1876///
1877/// Useful for giving cheap `usize` IDs to string names during elaboration.
1878#[allow(dead_code)]
1879#[derive(Debug, Default)]
1880pub struct NameTable {
1881    names: Vec<String>,
1882}
1883
1884impl NameTable {
1885    /// Create an empty table.
1886    #[allow(dead_code)]
1887    pub fn new() -> Self {
1888        Self::default()
1889    }
1890
1891    /// Intern `name` and return its ID.  If already present, returns the
1892    /// existing ID without inserting a duplicate.
1893    #[allow(dead_code)]
1894    pub fn intern(&mut self, name: &str) -> usize {
1895        if let Some(pos) = self.names.iter().position(|n| n == name) {
1896            return pos;
1897        }
1898        let id = self.names.len();
1899        self.names.push(name.to_owned());
1900        id
1901    }
1902
1903    /// Look up the string for an ID.
1904    #[allow(dead_code)]
1905    pub fn lookup(&self, id: usize) -> Option<&str> {
1906        self.names.get(id).map(String::as_str)
1907    }
1908
1909    /// Return the number of interned names.
1910    #[allow(dead_code)]
1911    pub fn len(&self) -> usize {
1912        self.names.len()
1913    }
1914
1915    /// Return `true` if the table is empty.
1916    #[allow(dead_code)]
1917    pub fn is_empty(&self) -> bool {
1918        self.names.is_empty()
1919    }
1920
1921    /// Clear all entries.
1922    #[allow(dead_code)]
1923    pub fn clear(&mut self) {
1924        self.names.clear();
1925    }
1926
1927    /// Return an iterator over `(id, name)` pairs.
1928    #[allow(dead_code)]
1929    pub fn iter(&self) -> impl Iterator<Item = (usize, &str)> {
1930        self.names.iter().enumerate().map(|(i, s)| (i, s.as_str()))
1931    }
1932}
1933
1934// ── DiagnosticLevel ──────────────────────────────────────────────────────────
1935
1936/// Severity levels for compiler diagnostics.
1937#[allow(dead_code)]
1938#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
1939pub enum DiagnosticLevel {
1940    /// Informational note; does not prevent compilation.
1941    Note,
1942    /// Warning; compilation continues.
1943    Warning,
1944    /// Error; compilation should stop.
1945    Error,
1946    /// Internal compiler error (ICE).
1947    Bug,
1948}
1949
1950impl DiagnosticLevel {
1951    /// Return a short label string.
1952    #[allow(dead_code)]
1953    pub fn label(self) -> &'static str {
1954        match self {
1955            Self::Note => "note",
1956            Self::Warning => "warning",
1957            Self::Error => "error",
1958            Self::Bug => "internal compiler error",
1959        }
1960    }
1961
1962    /// Return `true` if this level prevents a successful build.
1963    #[allow(dead_code)]
1964    pub fn is_fatal(self) -> bool {
1965        matches!(self, Self::Error | Self::Bug)
1966    }
1967}
1968
1969/// A single compiler diagnostic.
1970#[allow(dead_code)]
1971#[derive(Debug, Clone)]
1972pub struct Diagnostic {
1973    /// Severity level.
1974    pub level: DiagnosticLevel,
1975    /// Human-readable message.
1976    pub message: String,
1977    /// Optional source span.
1978    pub span: Option<Span>,
1979    /// Optional help/hint text.
1980    pub help: Option<String>,
1981}
1982
1983impl Diagnostic {
1984    /// Construct an error diagnostic.
1985    #[allow(dead_code)]
1986    pub fn error(message: impl Into<String>) -> Self {
1987        Self {
1988            level: DiagnosticLevel::Error,
1989            message: message.into(),
1990            span: None,
1991            help: None,
1992        }
1993    }
1994
1995    /// Construct a warning.
1996    #[allow(dead_code)]
1997    pub fn warning(message: impl Into<String>) -> Self {
1998        Self {
1999            level: DiagnosticLevel::Warning,
2000            message: message.into(),
2001            span: None,
2002            help: None,
2003        }
2004    }
2005
2006    /// Construct a note.
2007    #[allow(dead_code)]
2008    pub fn note(message: impl Into<String>) -> Self {
2009        Self {
2010            level: DiagnosticLevel::Note,
2011            message: message.into(),
2012            span: None,
2013            help: None,
2014        }
2015    }
2016
2017    /// Attach a source span.
2018    #[allow(dead_code)]
2019    pub fn with_span(mut self, span: Span) -> Self {
2020        self.span = Some(span);
2021        self
2022    }
2023
2024    /// Attach a help string.
2025    #[allow(dead_code)]
2026    pub fn with_help(mut self, help: impl Into<String>) -> Self {
2027        self.help = Some(help.into());
2028        self
2029    }
2030
2031    /// Return `true` if this diagnostic is fatal.
2032    #[allow(dead_code)]
2033    pub fn is_fatal(&self) -> bool {
2034        self.level.is_fatal()
2035    }
2036}
2037
2038/// Accumulator for multiple diagnostics.
2039#[allow(dead_code)]
2040#[derive(Debug, Default)]
2041pub struct DiagnosticBag {
2042    items: Vec<Diagnostic>,
2043}
2044
2045impl DiagnosticBag {
2046    /// Create an empty bag.
2047    #[allow(dead_code)]
2048    pub fn new() -> Self {
2049        Self::default()
2050    }
2051
2052    /// Push a diagnostic.
2053    #[allow(dead_code)]
2054    pub fn push(&mut self, diag: Diagnostic) {
2055        self.items.push(diag);
2056    }
2057
2058    /// Return `true` if there are any fatal diagnostics.
2059    #[allow(dead_code)]
2060    pub fn has_errors(&self) -> bool {
2061        self.items.iter().any(|d| d.is_fatal())
2062    }
2063
2064    /// Return the number of accumulated diagnostics.
2065    #[allow(dead_code)]
2066    pub fn len(&self) -> usize {
2067        self.items.len()
2068    }
2069
2070    /// Return `true` if the bag is empty.
2071    #[allow(dead_code)]
2072    pub fn is_empty(&self) -> bool {
2073        self.items.is_empty()
2074    }
2075
2076    /// Drain all diagnostics, returning them in order.
2077    #[allow(dead_code)]
2078    pub fn drain(&mut self) -> Vec<Diagnostic> {
2079        std::mem::take(&mut self.items)
2080    }
2081
2082    /// Iterate over diagnostics.
2083    #[allow(dead_code)]
2084    pub fn iter(&self) -> impl Iterator<Item = &Diagnostic> {
2085        self.items.iter()
2086    }
2087}
2088
2089// ── Simple scoped symbol table ────────────────────────────────────────────────
2090
2091/// A scoped symbol table supporting nested scopes.
2092///
2093/// Each `push_scope` / `pop_scope` pair delimits a lexical scope.  Lookups
2094/// search from the innermost scope outward.
2095#[allow(dead_code)]
2096#[derive(Debug)]
2097pub struct ScopeTable<K, V> {
2098    scopes: Vec<Vec<(K, V)>>,
2099}
2100
2101impl<K: Eq, V: Clone> ScopeTable<K, V> {
2102    /// Create a table with a single (global) scope.
2103    #[allow(dead_code)]
2104    pub fn new() -> Self {
2105        Self {
2106            scopes: vec![Vec::new()],
2107        }
2108    }
2109
2110    /// Push a new nested scope.
2111    #[allow(dead_code)]
2112    pub fn push_scope(&mut self) {
2113        self.scopes.push(Vec::new());
2114    }
2115
2116    /// Pop the innermost scope, discarding its bindings.
2117    /// Panics if called on the root scope.
2118    #[allow(dead_code)]
2119    pub fn pop_scope(&mut self) {
2120        assert!(self.scopes.len() > 1, "cannot pop root scope");
2121        self.scopes.pop();
2122    }
2123
2124    /// Bind `key` → `value` in the current (innermost) scope.
2125    #[allow(dead_code)]
2126    pub fn define(&mut self, key: K, value: V) {
2127        if let Some(scope) = self.scopes.last_mut() {
2128            scope.push((key, value));
2129        }
2130    }
2131
2132    /// Look up `key`, searching from innermost to outermost scope.
2133    #[allow(dead_code)]
2134    pub fn lookup(&self, key: &K) -> Option<&V> {
2135        for scope in self.scopes.iter().rev() {
2136            for (k, v) in scope.iter().rev() {
2137                if k == key {
2138                    return Some(v);
2139                }
2140            }
2141        }
2142        None
2143    }
2144
2145    /// Return `true` if `key` is defined in the current scope only.
2146    #[allow(dead_code)]
2147    pub fn defined_locally(&self, key: &K) -> bool {
2148        if let Some(scope) = self.scopes.last() {
2149            scope.iter().any(|(k, _)| k == key)
2150        } else {
2151            false
2152        }
2153    }
2154
2155    /// Current depth (1 = global scope only).
2156    #[allow(dead_code)]
2157    pub fn depth(&self) -> usize {
2158        self.scopes.len()
2159    }
2160}
2161
2162impl<K: Eq, V: Clone> Default for ScopeTable<K, V> {
2163    fn default() -> Self {
2164        Self::new()
2165    }
2166}
2167
2168// ── Counter utilities ─────────────────────────────────────────────────────────
2169
2170/// A monotonically increasing counter, useful for generating fresh variable IDs.
2171#[allow(dead_code)]
2172#[derive(Debug, Default)]
2173pub struct Counter {
2174    next: u64,
2175}
2176
2177impl Counter {
2178    /// Create a counter starting at zero.
2179    #[allow(dead_code)]
2180    pub fn new() -> Self {
2181        Self::default()
2182    }
2183
2184    /// Create a counter starting at `start`.
2185    #[allow(dead_code)]
2186    pub fn starting_at(start: u64) -> Self {
2187        Self { next: start }
2188    }
2189
2190    /// Return the next value and advance the counter.
2191    #[allow(dead_code)]
2192    pub fn next(&mut self) -> u64 {
2193        let val = self.next;
2194        self.next += 1;
2195        val
2196    }
2197
2198    /// Peek at the current value without advancing.
2199    #[allow(dead_code)]
2200    pub fn peek(&self) -> u64 {
2201        self.next
2202    }
2203
2204    /// Reset the counter to zero.
2205    #[allow(dead_code)]
2206    pub fn reset(&mut self) {
2207        self.next = 0;
2208    }
2209}
2210
2211// ── FreshName generator ───────────────────────────────────────────────────────
2212
2213/// Generates fresh name strings of the form `prefix_N`.
2214#[allow(dead_code)]
2215#[derive(Debug)]
2216pub struct FreshNameGen {
2217    prefix: String,
2218    counter: Counter,
2219}
2220
2221impl FreshNameGen {
2222    /// Create a generator with the given prefix.
2223    #[allow(dead_code)]
2224    pub fn new(prefix: impl Into<String>) -> Self {
2225        Self {
2226            prefix: prefix.into(),
2227            counter: Counter::new(),
2228        }
2229    }
2230
2231    /// Return the next fresh name.
2232    #[allow(dead_code)]
2233    pub fn fresh(&mut self) -> String {
2234        let n = self.counter.next();
2235        format!("{}_{}", self.prefix, n)
2236    }
2237
2238    /// Return the next fresh name as a `&'static str`-compatible owned `String`.
2239    #[allow(dead_code)]
2240    pub fn fresh_str(&mut self) -> String {
2241        self.fresh()
2242    }
2243
2244    /// Reset the counter (reuse names — use with caution).
2245    #[allow(dead_code)]
2246    pub fn reset(&mut self) {
2247        self.counter.reset();
2248    }
2249}
2250
2251// ── StringSet (ordered, for deterministic output) ────────────────────────────
2252
2253/// A set of `String` values backed by a sorted `Vec` for deterministic output.
2254#[allow(dead_code)]
2255#[derive(Debug, Default, Clone)]
2256pub struct StringSet {
2257    items: Vec<String>,
2258}
2259
2260impl StringSet {
2261    /// Create an empty set.
2262    #[allow(dead_code)]
2263    pub fn new() -> Self {
2264        Self::default()
2265    }
2266
2267    /// Insert `item`.  No-op if already present.  Returns `true` if new.
2268    #[allow(dead_code)]
2269    pub fn insert(&mut self, item: impl Into<String>) -> bool {
2270        let s = item.into();
2271        match self.items.binary_search(&s) {
2272            Ok(_) => false,
2273            Err(pos) => {
2274                self.items.insert(pos, s);
2275                true
2276            }
2277        }
2278    }
2279
2280    /// Return `true` if `item` is in the set.
2281    #[allow(dead_code)]
2282    pub fn contains(&self, item: &str) -> bool {
2283        self.items
2284            .binary_search_by_key(&item, String::as_str)
2285            .is_ok()
2286    }
2287
2288    /// Remove `item`.  Returns `true` if it was present.
2289    #[allow(dead_code)]
2290    pub fn remove(&mut self, item: &str) -> bool {
2291        match self.items.binary_search_by_key(&item, String::as_str) {
2292            Ok(pos) => {
2293                self.items.remove(pos);
2294                true
2295            }
2296            Err(_) => false,
2297        }
2298    }
2299
2300    /// Return the number of elements.
2301    #[allow(dead_code)]
2302    pub fn len(&self) -> usize {
2303        self.items.len()
2304    }
2305
2306    /// Return `true` if empty.
2307    #[allow(dead_code)]
2308    pub fn is_empty(&self) -> bool {
2309        self.items.is_empty()
2310    }
2311
2312    /// Iterate over items in sorted order.
2313    #[allow(dead_code)]
2314    pub fn iter(&self) -> impl Iterator<Item = &str> {
2315        self.items.iter().map(String::as_str)
2316    }
2317
2318    /// Compute the union of `self` and `other`.
2319    #[allow(dead_code)]
2320    pub fn union(&self, other: &StringSet) -> StringSet {
2321        let mut result = self.clone();
2322        for item in other.iter() {
2323            result.insert(item);
2324        }
2325        result
2326    }
2327
2328    /// Compute the intersection of `self` and `other`.
2329    #[allow(dead_code)]
2330    pub fn intersection(&self, other: &StringSet) -> StringSet {
2331        let mut result = StringSet::new();
2332        for item in self.iter() {
2333            if other.contains(item) {
2334                result.insert(item);
2335            }
2336        }
2337        result
2338    }
2339
2340    /// Compute the difference `self \ other`.
2341    #[allow(dead_code)]
2342    pub fn difference(&self, other: &StringSet) -> StringSet {
2343        let mut result = StringSet::new();
2344        for item in self.iter() {
2345            if !other.contains(item) {
2346                result.insert(item);
2347            }
2348        }
2349        result
2350    }
2351}
2352
2353// ── Multi-map ─────────────────────────────────────────────────────────────────
2354
2355/// A simple multi-map: each key may map to multiple values.
2356#[allow(dead_code)]
2357#[derive(Debug)]
2358pub struct MultiMap<K, V> {
2359    inner: Vec<(K, Vec<V>)>,
2360}
2361
2362impl<K, V> Default for MultiMap<K, V> {
2363    fn default() -> Self {
2364        Self { inner: Vec::new() }
2365    }
2366}
2367
2368impl<K: Eq, V> MultiMap<K, V> {
2369    /// Create an empty multi-map.
2370    #[allow(dead_code)]
2371    pub fn new() -> Self {
2372        Self::default()
2373    }
2374
2375    /// Insert a `(key, value)` pair.
2376    #[allow(dead_code)]
2377    pub fn insert(&mut self, key: K, value: V) {
2378        for (k, vs) in &mut self.inner {
2379            if k == &key {
2380                vs.push(value);
2381                return;
2382            }
2383        }
2384        self.inner.push((key, vec![value]));
2385    }
2386
2387    /// Return all values associated with `key`.
2388    #[allow(dead_code)]
2389    pub fn get(&self, key: &K) -> &[V] {
2390        for (k, vs) in &self.inner {
2391            if k == key {
2392                return vs;
2393            }
2394        }
2395        &[]
2396    }
2397
2398    /// Return `true` if `key` has at least one associated value.
2399    #[allow(dead_code)]
2400    pub fn contains_key(&self, key: &K) -> bool {
2401        self.inner.iter().any(|(k, _)| k == key)
2402    }
2403
2404    /// Return the number of distinct keys.
2405    #[allow(dead_code)]
2406    pub fn key_count(&self) -> usize {
2407        self.inner.len()
2408    }
2409
2410    /// Remove all entries for `key`.  Returns the removed values.
2411    #[allow(dead_code)]
2412    pub fn remove(&mut self, key: &K) -> Vec<V> {
2413        let mut result = Vec::new();
2414        let mut i = 0;
2415        while i < self.inner.len() {
2416            if &self.inner[i].0 == key {
2417                let (_, vs) = self.inner.remove(i);
2418                result = vs;
2419            } else {
2420                i += 1;
2421            }
2422        }
2423        result
2424    }
2425
2426    /// Iterate over `(key, values)` pairs.
2427    #[allow(dead_code)]
2428    pub fn iter(&self) -> impl Iterator<Item = (&K, &[V])> {
2429        self.inner.iter().map(|(k, vs)| (k, vs.as_slice()))
2430    }
2431}
2432
2433// ── Trie (prefix tree) ────────────────────────────────────────────────────────
2434
2435/// A simple trie mapping byte strings to values.
2436#[allow(dead_code)]
2437#[derive(Debug)]
2438pub struct Trie<V> {
2439    children: Vec<(u8, Trie<V>)>,
2440    value: Option<V>,
2441}
2442
2443impl<V> Trie<V> {
2444    /// Create an empty trie node.
2445    #[allow(dead_code)]
2446    pub fn new() -> Self {
2447        Self {
2448            children: Vec::new(),
2449            value: None,
2450        }
2451    }
2452
2453    /// Insert `key` → `value`.
2454    #[allow(dead_code)]
2455    pub fn insert(&mut self, key: &[u8], value: V) {
2456        if let Some((first, rest)) = key.split_first() {
2457            let child = self.get_or_create_child(*first);
2458            child.insert(rest, value);
2459        } else {
2460            self.value = Some(value);
2461        }
2462    }
2463
2464    /// Look up `key` and return a reference to the associated value, if any.
2465    #[allow(dead_code)]
2466    pub fn get(&self, key: &[u8]) -> Option<&V> {
2467        if let Some((first, rest)) = key.split_first() {
2468            for (b, child) in &self.children {
2469                if *b == *first {
2470                    return child.get(rest);
2471                }
2472            }
2473            None
2474        } else {
2475            self.value.as_ref()
2476        }
2477    }
2478
2479    /// Return `true` if `key` is present.
2480    #[allow(dead_code)]
2481    pub fn contains(&self, key: &[u8]) -> bool {
2482        self.get(key).is_some()
2483    }
2484
2485    /// Return all keys with the given `prefix`.
2486    #[allow(dead_code)]
2487    pub fn keys_with_prefix(&self, prefix: &[u8]) -> Vec<Vec<u8>> {
2488        match prefix.split_first() {
2489            Some((first, rest)) => {
2490                for (b, child) in &self.children {
2491                    if *b == *first {
2492                        return child
2493                            .keys_with_prefix(rest)
2494                            .into_iter()
2495                            .map(|mut k| {
2496                                k.insert(0, *first);
2497                                k
2498                            })
2499                            .collect();
2500                    }
2501                }
2502                Vec::new()
2503            }
2504            None => self.collect_all(Vec::new()),
2505        }
2506    }
2507
2508    fn get_or_create_child(&mut self, byte: u8) -> &mut Trie<V> {
2509        for i in 0..self.children.len() {
2510            if self.children[i].0 == byte {
2511                return &mut self.children[i].1;
2512            }
2513        }
2514        self.children.push((byte, Trie::new()));
2515        let last = self.children.len() - 1;
2516        &mut self.children[last].1
2517    }
2518
2519    fn collect_all(&self, prefix: Vec<u8>) -> Vec<Vec<u8>> {
2520        let mut result = Vec::new();
2521        if self.value.is_some() {
2522            result.push(prefix.clone());
2523        }
2524        for (b, child) in &self.children {
2525            let mut p = prefix.clone();
2526            p.push(*b);
2527            result.extend(child.collect_all(p));
2528        }
2529        result
2530    }
2531}
2532
2533impl<V> Default for Trie<V> {
2534    fn default() -> Self {
2535        Self::new()
2536    }
2537}
2538
2539// ── BitSet (fixed-width 64-bit) ───────────────────────────────────────────────
2540
2541/// A fixed-size bit set backed by a single `u64`.  Supports positions 0..63.
2542#[allow(dead_code)]
2543#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
2544pub struct BitSet64(u64);
2545
2546impl BitSet64 {
2547    /// Empty set.
2548    #[allow(dead_code)]
2549    pub const fn empty() -> Self {
2550        Self(0)
2551    }
2552
2553    /// Full set (all 64 bits set).
2554    #[allow(dead_code)]
2555    pub const fn full() -> Self {
2556        Self(u64::MAX)
2557    }
2558
2559    /// Set the bit at `pos`.
2560    #[allow(dead_code)]
2561    pub fn set(&mut self, pos: u8) {
2562        debug_assert!(pos < 64);
2563        self.0 |= 1u64 << pos;
2564    }
2565
2566    /// Clear the bit at `pos`.
2567    #[allow(dead_code)]
2568    pub fn clear(&mut self, pos: u8) {
2569        debug_assert!(pos < 64);
2570        self.0 &= !(1u64 << pos);
2571    }
2572
2573    /// Test whether the bit at `pos` is set.
2574    #[allow(dead_code)]
2575    pub fn test(&self, pos: u8) -> bool {
2576        debug_assert!(pos < 64);
2577        (self.0 >> pos) & 1 == 1
2578    }
2579
2580    /// Return the number of set bits.
2581    #[allow(dead_code)]
2582    pub fn count(&self) -> u32 {
2583        self.0.count_ones()
2584    }
2585
2586    /// Return `true` if no bits are set.
2587    #[allow(dead_code)]
2588    pub fn is_empty(&self) -> bool {
2589        self.0 == 0
2590    }
2591
2592    /// Compute bitwise AND.
2593    #[allow(dead_code)]
2594    pub fn and(self, other: Self) -> Self {
2595        Self(self.0 & other.0)
2596    }
2597
2598    /// Compute bitwise OR.
2599    #[allow(dead_code)]
2600    pub fn or(self, other: Self) -> Self {
2601        Self(self.0 | other.0)
2602    }
2603
2604    /// Compute bitwise XOR.
2605    #[allow(dead_code)]
2606    pub fn xor(self, other: Self) -> Self {
2607        Self(self.0 ^ other.0)
2608    }
2609
2610    /// Compute bitwise NOT.
2611    #[allow(dead_code)]
2612    pub fn not(self) -> Self {
2613        Self(!self.0)
2614    }
2615
2616    /// Iterate over set bit positions.
2617    #[allow(dead_code)]
2618    pub fn iter_ones(self) -> impl Iterator<Item = u8> {
2619        (0u8..64).filter(move |&i| self.test(i))
2620    }
2621}
2622
2623// ── PriorityQueue ─────────────────────────────────────────────────────────────
2624
2625/// A min-heap priority queue.
2626#[allow(dead_code)]
2627#[derive(Debug, Default)]
2628pub struct MinHeap<P: Ord, V> {
2629    heap: Vec<(P, V)>,
2630}
2631
2632impl<P: Ord, V> MinHeap<P, V> {
2633    /// Create an empty heap.
2634    #[allow(dead_code)]
2635    pub fn new() -> Self {
2636        Self { heap: Vec::new() }
2637    }
2638
2639    /// Push `(priority, value)` onto the heap.
2640    #[allow(dead_code)]
2641    pub fn push(&mut self, priority: P, value: V) {
2642        self.heap.push((priority, value));
2643        let mut i = self.heap.len() - 1;
2644        while i > 0 {
2645            let parent = (i - 1) / 2;
2646            if self.heap[parent].0 > self.heap[i].0 {
2647                self.heap.swap(parent, i);
2648                i = parent;
2649            } else {
2650                break;
2651            }
2652        }
2653    }
2654
2655    /// Pop the minimum-priority element.
2656    #[allow(dead_code)]
2657    pub fn pop(&mut self) -> Option<(P, V)> {
2658        if self.heap.is_empty() {
2659            return None;
2660        }
2661        let n = self.heap.len();
2662        self.heap.swap(0, n - 1);
2663        let min = self.heap.pop();
2664        self.sift_down(0);
2665        min
2666    }
2667
2668    /// Peek at the minimum-priority element without removing it.
2669    #[allow(dead_code)]
2670    pub fn peek(&self) -> Option<(&P, &V)> {
2671        self.heap.first().map(|(p, v)| (p, v))
2672    }
2673
2674    /// Return the number of elements.
2675    #[allow(dead_code)]
2676    pub fn len(&self) -> usize {
2677        self.heap.len()
2678    }
2679
2680    /// Return `true` if empty.
2681    #[allow(dead_code)]
2682    pub fn is_empty(&self) -> bool {
2683        self.heap.is_empty()
2684    }
2685
2686    fn sift_down(&mut self, mut i: usize) {
2687        let n = self.heap.len();
2688        loop {
2689            let left = 2 * i + 1;
2690            let right = 2 * i + 2;
2691            let mut smallest = i;
2692            if left < n && self.heap[left].0 < self.heap[smallest].0 {
2693                smallest = left;
2694            }
2695            if right < n && self.heap[right].0 < self.heap[smallest].0 {
2696                smallest = right;
2697            }
2698            if smallest == i {
2699                break;
2700            }
2701            self.heap.swap(i, smallest);
2702            i = smallest;
2703        }
2704    }
2705}
2706
2707// ── Graph (adjacency list) ────────────────────────────────────────────────────
2708
2709/// A directed graph with `n` nodes, represented as an adjacency list.
2710#[allow(dead_code)]
2711#[derive(Debug, Clone)]
2712pub struct DirectedGraph {
2713    adj: Vec<Vec<usize>>,
2714}
2715
2716impl DirectedGraph {
2717    /// Create a graph with `n` nodes and no edges.
2718    #[allow(dead_code)]
2719    pub fn new(n: usize) -> Self {
2720        Self {
2721            adj: vec![Vec::new(); n],
2722        }
2723    }
2724
2725    /// Add a directed edge `u → v`.
2726    #[allow(dead_code)]
2727    pub fn add_edge(&mut self, u: usize, v: usize) {
2728        self.adj[u].push(v);
2729    }
2730
2731    /// Return the number of nodes.
2732    #[allow(dead_code)]
2733    pub fn node_count(&self) -> usize {
2734        self.adj.len()
2735    }
2736
2737    /// Return the out-degree of node `u`.
2738    #[allow(dead_code)]
2739    pub fn out_degree(&self, u: usize) -> usize {
2740        self.adj[u].len()
2741    }
2742
2743    /// Iterate over the successors of `u`.
2744    #[allow(dead_code)]
2745    pub fn successors(&self, u: usize) -> &[usize] {
2746        &self.adj[u]
2747    }
2748
2749    /// Compute a topological ordering using Kahn's algorithm.
2750    /// Returns `None` if the graph contains a cycle.
2751    #[allow(dead_code)]
2752    pub fn topological_sort(&self) -> Option<Vec<usize>> {
2753        let n = self.adj.len();
2754        let mut in_deg = vec![0usize; n];
2755        for u in 0..n {
2756            for &v in &self.adj[u] {
2757                in_deg[v] += 1;
2758            }
2759        }
2760        let mut queue: std::collections::VecDeque<usize> =
2761            (0..n).filter(|&u| in_deg[u] == 0).collect();
2762        let mut order = Vec::new();
2763        while let Some(u) = queue.pop_front() {
2764            order.push(u);
2765            for &v in &self.adj[u] {
2766                in_deg[v] -= 1;
2767                if in_deg[v] == 0 {
2768                    queue.push_back(v);
2769                }
2770            }
2771        }
2772        if order.len() == n {
2773            Some(order)
2774        } else {
2775            None
2776        }
2777    }
2778
2779    /// Compute strongly connected components using Kosaraju's algorithm.
2780    #[allow(dead_code)]
2781    pub fn strongly_connected_components(&self) -> Vec<Vec<usize>> {
2782        let n = self.adj.len();
2783        // Pass 1: finish-time order
2784        let mut visited = vec![false; n];
2785        let mut finish_order = Vec::new();
2786        for start in 0..n {
2787            if !visited[start] {
2788                self.dfs_finish(start, &mut visited, &mut finish_order);
2789            }
2790        }
2791        // Build reverse graph
2792        let mut rev = vec![Vec::new(); n];
2793        for u in 0..n {
2794            for &v in &self.adj[u] {
2795                rev[v].push(u);
2796            }
2797        }
2798        // Pass 2: assign SCCs in reverse finish order
2799        let mut comp = vec![usize::MAX; n];
2800        let mut scc_id = 0;
2801        for &start in finish_order.iter().rev() {
2802            if comp[start] == usize::MAX {
2803                let mut stack = vec![start];
2804                while let Some(u) = stack.pop() {
2805                    if comp[u] != usize::MAX {
2806                        continue;
2807                    }
2808                    comp[u] = scc_id;
2809                    for &v in &rev[u] {
2810                        if comp[v] == usize::MAX {
2811                            stack.push(v);
2812                        }
2813                    }
2814                }
2815                scc_id += 1;
2816            }
2817        }
2818        let mut sccs: Vec<Vec<usize>> = vec![Vec::new(); scc_id];
2819        for u in 0..n {
2820            sccs[comp[u]].push(u);
2821        }
2822        sccs
2823    }
2824
2825    fn dfs_finish(&self, u: usize, visited: &mut Vec<bool>, order: &mut Vec<usize>) {
2826        let mut stack = vec![(u, 0usize)];
2827        while let Some((node, idx)) = stack.last_mut() {
2828            let _node = *node;
2829            if !visited[_node] {
2830                visited[_node] = true;
2831            }
2832            if *idx < self.adj[_node].len() {
2833                let next = self.adj[_node][*idx];
2834                *idx += 1;
2835                if !visited[next] {
2836                    stack.push((next, 0));
2837                }
2838            } else {
2839                order.push(_node);
2840                stack.pop();
2841            }
2842        }
2843    }
2844}
2845
2846// ── Tests ─────────────────────────────────────────────────────────────────────
2847
2848#[cfg(test)]
2849mod lib_extended_tests {
2850    use super::*;
2851
2852    #[test]
2853    fn test_span_merge() {
2854        let a = Span::new(0, 5, 1, 1);
2855        let b = Span::new(3, 10, 1, 4);
2856        let m = a.merge(&b);
2857        assert_eq!(m.start, 0);
2858        assert_eq!(m.end, 10);
2859    }
2860
2861    #[test]
2862    fn test_located_map() {
2863        let l = Located::dummy(42u32);
2864        let l2 = l.map(|x| x * 2);
2865        assert_eq!(l2.value, 84);
2866    }
2867
2868    #[test]
2869    fn test_name_table() {
2870        let mut t = NameTable::new();
2871        let id_a = t.intern("alpha");
2872        let id_b = t.intern("beta");
2873        let id_a2 = t.intern("alpha");
2874        assert_eq!(id_a, id_a2);
2875        assert_ne!(id_a, id_b);
2876        assert_eq!(t.lookup(id_a), Some("alpha"));
2877        assert_eq!(t.len(), 2);
2878    }
2879
2880    #[test]
2881    fn test_diagnostic_bag() {
2882        let mut bag = DiagnosticBag::new();
2883        assert!(!bag.has_errors());
2884        bag.push(Diagnostic::warning("minor issue"));
2885        assert!(!bag.has_errors());
2886        bag.push(Diagnostic::error("fatal problem"));
2887        assert!(bag.has_errors());
2888        assert_eq!(bag.len(), 2);
2889        let drained = bag.drain();
2890        assert_eq!(drained.len(), 2);
2891        assert!(bag.is_empty());
2892    }
2893
2894    #[test]
2895    fn test_scope_table() {
2896        let mut s: ScopeTable<&str, u32> = ScopeTable::new();
2897        s.define("x", 1);
2898        s.push_scope();
2899        s.define("x", 2);
2900        assert_eq!(s.lookup(&"x"), Some(&2));
2901        s.pop_scope();
2902        assert_eq!(s.lookup(&"x"), Some(&1));
2903    }
2904
2905    #[test]
2906    fn test_counter_and_fresh_name() {
2907        let mut c = Counter::new();
2908        assert_eq!(c.next(), 0);
2909        assert_eq!(c.next(), 1);
2910        assert_eq!(c.peek(), 2);
2911        c.reset();
2912        assert_eq!(c.next(), 0);
2913
2914        let mut gen = FreshNameGen::new("var");
2915        let n0 = gen.fresh();
2916        let n1 = gen.fresh();
2917        assert_eq!(n0, "var_0");
2918        assert_eq!(n1, "var_1");
2919    }
2920
2921    #[test]
2922    fn test_string_set_operations() {
2923        let mut s = StringSet::new();
2924        assert!(s.insert("banana"));
2925        assert!(s.insert("apple"));
2926        assert!(!s.insert("apple")); // duplicate
2927        assert!(s.contains("apple"));
2928        assert!(!s.contains("cherry"));
2929        assert_eq!(s.len(), 2);
2930        assert!(s.remove("apple"));
2931        assert!(!s.contains("apple"));
2932        let mut t = StringSet::new();
2933        t.insert("cherry");
2934        t.insert("banana");
2935        let u = s.union(&t);
2936        assert!(u.contains("banana"));
2937        assert!(u.contains("cherry"));
2938    }
2939
2940    #[test]
2941    fn test_multi_map() {
2942        let mut m: MultiMap<&str, u32> = MultiMap::new();
2943        m.insert("key", 1);
2944        m.insert("key", 2);
2945        m.insert("other", 3);
2946        assert_eq!(m.get(&"key"), &[1, 2]);
2947        assert_eq!(m.key_count(), 2);
2948        let removed = m.remove(&"key");
2949        assert_eq!(removed, vec![1, 2]);
2950        assert!(!m.contains_key(&"key"));
2951    }
2952
2953    #[test]
2954    fn test_trie() {
2955        let mut t: Trie<u32> = Trie::new();
2956        t.insert(b"hello", 1);
2957        t.insert(b"help", 2);
2958        t.insert(b"world", 3);
2959        assert_eq!(t.get(b"hello"), Some(&1));
2960        assert_eq!(t.get(b"help"), Some(&2));
2961        assert!(t.get(b"helo").is_none());
2962        assert!(t.contains(b"world"));
2963        let pfx = t.keys_with_prefix(b"hel");
2964        assert_eq!(pfx.len(), 2);
2965    }
2966
2967    #[test]
2968    fn test_bitset64() {
2969        let mut bs = BitSet64::empty();
2970        assert!(bs.is_empty());
2971        bs.set(5);
2972        bs.set(10);
2973        assert!(bs.test(5));
2974        assert!(bs.test(10));
2975        assert!(!bs.test(0));
2976        assert_eq!(bs.count(), 2);
2977        bs.clear(5);
2978        assert!(!bs.test(5));
2979        let ones: Vec<u8> = bs.iter_ones().collect();
2980        assert_eq!(ones, vec![10]);
2981    }
2982
2983    #[test]
2984    fn test_min_heap() {
2985        let mut heap: MinHeap<u32, &str> = MinHeap::new();
2986        heap.push(5, "five");
2987        heap.push(1, "one");
2988        heap.push(3, "three");
2989        assert_eq!(heap.len(), 3);
2990        let (p, v) = heap.pop().expect("pop should succeed");
2991        assert_eq!(p, 1);
2992        assert_eq!(v, "one");
2993        let (p2, _) = heap.pop().expect("pop should succeed");
2994        assert_eq!(p2, 3);
2995    }
2996
2997    #[test]
2998    fn test_directed_graph_topo_sort() {
2999        let mut g = DirectedGraph::new(4);
3000        g.add_edge(0, 1);
3001        g.add_edge(0, 2);
3002        g.add_edge(1, 3);
3003        g.add_edge(2, 3);
3004        let order = g.topological_sort().expect("should be a DAG");
3005        assert_eq!(order.len(), 4);
3006        // 0 must come before 1,2; 1 and 2 before 3
3007        let pos: Vec<usize> = {
3008            let mut p = vec![0usize; 4];
3009            for (i, &node) in order.iter().enumerate() {
3010                p[node] = i;
3011            }
3012            p
3013        };
3014        assert!(pos[0] < pos[1]);
3015        assert!(pos[0] < pos[2]);
3016        assert!(pos[1] < pos[3]);
3017        assert!(pos[2] < pos[3]);
3018    }
3019
3020    #[test]
3021    fn test_directed_graph_scc() {
3022        // 0 → 1 → 2 → 0, 3 (separate)
3023        let mut g = DirectedGraph::new(4);
3024        g.add_edge(0, 1);
3025        g.add_edge(1, 2);
3026        g.add_edge(2, 0);
3027        // node 3 is isolated
3028        let sccs = g.strongly_connected_components();
3029        // Should have 2 SCCs: {0,1,2} and {3}
3030        assert_eq!(sccs.len(), 2);
3031    }
3032
3033    #[test]
3034    fn test_diagnostic_level_ordering() {
3035        assert!(DiagnosticLevel::Note < DiagnosticLevel::Warning);
3036        assert!(DiagnosticLevel::Warning < DiagnosticLevel::Error);
3037        assert!(DiagnosticLevel::Error < DiagnosticLevel::Bug);
3038        assert!(DiagnosticLevel::Error.is_fatal());
3039        assert!(!DiagnosticLevel::Warning.is_fatal());
3040    }
3041}