aboutsummaryrefslogtreecommitdiff
path: root/src/lisp/prelude.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lisp/prelude.rs')
-rw-r--r--src/lisp/prelude.rs57
1 files changed, 22 insertions, 35 deletions
diff --git a/src/lisp/prelude.rs b/src/lisp/prelude.rs
index dffd9f4..27e7ad2 100644
--- a/src/lisp/prelude.rs
+++ b/src/lisp/prelude.rs
@@ -2,7 +2,7 @@ use crate::{
2 brush::Brush, 2 brush::Brush,
3 lisp::{ 3 lisp::{
4 error::{EvalError, LispError}, 4 error::{EvalError, LispError},
5 eval::eval, 5 eval::Evaluator,
6 expr::{Arity, LispExpr}, 6 expr::{Arity, LispExpr},
7 number::LispNumber, 7 number::LispNumber,
8 Environment, 8 Environment,
@@ -21,6 +21,7 @@ macro_rules! primitive {
21 let val = crate::lisp::expr::LispExpr::PrimitiveFunc(crate::lisp::expr::PrimitiveFunc { 21 let val = crate::lisp::expr::LispExpr::PrimitiveFunc(crate::lisp::expr::PrimitiveFunc {
22 arity: $arity, 22 arity: $arity,
23 closure: $closure, 23 closure: $closure,
24 name: $name,
24 }); 25 });
25 let _ = $env.insert($name.to_string(), val); 26 let _ = $env.insert($name.to_string(), val);
26 }; 27 };
@@ -241,41 +242,15 @@ pub fn new_env() -> Result<Environment, LispError> {
241 return Ok(LispExpr::Unit); 242 return Ok(LispExpr::Unit);
242 }); 243 });
243 244
244 primitive!(env, Arity::Exact(2), "map", |args, app| { 245 primitive!(env, Arity::Exact(2), "cons", |args, _| {
245 let mut apply_map = 246 if type_match!(args, 1 => LispExpr::Unit) {
246 |func: &LispExpr, ls: &Vec<LispExpr>| -> Result<Vec<LispExpr>, LispError> { 247 return Ok(LispExpr::List(vec![args[0].clone()]));
247 ls.into_iter() 248 } else if !type_match!(args, 1 => LispExpr::List(_)) {
248 .map(|arg| eval(&LispExpr::List(vec![func.clone(), arg.clone()]), app)) 249 return Ok(LispExpr::List(vec![args[0].clone(), args[1].clone()]));
249 .collect()
250 };
251 if matches!(&args[0], LispExpr::Function(_) | LispExpr::PrimitiveFunc(_)) {
252 match &args[1] {
253 LispExpr::List(ls) => return Ok(LispExpr::List(apply_map(&args[0], ls)?)),
254 _ => return Err(EvalError::TypeMismatch.into()),
255 }
256 } else {
257 return Err(EvalError::TypeMismatch.into());
258 }
259 });
260
261 primitive!(env, Arity::Exact(2), "filter", |args, app| {
262 let mut apply_filter =
263 |func: &LispExpr, ls: &Vec<LispExpr>| -> Result<Vec<LispExpr>, LispError> {
264 let mut result = vec![];
265 for arg in ls.into_iter() {
266 if eval(&LispExpr::List(vec![func.clone(), arg.clone()]), app)?.cast_bool() {
267 result.push(arg.clone())
268 }
269 }
270 Ok(result)
271 };
272 if matches!(&args[0], LispExpr::Function(_) | LispExpr::PrimitiveFunc(_)) {
273 match &args[1] {
274 LispExpr::List(ls) => return Ok(LispExpr::List(apply_filter(&args[0], ls)?)),
275 _ => return Err(EvalError::TypeMismatch.into()),
276 }
277 } else { 250 } else {
278 return Err(EvalError::TypeMismatch.into()); 251 let mut rest = args[1].unwrap_list();
252 rest.insert(0, args[0].clone());
253 return Ok(LispExpr::List(rest));
279 } 254 }
280 }); 255 });
281 256
@@ -332,5 +307,17 @@ pub fn new_env() -> Result<Environment, LispError> {
332 } 307 }
333 }); 308 });
334 309
310 primitive!(env, Arity::Exact(2), "assert-eq", |args, app| {
311 if args[0].compare(&args[1], &app.lisp_env)? {
312 return Ok(LispExpr::Unit);
313 } else {
314 return Err(EvalError::AssertionError {
315 expected: args[0].clone(),
316 got: args[1].clone(),
317 }
318 .into());
319 }
320 });
321
335 Ok(env) 322 Ok(env)
336} 323}