1#![allow(unused_macros)]
2use {
3 crate::Jump,
4 std::{error, fmt, io, num},
5};
6
7#[derive(Debug, PartialEq)]
9pub enum ErrorKind {
10 SyntaxError,
11 ParseError,
12 RuntimeError,
13
14 ArgNotFound,
15 WrongArgType,
16
17 Jump(Jump),
18}
19
20#[derive(Debug, PartialEq)]
22pub struct Error {
23 pub kind: ErrorKind,
24 pub details: String,
25 pub pos: usize,
26 pub len: usize,
27}
28
29impl Error {
30 pub fn new(kind: ErrorKind, details: String, pos: usize, len: usize) -> Error {
31 Error {
32 kind,
33 details,
34 pos,
35 len,
36 }
37 }
38}
39
40impl error::Error for Error {
41 fn description(&self) -> &str {
42 &self.details
43 }
44}
45
46impl fmt::Display for Error {
47 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48 write!(f, "Error: {}", self.details)
49 }
50}
51
52impl From<num::ParseIntError> for Error {
53 fn from(error: num::ParseIntError) -> Self {
54 Error {
55 kind: ErrorKind::ParseError,
56 details: format!("{}", error),
57 pos: 0,
58 len: 0,
59 }
60 }
61}
62
63impl From<io::Error> for Error {
64 fn from(error: io::Error) -> Self {
65 Error {
66 kind: ErrorKind::RuntimeError,
67 details: format!("{}", error),
68 pos: 0,
69 len: 0,
70 }
71 }
72}
73
74impl From<Error> for io::Error {
75 fn from(error: Error) -> Self {
76 io::Error::new(io::ErrorKind::Other, error.details)
77 }
78}
79
80macro_rules! scan_error {
82 ($pos:expr, $len:expr, $msg:expr) => {{
83 use crate::{Error, ErrorKind};
84 Err(Error::new(ErrorKind::SyntaxError, $msg.into(), $pos, $len))
85 }};
86 ($pos:expr, $len:expr, $msg:expr, $($args:expr),+) => {
87 scan_error!($pos, $len, format!($msg, $($args),*));
88 };
89}
90
91macro_rules! pos_error {
93 ($pos:expr, $msg:expr) => {{
94 use crate::{Error, ErrorKind};
95 Err(Error::new(ErrorKind::ParseError, $msg.into(), $pos, 1))
96 }};
97 ($pos:expr, $msg:expr, $($args:expr),+) => {
98 pos_error!($pos, format!($msg, $($args),+));
99 };
100}
101
102macro_rules! jump {
104 ($jump:expr) => {{
105 use crate::{Error, ErrorKind};
106 Err(Error::new(ErrorKind::Jump($jump), "".to_string(), 0, 0))
107 }};
108}
109
110macro_rules! error_kind {
112 ($kind:ident, $msg:expr) => {{
113 use crate::{Error, ErrorKind};
114 Error::new(ErrorKind::$kind, $msg.into(), 0, 0)
115 }};
116 ($kind:ident, $msg:expr, $($args:expr),*) => {
117 error_kind!($kind, format!($msg, $($args),*));
118 };
119}
120
121macro_rules! error {
123 ($msg:expr) => {{
124 use crate::{Error, ErrorKind};
125 Err(Error::new(ErrorKind::RuntimeError, $msg.into(), 0, 0))
126 }};
127 ($msg:expr, $($args:expr),*) => {
128 error!(format!($msg, $($args),*));
129 };
130}
131
132pub fn print_error<P: AsRef<std::path::Path>, S: AsRef<str>>(path: P, source: S, err: Error) {
135 let path = path.as_ref();
136 let source = source.as_ref();
137 let (red, blue, _gold, clear) = if std::env::var("NO_COLOR").is_ok() {
138 ("", "", "", "")
139 } else {
140 ("\x1b[91m", "\x1b[1;94m", "\x1b[1;93m", "\x1b[0m")
141 };
142
143 let (line, col) = line_and_col(source, err.pos);
144 println!(
146 " {}-->{} {}:{}:{}",
147 blue,
148 clear,
149 path.to_str().unwrap(),
150 line,
151 col
152 );
153 println!(" {}|{}", blue, clear);
154
155 let lines = source.split('\n');
156 let pline = |num| {
157 if let Some(line) = lines.clone().nth(num) {
158 println!("{} |{} {}", blue, clear, line)
159 }
160 };
161
162 if line > 2 {
163 pline(line - 3);
164 }
165 if line > 1 {
166 pline(line - 2);
167 }
168 println!(
169 "{}{: <3}|{} {}",
170 blue,
171 line,
172 clear,
173 lines.clone().nth(line - 1).unwrap()
174 );
175 println!(
176 " {}|{} {}{} {}{}",
177 blue,
178 red,
179 " ".repeat(if col > 0 { col - 1 } else { 0 }),
180 "^".repeat(std::cmp::min(err.len, 20)),
181 err.details,
182 clear
183 );
184 pline(line);
185 pline(line + 1);
186}
187
188pub fn line_and_col(source: &str, pos: usize) -> (usize, usize) {
190 let mut line = 1;
191 let mut col = 0;
192 for (i, c) in source.chars().enumerate() {
193 if c == '\n' {
194 if i == pos {
195 return (line, col + 1);
196 }
197 line += 1;
198 col = 0;
199 } else {
200 col += 1;
201 }
202 if i >= pos {
203 break;
204 }
205 }
206 (line, col)
207}