2021-11-03 16:34:05 +08:00
|
|
|
//! Datatypes to support source location information.
|
2021-12-28 01:28:55 +08:00
|
|
|
use crate::ast_gen::StrRef;
|
2024-06-12 14:45:03 +08:00
|
|
|
use std::cmp::Ordering;
|
2021-11-03 16:34:05 +08:00
|
|
|
use std::fmt;
|
|
|
|
|
2023-11-14 18:43:08 +08:00
|
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
2022-02-12 21:15:50 +08:00
|
|
|
pub struct FileName(pub StrRef);
|
2021-12-28 01:28:55 +08:00
|
|
|
impl Default for FileName {
|
|
|
|
fn default() -> Self {
|
|
|
|
FileName("unknown".into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<String> for FileName {
|
|
|
|
fn from(s: String) -> Self {
|
|
|
|
FileName(s.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-03 16:34:05 +08:00
|
|
|
/// A location somewhere in the sourcecode.
|
2023-11-14 18:43:08 +08:00
|
|
|
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
2021-11-03 16:34:05 +08:00
|
|
|
pub struct Location {
|
2022-02-12 21:15:50 +08:00
|
|
|
pub row: usize,
|
|
|
|
pub column: usize,
|
2024-06-12 14:45:03 +08:00
|
|
|
pub file: FileName,
|
2021-11-03 16:34:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for Location {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2023-11-30 14:30:37 +08:00
|
|
|
write!(f, "{}:{}:{}", self.file.0, self.row, self.column)
|
2021-11-03 16:34:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-14 18:43:08 +08:00
|
|
|
impl Ord for Location {
|
|
|
|
fn cmp(&self, other: &Self) -> Ordering {
|
|
|
|
let file_cmp = self.file.0.to_string().cmp(&other.file.0.to_string());
|
|
|
|
if file_cmp != Ordering::Equal {
|
2024-06-12 14:45:03 +08:00
|
|
|
return file_cmp;
|
2023-11-14 18:43:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
let row_cmp = self.row.cmp(&other.row);
|
|
|
|
if row_cmp != Ordering::Equal {
|
2024-06-12 14:45:03 +08:00
|
|
|
return row_cmp;
|
2023-11-14 18:43:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
self.column.cmp(&other.column)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialOrd for Location {
|
|
|
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
|
|
Some(self.cmp(other))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-03 16:34:05 +08:00
|
|
|
impl Location {
|
|
|
|
pub fn visualize<'a>(
|
|
|
|
&self,
|
|
|
|
line: &'a str,
|
|
|
|
desc: impl fmt::Display + 'a,
|
|
|
|
) -> impl fmt::Display + 'a {
|
|
|
|
struct Visualize<'a, D: fmt::Display> {
|
|
|
|
loc: Location,
|
|
|
|
line: &'a str,
|
|
|
|
desc: D,
|
|
|
|
}
|
|
|
|
impl<D: fmt::Display> fmt::Display for Visualize<'_, D> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(
|
|
|
|
f,
|
|
|
|
"{}\n{}\n{arrow:>pad$}",
|
|
|
|
self.desc,
|
|
|
|
self.line,
|
|
|
|
pad = self.loc.column,
|
|
|
|
arrow = "↑",
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2024-06-12 14:45:03 +08:00
|
|
|
Visualize { loc: *self, line, desc }
|
2021-11-03 16:34:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Location {
|
2021-12-28 01:28:55 +08:00
|
|
|
pub fn new(row: usize, column: usize, file: FileName) -> Self {
|
|
|
|
Location { row, column, file }
|
2021-11-03 16:34:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn row(&self) -> usize {
|
|
|
|
self.row
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn column(&self) -> usize {
|
|
|
|
self.column
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn reset(&mut self) {
|
|
|
|
self.row = 1;
|
|
|
|
self.column = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn go_right(&mut self) {
|
|
|
|
self.column += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn go_left(&mut self) {
|
|
|
|
self.column -= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn newline(&mut self) {
|
|
|
|
self.row += 1;
|
|
|
|
self.column = 1;
|
|
|
|
}
|
|
|
|
}
|