mazer_core/
interpreter.rs1use std::{collections::HashMap, fmt::Debug};
2
3use crate::parser::{LispErr, LispExpr};
4
5pub type Environment = HashMap<String, LispExpr>;
6
7#[derive(Debug)]
8pub struct Interpreter {
9 env: Environment,
10}
11
12impl Interpreter {
13 pub fn new() -> Self {
14 Interpreter {
15 env: Interpreter::stdenv(),
16 }
17 }
18
19 fn stdenv() -> Environment {
20 let mut env = HashMap::new();
21
22 env.insert("pi".to_string(), LispExpr::Number(std::f64::consts::PI));
24 env.insert("e".to_string(), LispExpr::Number(std::f64::consts::E));
25
26 env.insert("+".to_string(), LispExpr::Function(|args, _| {
28 let sum: f64 = args.iter().map(|arg| {
29 if let LispExpr::Number(n) = arg {
30 *n
31 } else {
32 0.0
33 }
34 }).sum();
35 Ok(LispExpr::Number(sum))
36 }));
37
38 env.insert("-".to_string(), LispExpr::Function(|args, _env| {
39 if args.is_empty() {
40 return Err(LispErr::new("Subtraction requires at least one argument"));
41 }
42
43 if let LispExpr::Number(first) = args[0] {
44 if args.len() == 1 {
45 return Ok(LispExpr::Number(-first));
47 }
48
49 let mut result = first;
50 for arg in &args[1..] {
51 if let LispExpr::Number(n) = arg {
52 result -= n;
53 } else {
54 return Err(LispErr::new(&format!("Expected number, got: {}", arg)));
55 }
56 }
57 Ok(LispExpr::Number(result))
58 } else {
59 Err(LispErr::new(&format!("Expected number, got: {}", args[0])))
60 }
61 }));
62
63 env.insert("*".to_string(), LispExpr::Function(|args, _env| {
64 let mut result = 1.0;
65 for arg in args {
66 if let LispExpr::Number(n) = arg {
67 result *= n;
68 } else {
69 return Err(LispErr::new(&format!("Expected number, got: {}", arg)));
70 }
71 }
72 Ok(LispExpr::Number(result))
73 }));
74
75 env.insert("/".to_string(), LispExpr::Function(|args, _env| {
76 if args.is_empty() {
77 return Err(LispErr::new("/ requires at least one argument"));
78 }
79
80 if let LispExpr::Number(first) = args[0] {
81 if args.len() == 1 {
82 if first == 0.0 {
84 return Err(LispErr::new("Division by zero"));
85 }
86 return Ok(LispExpr::Number(1.0 / first));
87 }
88
89 let mut result = first;
90 for arg in &args[1..] {
91 if let LispExpr::Number(n) = arg {
92 if *n == 0.0 {
93 return Err(LispErr::new("Division by zero"));
94 }
95 result /= n;
96 } else {
97 return Err(LispErr::new(&format!("Expected number, got: {}", arg)));
98 }
99 }
100 Ok(LispExpr::Number(result))
101 } else {
102 Err(LispErr::new(&format!("Expected number, got: {}", args[0])))
103 }
104 }));
105
106 env.insert("=".to_string(), LispExpr::Function(|args, _env| {
108 if args.len() < 2 {
109 return Err(LispErr::new("= requires at least two arguments"));
110 }
111
112 if let LispExpr::Number(first) = args[0] {
113 for arg in &args[1..] {
114 if let LispExpr::Number(n) = arg {
115 if first != *n {
116 return Ok(LispExpr::Boolean(false));
117 }
118 } else {
119 return Err(LispErr::new(&format!("Expected number, got: {}", arg)));
120 }
121 }
122 Ok(LispExpr::Boolean(true))
123 } else {
124 Err(LispErr::new(&format!("Expected number, got: {}", args[0])))
125 }
126 }));
127
128 env.insert(">".to_string(), LispExpr::Function(|args, _env| {
129 if args.len() != 2 {
130 return Err(LispErr::new("> requires exactly two arguments"));
131 }
132
133 if let (LispExpr::Number(a), LispExpr::Number(b)) = (&args[0], &args[1]) {
134 Ok(LispExpr::Boolean(a > b))
135 } else {
136 Err(LispErr::new(&format!("Expected number, got: {} and {}", args[0], args[1])))
137 }
138 }));
139
140 env.insert("<".to_string(), LispExpr::Function(|args, _env| {
141 if args.len() != 2 {
142 return Err(LispErr::new("< requires exactly two arguments"));
143 }
144
145 if let (LispExpr::Number(a), LispExpr::Number(b)) = (&args[0], &args[1]) {
146 Ok(LispExpr::Boolean(a < b))
147 } else {
148 Err(LispErr::new(&format!("Expected number, got: {} and {}", args[0], args[1])))
149 }
150 }));
151
152 env.insert("sqrt".to_string(), LispExpr::Function(|args, _env| {
154 if args.len() != 1 {
155 return Err(LispErr::new("sqrt requires exactly one argument"));
156 }
157
158 if let LispExpr::Number(n) = args[0] {
159 if n < 0.0 {
160 return Err(LispErr::new(&format!("Cannot take square root of negative number: {}", n)));
161 }
162 Ok(LispExpr::Number(n.sqrt()))
163 } else {
164 Err(LispErr::new(&format!("Expected number, got: {}", args[0])))
165 }
166 }));
167
168 env.insert("pow".to_string(), LispExpr::Function(|args, _env| {
169 if args.len() != 2 {
170 return Err(LispErr::new("pow requires exactly two arguments"));
171 }
172
173 if let (LispExpr::Number(base), LispExpr::Number(exp)) = (&args[0], &args[1]) {
174 Ok(LispExpr::Number(base.powf(*exp)))
175 } else {
176 Err(LispErr::new(&format!("Expected numbers, got: {} and {}", args[0], args[1])))
177 }
178 }));
179
180 env
181 }
182
183 pub fn environment(&self) -> Environment {
184 self.env.clone()
185 }
186
187 pub fn get_symbol(&self, symbol: String) -> Option<LispExpr> {
188 self.env.get(&symbol).cloned()
189 }
190
191 pub fn set_symbol(&mut self, symbol: String, definition: LispExpr) {
192 self.env.insert(symbol, definition);
193 }
194
195 pub fn eval(&self, symbol: String) -> Result<LispExpr, LispErr> {
196 let _expr = self.get_symbol(symbol.clone()).ok_or(LispErr::new(&format!("Symbol {} not found", symbol)))?;
197 unimplemented!("interpreter::eval")
198 }
199}