1#![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#[allow(dead_code)]
648#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
649pub enum BuildPhase {
650 Primitives,
652 Collections,
654 TypeClasses,
656 Theorems,
658 Automation,
660}
661
662impl BuildPhase {
663 #[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 #[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#[allow(dead_code)]
690#[derive(Debug, Clone)]
691pub struct StdModuleEntry {
692 pub qualified_name: &'static str,
694 pub phase: BuildPhase,
696 pub default_load: bool,
698 pub description: &'static str,
700}
701
702#[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#[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#[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#[allow(dead_code)]
889pub fn all_modules() -> &'static [StdModuleEntry] {
890 STD_MODULE_REGISTRY
891}
892
893#[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#[allow(dead_code)]
904pub fn count_total_modules() -> usize {
905 STD_MODULE_REGISTRY.len()
906}
907
908#[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#[allow(dead_code)]
918#[derive(Debug, Clone, Copy)]
919pub struct ModuleDep {
920 pub dependent: &'static str,
922 pub dependency: &'static str,
924}
925
926#[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#[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#[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#[allow(dead_code)]
1009pub const STD_VERSION: &str = "0.1.1";
1010
1011#[allow(dead_code)]
1013#[derive(Debug, Clone, Default)]
1014pub struct StdFeatures {
1015 pub classical: bool,
1017 pub propext: bool,
1019 pub funext: bool,
1021 pub quotient: bool,
1023 pub category_theory: bool,
1025 pub topology: bool,
1027 pub reals: bool,
1029}
1030
1031impl StdFeatures {
1032 #[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 #[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 #[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#[allow(dead_code)]
1080#[derive(Debug, Clone, Default)]
1081pub struct StdLibStats {
1082 pub total_modules: usize,
1084 pub default_modules: usize,
1086 pub per_phase: [usize; 5],
1088}
1089
1090impl StdLibStats {
1091 #[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 #[allow(dead_code)]
1112 pub fn all_phases_populated(&self) -> bool {
1113 self.per_phase.iter().all(|&n| n > 0)
1114 }
1115
1116 #[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#[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 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 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 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 }
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 assert_eq!(f.count_enabled(), 3);
1363 }
1364
1365 #[test]
1366 fn test_module_dep_dependent_in_registry() {
1367 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#[allow(dead_code)]
1416#[derive(Debug, Clone)]
1417pub struct StdEntry {
1418 pub name: &'static str,
1420 pub module: &'static str,
1422 pub description: &'static str,
1424 pub is_theorem: bool,
1426}
1427
1428#[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#[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#[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#[allow(dead_code)]
1510pub fn all_theorems() -> Vec<&'static StdEntry> {
1511 STD_KNOWN_ENTRIES.iter().filter(|e| e.is_theorem).collect()
1512}
1513
1514#[allow(dead_code)]
1516#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1517pub enum StdCategory {
1518 Arithmetic,
1520 Logic,
1522 Data,
1524 TypeClass,
1526 IO,
1528 String,
1530 Tactic,
1532 Universe,
1534}
1535
1536impl StdCategory {
1537 #[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#[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#[allow(dead_code)]
1577pub struct StdVersion {
1578 pub major: u32,
1580 pub minor: u32,
1582 pub patch: u32,
1584 pub pre: &'static str,
1586}
1587
1588impl StdVersion {
1589 #[allow(dead_code)]
1591 pub const CURRENT: StdVersion = StdVersion {
1592 major: 0,
1593 minor: 1,
1594 patch: 0,
1595 pre: "alpha",
1596 };
1597
1598 #[allow(dead_code)]
1600 pub fn format_version(&self) -> String {
1601 self.to_string()
1602 }
1603
1604 #[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#[allow(dead_code)]
1769#[derive(Debug, Clone, PartialEq, Eq)]
1770pub struct Span {
1771 pub start: usize,
1773 pub end: usize,
1775 pub line: u32,
1777 pub column: u32,
1779}
1780
1781impl Span {
1782 #[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 #[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 #[allow(dead_code)]
1806 pub fn len(&self) -> usize {
1807 self.end.saturating_sub(self.start)
1808 }
1809
1810 #[allow(dead_code)]
1812 pub fn is_empty(&self) -> bool {
1813 self.start >= self.end
1814 }
1815
1816 #[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#[allow(dead_code)]
1830#[derive(Debug, Clone)]
1831pub struct Located<T> {
1832 pub value: T,
1834 pub span: Span,
1836}
1837
1838impl<T> Located<T> {
1839 #[allow(dead_code)]
1841 pub fn new(value: T, span: Span) -> Self {
1842 Self { value, span }
1843 }
1844
1845 #[allow(dead_code)]
1847 pub fn dummy(value: T) -> Self {
1848 Self {
1849 value,
1850 span: Span::dummy(),
1851 }
1852 }
1853
1854 #[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 #[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#[allow(dead_code)]
1879#[derive(Debug, Default)]
1880pub struct NameTable {
1881 names: Vec<String>,
1882}
1883
1884impl NameTable {
1885 #[allow(dead_code)]
1887 pub fn new() -> Self {
1888 Self::default()
1889 }
1890
1891 #[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 #[allow(dead_code)]
1905 pub fn lookup(&self, id: usize) -> Option<&str> {
1906 self.names.get(id).map(String::as_str)
1907 }
1908
1909 #[allow(dead_code)]
1911 pub fn len(&self) -> usize {
1912 self.names.len()
1913 }
1914
1915 #[allow(dead_code)]
1917 pub fn is_empty(&self) -> bool {
1918 self.names.is_empty()
1919 }
1920
1921 #[allow(dead_code)]
1923 pub fn clear(&mut self) {
1924 self.names.clear();
1925 }
1926
1927 #[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#[allow(dead_code)]
1938#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
1939pub enum DiagnosticLevel {
1940 Note,
1942 Warning,
1944 Error,
1946 Bug,
1948}
1949
1950impl DiagnosticLevel {
1951 #[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 #[allow(dead_code)]
1964 pub fn is_fatal(self) -> bool {
1965 matches!(self, Self::Error | Self::Bug)
1966 }
1967}
1968
1969#[allow(dead_code)]
1971#[derive(Debug, Clone)]
1972pub struct Diagnostic {
1973 pub level: DiagnosticLevel,
1975 pub message: String,
1977 pub span: Option<Span>,
1979 pub help: Option<String>,
1981}
1982
1983impl Diagnostic {
1984 #[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 #[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 #[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 #[allow(dead_code)]
2019 pub fn with_span(mut self, span: Span) -> Self {
2020 self.span = Some(span);
2021 self
2022 }
2023
2024 #[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 #[allow(dead_code)]
2033 pub fn is_fatal(&self) -> bool {
2034 self.level.is_fatal()
2035 }
2036}
2037
2038#[allow(dead_code)]
2040#[derive(Debug, Default)]
2041pub struct DiagnosticBag {
2042 items: Vec<Diagnostic>,
2043}
2044
2045impl DiagnosticBag {
2046 #[allow(dead_code)]
2048 pub fn new() -> Self {
2049 Self::default()
2050 }
2051
2052 #[allow(dead_code)]
2054 pub fn push(&mut self, diag: Diagnostic) {
2055 self.items.push(diag);
2056 }
2057
2058 #[allow(dead_code)]
2060 pub fn has_errors(&self) -> bool {
2061 self.items.iter().any(|d| d.is_fatal())
2062 }
2063
2064 #[allow(dead_code)]
2066 pub fn len(&self) -> usize {
2067 self.items.len()
2068 }
2069
2070 #[allow(dead_code)]
2072 pub fn is_empty(&self) -> bool {
2073 self.items.is_empty()
2074 }
2075
2076 #[allow(dead_code)]
2078 pub fn drain(&mut self) -> Vec<Diagnostic> {
2079 std::mem::take(&mut self.items)
2080 }
2081
2082 #[allow(dead_code)]
2084 pub fn iter(&self) -> impl Iterator<Item = &Diagnostic> {
2085 self.items.iter()
2086 }
2087}
2088
2089#[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 #[allow(dead_code)]
2104 pub fn new() -> Self {
2105 Self {
2106 scopes: vec![Vec::new()],
2107 }
2108 }
2109
2110 #[allow(dead_code)]
2112 pub fn push_scope(&mut self) {
2113 self.scopes.push(Vec::new());
2114 }
2115
2116 #[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 #[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 #[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 #[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 #[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#[allow(dead_code)]
2172#[derive(Debug, Default)]
2173pub struct Counter {
2174 next: u64,
2175}
2176
2177impl Counter {
2178 #[allow(dead_code)]
2180 pub fn new() -> Self {
2181 Self::default()
2182 }
2183
2184 #[allow(dead_code)]
2186 pub fn starting_at(start: u64) -> Self {
2187 Self { next: start }
2188 }
2189
2190 #[allow(dead_code)]
2192 pub fn next(&mut self) -> u64 {
2193 let val = self.next;
2194 self.next += 1;
2195 val
2196 }
2197
2198 #[allow(dead_code)]
2200 pub fn peek(&self) -> u64 {
2201 self.next
2202 }
2203
2204 #[allow(dead_code)]
2206 pub fn reset(&mut self) {
2207 self.next = 0;
2208 }
2209}
2210
2211#[allow(dead_code)]
2215#[derive(Debug)]
2216pub struct FreshNameGen {
2217 prefix: String,
2218 counter: Counter,
2219}
2220
2221impl FreshNameGen {
2222 #[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 #[allow(dead_code)]
2233 pub fn fresh(&mut self) -> String {
2234 let n = self.counter.next();
2235 format!("{}_{}", self.prefix, n)
2236 }
2237
2238 #[allow(dead_code)]
2240 pub fn fresh_str(&mut self) -> String {
2241 self.fresh()
2242 }
2243
2244 #[allow(dead_code)]
2246 pub fn reset(&mut self) {
2247 self.counter.reset();
2248 }
2249}
2250
2251#[allow(dead_code)]
2255#[derive(Debug, Default, Clone)]
2256pub struct StringSet {
2257 items: Vec<String>,
2258}
2259
2260impl StringSet {
2261 #[allow(dead_code)]
2263 pub fn new() -> Self {
2264 Self::default()
2265 }
2266
2267 #[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 #[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 #[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 #[allow(dead_code)]
2302 pub fn len(&self) -> usize {
2303 self.items.len()
2304 }
2305
2306 #[allow(dead_code)]
2308 pub fn is_empty(&self) -> bool {
2309 self.items.is_empty()
2310 }
2311
2312 #[allow(dead_code)]
2314 pub fn iter(&self) -> impl Iterator<Item = &str> {
2315 self.items.iter().map(String::as_str)
2316 }
2317
2318 #[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 #[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 #[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#[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 #[allow(dead_code)]
2371 pub fn new() -> Self {
2372 Self::default()
2373 }
2374
2375 #[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 #[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 #[allow(dead_code)]
2400 pub fn contains_key(&self, key: &K) -> bool {
2401 self.inner.iter().any(|(k, _)| k == key)
2402 }
2403
2404 #[allow(dead_code)]
2406 pub fn key_count(&self) -> usize {
2407 self.inner.len()
2408 }
2409
2410 #[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 #[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#[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 #[allow(dead_code)]
2446 pub fn new() -> Self {
2447 Self {
2448 children: Vec::new(),
2449 value: None,
2450 }
2451 }
2452
2453 #[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 #[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 #[allow(dead_code)]
2481 pub fn contains(&self, key: &[u8]) -> bool {
2482 self.get(key).is_some()
2483 }
2484
2485 #[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#[allow(dead_code)]
2543#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
2544pub struct BitSet64(u64);
2545
2546impl BitSet64 {
2547 #[allow(dead_code)]
2549 pub const fn empty() -> Self {
2550 Self(0)
2551 }
2552
2553 #[allow(dead_code)]
2555 pub const fn full() -> Self {
2556 Self(u64::MAX)
2557 }
2558
2559 #[allow(dead_code)]
2561 pub fn set(&mut self, pos: u8) {
2562 debug_assert!(pos < 64);
2563 self.0 |= 1u64 << pos;
2564 }
2565
2566 #[allow(dead_code)]
2568 pub fn clear(&mut self, pos: u8) {
2569 debug_assert!(pos < 64);
2570 self.0 &= !(1u64 << pos);
2571 }
2572
2573 #[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 #[allow(dead_code)]
2582 pub fn count(&self) -> u32 {
2583 self.0.count_ones()
2584 }
2585
2586 #[allow(dead_code)]
2588 pub fn is_empty(&self) -> bool {
2589 self.0 == 0
2590 }
2591
2592 #[allow(dead_code)]
2594 pub fn and(self, other: Self) -> Self {
2595 Self(self.0 & other.0)
2596 }
2597
2598 #[allow(dead_code)]
2600 pub fn or(self, other: Self) -> Self {
2601 Self(self.0 | other.0)
2602 }
2603
2604 #[allow(dead_code)]
2606 pub fn xor(self, other: Self) -> Self {
2607 Self(self.0 ^ other.0)
2608 }
2609
2610 #[allow(dead_code)]
2612 pub fn not(self) -> Self {
2613 Self(!self.0)
2614 }
2615
2616 #[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#[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 #[allow(dead_code)]
2635 pub fn new() -> Self {
2636 Self { heap: Vec::new() }
2637 }
2638
2639 #[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 #[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 #[allow(dead_code)]
2670 pub fn peek(&self) -> Option<(&P, &V)> {
2671 self.heap.first().map(|(p, v)| (p, v))
2672 }
2673
2674 #[allow(dead_code)]
2676 pub fn len(&self) -> usize {
2677 self.heap.len()
2678 }
2679
2680 #[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#[allow(dead_code)]
2711#[derive(Debug, Clone)]
2712pub struct DirectedGraph {
2713 adj: Vec<Vec<usize>>,
2714}
2715
2716impl DirectedGraph {
2717 #[allow(dead_code)]
2719 pub fn new(n: usize) -> Self {
2720 Self {
2721 adj: vec![Vec::new(); n],
2722 }
2723 }
2724
2725 #[allow(dead_code)]
2727 pub fn add_edge(&mut self, u: usize, v: usize) {
2728 self.adj[u].push(v);
2729 }
2730
2731 #[allow(dead_code)]
2733 pub fn node_count(&self) -> usize {
2734 self.adj.len()
2735 }
2736
2737 #[allow(dead_code)]
2739 pub fn out_degree(&self, u: usize) -> usize {
2740 self.adj[u].len()
2741 }
2742
2743 #[allow(dead_code)]
2745 pub fn successors(&self, u: usize) -> &[usize] {
2746 &self.adj[u]
2747 }
2748
2749 #[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 #[allow(dead_code)]
2781 pub fn strongly_connected_components(&self) -> Vec<Vec<usize>> {
2782 let n = self.adj.len();
2783 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 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 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#[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")); 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 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 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 let sccs = g.strongly_connected_components();
3029 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}