Skip to main content

lambda_ref_cat/
error.rs

1//! Project-wide error type.
2//!
3//! Every fallible operation in `lambda-ref-cat` returns [`Error`].  The
4//! enum covers lexical, syntactic, evaluation, and heap-side failures.
5
6use crate::heap::Address;
7use crate::syntax::{Position, VarName};
8
9/// All errors in lambda-ref-cat.
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum Error {
12    /// The lexer encountered a character that does not begin any token.
13    UnexpectedChar {
14        /// Byte offset in the source where the character was found.
15        at: Position,
16        /// The offending character.
17        ch: char,
18    },
19    /// Input ended while the parser still required more tokens.
20    UnexpectedEnd {
21        /// Short description of what was expected.
22        expected: &'static str,
23    },
24    /// The parser found a token that does not satisfy the current production.
25    UnexpectedToken {
26        /// Byte offset where the offending token began.
27        at: Position,
28        /// Short description of what was expected.
29        expected: &'static str,
30        /// Rendering of the token that was actually found.
31        found: String,
32    },
33    /// Evaluation referenced a variable not bound in the current environment.
34    UnboundVariable {
35        /// The unbound name.
36        name: VarName,
37    },
38    /// Evaluation exceeded its step budget.
39    FuelExhausted {
40        /// The configured step limit that was hit.
41        limit: u64,
42    },
43    /// A dereference or assignment targeted an address not present in the heap.
44    DanglingReference {
45        /// The address that could not be resolved.
46        address: Address,
47    },
48    /// Dereference or assignment was attempted on a value that is not a cell
49    /// reference.
50    NotAReference {
51        /// Rendering of the offending non-reference value.
52        found: String,
53    },
54    /// Application was attempted with a non-function value in the function
55    /// position.
56    NotAFunction {
57        /// Rendering of the offending non-function value.
58        found: String,
59    },
60}
61
62impl std::fmt::Display for Error {
63    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64        match self {
65            Self::UnexpectedChar { at, ch } => {
66                write!(f, "unexpected character {ch:?} at byte {}", at.value())
67            }
68            Self::UnexpectedEnd { expected } => {
69                write!(f, "unexpected end of input; expected {expected}")
70            }
71            Self::UnexpectedToken {
72                at,
73                expected,
74                found,
75            } => {
76                write!(
77                    f,
78                    "unexpected token {found:?} at byte {}; expected {expected}",
79                    at.value()
80                )
81            }
82            Self::UnboundVariable { name } => {
83                write!(f, "unbound variable {:?}", name.as_str())
84            }
85            Self::FuelExhausted { limit } => {
86                write!(f, "evaluation exceeded step limit of {limit}")
87            }
88            Self::DanglingReference { address } => {
89                write!(f, "dangling reference to address {address}")
90            }
91            Self::NotAReference { found } => {
92                write!(f, "expected a reference, found {found}")
93            }
94            Self::NotAFunction { found } => {
95                write!(f, "expected a function, found {found}")
96            }
97        }
98    }
99}
100
101impl std::error::Error for Error {}