Skip to main content

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}