diff options
Diffstat (limited to 'src/lisp/prelude.rs')
-rw-r--r-- | src/lisp/prelude.rs | 57 |
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 | } |