use thiserror::Error;
#[derive(Error, Debug)]
pub enum EvalError {
#[error("Index {index} is out of bounds for array of length {length}")]
IndexOutOfBounds { index: i64, length: usize },
#[error("Feature not implemented: {feature}")]
NotImplemented { feature: String },
#[error("Function '{function_name}' has no evaluation implementation")]
NoEvalImplementation { function_name: String },
#[error("Variable '{name}' not found in environment")]
VariableNotFound { name: String },
#[error("Error in function '{function}': {error}")]
FunctionError {
function: String,
#[source]
error: Box<dyn std::error::Error + Send + Sync + 'static>,
},
#[error("{message}")]
ExecutionError {
message: String,
#[source]
source: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
},
}
impl EvalError {
pub fn function_error(
function: impl Into<String>,
error: impl std::error::Error + Send + Sync + 'static,
) -> Self {
Self::FunctionError {
function: function.into(),
error: Box::new(error),
}
}
pub fn execution(message: impl Into<String>) -> Self {
Self::ExecutionError {
message: message.into(),
source: None,
}
}
pub fn execution_with_source(
message: impl Into<String>,
source: impl std::error::Error + Send + Sync + 'static,
) -> Self {
Self::ExecutionError {
message: message.into(),
source: Some(Box::new(source)),
}
}
}
impl From<anyhow::Error> for EvalError {
fn from(err: anyhow::Error) -> Self {
Self::ExecutionError {
message: err.to_string(),
source: None,
}
}
}
impl EvalError {
pub fn is_unfoldable(&self) -> bool {
matches!(
self,
EvalError::NotImplemented { .. }
| EvalError::NoEvalImplementation { .. }
| EvalError::VariableNotFound { .. }
)
}
}
pub type EvalResult<T> = Result<T, EvalError>;