1#![allow(non_snake_case)]
3use std::ops::Range;
4
5use crate::intern::interned::Symbol;
6
7#[derive(Clone, Copy, PartialEq, Eq, Hash)]
9pub struct Span {
10 pub path: Symbol,
11 pub head: u32,
12 pub tail: u32,
13}
14
15impl std::fmt::Debug for Span {
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 let Self { path, head, tail } = self;
18 match path.0 {
19 "" => write!(f, "[{head}:{tail}]"),
20 _ => write!(f, "[{path}:{head}:{tail}]"),
21 }
22 }
23}
24
25#[expect(non_snake_case)]
26pub const fn Span(path: Symbol, head: u32, tail: u32) -> Span {
28 Span { path, head, tail }
29}
30
31impl Span {
32 pub fn merge(self, other: Span) -> Span {
34 if !(self.path.is_empty() || other.path.is_empty()) {
35 assert_eq!(self.path, other.path, "Attempted to merge unrelated paths!")
36 }
37 Span { path: self.path, head: self.head.min(other.head), tail: self.tail.max(other.tail) }
38 }
39}
40
41impl From<Span> for Range<usize> {
42 fn from(value: Span) -> Self {
43 let Span { path: _, head, tail } = value;
44 (head as usize)..(tail as usize)
45 }
46}
47
48impl std::fmt::Display for Span {
49 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 let Self { path, head, tail } = self;
51 match path.0 {
52 "" => write!(f, "{head}:{tail}"),
53 _ => write!(f, "{path}:{head}:{tail}"),
54 }
55 }
56}