1use crate::lisp::{Lenv, Lerr, LerrType, Llambda, Lval};
2
3pub fn eval(env: &mut Lenv, expr: Lval) -> Result<Lval, Lerr> {
4 match expr {
5 Lval::Sym(s) => eval_symbol(env, s),
6 Lval::Sexpr(vec) => eval_sexpression(env, vec),
7 _ => Ok(expr),
8 }
9}
10
11fn eval_symbol(env: &mut Lenv, s: String) -> Result<Lval, Lerr> {
12 match env.get(&s) {
13 Some(lval) => Ok(lval.clone()),
14 None => Err(Lerr::new(
15 LerrType::UnboundSymbol,
16 format!("{:?} has not been defined", s),
17 )),
18 }
19}
20
21fn eval_sexpression(env: &mut Lenv, sexpr: Vec<Lval>) -> Result<Lval, Lerr> {
22 let results = sexpr
24 .into_iter()
25 .map(|expr| eval(env, expr))
26 .collect::<Result<Vec<Lval>, Lerr>>()?;
27
28 if results.len() == 0 {
29 return Ok(Lval::Sexpr(results));
31 } else if results.len() == 1 {
32 let op = results[0].clone();
34 match op {
35 Lval::Fun(fun) => fun(env, vec![]),
36 Lval::Lambda(lambda) => call(env, lambda, vec![]),
37 _ => Ok(op),
38 }
39 } else {
40 let operands = (&results[1..]).to_vec();
41 match results[0].clone() {
43 Lval::Fun(fun) => fun(env, operands),
44 Lval::Lambda(lambda) => call(env, lambda, operands),
45 _ => Err(Lerr::new(
46 LerrType::BadOp,
47 format!("{:?} is not a valid operator", results[0]),
48 )),
49 }
50 }
51}
52
53pub fn call(env: &mut Lenv, mut func: Llambda, mut args: Vec<Lval>) -> Result<Lval, Lerr> {
54 let given = args.len();
55 let total = func.args.len();
56
57 while args.len() != 0 {
59 if func.args.len() == 0 {
61 return Err(Lerr::new(
62 LerrType::IncorrectParamCount,
63 format!("Function needed {} arg(s) but was given {}", total, given),
64 ));
65 }
66 let sym = func.args[0].clone();
68 func.args = func.args[1..].to_vec();
70
71 if sym == ":" {
72 if func.args.len() != 1 {
73 return Err(Lerr::new(
74 LerrType::IncorrectParamCount,
75 format!(": operator needs to be followed by arg"),
76 ));
77 }
78
79 let sym = func.args[0].clone();
80 func.args = func.args[1..].to_vec();
81 func.env.insert(&sym, Lval::Qexpr(args));
82 break;
84 } else {
85 let val = args[0].clone();
86 args = args[1..].to_vec();
87 func.env.insert(&sym, val);
88 }
89 }
90
91 if func.args.len() == 0 {
92 env.push(func.env.peek().unwrap().clone());
93 let res = eval(env, Lval::Sexpr(func.body));
94 env.pop();
95 res
96 } else {
97 Ok(Lval::Lambda(func))
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104 use crate::lisp::{env::init_env, to_lambda};
105
106 fn empty_fun(_env: &mut Lenv, _operands: Vec<Lval>) -> Result<Lval, Lerr> {
107 Ok(Lval::Sexpr(vec![]))
108 }
109
110 #[test]
111 fn it_handles_singular_numbers() {
112 let env = &mut init_env();
113 assert_eq!(eval(env, Lval::Num(1_f64)).unwrap(), Lval::Num(1_f64));
114 assert_eq!(
115 eval(env, Lval::Sexpr(vec![Lval::Num(1_f64)])).unwrap(),
116 Lval::Num(1_f64)
117 );
118 }
119
120 #[test]
121 fn it_handles_singular_symbols() {
122 let env = &mut init_env();
123 assert_eq!(
124 eval(env, Lval::Sym(String::from("+"))).unwrap(),
125 Lval::Fun(empty_fun)
126 );
127 assert_eq!(
128 eval(env, Lval::Sexpr(vec![Lval::Sym(String::from("*"))])).unwrap(),
129 Lval::Fun(empty_fun)
130 );
131 }
132
133 #[test]
134 fn it_handles_empty_expressions() {
135 let env = &mut init_env();
136 assert_eq!(eval(env, Lval::Sexpr(vec![])).unwrap(), Lval::Sexpr(vec![]));
137 assert_eq!(
138 eval(
139 env,
140 Lval::Sexpr(vec![Lval::Sexpr(vec![Lval::Sexpr(vec![])])])
141 )
142 .unwrap(),
143 Lval::Sexpr(vec![])
144 );
145 }
146
147 #[test]
148 fn it_uses_operators_properly() {
149 let env = &mut init_env();
150 assert_eq!(
151 eval(
152 env,
153 Lval::Sexpr(vec![
154 Lval::Sym(String::from("+")),
155 Lval::Num(1_f64),
156 Lval::Num(1_f64),
157 ])
158 )
159 .unwrap(),
160 Lval::Num(2_f64)
161 );
162 let _ = eval(
163 env,
164 Lval::Sexpr(vec![
165 Lval::Sym(String::from("+")),
166 Lval::Sym(String::from("+")),
167 Lval::Num(1_f64),
168 ]),
169 )
170 .map_err(|err| assert_eq!(err.etype, LerrType::BadNum));
171 let _ = eval(
172 env,
173 Lval::Sexpr(vec![Lval::Num(1_f64), Lval::Num(1_f64), Lval::Num(1_f64)]),
174 )
175 .map_err(|err| assert_eq!(err.etype, LerrType::BadOp));
176 }
177
178 #[test]
179 fn it_handles_nested_sexpressions() {
180 let env = &mut init_env();
181 assert_eq!(
182 eval(
183 env,
184 Lval::Sexpr(vec![
185 Lval::Sym(String::from("+")),
186 Lval::Num(1_f64),
187 Lval::Sexpr(vec![
188 Lval::Sym(String::from("+")),
189 Lval::Num(1_f64),
190 Lval::Num(1_f64),
191 ]),
192 ])
193 )
194 .unwrap(),
195 Lval::Num(3_f64)
196 );
197 }
198
199 #[test]
200 fn it_handles_symbols() {
201 let mut env = init_env();
202
203 assert_eq!(
204 eval(
205 &mut env,
206 Lval::Sexpr(vec![
207 Lval::Sym(String::from("def")),
208 Lval::Qexpr(vec![Lval::Sym(String::from("a"))]),
209 Lval::Num(1_f64),
210 ]),
211 )
212 .unwrap(),
213 Lval::Sexpr(vec![])
214 );
215 assert_eq!(
216 eval_symbol(&mut env, String::from("a")).unwrap(),
217 Lval::Num(1_f64)
218 );
219
220 env.push(crate::lisp::Lookup::new());
221 assert_eq!(
222 eval(
223 &mut env,
224 Lval::Sexpr(vec![
225 Lval::Sym(String::from("def")),
226 Lval::Qexpr(vec![Lval::Sym(String::from("b"))]),
227 Lval::Num(2_f64),
228 ]),
229 )
230 .unwrap(),
231 Lval::Sexpr(vec![])
232 );
233 assert_eq!(
234 eval_symbol(&mut env, String::from("a")).unwrap(),
235 Lval::Num(1_f64)
236 );
237 assert_eq!(
238 eval_symbol(&mut env, String::from("b")).unwrap(),
239 Lval::Num(2_f64)
240 );
241
242 assert_eq!(
243 eval(
244 &mut env,
245 Lval::Sexpr(vec![
246 Lval::Sym(String::from("def")),
247 Lval::Qexpr(vec![Lval::Sym(String::from("c"))]),
248 Lval::Num(3_f64),
249 ]),
250 )
251 .unwrap(),
252 Lval::Sexpr(vec![])
253 );
254 assert_eq!(
255 eval_symbol(&mut env, String::from("a")).unwrap(),
256 Lval::Num(1_f64)
257 );
258 assert_eq!(
259 eval_symbol(&mut env, String::from("b")).unwrap(),
260 Lval::Num(2_f64)
261 );
262 assert_eq!(
263 eval_symbol(&mut env, String::from("c")).unwrap(),
264 Lval::Num(3_f64)
265 );
266 }
267
268 #[test]
269 fn it_handles_lambdas() {
270 let env = &mut init_env();
271
272 let immediately_invoked =
273 Llambda::new(vec![], vec![Lval::Num(71_f64)], env.peek().unwrap().clone());
274 assert_eq!(
275 eval(env, Lval::Sexpr(vec![Lval::Lambda(immediately_invoked)])).unwrap(),
276 Lval::Num(71_f64)
277 );
278
279 let lambda = Llambda::new(
281 vec![String::from("a")],
282 vec![
283 Lval::Sym(String::from("+")),
284 Lval::Sym(String::from("a")),
285 Lval::Sym(String::from("a")),
286 ],
287 env.peek().unwrap().clone(),
288 );
289 assert_eq!(
290 call(env, lambda, vec![Lval::Num(5_f64)]).unwrap(),
291 Lval::Num(10_f64)
292 );
293
294 let lambda = Llambda::new(
296 vec![String::from("c"), String::from("d")],
297 vec![
298 Lval::Sym(String::from("*")),
299 Lval::Sym(String::from("c")),
300 Lval::Sym(String::from("d")),
301 ],
302 env.peek().unwrap().clone(),
303 );
304 let new_lambda = call(env, lambda, vec![Lval::Num(15_f64)]).unwrap();
305 assert_eq!(
306 call(env, to_lambda(&new_lambda).unwrap(), vec![Lval::Num(5_f64)]).unwrap(),
307 Lval::Num(75_f64)
308 );
309 }
310
311 #[test]
312 fn it_handles_nested_lambdas() {
313 let env = &mut init_env();
314
315 let f = Lval::Sexpr(vec![
316 Lval::Sexpr(vec![
317 Lval::Sym(String::from("\\")),
318 Lval::Qexpr(vec![Lval::Sym(String::from("e"))]),
319 Lval::Qexpr(vec![
320 Lval::Sym(String::from("\\")),
321 Lval::Qexpr(vec![Lval::Sym(String::from("f"))]),
322 Lval::Qexpr(vec![Lval::Sym(String::from("e"))]),
323 ]),
324 ]),
325 Lval::Num(5_f64),
326 ]);
327
328 let partial = eval(env, f).unwrap();
330 let partial_lambda = to_lambda(&partial).unwrap();
331 assert_eq!(partial_lambda.args.len(), 1);
332 assert!(partial_lambda.env.get("+").is_some()); assert!(partial_lambda.env.get("e").is_some()); assert_eq!(
336 call(env, partial_lambda, vec![Lval::Num(25_f64)]).unwrap(),
337 Lval::Num(5_f64)
338 );
339 }
340}
341