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 {}