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