use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SourceId(pub u32);
impl fmt::Display for SourceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SourceId({})", self.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Span {
pub source: SourceId,
pub start: usize,
pub end: usize,
}
impl Span {
pub fn new(source: SourceId, start: usize, end: usize) -> Self {
Self { source, start, end }
}
pub fn len(&self) -> usize {
self.end.saturating_sub(self.start)
}
pub fn is_empty(&self) -> bool {
self.start >= self.end
}
}
impl fmt::Display for Span {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}..{}", self.source, self.start, self.end)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SourceKind {
File,
MacroExpansion {
macro_name: String,
expansion_site: Span,
},
Generated {
generator: String,
},
Repl,
}
impl fmt::Display for SourceKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SourceKind::File => write!(f, "file"),
SourceKind::MacroExpansion { macro_name, .. } => {
write!(f, "macro expansion of `{}`", macro_name)
}
SourceKind::Generated { generator } => write!(f, "generated by `{}`", generator),
SourceKind::Repl => write!(f, "repl"),
}
}
}
#[derive(Debug, Clone)]
pub struct SourceInfo {
pub id: SourceId,
pub name: String,
pub content: String,
pub kind: SourceKind,
}
#[derive(Debug, Clone, Default)]
pub struct SpanChain {
pub spans: Vec<Span>,
}
impl SpanChain {
pub fn new() -> Self {
Self { spans: Vec::new() }
}
pub fn push(&mut self, span: Span) {
self.spans.push(span);
}
pub fn innermost(&self) -> Option<&Span> {
self.spans.last()
}
pub fn outermost(&self) -> Option<&Span> {
self.spans.first()
}
pub fn depth(&self) -> usize {
self.spans.len()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Position {
pub line: u32,
pub col: u32,
}
impl Position {
pub fn new(line: u32, col: u32) -> Self {
Self { line, col }
}
}
impl fmt::Display for Position {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}", self.line + 1, self.col + 1)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct LineColumn {
pub source: SourceId,
pub position: Position,
}
impl LineColumn {
pub fn new(source: SourceId, line: u32, col: u32) -> Self {
Self {
source,
position: Position::new(line, col),
}
}
}
impl fmt::Display for LineColumn {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}", self.source, self.position)
}
}
#[derive(Debug, Default)]
pub struct SourceMap {
pub sources: Vec<SourceInfo>,
pub next_id: u32,
}