diff options
Diffstat (limited to 'src/lisp/eval.rs')
-rw-r--r-- | src/lisp/eval.rs | 55 |
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 | ||
297 | pub fn lookup(env_list: &[Environment], key: &str) -> Result<LispExpr, LispError> { | 292 | pub 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(), |