bean_script/
error.rs

1use std::fmt::{self, Display, Formatter};
2
3#[derive(Debug)]
4pub enum ErrorSource {
5	Internal,
6	Builtin(String),
7	Line(usize),
8	File(String),
9}
10
11#[derive(Debug)]
12pub struct Error {
13	trace: Vec<ErrorSource>,
14	msg: String,
15}
16
17impl Error {
18	pub fn new(msg: &str, source: ErrorSource) -> Self {
19		Self {
20			msg: String::from(msg),
21			trace: vec![source],
22		}
23	}
24
25	pub fn get_source(&self) -> String {
26		let mut ln = None;
27		let mut file = None;
28		for source in &self.trace {
29			match source {
30				ErrorSource::Line(line) => {
31					if ln.is_none() {
32						ln = Some(line)
33					}
34				}
35				ErrorSource::File(path) => {
36					if file.is_none() {
37						file = Some(path)
38					}
39				}
40				_ => (),
41			}
42			if ln.is_some() && file.is_some() {
43				break;
44			}
45		}
46		format!("{}:{}", file.unwrap_or(&String::from("input")), ln.unwrap())
47	}
48}
49
50impl Display for Error {
51	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
52		f.write_str(&self.msg)?;
53		f.write_fmt(format_args!(
54			"\n\x1b[36m->\x1b[0m {}\x1b[3m",
55			self.get_source()
56		))?;
57		for source in &self.trace {
58			match source {
59				ErrorSource::Internal => (),
60				ErrorSource::Builtin(name) => {
61					f.write_str("\n\t")?;
62					f.write_fmt(format_args!("(builtin {})", name))?
63				}
64				ErrorSource::Line(ln) => {
65					f.write_str("\n\t")?;
66					f.write_fmt(format_args!("(line {})", ln))?;
67				}
68				ErrorSource::File(path) => {
69					f.write_str("\n\t")?;
70					f.write_fmt(format_args!("(file {})", path))?
71				}
72			}
73		}
74		f.write_str("\x1b[0m")?;
75		Ok(())
76	}
77}
78
79pub trait BeanResult {
80	fn trace(self, source: ErrorSource) -> Self;
81}
82
83impl<T> BeanResult for Result<T, Error> {
84	fn trace(mut self, source: ErrorSource) -> Self {
85		if let Err(error) = &mut self {
86			error.trace.push(source)
87		}
88		self
89	}
90}
91
92impl BeanResult for Error {
93	fn trace(mut self, source: ErrorSource) -> Self {
94		self.trace.push(source);
95		self
96	}
97}