1use crate::interpreter::interpreter_stack_value::RibInterpreterStackValue;
16use crate::{InstructionId, TypeHint};
17use golem_wasm_rpc::{Value, ValueAndType};
18use std::fmt::{Display, Formatter};
19
20#[derive(Debug)]
21pub enum RibRuntimeError {
22 ArithmeticError {
23 message: String,
24 },
25 CastError {
26 from: CastFrom,
27 to: TypeHint,
28 },
29 ExhaustedIterator,
30 FieldNotFound {
31 field: String,
32 },
33 FunctionInvokeError {
34 function_name: String,
35 error: Box<dyn std::error::Error + Send + Sync>,
36 },
37 IndexOutOfBound {
38 index: usize,
39 size: usize,
40 },
41 InfiniteComputation {
42 message: String,
43 },
44 InputNotFound(String),
45 InvariantViolation(InvariantViolation),
46 InvalidComparison {
47 message: String,
48 left: Option<ValueAndType>,
49 right: Option<ValueAndType>,
50 },
51 NoResult,
52 ThrownError(String),
53 TypeMismatch {
54 expected: Vec<TypeHint>,
55 found: InvalidItem,
56 },
57}
58
59impl std::error::Error for RibRuntimeError {}
60
61#[derive(Debug, Clone, PartialEq)]
62pub enum CastFrom {
63 FromValue(Value),
64 FromType(TypeHint),
65 FromCustom(String),
66}
67
68impl Display for CastFrom {
69 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
70 match self {
71 CastFrom::FromValue(value) => write!(f, "{value:?}"),
72 CastFrom::FromType(typ) => write!(f, "{typ}"),
73 CastFrom::FromCustom(custom) => write!(f, "{custom}"),
74 }
75 }
76}
77
78#[derive(Debug, Clone, PartialEq)]
79pub enum InvalidItem {
80 RuntimeValue(Value),
81 Type(TypeHint),
82 Custom(String),
83}
84
85pub fn arithmetic_error(message: &str) -> RibRuntimeError {
86 RibRuntimeError::ArithmeticError {
87 message: message.to_string(),
88 }
89}
90
91pub fn cast_error(from: Value, to: TypeHint) -> RibRuntimeError {
92 RibRuntimeError::CastError {
93 from: CastFrom::FromValue(from),
94 to,
95 }
96}
97
98pub fn cast_error_custom<T: Display>(from: T, to: TypeHint) -> RibRuntimeError {
99 RibRuntimeError::CastError {
100 from: CastFrom::FromCustom(from.to_string()),
101 to,
102 }
103}
104
105pub fn empty_stack() -> RibRuntimeError {
106 RibRuntimeError::InvariantViolation(InvariantViolation::InsufficientStackItems(1))
107}
108
109pub fn exhausted_iterator() -> RibRuntimeError {
110 RibRuntimeError::ExhaustedIterator
111}
112
113pub fn field_not_found(field_name: &str) -> RibRuntimeError {
114 RibRuntimeError::FieldNotFound {
115 field: field_name.to_string(),
116 }
117}
118
119pub fn function_invoke_fail(
120 function_name: &str,
121 error: Box<dyn std::error::Error + Send + Sync>,
122) -> RibRuntimeError {
123 RibRuntimeError::FunctionInvokeError {
124 function_name: function_name.to_string(),
125 error,
126 }
127}
128
129pub fn index_out_of_bound(index: usize, size: usize) -> RibRuntimeError {
130 RibRuntimeError::IndexOutOfBound { index, size }
131}
132
133pub fn infinite_computation(message: &str) -> RibRuntimeError {
134 RibRuntimeError::InfiniteComputation {
135 message: message.to_string(),
136 }
137}
138
139pub fn input_not_found(input_name: &str) -> RibRuntimeError {
140 RibRuntimeError::InputNotFound(input_name.to_string())
141}
142
143pub fn instruction_jump_error(instruction_id: InstructionId) -> RibRuntimeError {
144 RibRuntimeError::InvariantViolation(InvariantViolation::InstructionJumpError(instruction_id))
145}
146
147pub fn insufficient_stack_items(size: usize) -> RibRuntimeError {
148 RibRuntimeError::InvariantViolation(InvariantViolation::InsufficientStackItems(size))
149}
150
151pub fn invalid_comparison(
152 message: &str,
153 left: Option<ValueAndType>,
154 right: Option<ValueAndType>,
155) -> RibRuntimeError {
156 RibRuntimeError::InvalidComparison {
157 message: message.to_string(),
158 left,
159 right,
160 }
161}
162
163pub fn invalid_type_with_stack_value(
164 expected: Vec<TypeHint>,
165 found: RibInterpreterStackValue,
166) -> RibRuntimeError {
167 RibRuntimeError::TypeMismatch {
168 expected,
169 found: InvalidItem::Custom(found.to_string()),
170 }
171}
172
173pub fn type_mismatch_with_value(expected: Vec<TypeHint>, found: Value) -> RibRuntimeError {
174 RibRuntimeError::TypeMismatch {
175 expected,
176 found: InvalidItem::RuntimeValue(found),
177 }
178}
179
180pub fn type_mismatch_with_type_hint(expected: Vec<TypeHint>, found: TypeHint) -> RibRuntimeError {
181 RibRuntimeError::TypeMismatch {
182 expected,
183 found: InvalidItem::Type(found),
184 }
185}
186
187pub fn no_result() -> RibRuntimeError {
188 RibRuntimeError::NoResult
189}
190
191pub fn throw_error(message: &str) -> RibRuntimeError {
192 RibRuntimeError::ThrownError(message.to_string())
193}
194
195#[derive(Debug, Clone, PartialEq)]
196pub enum InvariantViolation {
197 InsufficientStackItems(usize),
198 InternalCorruptedState(String),
199 InstructionJumpError(InstructionId),
200}
201
202impl Display for RibRuntimeError {
203 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
204 match self {
205 RibRuntimeError::InputNotFound(input_name) => {
206 write!(f, "input not found: {input_name}")
207 }
208 RibRuntimeError::ExhaustedIterator => write!(f, "no more values in iterator"),
209 RibRuntimeError::FieldNotFound { field } => {
210 write!(f, "field not found: {field}")
211 }
212 RibRuntimeError::InvariantViolation(violation) => {
213 write!(f, "internal error: {violation:?}")
214 }
215 RibRuntimeError::ThrownError(message) => write!(f, "error: {message}"),
216 RibRuntimeError::CastError { from, to } => {
217 write!(f, "cast error from {from} to {to}")
218 }
219 RibRuntimeError::TypeMismatch { expected, found } => {
220 write!(
221 f,
222 "runtime type mismatch: expected {expected:?}, found {found:?}"
223 )
224 }
225 RibRuntimeError::NoResult => write!(f, "No result"),
226 RibRuntimeError::InfiniteComputation { message } => {
227 write!(f, "infinite computation detected: {message}")
228 }
229 RibRuntimeError::IndexOutOfBound { index, size } => {
230 write!(f, "index out of bound: {index} (size: {size})")
231 }
232 RibRuntimeError::InvalidComparison {
233 message,
234 left,
235 right,
236 } => match (left, right) {
237 (Some(left), Some(right)) => {
238 write!(
239 f,
240 "Invalid comparison: {message} (left: {left}, right: {right})"
241 )
242 }
243 _ => {
244 write!(f, "Invalid comparison: {message} ")
245 }
246 },
247 RibRuntimeError::ArithmeticError { message } => {
248 write!(f, "arithmetic error: {message}")
249 }
250 RibRuntimeError::FunctionInvokeError {
251 function_name,
252 error,
253 } => {
254 write!(f, "failed to invoke function {function_name}: {error}")
255 }
256 }
257 }
258}