1use std::fmt;
4
5#[derive(Debug, Clone)]
7pub struct EvalError {
8 pub message: String,
10 pub kind: EvalErrorKind,
12}
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum EvalErrorKind {
17 DivisionByZero,
19 ModuloByZero,
21 Overflow,
23 RangeError,
25 TypeMismatch,
27 UnknownIdentifier,
29 UnknownFunction,
31 IndexOutOfBounds,
33 KeyNotFound,
35 InvalidArgument,
37 NoMatchingOverload,
39 FieldNotFound,
41 InvalidConversion,
43 Internal,
45}
46
47impl EvalError {
48 pub fn new(kind: EvalErrorKind, message: impl Into<String>) -> Self {
50 Self {
51 message: message.into(),
52 kind,
53 }
54 }
55
56 pub fn division_by_zero() -> Self {
58 Self::new(EvalErrorKind::DivisionByZero, "division by zero")
59 }
60
61 pub fn modulo_by_zero() -> Self {
63 Self::new(EvalErrorKind::ModuloByZero, "modulo by zero")
64 }
65
66 pub fn overflow(message: impl Into<String>) -> Self {
68 Self::new(EvalErrorKind::Overflow, message)
69 }
70
71 pub fn range_error(message: impl Into<String>) -> Self {
73 Self::new(EvalErrorKind::RangeError, message)
74 }
75
76 pub fn type_mismatch(expected: &str, actual: &str) -> Self {
78 Self::new(
79 EvalErrorKind::TypeMismatch,
80 format!("expected {}, got {}", expected, actual),
81 )
82 }
83
84 pub fn unknown_identifier(name: &str) -> Self {
86 Self::new(
87 EvalErrorKind::UnknownIdentifier,
88 format!("unknown identifier: {}", name),
89 )
90 }
91
92 pub fn unknown_function(name: &str) -> Self {
94 Self::new(
95 EvalErrorKind::UnknownFunction,
96 format!("unknown function: {}", name),
97 )
98 }
99
100 pub fn index_out_of_bounds(index: i64, len: usize) -> Self {
102 Self::new(
103 EvalErrorKind::IndexOutOfBounds,
104 format!("index {} out of bounds for length {}", index, len),
105 )
106 }
107
108 pub fn key_not_found(key: &str) -> Self {
110 Self::new(
111 EvalErrorKind::KeyNotFound,
112 format!("key not found: {}", key),
113 )
114 }
115
116 pub fn invalid_argument(message: impl Into<String>) -> Self {
118 Self::new(EvalErrorKind::InvalidArgument, message)
119 }
120
121 pub fn no_matching_overload(func: &str) -> Self {
123 Self::new(
124 EvalErrorKind::NoMatchingOverload,
125 format!("no matching overload for function: {}", func),
126 )
127 }
128
129 pub fn field_not_found(field: &str) -> Self {
131 Self::new(
132 EvalErrorKind::FieldNotFound,
133 format!("field not found: {}", field),
134 )
135 }
136
137 pub fn invalid_conversion(from: &str, to: &str) -> Self {
139 Self::new(
140 EvalErrorKind::InvalidConversion,
141 format!("cannot convert {} to {}", from, to),
142 )
143 }
144
145 pub fn internal(message: impl Into<String>) -> Self {
147 Self::new(EvalErrorKind::Internal, message)
148 }
149}
150
151impl fmt::Display for EvalError {
152 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153 write!(f, "{}", self.message)
154 }
155}
156
157impl std::error::Error for EvalError {}
158
159impl From<&str> for EvalError {
160 fn from(s: &str) -> Self {
161 Self::new(EvalErrorKind::Internal, s)
162 }
163}
164
165impl From<String> for EvalError {
166 fn from(s: String) -> Self {
167 Self::new(EvalErrorKind::Internal, s)
168 }
169}