Skip to main content

panproto_expr/
error.rs

1//! Error types for expression evaluation and type-checking.
2
3/// Errors that can occur during expression evaluation or type-checking.
4#[derive(Debug, thiserror::Error)]
5#[non_exhaustive]
6pub enum ExprError {
7    /// Evaluation exceeded the configured step limit.
8    #[error("step limit exceeded after {0} steps")]
9    StepLimitExceeded(u64),
10
11    /// Evaluation exceeded the configured recursion depth.
12    #[error("recursion depth exceeded: {0}")]
13    DepthExceeded(u32),
14
15    /// A variable was referenced but not bound in the environment.
16    #[error("unbound variable: {0}")]
17    UnboundVariable(String),
18
19    /// An operation received a value of the wrong type.
20    #[error("type error: expected {expected}, got {got}")]
21    TypeError {
22        /// The expected type name.
23        expected: String,
24        /// The actual type name.
25        got: String,
26    },
27
28    /// A builtin was applied to the wrong number of arguments.
29    #[error("arity mismatch for {op}: expected {expected}, got {got}")]
30    ArityMismatch {
31        /// The builtin operation name.
32        op: String,
33        /// Expected number of arguments.
34        expected: usize,
35        /// Actual number of arguments.
36        got: usize,
37    },
38
39    /// List index was out of bounds.
40    #[error("index out of bounds: {index} for list of length {len}")]
41    IndexOutOfBounds {
42        /// The index that was attempted.
43        index: i64,
44        /// The actual list length.
45        len: usize,
46    },
47
48    /// A field was not found in a record.
49    #[error("field not found: {0}")]
50    FieldNotFound(String),
51
52    /// No pattern arm matched the scrutinee.
53    #[error("non-exhaustive match")]
54    NonExhaustiveMatch,
55
56    /// Division by zero.
57    #[error("division by zero")]
58    DivisionByZero,
59
60    /// A list operation exceeded the configured maximum list length.
61    #[error("list length limit exceeded: {0}")]
62    ListLengthExceeded(usize),
63
64    /// Failed to parse a string as a number.
65    #[error("parse error: cannot convert {value:?} to {target_type}")]
66    ParseError {
67        /// The string value that failed to parse.
68        value: String,
69        /// The target type name.
70        target_type: String,
71    },
72
73    /// Attempted to call a non-function value.
74    #[error("not a function")]
75    NotAFunction,
76
77    /// Integer arithmetic overflowed.
78    #[error("integer overflow")]
79    Overflow,
80
81    /// Float value is not representable as an integer (NaN, infinity, or out of range).
82    #[error("float not representable as integer: {0}")]
83    FloatNotRepresentable(String),
84
85    /// A builtin that reads an instance graph was evaluated without one.
86    ///
87    /// The graph traversal builtins (`edge`, `children`, `has_edge`,
88    /// `edge_count`, `anchor`) have no meaning apart from an instance. Reach
89    /// them through `panproto_inst::eval_with_instance` or
90    /// `panproto_inst::eval_with_element_ops`, or supply any other
91    /// [`BuiltinResolver`](crate::eval::BuiltinResolver).
92    #[error("{op} needs an instance to traverse, and evaluation was given none")]
93    NoInstanceContext {
94        /// The builtin operation that needs an instance.
95        op: String,
96    },
97
98    /// A builtin operation reached a category handler that does not implement it.
99    ///
100    /// The top-level dispatch in [`apply_builtin`](crate::builtin::apply_builtin)
101    /// routes each [`BuiltinOp`](crate::expr::BuiltinOp) to the category handler
102    /// that implements it. This error signals a misrouted operation: a
103    /// per-category handler received an op outside its category.
104    #[error("internal dispatch error: operation {op} routed to the wrong category handler")]
105    InternalDispatch {
106        /// The misrouted builtin operation.
107        op: String,
108    },
109}