aboutsummaryrefslogtreecommitdiff
path: root/src/lisp/eval.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lisp/eval.rs')
-rw-r--r--src/lisp/eval.rs55
1 files changed, 25 insertions, 30 deletions
diff --git a/src/lisp/eval.rs b/src/lisp/eval.rs
index 9276ef5..329b6ab 100644
--- a/src/lisp/eval.rs
+++ b/src/lisp/eval.rs
@@ -76,7 +76,7 @@ where
76 self.eval(&LispExpr::List(f.body.clone())) 76 self.eval(&LispExpr::List(f.body.clone()))
77 }; 77 };
78 self.app.lisp_env.pop(); 78 self.app.lisp_env.pop();
79 return result; 79 result
80 } 80 }
81 } 81 }
82 LispExpr::List(_) => { 82 LispExpr::List(_) => {
@@ -108,7 +108,7 @@ where
108 error!("Unable to create global definition"); 108 error!("Unable to create global definition");
109 return Err(EvalError::BadForm.into()); 109 return Err(EvalError::BadForm.into());
110 } 110 }
111 return Ok(LispExpr::Unit); 111 Ok(LispExpr::Unit)
112 } 112 }
113 [LispExpr::List(shorthand), LispExpr::List(body)] => { 113 [LispExpr::List(shorthand), LispExpr::List(body)] => {
114 // (define (func arg) <body>) shorthand 114 // (define (func arg) <body>) shorthand
@@ -130,12 +130,12 @@ where
130 130
131 let local_env = &mut self.app.lisp_env.last_mut(); 131 let local_env = &mut self.app.lisp_env.last_mut();
132 if let Some(env) = local_env { 132 if let Some(env) = local_env {
133 env.insert(id.into(), value); 133 env.insert(id, value);
134 } else { 134 } else {
135 error!("Unable to create global definition"); 135 error!("Unable to create global definition");
136 return Err(EvalError::BadForm.into()); 136 return Err(EvalError::BadForm.into());
137 } 137 }
138 return Ok(LispExpr::Unit); 138 Ok(LispExpr::Unit)
139 } 139 }
140 _ => { 140 _ => {
141 error!("Invalid usage of `define`"); 141 error!("Invalid usage of `define`");
@@ -154,17 +154,16 @@ where
154 let value = self.eval(&expr)?; 154 let value = self.eval(&expr)?;
155 let local_env = self.app.lisp_env.last_mut(); 155 let local_env = self.app.lisp_env.last_mut();
156 if let Some(env) = local_env { 156 if let Some(env) = local_env {
157 return env 157 env.insert(id.into(), value)
158 .insert(id.into(), value) 158 .ok_or_else(|| EvalError::UnboundVariable(id.into()).into())
159 .ok_or(EvalError::UnboundVariable(id.into()).into());
160 } else { 159 } else {
161 error!("Unable to set in global env!"); 160 error!("Unable to set in global env!");
162 return Err(EvalError::BadForm.into()); 161 Err(EvalError::BadForm.into())
163 } 162 }
164 } 163 }
165 _ => { 164 _ => {
166 error!("Invalid usage of `set!`"); 165 error!("Invalid usage of `set!`");
167 return Err(EvalError::BadForm.into()); 166 Err(EvalError::BadForm.into())
168 } 167 }
169 } 168 }
170 } 169 }
@@ -172,15 +171,15 @@ where
172 pub fn eval_if(&mut self, args: &[LispExpr]) -> Result<LispExpr, LispError> { 171 pub fn eval_if(&mut self, args: &[LispExpr]) -> Result<LispExpr, LispError> {
173 let arity = Arity::Exact(3); 172 let arity = Arity::Exact(3);
174 if !arity.check(args) { 173 if !arity.check(args) {
175 return Err(arity.to_error()); 174 Err(arity.to_error())
176 } else { 175 } else {
177 match args { 176 match args {
178 [predicate, then, else_] => { 177 [predicate, then, else_] => {
179 let predicate = self.eval(&predicate)?; 178 let predicate = self.eval(&predicate)?;
180 if matches!(predicate, LispExpr::BoolLit(false)) { 179 if matches!(predicate, LispExpr::BoolLit(false)) {
181 return self.eval(&else_); 180 self.eval(&else_)
182 } else { 181 } else {
183 return self.eval(&then); 182 self.eval(&then)
184 } 183 }
185 } 184 }
186 _ => { 185 _ => {
@@ -194,7 +193,7 @@ where
194 let arity = Arity::Atleast(1); 193 let arity = Arity::Atleast(1);
195 let valid_cond_stmt = |expr: &LispExpr| matches!(expr, LispExpr::List(v) if v.len() == 2); 194 let valid_cond_stmt = |expr: &LispExpr| matches!(expr, LispExpr::List(v) if v.len() == 2);
196 if !arity.check(args) { 195 if !arity.check(args) {
197 return Err(arity.to_error()); 196 Err(arity.to_error())
198 } else { 197 } else {
199 for cond_stmt in args { 198 for cond_stmt in args {
200 if valid_cond_stmt(cond_stmt) { 199 if valid_cond_stmt(cond_stmt) {
@@ -211,7 +210,7 @@ where
211 return Err(EvalError::BadForm.into()); 210 return Err(EvalError::BadForm.into());
212 } 211 }
213 } 212 }
214 return Ok(LispExpr::Unit); 213 Ok(LispExpr::Unit)
215 } 214 }
216 } 215 }
217 216
@@ -220,7 +219,7 @@ where
220 let valid_binding_stmt = 219 let valid_binding_stmt =
221 |expr: &LispExpr| matches!(expr, LispExpr::List(v) if v.len() == 2); 220 |expr: &LispExpr| matches!(expr, LispExpr::List(v) if v.len() == 2);
222 if !arity.check(args) { 221 if !arity.check(args) {
223 return Err(arity.to_error()); 222 Err(arity.to_error())
224 } else { 223 } else {
225 let nested_env = Environment::new(); 224 let nested_env = Environment::new();
226 self.app.lisp_env.push(nested_env); 225 self.app.lisp_env.push(nested_env);
@@ -247,11 +246,11 @@ where
247 } 246 }
248 let result = self.eval(&body); 247 let result = self.eval(&body);
249 self.app.lisp_env.pop(); 248 self.app.lisp_env.pop();
250 return result; 249 result
251 } 250 }
252 _ => { 251 _ => {
253 error!("bad `let` form"); 252 error!("bad `let` form");
254 return Err(EvalError::BadForm.into()); 253 Err(EvalError::BadForm.into())
255 } 254 }
256 } 255 }
257 } 256 }
@@ -277,32 +276,28 @@ pub fn create_lambda(cdr: &[LispExpr]) -> Result<LispExpr, LispError> {
277 return Err(arity.to_error()); 276 return Err(arity.to_error());
278 } 277 }
279 match cdr { 278 match cdr {
280 [LispExpr::List(params), LispExpr::List(body)] if type_match!(params, (..) => LispExpr::Ident(_)) => 279 [LispExpr::List(params), LispExpr::List(body)] if type_match!(params, (..) => LispExpr::Ident(_)) => {
281 { 280 Ok(LispExpr::Function(LispFunction {
282 return Ok(LispExpr::Function(LispFunction { 281 params: params.iter().map(|p| p.unwrap_ident()).collect::<Vec<_>>(),
283 params: params
284 .into_iter()
285 .map(|p| p.unwrap_ident())
286 .collect::<Vec<_>>(),
287 body: body.clone(), 282 body: body.clone(),
288 })); 283 }))
289 } 284 }
290 _ => { 285 _ => {
291 error!("Invalid usage of `lambda`"); 286 error!("Invalid usage of `lambda`");
292 return Err(EvalError::BadForm.into()); 287 Err(EvalError::BadForm.into())
293 } 288 }
294 } 289 }
295} 290}
296 291
297pub fn lookup(env_list: &[Environment], key: &str) -> Result<LispExpr, LispError> { 292pub fn lookup(env_list: &[Environment], key: &str) -> Result<LispExpr, LispError> {
298 if env_list.is_empty() { 293 if env_list.is_empty() {
299 return Err(EvalError::UnboundVariable(key.into()).into()); 294 Err(EvalError::UnboundVariable(key.into()).into())
300 } else { 295 } else {
301 let local_env = env_list.last().unwrap(); 296 let local_env = env_list.last().unwrap();
302 if let Some(val) = local_env.get(key) { 297 if let Some(val) = local_env.get(key) {
303 return Ok(val.clone()); 298 Ok(val.clone())
304 } else { 299 } else {
305 return lookup(&env_list[..env_list.len() - 1], key); 300 lookup(&env_list[..env_list.len() - 1], key)
306 } 301 }
307 } 302 }
308} 303}
@@ -314,7 +309,7 @@ mod tests {
314 use crate::lisp::{expr::LispExpr, lex::Lexer, number::LispNumber, parse::Parser}; 309 use crate::lisp::{expr::LispExpr, lex::Lexer, number::LispNumber, parse::Parser};
315 310
316 fn run(code: &str, app: &mut AppState) -> LispExpr { 311 fn run(code: &str, app: &mut AppState) -> LispExpr {
317 let mut parser = Parser::new(Lexer::new(code, 0)); 312 let mut parser = Parser::new(Lexer::new(code));
318 let mut evaluator = Evaluator { 313 let mut evaluator = Evaluator {
319 app, 314 app,
320 context: Vec::new(), 315 context: Vec::new(),