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.rs37
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
218pub fn quote_var(args: &[LispExpr]) -> Result<LispExpr, LispError> { 218pub 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}