mazer_core/evaluation.rs
1use crate::{interpreter::{Environment, Interpreter}, parser::{LispErr, LispExpr}};
2
3
4impl Interpreter {
5 pub fn eval_expr(expr: &LispExpr, env: &mut Environment) -> Result<LispExpr, LispErr> {
6 match expr {
7 // Self-evaluating expressions
8 LispExpr::Number(_) |
9 LispExpr::String(_) |
10 LispExpr::Boolean(_) |
11 LispExpr::Nil => Ok(expr.clone()),
12
13 LispExpr::Function(_) => {
14 Ok(expr.clone())
15 }
16
17 // Symbol lookup
18 LispExpr::Symbol(s) => {
19 if let Some(value) = env.get(s) {
20 // if value is a list then it must be evaluated (recursively)
21 if let LispExpr::List(list) = value {
22 return Interpreter::eval_expr(&LispExpr::List(list.clone()), env);
23 }
24 Ok(value.clone())
25 } else {
26 Err(LispErr::new(&format!("Symbol {} not found", s)))
27 }
28 },
29
30 // List evaluation (function call or special form)
31 LispExpr::List(list) => {
32 if list.is_empty() {
33 return Ok(LispExpr::Nil);
34 }
35
36 // Check for special forms first
37 if let LispExpr::Symbol(op) = &list[0] {
38 match op.as_str() {
39 "quote" => {
40 if list.len() != 2 {
41 return Err(LispErr::new("quote requires exactly one argument"));
42 }
43 return Ok(list[1].clone());
44 },
45
46 "if" => {
47 if list.len() < 3 || list.len() > 4 {
48 return Err(LispErr::new("if requires 2 or 3 arguments"));
49 }
50
51 let condition = Interpreter::eval_expr(&list[1], env)?;
52 match condition {
53 LispExpr::Boolean(false) | LispExpr::Nil => {
54 if list.len() == 4 {
55 Interpreter::eval_expr(&list[3], env)
56 } else {
57 Ok(LispExpr::Nil)
58 }
59 },
60 _ => Interpreter::eval_expr(&list[2], env),
61 }
62 },
63
64 "define" => {
65 if list.len() != 3 {
66 return Err(LispErr::new("define requires exactly two arguments"));
67 }
68
69 if let LispExpr::Symbol(name) = &list[1] {
70 let value = Interpreter::eval_expr(&list[2], env)?;
71 env.insert(name.clone(), value.clone());
72 Ok(value)
73 } else {
74 Err(LispErr::new("First argument to define must be a symbol"))
75 }
76 },
77
78 "lambda" => {
79 if list.len() < 3 {
80 return Err(LispErr::new("lambda requires at least 2 arguments"));
81 }
82
83 Err(LispErr::new("Lambda functions not implemented yet"))
84 },
85
86 _ => {
87 // Regular function call
88 let evaluated_op = Interpreter::eval_expr(&list[0], env)?;
89
90 match evaluated_op {
91 LispExpr::Function(func) => {
92 let mut evaluated_args = Vec::new();
93 for arg in &list[1..] {
94 evaluated_args.push(Interpreter::eval_expr(arg, env)?);
95 }
96 func(evaluated_args, env)
97 },
98 _ => Err(LispErr::new(&format!("Expected function, got: {}", evaluated_op))),
99 }
100 }
101 }
102 } else {
103 // First element is not a symbol
104 let evaluated_op = Interpreter::eval_expr(&list[0], env)?;
105 match evaluated_op {
106 LispExpr::Function(func) => {
107 let mut evaluated_args = Vec::new();
108 for arg in &list[1..] {
109 evaluated_args.push(Interpreter::eval_expr(arg, env)?);
110 }
111 func(evaluated_args, env)
112 },
113 _ => Err(LispErr::new(&format!("Expected function, got: {}", evaluated_op))),
114 }
115 }
116 }
117 }
118 }
119}