1use super::*;
2use std::fmt;
3
4pub type EvalResult<T, E = Error> = std::result::Result<T, E>;
6
7pub(super) trait EvalResultExt {
8 fn add_errors(self, rhs: Self) -> Self;
9}
10
11impl EvalResultExt for EvalResult<(), Errors> {
12 fn add_errors(self, rhs: Self) -> Self {
13 match self {
14 Err(mut lhs) => {
15 lhs.extend_from_result(rhs);
16 Err(lhs)
17 }
18 _ => rhs,
19 }
20 }
21}
22
23#[derive(Debug, Clone, PartialEq, Eq)]
28pub struct Errors {
29 inner: Vec<Error>,
30}
31
32impl Errors {
33 fn extend_from_result(&mut self, res: EvalResult<(), Errors>) {
34 if let Err(errors) = res {
35 self.inner.extend(errors);
36 }
37 }
38
39 #[inline]
41 #[allow(clippy::len_without_is_empty)]
42 pub fn len(&self) -> usize {
43 self.inner.len()
44 }
45
46 #[inline]
48 pub fn iter(&self) -> std::slice::Iter<Error> {
49 self.inner.iter()
50 }
51}
52
53impl fmt::Display for Errors {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 if self.len() == 1 {
56 self.inner[0].fmt(f)
57 } else {
58 writeln!(f, "{} errors occurred:", self.len())?;
59
60 for error in self {
61 writeln!(f, "- {error}")?;
62 }
63
64 Ok(())
65 }
66 }
67}
68
69impl From<Error> for Errors {
70 #[inline]
71 fn from(error: Error) -> Self {
72 Errors { inner: vec![error] }
73 }
74}
75
76impl std::error::Error for Errors {}
77
78impl IntoIterator for Errors {
79 type Item = Error;
80 type IntoIter = std::vec::IntoIter<Error>;
81
82 fn into_iter(self) -> Self::IntoIter {
83 self.inner.into_iter()
84 }
85}
86
87impl<'a> IntoIterator for &'a Errors {
88 type Item = &'a Error;
89 type IntoIter = std::slice::Iter<'a, Error>;
90
91 fn into_iter(self) -> Self::IntoIter {
92 self.iter()
93 }
94}
95
96#[derive(Debug, Clone, PartialEq, Eq)]
98pub struct Error {
99 inner: Box<ErrorInner>,
100}
101
102impl Error {
103 pub(super) fn new<T>(kind: T) -> Error
104 where
105 T: Into<ErrorKind>,
106 {
107 Error::new_with_expr(kind, None)
108 }
109
110 pub(super) fn new_with_expr<T>(kind: T, expr: Option<Expression>) -> Error
111 where
112 T: Into<ErrorKind>,
113 {
114 Error {
115 inner: Box::new(ErrorInner::new(kind.into(), expr)),
116 }
117 }
118
119 pub(super) fn unexpected<T>(value: T, expected: &'static str) -> Error
120 where
121 T: Into<Value>,
122 {
123 Error::new(ErrorKind::Unexpected(value.into(), expected))
124 }
125
126 pub fn kind(&self) -> &ErrorKind {
128 &self.inner.kind
129 }
130
131 pub fn expr(&self) -> Option<&Expression> {
133 self.inner.expr.as_ref()
134 }
135
136 pub fn into_kind(self) -> ErrorKind {
138 self.inner.kind
139 }
140}
141
142impl fmt::Display for Error {
143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 fmt::Display::fmt(&self.inner, f)
145 }
146}
147
148impl From<ErrorKind> for Error {
149 fn from(kind: ErrorKind) -> Self {
150 Error::new(kind)
151 }
152}
153
154impl From<crate::Error> for Error {
155 fn from(err: crate::Error) -> Self {
156 Error::new(ErrorKind::Message(err.to_string()))
157 }
158}
159
160impl std::error::Error for Error {}
161
162#[derive(Debug, Clone, PartialEq, Eq)]
166struct ErrorInner {
167 kind: ErrorKind,
168 expr: Option<Expression>,
169}
170
171impl ErrorInner {
172 fn new(kind: ErrorKind, expr: Option<Expression>) -> ErrorInner {
173 ErrorInner { kind, expr }
174 }
175}
176
177impl fmt::Display for ErrorInner {
178 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179 write!(f, "{}", self.kind)?;
180
181 if let Some(expr) = &self.expr {
182 write!(f, " in expression `{expr}`")?;
183 }
184
185 Ok(())
186 }
187}
188
189#[derive(Debug, Clone, PartialEq, Eq)]
192#[non_exhaustive]
193pub enum ErrorKind {
194 Message(String),
196 UndefinedVar(Identifier),
198 UndefinedFunc(FuncName),
200 Unexpected(Value, &'static str),
202 Index(usize),
204 UnaryOp(UnaryOperator, Value),
206 BinaryOp(Value, BinaryOperator, Value),
208 NoSuchKey(String),
210 KeyExists(String),
212 FuncCall(FuncName, String),
214}
215
216impl From<Error> for ErrorKind {
217 fn from(err: Error) -> Self {
218 err.into_kind()
219 }
220}
221
222impl From<&str> for ErrorKind {
223 fn from(msg: &str) -> Self {
224 ErrorKind::Message(msg.to_owned())
225 }
226}
227
228impl From<String> for ErrorKind {
229 fn from(msg: String) -> Self {
230 ErrorKind::Message(msg)
231 }
232}
233
234impl fmt::Display for ErrorKind {
235 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
236 match self {
237 ErrorKind::Message(msg) => f.write_str(msg),
238 ErrorKind::UndefinedVar(ident) => {
239 write!(f, "undefined variable `{ident}`")
240 }
241 ErrorKind::UndefinedFunc(func_name) => {
242 write!(f, "undefined function `{func_name}`")
243 }
244 ErrorKind::Unexpected(value, expected) => {
245 write!(f, "unexpected value `{value}`, expected {expected}")
246 }
247 ErrorKind::Index(index) => write!(f, "index out of bounds: {index}"),
248 ErrorKind::NoSuchKey(key) => write!(f, "no such key: `{key}`"),
249 ErrorKind::KeyExists(key) => write!(f, "key `{key}` already exists"),
250 ErrorKind::UnaryOp(operator, value) => write!(
251 f,
252 "unary operator `{operator}` is not applicable to `{value}`",
253 ),
254 ErrorKind::BinaryOp(lhs, operator, rhs) => write!(
255 f,
256 "binary operator `{operator}` is not applicable to `{lhs}` and `{rhs}`",
257 ),
258 ErrorKind::FuncCall(name, msg) => {
259 write!(f, "error calling function `{name}`: {msg}")
260 }
261 }
262 }
263}