1pub mod builtin;
2pub mod env;
3pub mod eval;
4pub mod parser;
5
6use env::{Lenv, Lookup};
7use std::{error::Error, fmt};
8
9#[derive(Clone)]
10pub enum Lval {
11 Sym(String),
12 Num(f64),
13 Sexpr(Vec<Lval>),
14 Qexpr(Vec<Lval>),
15 Fun(Lfun),
16 Lambda(Llambda),
17 Str(String),
18}
19
20impl PartialEq for Lval {
21 fn eq(&self, other: &Self) -> bool {
22 match self {
23 Lval::Sym(a) => match other {
24 Lval::Sym(b) => a == b,
25 _ => false,
26 },
27 Lval::Num(a) => match other {
28 Lval::Num(b) => a == b,
29 _ => false,
30 },
31 Lval::Sexpr(a) => match other {
32 Lval::Sexpr(b) => a == b,
33 _ => false,
34 },
35 Lval::Qexpr(a) => match other {
36 Lval::Qexpr(b) => a == b,
37 _ => false,
38 },
39 Lval::Fun(_) => match other {
40 Lval::Fun(_) => true,
41 _ => false,
42 },
43 Lval::Str(_) => match other {
44 Lval::Str(_) => true,
45 _ => false,
46 },
47 Lval::Lambda(a) => match other {
48 Lval::Lambda(b) => a.body == b.body && a.args == b.args,
49 _ => false,
50 },
51 }
52 }
53}
54
55impl fmt::Debug for Lval {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 match &self {
58 Lval::Sym(s) => write!(f, "{}", s),
59 Lval::Num(n) => write!(f, "{}", n),
60 Lval::Sexpr(s) => write!(
61 f,
62 "({})",
63 s.into_iter()
64 .map(|x| match x {
65 Lval::Sym(sym) => format!("{}", sym),
66 _ => format!("{:?}", x),
67 })
68 .collect::<Vec<String>>()
69 .join(" ")
70 ),
71 Lval::Qexpr(q) => write!(
72 f,
73 "[{}]",
74 q.into_iter()
75 .map(|x| match x {
76 Lval::Sym(sym) => format!("{}", sym),
77 _ => format!("{:?}", x),
78 })
79 .collect::<Vec<String>>()
80 .join(" ")
81 ),
82 Lval::Fun(_) => write!(f, "builtin"),
83 Lval::Str(s) => write!(f, "{}", s),
84 Lval::Lambda(l) => write!(
85 f,
86 "(\\ [{}] [{}])",
87 l.args.join(" "),
88 l.body
89 .to_owned()
90 .into_iter()
91 .map(|x| match x {
92 Lval::Sym(sym) => format!("{}", sym),
93 _ => format!("{:?}", x),
94 })
95 .collect::<Vec<String>>()
96 .join(" ")
97 ),
98 }
99 }
100}
101
102#[derive(Clone)]
103pub struct Llambda {
104 args: Vec<String>,
105 body: Vec<Lval>,
106 env: Lenv,
107}
108
109impl Llambda {
110 fn new(args: Vec<String>, body: Vec<Lval>, lookup: Lookup) -> Self {
111 let mut lenv = Lenv::new();
112 lenv.push(lookup);
113 Llambda {
114 args,
115 body,
116 env: lenv,
117 }
118 }
119}
120
121#[derive(Clone, PartialEq)]
122pub struct Lerr {
123 etype: LerrType,
124 details: String,
125 message: String,
126}
127
128impl Lerr {
129 fn new(etype: LerrType, message: String) -> Lerr {
130 let msg = match &etype {
131 LerrType::DivZero => "Cannot Divide By Zero",
132 LerrType::BadOp => "Invalid Operator",
133 LerrType::BadNum => "Invalid Operand",
134 LerrType::IncorrectParamCount => "Incorrect Number of Params passed to function",
135 LerrType::WrongType => "Incorrect Data Type used",
136 LerrType::EmptyList => "Empty List passed to function",
137 LerrType::UnboundSymbol => "This Symbol has not been Defined",
138 LerrType::Interrupt => "User defined Error",
139 };
140
141 Lerr {
142 details: msg.to_string(),
143 message,
144 etype,
145 }
146 }
147}
148
149impl fmt::Debug for Lerr {
150 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
151 write!(
152 f,
153 "Error: {:?} - {}; {}",
154 self.etype, self.details, self.message
155 )
156 }
157}
158
159impl fmt::Display for Lerr {
160 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
161 write!(f, "{}", self.details)
162 }
163}
164
165impl Error for Lerr {
166 fn description(&self) -> &str {
167 &self.details
168 }
169}
170
171#[derive(Clone, Debug, PartialEq)]
172pub enum LerrType {
173 DivZero,
174 BadOp,
175 BadNum,
176 IncorrectParamCount,
177 EmptyList,
178 WrongType,
179 UnboundSymbol,
180 Interrupt,
181}
182
183pub type Lfun = fn(&mut Lenv, Vec<Lval>) -> Result<Lval, Lerr>;
184
185pub fn add_builtin(env: &mut Lenv, sym: &str, fun: Lfun) {
186 env.insert(sym, Lval::Fun(fun));
187}
188
189fn to_num(expr: Lval) -> Option<f64> {
190 if let Lval::Num(n) = expr {
191 Some(n)
192 } else {
193 None
194 }
195}
196
197fn to_sym(expr: Lval) -> Option<String> {
198 if let Lval::Sym(s) = expr {
199 Some(s.clone())
200 } else {
201 None
202 }
203}
204
205fn to_str(expr: Lval) -> Option<String> {
206 if let Lval::Str(s) = expr {
207 Some(s.clone())
208 } else {
209 None
210 }
211}
212
213fn to_qexpr(expr: Lval) -> Option<Vec<Lval>> {
214 if let Lval::Qexpr(s) = expr {
215 Some(s.clone())
216 } else {
217 None
218 }
219}
220
221#[cfg(test)]
222fn to_lambda(expr: &Lval) -> Option<Llambda> {
223 if let Lval::Lambda(s) = expr {
224 Some(s.clone())
225 } else {
226 None
227 }
228}
229
230pub fn lisp(env: &mut Lenv, input: &str) -> String {
231 if "env" == input {
232 return format!("{:#?}", env.peek().unwrap());
233 }
234
235 let ast = parser::parse(input);
236 match ast {
237 Ok(tree) => match eval::eval(env, tree.1) {
238 Ok(r) => format!("{:?}", r),
239 Err(r) => format!("{:?}", r),
240 },
241 Err(e) => format!("Error: Parsing Error - Could not parse the input; {}", e),
242 }
243}