aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lisp/eval.rs37
-rw-r--r--src/lisp/std.lisp7
2 files changed, 31 insertions, 13 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}
diff --git a/src/lisp/std.lisp b/src/lisp/std.lisp
index 8350482..d54b32c 100644
--- a/src/lisp/std.lisp
+++ b/src/lisp/std.lisp
@@ -36,10 +36,9 @@
36 (filter pred (cdr ls))))) 36 (filter pred (cdr ls)))))
37 37
38(define (member? item ls) 38(define (member? item ls)
39 (if (null? ls) 39 (fold #f
40 #f 40 (lambda (acc x) (or acc (eq? item x)))
41 (or (eq? item (car ls)) 41 ls))
42 (member? item (cdr ls)))))
43 42
44(define (assert expr) 43(define (assert expr)
45 (assert-eq #t expr)) 44 (assert-eq #t expr))