1use rimu_ast::Expression;
2use rimu_meta::{ErrorReport, Span};
3
4use crate::{EnvironmentError, SerdeValue, SerdeValueObject};
5
6#[derive(Debug, thiserror::Error, Clone, PartialEq)]
7pub enum EvalError {
8 #[error("{source}")]
9 Environment {
10 span: Span,
11 #[source]
12 source: EnvironmentError,
13 },
14 #[error("missing variable: {var}")]
15 MissingVariable { span: Span, var: String },
16 #[error("tried to call non-function: {expr}")]
17 CallNonFunction { span: Span, expr: Expression },
18 #[error("missing argument: {index}")]
19 MissingArgument { span: Span, index: usize },
20 #[error("type error, expected: {expected}, got: {got}")]
21 TypeError {
22 span: Span,
23 expected: String,
24 got: SerdeValue,
25 },
26 #[error("index out of bounds, index: {index}, length: {length}")]
27 IndexOutOfBounds {
28 container_span: Span,
29 index_span: Span,
30 index: isize,
31 length: usize,
32 },
33 #[error("key error, key: {key}, object: {object:?}")]
34 KeyNotFound {
35 key_span: Span,
36 key: String,
37 object_span: Span,
38 object: SerdeValueObject,
39 },
40 #[error("range start >= end, start: {start}, end: {end}")]
41 RangeStartGreaterThanOrEqualToEnd {
42 span: Span,
43 start: usize,
44 end: usize,
45 },
46 #[error("unterminated interpolation: {src}")]
47 UnterminatedInterpolation { span: Span, src: String },
48 #[error("cannot be interpolated into a string: {value}")]
49 InvalidInterpolationValue { span: Span, value: SerdeValue },
50 #[error("error expression")]
51 ErrorExpression { span: Span },
52}
53
54impl From<EvalError> for ErrorReport {
55 fn from(value: EvalError) -> Self {
56 let (span, msg, labels, notes): (Span, &str, Vec<(Span, String)>, Vec<String>) = match value
57 {
58 EvalError::Environment { span, source } => (
59 span.clone(),
60 "Eval: Environment error",
61 vec![(span.clone(), format!("{}", source))],
62 vec![],
63 ),
64 EvalError::MissingVariable { span, var } => (
65 span.clone(),
66 "Eval: Missing variable",
67 vec![(span.clone(), format!("Not in environment: {}", var))],
68 vec![],
69 ),
70 EvalError::CallNonFunction { span, expr } => (
71 span.clone(),
72 "Eval: Tried to call non-function",
73 vec![(span.clone(), format!("Not a function: {}", expr))],
74 vec![],
75 ),
76 EvalError::MissingArgument { span, index } => (
77 span.clone(),
78 "Eval: Tried to call function without required argument",
79 vec![(span.clone(), format!("Argument index: {}", index))],
80 vec![],
81 ),
82 EvalError::TypeError {
83 span,
84 expected,
85 got,
86 } => (
87 span.clone(),
88 "Eval: Unexpected type",
89 vec![(
90 span.clone(),
91 format!("Expected: {}, got: {}", expected, got),
92 )],
93 vec![],
94 ),
95 EvalError::IndexOutOfBounds {
96 container_span,
97 index,
98 index_span,
99 length,
100 } => (
101 container_span.clone().union(index_span.clone()),
102 "Eval: Index out of bounds",
103 vec![
104 (container_span.clone(), format!("Length: {}", length)),
105 (index_span.clone(), format!("Index: {}", index)),
106 ],
107 vec![],
108 ),
109 EvalError::KeyNotFound {
110 key_span,
111 key,
112 object_span,
113 object,
114 } => (
115 key_span.clone().union(object_span.clone()),
116 "Eval: Key not found",
117 vec![
118 (
119 object_span.clone(),
120 format!("Object: {}", SerdeValue::Object(object.clone())),
121 ),
122 (key_span.clone(), format!("Key: {}", key)),
123 ],
124 vec![],
125 ),
126 EvalError::RangeStartGreaterThanOrEqualToEnd { span, start, end } => (
127 span.clone(),
128 "Eval: Range start >= end",
129 vec![(span.clone(), format!("{} >= {}", start, end))],
130 vec![],
131 ),
132 EvalError::UnterminatedInterpolation { span, src } => (
133 span.clone(),
134 "Eval: Unterminated interpolation",
135 vec![(span.clone(), format!("Source: {}", src))],
136 vec![],
137 ),
138 EvalError::InvalidInterpolationValue { span, value } => (
139 span.clone(),
140 "Eval: Cannot be interpolated into a string",
141 vec![(
142 span.clone(),
143 format!("Value cannot be interpolated into a string: {}", value),
144 )],
145 vec![],
146 ),
147 EvalError::ErrorExpression { span } => (
148 span.clone(),
149 "Eval: Expression error",
150 vec![(span.clone(), "Error".to_string())],
151 vec![],
152 ),
153 };
154
155 ErrorReport {
156 span,
157 message: msg.into(),
158 labels,
159 notes,
160 }
161 }
162}