evalexpr_jit/
errors.rs

1//! Error types for the evalexpr-jit crate.
2//!
3//! This module defines the various error types that can occur during expression parsing,
4//! AST conversion, and JIT compilation. The main error types are:
5//!
6//! - `ConvertError`: Errors during conversion from evalexpr AST to internal representation
7//! - `BuilderError`: Errors during JIT compilation with Cranelift
8//! - `EquationError`: High-level errors when working with equations
9//!
10//! Each error type implements the standard Error trait and provides detailed error messages.
11
12use cranelift_codegen::CodegenError;
13use cranelift_module::ModuleError;
14use evalexpr::{DefaultNumericTypes, EvalexprError};
15use thiserror::Error;
16
17/// Errors that can occur during conversion from evalexpr AST to our internal AST representation.
18///
19/// This enum represents various failure modes when converting the evalexpr expression tree
20/// into our own AST format that can be used for JIT compilation and symbolic differentiation.
21#[derive(Error, Debug)]
22pub enum ConvertError {
23    /// Error when trying to convert an exponent that is not a valid integer constant
24    #[error("Could not convert exponent in Exp operator: {0}")]
25    ExpOperator(String),
26    /// Error when encountering an operator that is not supported by our implementation
27    #[error("Unsupported operator: {0}")]
28    UnsupportedOperator(String),
29    /// Error when encountering a function that is not supported by our implementation
30    #[error("Unsupported function: {0}")]
31    UnsupportedFunction(String),
32    /// Error when the root node does not have exactly one child
33    #[error("Expected single child for root node: {0}")]
34    RootNode(String),
35    /// Error when a constant value is not a floating point number
36    #[error("Expected float constant: {0}")]
37    ConstOperator(String),
38    /// Error when a variable is not found in the variable map
39    #[error("Variable not found: {0}")]
40    VariableNotFound(String),
41}
42
43/// Errors that can occur during JIT compilation of expressions.
44///
45/// This enum represents various failure modes in the process of converting our AST
46/// into machine code using Cranelift as the JIT compiler backend.
47#[derive(Error, Debug)]
48pub enum BuilderError {
49    /// Error when the target machine architecture is not supported
50    #[error("host machine is not supported: {0}")]
51    HostMachineNotSupported(String),
52    /// Error during Cranelift code generation
53    #[error("codegen error: {0}")]
54    CodegenError(CodegenError),
55    /// Error in the Cranelift JIT module
56    #[error("module error: {0}")]
57    ModuleError(ModuleError),
58    /// Error when defining the JIT function
59    #[error("function error: {0}")]
60    FunctionError(String),
61    /// Error when declaring the JIT function
62    #[error("declaration error: {0}")]
63    DeclarationError(String),
64}
65
66/// High-level errors that can occur when working with mathematical equations.
67///
68/// This enum represents the various ways that equation parsing, compilation,
69/// and differentiation can fail. It wraps lower-level errors from the expression
70/// conversion and JIT compilation stages.
71#[derive(Debug, Error)]
72pub enum EquationError {
73    /// Error when parsing the initial expression string with evalexpr
74    #[error("Failed to build Evalexpr AST")]
75    BuildEvalexprError(#[from] EvalexprError<DefaultNumericTypes>),
76    /// Error when converting from evalexpr AST to our internal JIT-compatible AST representation
77    #[error("Failed to build JIT AST")]
78    BuildJITError(#[from] ConvertError),
79    /// Error when JIT compiling the expression
80    #[error("Failed to build JIT function")]
81    BuildFunctionError(#[from] BuilderError),
82    /// Error when trying to get derivative for a variable that doesn't exist
83    #[error("Derivative not found for variable: {0}")]
84    DerivativeNotFound(String),
85    /// Error when the input length is not the same as the number of variables
86    #[error("Invalid input length: expected {expected}, got {got}")]
87    InvalidInputLength { expected: usize, got: usize },
88    /// Error when a variable is not found in the equation
89    #[error("Variable not found in equation: {0}")]
90    VariableNotFound(String),
91    /// Error when the output length is not the same as the number of equations
92    #[error("Invalid output length: expected {expected}, got {got}")]
93    InvalidOutputLength { expected: usize, got: usize },
94    /// Error when the output type is wrong
95    #[error("Matrix output required: Got vector output for this system")]
96    MatrixOutputRequired,
97    /// Error when the matrix dimensions are invalid
98    #[error("Invalid matrix dimensions: expected {expected_rows}x{expected_cols}, got {got_rows}x{got_cols}")]
99    InvalidMatrixDimensions {
100        expected_rows: usize,
101        expected_cols: usize,
102        got_rows: usize,
103        got_cols: usize,
104    },
105}