lithia/
errors.rs

1use std::{error::Error, fmt, rc::Rc};
2
3use crate::object::Object;
4
5pub type LispResult = Result<Rc<Object>, LispError>;
6pub type RustFuncResult = Result<Rc<Object>, RustFuncError>;
7
8#[derive(Debug, Clone)]
9pub enum LispErrorKind {
10    Parser,
11    Eval,
12    RustFunc,
13}
14
15#[derive(Debug)]
16pub struct LispError {
17    kind: LispErrorKind,
18    error: Box<dyn Error>,
19}
20
21impl LispError {
22    pub fn new<E>(kind: LispErrorKind, error: E) -> Self
23    where
24        E: Into<Box<dyn Error>>,
25    {
26        let error = error.into();
27
28        Self { kind, error }
29    }
30}
31
32impl fmt::Display for LispError {
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        match self.kind {
35            LispErrorKind::Parser => write!(f, "Error parsing code: {}", self.error),
36            LispErrorKind::Eval => write!(f, "Error evaluating object: {}", self.error),
37            LispErrorKind::RustFunc => write!(f, "{}", self.error),
38        }
39    }
40}
41
42impl Error for LispError {
43    fn source(&self) -> Option<&(dyn Error + 'static)> {
44        Some(&*self.error)
45    }
46}
47
48#[derive(Debug, Clone)]
49pub enum ParserError {
50    UnmatchedToken(char),
51    InvalidToken(String),
52    UnparsableAtom(String),
53    EmptyQuote,
54}
55
56impl fmt::Display for ParserError {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        match self {
59            Self::UnmatchedToken(c) => write!(f, "Unmatched token: '{}'", c),
60            Self::UnparsableAtom(a) => write!(f, "Unparsable atom: {}", a),
61            Self::InvalidToken(c) => write!(f, "Invalid token: '{}'", c),
62            Self::EmptyQuote => write!(f, "Empty quote"),
63        }
64    }
65}
66
67impl Error for ParserError {}
68
69#[derive(Debug, Clone)]
70pub enum EvalError {
71    UnknownSymbol(String),
72    GlobalExists(String),
73    NonFunction(Rc<Object>),
74}
75
76impl fmt::Display for EvalError {
77    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78        match self {
79            Self::UnknownSymbol(s) => write!(f, "Unknown symbol: {}", s),
80            Self::GlobalExists(s) => write!(f, "Global already exists: {}", s),
81            Self::NonFunction(o) => write!(f, "Attempt to call non-function: {}", o),
82        }
83    }
84}
85
86impl Error for EvalError {}
87
88#[derive(Debug)]
89pub enum RustFuncError {
90    InvalidArguments(ArgumentsError),
91    LispError(LispError),
92}
93
94impl RustFuncError {
95    pub fn new_args_error(error: ArgumentsError) -> Self {
96        Self::InvalidArguments(error)
97    }
98}
99
100impl fmt::Display for RustFuncError {
101    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102        match self {
103            Self::InvalidArguments(e) => {
104                write!(f, "Error running function: Invalid arguments: {}", e)
105            }
106            Self::LispError(e) => write!(f, "{}", e),
107        }
108    }
109}
110
111impl Error for RustFuncError {
112    fn source(&self) -> Option<&(dyn Error + 'static)> {
113        match self {
114            Self::InvalidArguments(e) => Some(e),
115            Self::LispError(e) => Some(e),
116        }
117    }
118}
119
120impl From<LispError> for RustFuncError {
121    fn from(error: LispError) -> Self {
122        Self::LispError(error)
123    }
124}
125
126#[derive(Debug, Clone)]
127pub enum ArgumentsError {
128    TooMany,
129    NotEnough,
130    WrongType,
131    DottedPair,
132}
133
134impl fmt::Display for ArgumentsError {
135    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136        match self {
137            Self::TooMany => write!(f, "Too many arguments"),
138            Self::NotEnough => write!(f, "Not enough arguments"),
139            Self::WrongType => write!(f, "Arguments of wrong type"),
140            Self::DottedPair => write!(f, "Dotted-pair arguments not accepted"),
141        }
142    }
143}
144
145impl Error for ArgumentsError {}