Skip to main content

lambda_cat/
error.rs

1//! Project-wide error type.
2//!
3//! Every fallible operation in `lambda-cat` returns [`Error`].  The enum covers
4//! lexical, syntactic, and evaluation failures across the pipeline.
5
6use crate::syntax::{Position, VarName};
7
8/// All errors in lambda-cat.
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub enum Error {
11    /// The lexer encountered a character that does not begin any token.
12    UnexpectedChar {
13        /// Byte offset in the source where the character was found.
14        at: Position,
15        /// The offending character.
16        ch: char,
17    },
18    /// Input ended while the parser still required more tokens.
19    UnexpectedEnd {
20        /// Short description of what was expected, e.g. `"expression"`.
21        expected: &'static str,
22    },
23    /// The parser found a token that does not satisfy the current production.
24    UnexpectedToken {
25        /// Byte offset in the source where the offending token began.
26        at: Position,
27        /// Short description of what was expected, e.g. `"identifier"`.
28        expected: &'static str,
29        /// Human-readable rendering of the token that was actually found.
30        found: String,
31    },
32    /// Evaluation referenced a variable not bound in the current environment.
33    UnboundVariable {
34        /// The unbound name.
35        name: VarName,
36    },
37    /// Evaluation exceeded its step budget.
38    FuelExhausted {
39        /// The configured step limit that was hit.
40        limit: u64,
41    },
42}
43
44impl std::fmt::Display for Error {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        match self {
47            Self::UnexpectedChar { at, ch } => {
48                write!(f, "unexpected character {ch:?} at byte {}", at.value())
49            }
50            Self::UnexpectedEnd { expected } => {
51                write!(f, "unexpected end of input; expected {expected}")
52            }
53            Self::UnexpectedToken {
54                at,
55                expected,
56                found,
57            } => {
58                write!(
59                    f,
60                    "unexpected token {found:?} at byte {}; expected {expected}",
61                    at.value()
62                )
63            }
64            Self::UnboundVariable { name } => {
65                write!(f, "unbound variable {:?}", name.as_str())
66            }
67            Self::FuelExhausted { limit } => {
68                write!(f, "evaluation exceeded step limit of {limit}")
69            }
70        }
71    }
72}
73
74impl std::error::Error for Error {}