rimu_value/
eval.rs

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}