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
use crate::ast::{Ast, LispAtom};
use crate::env::Environment;
use crate::error::LispError;
use crate::special_forms::{eval_special_form, SPECIAL_FORMS};
pub fn eval_expr(input: Ast, env: &mut Environment) -> Result<Ast, LispError> {
match input {
Ast::List(list) => match list.get(0) {
Some(Ast::Atom(LispAtom::Symbol(symbol))) => {
if let Some(special_form) = SPECIAL_FORMS.get(symbol.as_str()) {
eval_special_form(list, env, special_form)
} else {
eval_list(list, env)
}
}
_ => eval_list(list, env),
},
Ast::Atom(LispAtom::Symbol(symbol)) => eval_symbol(&symbol, env), _ => Ok(input), }
}
fn eval_list(list: Vec<Ast>, env: &mut Environment) -> Result<Ast, LispError> {
let mut list = list.into_iter();
let func = list
.next()
.ok_or(LispError::Type)
.and_then(|ast| eval_expr(ast, env))?;
let args: Vec<Ast> = list
.map(|ast| eval_expr(ast, env))
.collect::<Result<_, LispError>>()?;
if let Ast::Function(func) = func {
func.arity().check_arity(args.len())?;
func.call(args, env)
} else {
Err(LispError::Type)
}
}
fn eval_symbol(symbol: &str, env: &mut Environment) -> Result<Ast, LispError> {
env.get(symbol).ok_or(LispError::Type)
}