//! Datatypes to support source location information. use std::fmt; /// A location somewhere in the sourcecode. #[derive(Clone, Copy, Debug, Default, PartialEq)] pub struct Location { row: usize, column: usize, } impl fmt::Display for Location { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "line {} column {}", self.row, self.column) } } 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 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 = "↑", ) } } Visualize { loc: *self, line, desc, } } } impl Location { pub fn new(row: usize, column: usize) -> Self { Location { row, column } } 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; } }