diff options
Diffstat (limited to 'src/lisp/eval.rs')
-rw-r--r-- | src/lisp/eval.rs | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/src/lisp/eval.rs b/src/lisp/eval.rs index cb8ce68..d11ad30 100644 --- a/src/lisp/eval.rs +++ b/src/lisp/eval.rs | |||
@@ -31,7 +31,7 @@ where | |||
31 | LispExpr::Number(_) => Ok(expr.clone()), | 31 | LispExpr::Number(_) => Ok(expr.clone()), |
32 | LispExpr::BoolLit(_) => Ok(expr.clone()), | 32 | LispExpr::BoolLit(_) => Ok(expr.clone()), |
33 | LispExpr::Ident(ref id) => lookup(&self.app.lisp_env, id), | 33 | LispExpr::Ident(ref id) => lookup(&self.app.lisp_env, id), |
34 | LispExpr::Quote(_, _) => Ok(expr.clone()), | 34 | LispExpr::Quote(item, _) => Ok(apply_quote(&item.as_ref())), |
35 | LispExpr::List(li) => { | 35 | LispExpr::List(li) => { |
36 | let func_expr = &li[0]; | 36 | let func_expr = &li[0]; |
37 | match func_expr { | 37 | match func_expr { |
@@ -41,7 +41,7 @@ where | |||
41 | "lambda" => create_lambda(&li[1..]), | 41 | "lambda" => create_lambda(&li[1..]), |
42 | "if" => self.eval_if(&li[1..]), | 42 | "if" => self.eval_if(&li[1..]), |
43 | "cond" => self.eval_cond(&li[1..]), | 43 | "cond" => self.eval_cond(&li[1..]), |
44 | "quote" => quote_var(&li[1..]), | 44 | "quote" => Ok(apply_quote(&li[1])), |
45 | _ => { | 45 | _ => { |
46 | let mut new_ls = vec![self.eval(&func_expr)?]; | 46 | let mut new_ls = vec![self.eval(&func_expr)?]; |
47 | new_ls.extend(li[1..].to_vec()); | 47 | new_ls.extend(li[1..].to_vec()); |
@@ -215,12 +215,15 @@ where | |||
215 | } | 215 | } |
216 | } | 216 | } |
217 | 217 | ||
218 | pub fn quote_var(args: &[LispExpr]) -> Result<LispExpr, LispError> { | 218 | pub fn apply_quote(arg: &LispExpr) -> LispExpr { |
219 | let arity = Arity::Exact(1); | 219 | match arg { |
220 | if !arity.check(args) { | 220 | i @ LispExpr::Unit |
221 | return Err(arity.to_error()); | 221 | | i @ LispExpr::StringLit(_) |
222 | } else { | 222 | | i @ LispExpr::Char(_) |
223 | return Ok(args[0].clone().quote(1)); | 223 | | i @ LispExpr::Number(_) |
224 | | i @ LispExpr::BoolLit(_) => i.clone(), | ||
225 | LispExpr::List(ls) => LispExpr::List(ls.iter().map(|a| apply_quote(a)).collect::<Vec<_>>()), | ||
226 | _ => arg.clone(), | ||
224 | } | 227 | } |
225 | } | 228 | } |
226 | 229 | ||
@@ -313,12 +316,28 @@ mod tests { | |||
313 | assert!(run("(eq? '(1 2 3) '(1 2 3))", app).cast_bool()); | 316 | assert!(run("(eq? '(1 2 3) '(1 2 3))", app).cast_bool()); |
314 | assert!(run("(eq? '(1 '(1 2 3)) '(1 '(1 2 3)))", app).cast_bool(),); | 317 | assert!(run("(eq? '(1 '(1 2 3)) '(1 '(1 2 3)))", app).cast_bool(),); |
315 | assert!(run("(eq? '#t '#t)", app).cast_bool()); | 318 | assert!(run("(eq? '#t '#t)", app).cast_bool()); |
319 | |||
320 | assert!(run("(eq? 1 '1)", app).cast_bool()); | ||
321 | assert_eq!( | ||
322 | run("'(1 2 3)", app), | ||
323 | LispExpr::List( | ||
324 | vec![1, 2, 3] | ||
325 | .into_iter() | ||
326 | .map(LispNumber::Integer) | ||
327 | .map(LispExpr::Number) | ||
328 | .collect() | ||
329 | ), | ||
330 | ); | ||
331 | assert_eq!( | ||
332 | run("(caar (cdr '(1 (4 5))))", app), | ||
333 | LispExpr::Number(LispNumber::Integer(4)) | ||
334 | ); | ||
316 | } | 335 | } |
317 | 336 | ||
318 | fn eval_logical(app: &mut AppState) { | 337 | fn eval_logical(app: &mut AppState) { |
319 | assert!(run("(and #t #t)", app).cast_bool()); | 338 | assert!(run("(and #t #t)", app).cast_bool()); |
320 | assert!(run("(or #f #t)", app).cast_bool()); | 339 | assert!(run("(or #f #t)", app).cast_bool()); |
321 | assert!(run("(not #t)", app).cast_bool()); | 340 | assert!(!run("(not #t)", app).cast_bool()); |
322 | assert_eq!(run("(not #f)", app), run("(not (not #t))", app)); | 341 | assert_eq!(run("(not #f)", app), run("(not (not #t))", app)); |
323 | } | 342 | } |
324 | } | 343 | } |