camel_language_api/
error.rs1use camel_api::{ErrorPosition, ExpressionErrorClass};
2use thiserror::Error;
3
4#[derive(Debug, Error)]
5#[non_exhaustive]
6pub enum LanguageError {
7 #[error("parse error in expression `{expr}`: {reason}")]
8 ParseError { expr: String, reason: String },
9
10 #[error("evaluation error: {0}")]
11 EvalError(String),
12
13 #[error("unknown variable: {0}")]
14 UnknownVariable(String),
15
16 #[error("language `{0}` not found in registry")]
17 NotFound(String),
18
19 #[error("feature '{feature}' not supported by language '{language}'")]
20 NotSupported { feature: String, language: String },
21
22 #[error(
29 "evaluation failure: {class}{}{}",
30 position.map(|p| format!(" at {p}")).unwrap_or_default(),
31 detail.as_deref().map(|d| format!(": {d}")).unwrap_or_default()
32 )]
33 EvalFailure {
34 class: ExpressionErrorClass,
35 position: Option<ErrorPosition>,
36 detail: Option<String>,
37 },
38
39 #[error(
42 "type mismatch: expected {expected}, actual {actual}{}",
43 position.map(|p| format!(" at {p}")).unwrap_or_default()
44 )]
45 TypeMismatch {
46 expected: String,
47 actual: String,
48 position: Option<ErrorPosition>,
49 },
50
51 #[error("conversion error: cannot convert {source_type} to {target}")]
56 ConversionError { source_type: String, target: String },
57}
58
59impl LanguageError {
60 pub fn eval_error(expr: &str, message: impl std::fmt::Display) -> Self {
64 LanguageError::EvalError(format!("in expression `{expr}`: {message}"))
65 }
66
67 pub fn class(&self) -> Option<ExpressionErrorClass> {
73 match self {
74 Self::ParseError { .. } => Some(ExpressionErrorClass::Parse),
75 Self::EvalError(_) => Some(ExpressionErrorClass::Runtime),
76 Self::EvalFailure { class, .. } => Some(*class),
77 Self::TypeMismatch { .. } => Some(ExpressionErrorClass::TypeMismatch),
78 Self::ConversionError { .. } => Some(ExpressionErrorClass::Conversion),
79 Self::UnknownVariable(_) | Self::NotFound(_) | Self::NotSupported { .. } => None,
80 }
81 }
82
83 pub fn position(&self) -> Option<ErrorPosition> {
86 match self {
87 Self::EvalFailure { position, .. } | Self::TypeMismatch { position, .. } => *position,
88 _ => None,
89 }
90 }
91}