Skip to main content

oxilean_std/
std_utilities.rs

1//! Extended standard library utility types: Span, Located, NameTable,
2//! DiagnosticLevel, Diagnostic, DiagnosticBag, ScopeTable, Counter,
3//! FreshNameGen, StringSet, MultiMap, Trie, BitSet64, MinHeap, DirectedGraph.
4
5#![allow(dead_code)]
6#![allow(missing_docs)]
7
8// ── Span ─────────────────────────────────────────────────────────────────────
9
10/// Utility type for carrying source-location metadata.
11#[allow(dead_code)]
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct Span {
14    /// Byte offset of the first character.
15    pub start: usize,
16    /// Byte offset one past the last character.
17    pub end: usize,
18    /// 1-based line number of the start.
19    pub line: u32,
20    /// 1-based column number of the start.
21    pub column: u32,
22}
23
24impl Span {
25    /// Create a new span.
26    #[allow(dead_code)]
27    pub fn new(start: usize, end: usize, line: u32, column: u32) -> Self {
28        Self {
29            start,
30            end,
31            line,
32            column,
33        }
34    }
35
36    /// Create a dummy span (all zeros).
37    #[allow(dead_code)]
38    pub fn dummy() -> Self {
39        Self {
40            start: 0,
41            end: 0,
42            line: 0,
43            column: 0,
44        }
45    }
46
47    /// Return the length in bytes.
48    #[allow(dead_code)]
49    pub fn len(&self) -> usize {
50        self.end.saturating_sub(self.start)
51    }
52
53    /// Return `true` if the span covers zero bytes.
54    #[allow(dead_code)]
55    pub fn is_empty(&self) -> bool {
56        self.start >= self.end
57    }
58
59    /// Merge two spans: from the earlier start to the later end.
60    #[allow(dead_code)]
61    pub fn merge(&self, other: &Span) -> Span {
62        Span {
63            start: self.start.min(other.start),
64            end: self.end.max(other.end),
65            line: self.line.min(other.line),
66            column: self.column,
67        }
68    }
69}
70
71/// A value annotated with a `Span`.
72#[allow(dead_code)]
73#[derive(Debug, Clone)]
74pub struct Located<T> {
75    /// The wrapped value.
76    pub value: T,
77    /// The source span.
78    pub span: Span,
79}
80
81impl<T> Located<T> {
82    /// Wrap `value` with a `span`.
83    #[allow(dead_code)]
84    pub fn new(value: T, span: Span) -> Self {
85        Self { value, span }
86    }
87
88    /// Wrap `value` with a dummy span.
89    #[allow(dead_code)]
90    pub fn dummy(value: T) -> Self {
91        Self {
92            value,
93            span: Span::dummy(),
94        }
95    }
96
97    /// Map over the inner value.
98    #[allow(dead_code)]
99    pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Located<U> {
100        Located {
101            value: f(self.value),
102            span: self.span,
103        }
104    }
105
106    /// Return a reference to the inner value.
107    #[allow(dead_code)]
108    pub fn as_ref(&self) -> Located<&T> {
109        Located {
110            value: &self.value,
111            span: self.span.clone(),
112        }
113    }
114}
115
116// ── Simple name-interning table ───────────────────────────────────────────────
117
118/// A simple string-interning table backed by a `Vec`.
119///
120/// Useful for giving cheap `usize` IDs to string names during elaboration.
121#[allow(dead_code)]
122#[derive(Debug, Default)]
123pub struct NameTable {
124    names: Vec<String>,
125}
126
127impl NameTable {
128    /// Create an empty table.
129    #[allow(dead_code)]
130    pub fn new() -> Self {
131        Self::default()
132    }
133
134    /// Intern `name` and return its ID.  If already present, returns the
135    /// existing ID without inserting a duplicate.
136    #[allow(dead_code)]
137    pub fn intern(&mut self, name: &str) -> usize {
138        if let Some(pos) = self.names.iter().position(|n| n == name) {
139            return pos;
140        }
141        let id = self.names.len();
142        self.names.push(name.to_owned());
143        id
144    }
145
146    /// Look up the string for an ID.
147    #[allow(dead_code)]
148    pub fn lookup(&self, id: usize) -> Option<&str> {
149        self.names.get(id).map(String::as_str)
150    }
151
152    /// Return the number of interned names.
153    #[allow(dead_code)]
154    pub fn len(&self) -> usize {
155        self.names.len()
156    }
157
158    /// Return `true` if the table is empty.
159    #[allow(dead_code)]
160    pub fn is_empty(&self) -> bool {
161        self.names.is_empty()
162    }
163
164    /// Clear all entries.
165    #[allow(dead_code)]
166    pub fn clear(&mut self) {
167        self.names.clear();
168    }
169
170    /// Return an iterator over `(id, name)` pairs.
171    #[allow(dead_code)]
172    pub fn iter(&self) -> impl Iterator<Item = (usize, &str)> {
173        self.names.iter().enumerate().map(|(i, s)| (i, s.as_str()))
174    }
175}
176
177// ── DiagnosticLevel ──────────────────────────────────────────────────────────
178
179/// Severity levels for compiler diagnostics.
180#[allow(dead_code)]
181#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
182pub enum DiagnosticLevel {
183    /// Informational note; does not prevent compilation.
184    Note,
185    /// Warning; compilation continues.
186    Warning,
187    /// Error; compilation should stop.
188    Error,
189    /// Internal compiler error (ICE).
190    Bug,
191}
192
193impl DiagnosticLevel {
194    /// Return a short label string.
195    #[allow(dead_code)]
196    pub fn label(self) -> &'static str {
197        match self {
198            Self::Note => "note",
199            Self::Warning => "warning",
200            Self::Error => "error",
201            Self::Bug => "internal compiler error",
202        }
203    }
204
205    /// Return `true` if this level prevents a successful build.
206    #[allow(dead_code)]
207    pub fn is_fatal(self) -> bool {
208        matches!(self, Self::Error | Self::Bug)
209    }
210}
211
212/// A single compiler diagnostic.
213#[allow(dead_code)]
214#[derive(Debug, Clone)]
215pub struct Diagnostic {
216    /// Severity level.
217    pub level: DiagnosticLevel,
218    /// Human-readable message.
219    pub message: String,
220    /// Optional source span.
221    pub span: Option<Span>,
222    /// Optional help/hint text.
223    pub help: Option<String>,
224}
225
226impl Diagnostic {
227    /// Construct an error diagnostic.
228    #[allow(dead_code)]
229    pub fn error(message: impl Into<String>) -> Self {
230        Self {
231            level: DiagnosticLevel::Error,
232            message: message.into(),
233            span: None,
234            help: None,
235        }
236    }
237
238    /// Construct a warning.
239    #[allow(dead_code)]
240    pub fn warning(message: impl Into<String>) -> Self {
241        Self {
242            level: DiagnosticLevel::Warning,
243            message: message.into(),
244            span: None,
245            help: None,
246        }
247    }
248
249    /// Construct a note.
250    #[allow(dead_code)]
251    pub fn note(message: impl Into<String>) -> Self {
252        Self {
253            level: DiagnosticLevel::Note,
254            message: message.into(),
255            span: None,
256            help: None,
257        }
258    }
259
260    /// Attach a source span.
261    #[allow(dead_code)]
262    pub fn with_span(mut self, span: Span) -> Self {
263        self.span = Some(span);
264        self
265    }
266
267    /// Attach a help string.
268    #[allow(dead_code)]
269    pub fn with_help(mut self, help: impl Into<String>) -> Self {
270        self.help = Some(help.into());
271        self
272    }
273
274    /// Return `true` if this diagnostic is fatal.
275    #[allow(dead_code)]
276    pub fn is_fatal(&self) -> bool {
277        self.level.is_fatal()
278    }
279}
280
281/// Accumulator for multiple diagnostics.
282#[allow(dead_code)]
283#[derive(Debug, Default)]
284pub struct DiagnosticBag {
285    items: Vec<Diagnostic>,
286}
287
288impl DiagnosticBag {
289    /// Create an empty bag.
290    #[allow(dead_code)]
291    pub fn new() -> Self {
292        Self::default()
293    }
294
295    /// Push a diagnostic.
296    #[allow(dead_code)]
297    pub fn push(&mut self, diag: Diagnostic) {
298        self.items.push(diag);
299    }
300
301    /// Return `true` if there are any fatal diagnostics.
302    #[allow(dead_code)]
303    pub fn has_errors(&self) -> bool {
304        self.items.iter().any(|d| d.is_fatal())
305    }
306
307    /// Return the number of accumulated diagnostics.
308    #[allow(dead_code)]
309    pub fn len(&self) -> usize {
310        self.items.len()
311    }
312
313    /// Return `true` if the bag is empty.
314    #[allow(dead_code)]
315    pub fn is_empty(&self) -> bool {
316        self.items.is_empty()
317    }
318
319    /// Drain all diagnostics, returning them in order.
320    #[allow(dead_code)]
321    pub fn drain(&mut self) -> Vec<Diagnostic> {
322        std::mem::take(&mut self.items)
323    }
324
325    /// Iterate over diagnostics.
326    #[allow(dead_code)]
327    pub fn iter(&self) -> impl Iterator<Item = &Diagnostic> {
328        self.items.iter()
329    }
330}
331
332// ── Simple scoped symbol table ────────────────────────────────────────────────
333
334/// A scoped symbol table supporting nested scopes.
335///
336/// Each `push_scope` / `pop_scope` pair delimits a lexical scope.  Lookups
337/// search from the innermost scope outward.
338#[allow(dead_code)]
339#[derive(Debug)]
340pub struct ScopeTable<K, V> {
341    scopes: Vec<Vec<(K, V)>>,
342}
343
344impl<K: Eq, V: Clone> ScopeTable<K, V> {
345    /// Create a table with a single (global) scope.
346    #[allow(dead_code)]
347    pub fn new() -> Self {
348        Self {
349            scopes: vec![Vec::new()],
350        }
351    }
352
353    /// Push a new nested scope.
354    #[allow(dead_code)]
355    pub fn push_scope(&mut self) {
356        self.scopes.push(Vec::new());
357    }
358
359    /// Pop the innermost scope, discarding its bindings.
360    /// Panics if called on the root scope.
361    #[allow(dead_code)]
362    pub fn pop_scope(&mut self) {
363        assert!(self.scopes.len() > 1, "cannot pop root scope");
364        self.scopes.pop();
365    }
366
367    /// Bind `key` → `value` in the current (innermost) scope.
368    #[allow(dead_code)]
369    pub fn define(&mut self, key: K, value: V) {
370        if let Some(scope) = self.scopes.last_mut() {
371            scope.push((key, value));
372        }
373    }
374
375    /// Look up `key`, searching from innermost to outermost scope.
376    #[allow(dead_code)]
377    pub fn lookup(&self, key: &K) -> Option<&V> {
378        for scope in self.scopes.iter().rev() {
379            for (k, v) in scope.iter().rev() {
380                if k == key {
381                    return Some(v);
382                }
383            }
384        }
385        None
386    }
387
388    /// Return `true` if `key` is defined in the current scope only.
389    #[allow(dead_code)]
390    pub fn defined_locally(&self, key: &K) -> bool {
391        if let Some(scope) = self.scopes.last() {
392            scope.iter().any(|(k, _)| k == key)
393        } else {
394            false
395        }
396    }
397
398    /// Current depth (1 = global scope only).
399    #[allow(dead_code)]
400    pub fn depth(&self) -> usize {
401        self.scopes.len()
402    }
403}
404
405impl<K: Eq, V: Clone> Default for ScopeTable<K, V> {
406    fn default() -> Self {
407        Self::new()
408    }
409}
410
411// ── Counter utilities ─────────────────────────────────────────────────────────
412
413/// A monotonically increasing counter, useful for generating fresh variable IDs.
414#[allow(dead_code)]
415#[derive(Debug, Default)]
416pub struct Counter {
417    next: u64,
418}
419
420impl Counter {
421    /// Create a counter starting at zero.
422    #[allow(dead_code)]
423    pub fn new() -> Self {
424        Self::default()
425    }
426
427    /// Create a counter starting at `start`.
428    #[allow(dead_code)]
429    pub fn starting_at(start: u64) -> Self {
430        Self { next: start }
431    }
432
433    /// Return the next value and advance the counter.
434    #[allow(dead_code)]
435    pub fn next(&mut self) -> u64 {
436        let val = self.next;
437        self.next += 1;
438        val
439    }
440
441    /// Peek at the current value without advancing.
442    #[allow(dead_code)]
443    pub fn peek(&self) -> u64 {
444        self.next
445    }
446
447    /// Reset the counter to zero.
448    #[allow(dead_code)]
449    pub fn reset(&mut self) {
450        self.next = 0;
451    }
452}
453
454// ── FreshName generator ───────────────────────────────────────────────────────
455
456/// Generates fresh name strings of the form `prefix_N`.
457#[allow(dead_code)]
458#[derive(Debug)]
459pub struct FreshNameGen {
460    prefix: String,
461    counter: Counter,
462}
463
464impl FreshNameGen {
465    /// Create a generator with the given prefix.
466    #[allow(dead_code)]
467    pub fn new(prefix: impl Into<String>) -> Self {
468        Self {
469            prefix: prefix.into(),
470            counter: Counter::new(),
471        }
472    }
473
474    /// Return the next fresh name.
475    #[allow(dead_code)]
476    pub fn fresh(&mut self) -> String {
477        let n = self.counter.next();
478        format!("{}_{}", self.prefix, n)
479    }
480
481    /// Return the next fresh name as a `&'static str`-compatible owned `String`.
482    #[allow(dead_code)]
483    pub fn fresh_str(&mut self) -> String {
484        self.fresh()
485    }
486
487    /// Reset the counter (reuse names — use with caution).
488    #[allow(dead_code)]
489    pub fn reset(&mut self) {
490        self.counter.reset();
491    }
492}
493
494// ── StringSet (ordered, for deterministic output) ────────────────────────────
495
496/// A set of `String` values backed by a sorted `Vec` for deterministic output.
497#[allow(dead_code)]
498#[derive(Debug, Default, Clone)]
499pub struct StringSet {
500    items: Vec<String>,
501}
502
503impl StringSet {
504    /// Create an empty set.
505    #[allow(dead_code)]
506    pub fn new() -> Self {
507        Self::default()
508    }
509
510    /// Insert `item`.  No-op if already present.  Returns `true` if new.
511    #[allow(dead_code)]
512    pub fn insert(&mut self, item: impl Into<String>) -> bool {
513        let s = item.into();
514        match self.items.binary_search(&s) {
515            Ok(_) => false,
516            Err(pos) => {
517                self.items.insert(pos, s);
518                true
519            }
520        }
521    }
522
523    /// Return `true` if `item` is in the set.
524    #[allow(dead_code)]
525    pub fn contains(&self, item: &str) -> bool {
526        self.items
527            .binary_search_by_key(&item, String::as_str)
528            .is_ok()
529    }
530
531    /// Remove `item`.  Returns `true` if it was present.
532    #[allow(dead_code)]
533    pub fn remove(&mut self, item: &str) -> bool {
534        match self.items.binary_search_by_key(&item, String::as_str) {
535            Ok(pos) => {
536                self.items.remove(pos);
537                true
538            }
539            Err(_) => false,
540        }
541    }
542
543    /// Return the number of elements.
544    #[allow(dead_code)]
545    pub fn len(&self) -> usize {
546        self.items.len()
547    }
548
549    /// Return `true` if empty.
550    #[allow(dead_code)]
551    pub fn is_empty(&self) -> bool {
552        self.items.is_empty()
553    }
554
555    /// Iterate over items in sorted order.
556    #[allow(dead_code)]
557    pub fn iter(&self) -> impl Iterator<Item = &str> {
558        self.items.iter().map(String::as_str)
559    }
560
561    /// Compute the union of `self` and `other`.
562    #[allow(dead_code)]
563    pub fn union(&self, other: &StringSet) -> StringSet {
564        let mut result = self.clone();
565        for item in other.iter() {
566            result.insert(item);
567        }
568        result
569    }
570
571    /// Compute the intersection of `self` and `other`.
572    #[allow(dead_code)]
573    pub fn intersection(&self, other: &StringSet) -> StringSet {
574        let mut result = StringSet::new();
575        for item in self.iter() {
576            if other.contains(item) {
577                result.insert(item);
578            }
579        }
580        result
581    }
582
583    /// Compute the difference `self \ other`.
584    #[allow(dead_code)]
585    pub fn difference(&self, other: &StringSet) -> StringSet {
586        let mut result = StringSet::new();
587        for item in self.iter() {
588            if !other.contains(item) {
589                result.insert(item);
590            }
591        }
592        result
593    }
594}
595
596// ── Multi-map ─────────────────────────────────────────────────────────────────
597
598/// A simple multi-map: each key may map to multiple values.
599#[allow(dead_code)]
600#[derive(Debug)]
601pub struct MultiMap<K, V> {
602    inner: Vec<(K, Vec<V>)>,
603}
604
605impl<K, V> Default for MultiMap<K, V> {
606    fn default() -> Self {
607        Self { inner: Vec::new() }
608    }
609}
610
611impl<K: Eq, V> MultiMap<K, V> {
612    /// Create an empty multi-map.
613    #[allow(dead_code)]
614    pub fn new() -> Self {
615        Self::default()
616    }
617
618    /// Insert a `(key, value)` pair.
619    #[allow(dead_code)]
620    pub fn insert(&mut self, key: K, value: V) {
621        for (k, vs) in &mut self.inner {
622            if k == &key {
623                vs.push(value);
624                return;
625            }
626        }
627        self.inner.push((key, vec![value]));
628    }
629
630    /// Return all values associated with `key`.
631    #[allow(dead_code)]
632    pub fn get(&self, key: &K) -> &[V] {
633        for (k, vs) in &self.inner {
634            if k == key {
635                return vs;
636            }
637        }
638        &[]
639    }
640
641    /// Return `true` if `key` has at least one associated value.
642    #[allow(dead_code)]
643    pub fn contains_key(&self, key: &K) -> bool {
644        self.inner.iter().any(|(k, _)| k == key)
645    }
646
647    /// Return the number of distinct keys.
648    #[allow(dead_code)]
649    pub fn key_count(&self) -> usize {
650        self.inner.len()
651    }
652
653    /// Remove all entries for `key`.  Returns the removed values.
654    #[allow(dead_code)]
655    pub fn remove(&mut self, key: &K) -> Vec<V> {
656        let mut result = Vec::new();
657        let mut i = 0;
658        while i < self.inner.len() {
659            if &self.inner[i].0 == key {
660                let (_, vs) = self.inner.remove(i);
661                result = vs;
662            } else {
663                i += 1;
664            }
665        }
666        result
667    }
668
669    /// Iterate over `(key, values)` pairs.
670    #[allow(dead_code)]
671    pub fn iter(&self) -> impl Iterator<Item = (&K, &[V])> {
672        self.inner.iter().map(|(k, vs)| (k, vs.as_slice()))
673    }
674}
675
676// ── Trie (prefix tree) ────────────────────────────────────────────────────────
677
678/// A simple trie mapping byte strings to values.
679#[allow(dead_code)]
680#[derive(Debug)]
681pub struct Trie<V> {
682    children: Vec<(u8, Trie<V>)>,
683    value: Option<V>,
684}
685
686impl<V> Trie<V> {
687    /// Create an empty trie node.
688    #[allow(dead_code)]
689    pub fn new() -> Self {
690        Self {
691            children: Vec::new(),
692            value: None,
693        }
694    }
695
696    /// Insert `key` → `value`.
697    #[allow(dead_code)]
698    pub fn insert(&mut self, key: &[u8], value: V) {
699        if let Some((first, rest)) = key.split_first() {
700            let child = self.get_or_create_child(*first);
701            child.insert(rest, value);
702        } else {
703            self.value = Some(value);
704        }
705    }
706
707    /// Look up `key` and return a reference to the associated value, if any.
708    #[allow(dead_code)]
709    pub fn get(&self, key: &[u8]) -> Option<&V> {
710        if let Some((first, rest)) = key.split_first() {
711            for (b, child) in &self.children {
712                if *b == *first {
713                    return child.get(rest);
714                }
715            }
716            None
717        } else {
718            self.value.as_ref()
719        }
720    }
721
722    /// Return `true` if `key` is present.
723    #[allow(dead_code)]
724    pub fn contains(&self, key: &[u8]) -> bool {
725        self.get(key).is_some()
726    }
727
728    /// Return all keys with the given `prefix`.
729    #[allow(dead_code)]
730    pub fn keys_with_prefix(&self, prefix: &[u8]) -> Vec<Vec<u8>> {
731        match prefix.split_first() {
732            Some((first, rest)) => {
733                for (b, child) in &self.children {
734                    if *b == *first {
735                        return child
736                            .keys_with_prefix(rest)
737                            .into_iter()
738                            .map(|mut k| {
739                                k.insert(0, *first);
740                                k
741                            })
742                            .collect();
743                    }
744                }
745                Vec::new()
746            }
747            None => self.collect_all(Vec::new()),
748        }
749    }
750
751    fn get_or_create_child(&mut self, byte: u8) -> &mut Trie<V> {
752        for i in 0..self.children.len() {
753            if self.children[i].0 == byte {
754                return &mut self.children[i].1;
755            }
756        }
757        self.children.push((byte, Trie::new()));
758        let last = self.children.len() - 1;
759        &mut self.children[last].1
760    }
761
762    fn collect_all(&self, prefix: Vec<u8>) -> Vec<Vec<u8>> {
763        let mut result = Vec::new();
764        if self.value.is_some() {
765            result.push(prefix.clone());
766        }
767        for (b, child) in &self.children {
768            let mut p = prefix.clone();
769            p.push(*b);
770            result.extend(child.collect_all(p));
771        }
772        result
773    }
774}
775
776impl<V> Default for Trie<V> {
777    fn default() -> Self {
778        Self::new()
779    }
780}
781
782// ── BitSet (fixed-width 64-bit) ───────────────────────────────────────────────
783
784/// A fixed-size bit set backed by a single `u64`.  Supports positions 0..63.
785#[allow(dead_code)]
786#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
787pub struct BitSet64(u64);
788
789impl BitSet64 {
790    /// Empty set.
791    #[allow(dead_code)]
792    pub const fn empty() -> Self {
793        Self(0)
794    }
795
796    /// Full set (all 64 bits set).
797    #[allow(dead_code)]
798    pub const fn full() -> Self {
799        Self(u64::MAX)
800    }
801
802    /// Set the bit at `pos`.
803    #[allow(dead_code)]
804    pub fn set(&mut self, pos: u8) {
805        debug_assert!(pos < 64);
806        self.0 |= 1u64 << pos;
807    }
808
809    /// Clear the bit at `pos`.
810    #[allow(dead_code)]
811    pub fn clear(&mut self, pos: u8) {
812        debug_assert!(pos < 64);
813        self.0 &= !(1u64 << pos);
814    }
815
816    /// Test whether the bit at `pos` is set.
817    #[allow(dead_code)]
818    pub fn test(&self, pos: u8) -> bool {
819        debug_assert!(pos < 64);
820        (self.0 >> pos) & 1 == 1
821    }
822
823    /// Return the number of set bits.
824    #[allow(dead_code)]
825    pub fn count(&self) -> u32 {
826        self.0.count_ones()
827    }
828
829    /// Return `true` if no bits are set.
830    #[allow(dead_code)]
831    pub fn is_empty(&self) -> bool {
832        self.0 == 0
833    }
834
835    /// Compute bitwise AND.
836    #[allow(dead_code)]
837    pub fn and(self, other: Self) -> Self {
838        Self(self.0 & other.0)
839    }
840
841    /// Compute bitwise OR.
842    #[allow(dead_code)]
843    pub fn or(self, other: Self) -> Self {
844        Self(self.0 | other.0)
845    }
846
847    /// Compute bitwise XOR.
848    #[allow(dead_code)]
849    pub fn xor(self, other: Self) -> Self {
850        Self(self.0 ^ other.0)
851    }
852
853    /// Compute bitwise NOT.
854    #[allow(dead_code)]
855    pub fn not(self) -> Self {
856        Self(!self.0)
857    }
858
859    /// Iterate over set bit positions.
860    #[allow(dead_code)]
861    pub fn iter_ones(self) -> impl Iterator<Item = u8> {
862        (0u8..64).filter(move |&i| self.test(i))
863    }
864}
865
866// ── PriorityQueue ─────────────────────────────────────────────────────────────
867
868/// A min-heap priority queue.
869#[allow(dead_code)]
870#[derive(Debug, Default)]
871pub struct MinHeap<P: Ord, V> {
872    heap: Vec<(P, V)>,
873}
874
875impl<P: Ord, V> MinHeap<P, V> {
876    /// Create an empty heap.
877    #[allow(dead_code)]
878    pub fn new() -> Self {
879        Self { heap: Vec::new() }
880    }
881
882    /// Push `(priority, value)` onto the heap.
883    #[allow(dead_code)]
884    pub fn push(&mut self, priority: P, value: V) {
885        self.heap.push((priority, value));
886        let mut i = self.heap.len() - 1;
887        while i > 0 {
888            let parent = (i - 1) / 2;
889            if self.heap[parent].0 > self.heap[i].0 {
890                self.heap.swap(parent, i);
891                i = parent;
892            } else {
893                break;
894            }
895        }
896    }
897
898    /// Pop the minimum-priority element.
899    #[allow(dead_code)]
900    pub fn pop(&mut self) -> Option<(P, V)> {
901        if self.heap.is_empty() {
902            return None;
903        }
904        let n = self.heap.len();
905        self.heap.swap(0, n - 1);
906        let min = self.heap.pop();
907        self.sift_down(0);
908        min
909    }
910
911    /// Peek at the minimum-priority element without removing it.
912    #[allow(dead_code)]
913    pub fn peek(&self) -> Option<(&P, &V)> {
914        self.heap.first().map(|(p, v)| (p, v))
915    }
916
917    /// Return the number of elements.
918    #[allow(dead_code)]
919    pub fn len(&self) -> usize {
920        self.heap.len()
921    }
922
923    /// Return `true` if empty.
924    #[allow(dead_code)]
925    pub fn is_empty(&self) -> bool {
926        self.heap.is_empty()
927    }
928
929    fn sift_down(&mut self, mut i: usize) {
930        let n = self.heap.len();
931        loop {
932            let left = 2 * i + 1;
933            let right = 2 * i + 2;
934            let mut smallest = i;
935            if left < n && self.heap[left].0 < self.heap[smallest].0 {
936                smallest = left;
937            }
938            if right < n && self.heap[right].0 < self.heap[smallest].0 {
939                smallest = right;
940            }
941            if smallest == i {
942                break;
943            }
944            self.heap.swap(i, smallest);
945            i = smallest;
946        }
947    }
948}
949
950// ── Graph (adjacency list) ────────────────────────────────────────────────────
951
952/// A directed graph with `n` nodes, represented as an adjacency list.
953#[allow(dead_code)]
954#[derive(Debug, Clone)]
955pub struct DirectedGraph {
956    adj: Vec<Vec<usize>>,
957}
958
959impl DirectedGraph {
960    /// Create a graph with `n` nodes and no edges.
961    #[allow(dead_code)]
962    pub fn new(n: usize) -> Self {
963        Self {
964            adj: vec![Vec::new(); n],
965        }
966    }
967
968    /// Add a directed edge `u → v`.
969    #[allow(dead_code)]
970    pub fn add_edge(&mut self, u: usize, v: usize) {
971        self.adj[u].push(v);
972    }
973
974    /// Return the number of nodes.
975    #[allow(dead_code)]
976    pub fn node_count(&self) -> usize {
977        self.adj.len()
978    }
979
980    /// Return the out-degree of node `u`.
981    #[allow(dead_code)]
982    pub fn out_degree(&self, u: usize) -> usize {
983        self.adj[u].len()
984    }
985
986    /// Iterate over the successors of `u`.
987    #[allow(dead_code)]
988    pub fn successors(&self, u: usize) -> &[usize] {
989        &self.adj[u]
990    }
991
992    /// Compute a topological ordering using Kahn's algorithm.
993    /// Returns `None` if the graph contains a cycle.
994    #[allow(dead_code)]
995    pub fn topological_sort(&self) -> Option<Vec<usize>> {
996        let n = self.adj.len();
997        let mut in_deg = vec![0usize; n];
998        for u in 0..n {
999            for &v in &self.adj[u] {
1000                in_deg[v] += 1;
1001            }
1002        }
1003        let mut queue: std::collections::VecDeque<usize> =
1004            (0..n).filter(|&u| in_deg[u] == 0).collect();
1005        let mut order = Vec::new();
1006        while let Some(u) = queue.pop_front() {
1007            order.push(u);
1008            for &v in &self.adj[u] {
1009                in_deg[v] -= 1;
1010                if in_deg[v] == 0 {
1011                    queue.push_back(v);
1012                }
1013            }
1014        }
1015        if order.len() == n {
1016            Some(order)
1017        } else {
1018            None
1019        }
1020    }
1021
1022    /// Compute strongly connected components using Kosaraju's algorithm.
1023    #[allow(dead_code)]
1024    pub fn strongly_connected_components(&self) -> Vec<Vec<usize>> {
1025        let n = self.adj.len();
1026        // Pass 1: finish-time order
1027        let mut visited = vec![false; n];
1028        let mut finish_order = Vec::new();
1029        for start in 0..n {
1030            if !visited[start] {
1031                self.dfs_finish(start, &mut visited, &mut finish_order);
1032            }
1033        }
1034        // Build reverse graph
1035        let mut rev = vec![Vec::new(); n];
1036        for u in 0..n {
1037            for &v in &self.adj[u] {
1038                rev[v].push(u);
1039            }
1040        }
1041        // Pass 2: assign SCCs in reverse finish order
1042        let mut comp = vec![usize::MAX; n];
1043        let mut scc_id = 0;
1044        for &start in finish_order.iter().rev() {
1045            if comp[start] == usize::MAX {
1046                let mut stack = vec![start];
1047                while let Some(u) = stack.pop() {
1048                    if comp[u] != usize::MAX {
1049                        continue;
1050                    }
1051                    comp[u] = scc_id;
1052                    for &v in &rev[u] {
1053                        if comp[v] == usize::MAX {
1054                            stack.push(v);
1055                        }
1056                    }
1057                }
1058                scc_id += 1;
1059            }
1060        }
1061        let mut sccs: Vec<Vec<usize>> = vec![Vec::new(); scc_id];
1062        for u in 0..n {
1063            sccs[comp[u]].push(u);
1064        }
1065        sccs
1066    }
1067
1068    fn dfs_finish(&self, u: usize, visited: &mut Vec<bool>, order: &mut Vec<usize>) {
1069        let mut stack = vec![(u, 0usize)];
1070        while let Some((node, idx)) = stack.last_mut() {
1071            let _node = *node;
1072            if !visited[_node] {
1073                visited[_node] = true;
1074            }
1075            if *idx < self.adj[_node].len() {
1076                let next = self.adj[_node][*idx];
1077                *idx += 1;
1078                if !visited[next] {
1079                    stack.push((next, 0));
1080                }
1081            } else {
1082                order.push(_node);
1083                stack.pop();
1084            }
1085        }
1086    }
1087}
1088
1089// ── Tests ─────────────────────────────────────────────────────────────────────
1090
1091#[cfg(test)]
1092mod tests {
1093    use super::*;
1094
1095    #[test]
1096    fn test_span_merge() {
1097        let a = Span::new(0, 5, 1, 1);
1098        let b = Span::new(3, 10, 1, 4);
1099        let m = a.merge(&b);
1100        assert_eq!(m.start, 0);
1101        assert_eq!(m.end, 10);
1102    }
1103
1104    #[test]
1105    fn test_located_map() {
1106        let l = Located::dummy(42u32);
1107        let l2 = l.map(|x| x * 2);
1108        assert_eq!(l2.value, 84);
1109    }
1110
1111    #[test]
1112    fn test_name_table() {
1113        let mut t = NameTable::new();
1114        let id_a = t.intern("alpha");
1115        let id_b = t.intern("beta");
1116        let id_a2 = t.intern("alpha");
1117        assert_eq!(id_a, id_a2);
1118        assert_ne!(id_a, id_b);
1119        assert_eq!(t.lookup(id_a), Some("alpha"));
1120        assert_eq!(t.len(), 2);
1121    }
1122
1123    #[test]
1124    fn test_diagnostic_bag() {
1125        let mut bag = DiagnosticBag::new();
1126        assert!(!bag.has_errors());
1127        bag.push(Diagnostic::warning("minor issue"));
1128        assert!(!bag.has_errors());
1129        bag.push(Diagnostic::error("fatal problem"));
1130        assert!(bag.has_errors());
1131        assert_eq!(bag.len(), 2);
1132        let drained = bag.drain();
1133        assert_eq!(drained.len(), 2);
1134        assert!(bag.is_empty());
1135    }
1136
1137    #[test]
1138    fn test_scope_table() {
1139        let mut s: ScopeTable<&str, u32> = ScopeTable::new();
1140        s.define("x", 1);
1141        s.push_scope();
1142        s.define("x", 2);
1143        assert_eq!(s.lookup(&"x"), Some(&2));
1144        s.pop_scope();
1145        assert_eq!(s.lookup(&"x"), Some(&1));
1146    }
1147
1148    #[test]
1149    fn test_counter_and_fresh_name() {
1150        let mut c = Counter::new();
1151        assert_eq!(c.next(), 0);
1152        assert_eq!(c.next(), 1);
1153        assert_eq!(c.peek(), 2);
1154        c.reset();
1155        assert_eq!(c.next(), 0);
1156
1157        let mut gen = FreshNameGen::new("var");
1158        let n0 = gen.fresh();
1159        let n1 = gen.fresh();
1160        assert_eq!(n0, "var_0");
1161        assert_eq!(n1, "var_1");
1162    }
1163
1164    #[test]
1165    fn test_string_set_operations() {
1166        let mut s = StringSet::new();
1167        assert!(s.insert("banana"));
1168        assert!(s.insert("apple"));
1169        assert!(!s.insert("apple")); // duplicate
1170        assert!(s.contains("apple"));
1171        assert!(!s.contains("cherry"));
1172        assert_eq!(s.len(), 2);
1173        assert!(s.remove("apple"));
1174        assert!(!s.contains("apple"));
1175        let mut t = StringSet::new();
1176        t.insert("cherry");
1177        t.insert("banana");
1178        let u = s.union(&t);
1179        assert!(u.contains("banana"));
1180        assert!(u.contains("cherry"));
1181    }
1182
1183    #[test]
1184    fn test_multi_map() {
1185        let mut m: MultiMap<&str, u32> = MultiMap::new();
1186        m.insert("key", 1);
1187        m.insert("key", 2);
1188        m.insert("other", 3);
1189        assert_eq!(m.get(&"key"), &[1, 2]);
1190        assert_eq!(m.key_count(), 2);
1191        let removed = m.remove(&"key");
1192        assert_eq!(removed, vec![1, 2]);
1193        assert!(!m.contains_key(&"key"));
1194    }
1195
1196    #[test]
1197    fn test_trie() {
1198        let mut t: Trie<u32> = Trie::new();
1199        t.insert(b"hello", 1);
1200        t.insert(b"help", 2);
1201        t.insert(b"world", 3);
1202        assert_eq!(t.get(b"hello"), Some(&1));
1203        assert_eq!(t.get(b"help"), Some(&2));
1204        assert!(t.get(b"helo").is_none());
1205        assert!(t.contains(b"world"));
1206        let pfx = t.keys_with_prefix(b"hel");
1207        assert_eq!(pfx.len(), 2);
1208    }
1209
1210    #[test]
1211    fn test_bitset64() {
1212        let mut bs = BitSet64::empty();
1213        assert!(bs.is_empty());
1214        bs.set(5);
1215        bs.set(10);
1216        assert!(bs.test(5));
1217        assert!(bs.test(10));
1218        assert!(!bs.test(0));
1219        assert_eq!(bs.count(), 2);
1220        bs.clear(5);
1221        assert!(!bs.test(5));
1222        let ones: Vec<u8> = bs.iter_ones().collect();
1223        assert_eq!(ones, vec![10]);
1224    }
1225
1226    #[test]
1227    fn test_min_heap() {
1228        let mut heap: MinHeap<u32, &str> = MinHeap::new();
1229        heap.push(5, "five");
1230        heap.push(1, "one");
1231        heap.push(3, "three");
1232        assert_eq!(heap.len(), 3);
1233        let (p, v) = heap.pop().expect("pop should succeed");
1234        assert_eq!(p, 1);
1235        assert_eq!(v, "one");
1236        let (p2, _) = heap.pop().expect("pop should succeed");
1237        assert_eq!(p2, 3);
1238    }
1239
1240    #[test]
1241    fn test_directed_graph_topo_sort() {
1242        let mut g = DirectedGraph::new(4);
1243        g.add_edge(0, 1);
1244        g.add_edge(0, 2);
1245        g.add_edge(1, 3);
1246        g.add_edge(2, 3);
1247        let order = g.topological_sort().expect("should be a DAG");
1248        assert_eq!(order.len(), 4);
1249        // 0 must come before 1,2; 1 and 2 before 3
1250        let pos: Vec<usize> = {
1251            let mut p = vec![0usize; 4];
1252            for (i, &node) in order.iter().enumerate() {
1253                p[node] = i;
1254            }
1255            p
1256        };
1257        assert!(pos[0] < pos[1]);
1258        assert!(pos[0] < pos[2]);
1259        assert!(pos[1] < pos[3]);
1260        assert!(pos[2] < pos[3]);
1261    }
1262
1263    #[test]
1264    fn test_directed_graph_scc() {
1265        // 0 → 1 → 2 → 0, 3 (separate)
1266        let mut g = DirectedGraph::new(4);
1267        g.add_edge(0, 1);
1268        g.add_edge(1, 2);
1269        g.add_edge(2, 0);
1270        // node 3 is isolated
1271        let sccs = g.strongly_connected_components();
1272        // Should have 2 SCCs: {0,1,2} and {3}
1273        assert_eq!(sccs.len(), 2);
1274    }
1275
1276    #[test]
1277    fn test_diagnostic_level_ordering() {
1278        assert!(DiagnosticLevel::Note < DiagnosticLevel::Warning);
1279        assert!(DiagnosticLevel::Warning < DiagnosticLevel::Error);
1280        assert!(DiagnosticLevel::Error < DiagnosticLevel::Bug);
1281        assert!(DiagnosticLevel::Error.is_fatal());
1282        assert!(!DiagnosticLevel::Warning.is_fatal());
1283    }
1284}