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.rs46
1 files changed, 34 insertions, 12 deletions
diff --git a/src/lisp/prelude.rs b/src/lisp/prelude.rs
index 372bb00..add405c 100644
--- a/src/lisp/prelude.rs
+++ b/src/lisp/prelude.rs
@@ -153,8 +153,11 @@ pub fn new_env() -> Result<Environment, LispError> {
153 (LispExpr::Unit, LispExpr::Unit) => Ok(true), 153 (LispExpr::Unit, LispExpr::Unit) => Ok(true),
154 (LispExpr::Number(s), LispExpr::Number(o)) => Ok(s == o), 154 (LispExpr::Number(s), LispExpr::Number(o)) => Ok(s == o),
155 (LispExpr::List(s), LispExpr::List(o)) => Ok(s.iter().zip(o).all(|(a, b)| a == b)), 155 (LispExpr::List(s), LispExpr::List(o)) => Ok(s.iter().zip(o).all(|(a, b)| a == b)),
156 (LispExpr::DottedList(s), LispExpr::DottedList(o)) => Ok(s.iter().zip(o).all(|(a, b)| a == b)),
156 (LispExpr::List(s), LispExpr::Unit) => Ok(s.len() == 0), 157 (LispExpr::List(s), LispExpr::Unit) => Ok(s.len() == 0),
157 (LispExpr::Unit, LispExpr::List(s)) => Ok(s.len() == 0), 158 (LispExpr::Unit, LispExpr::List(s)) => Ok(s.len() == 0),
159 (LispExpr::DottedList(_), LispExpr::Unit) => Ok(false),
160 (LispExpr::Unit, LispExpr::DottedList(_)) => Ok(false),
158 (LispExpr::StringLit(s), LispExpr::StringLit(o)) => Ok(s == o), 161 (LispExpr::StringLit(s), LispExpr::StringLit(o)) => Ok(s == o),
159 (LispExpr::Char(s), LispExpr::Char(o)) => Ok(s == o), 162 (LispExpr::Char(s), LispExpr::Char(o)) => Ok(s == o),
160 (LispExpr::BoolLit(s), LispExpr::BoolLit(o)) => Ok(s == o), 163 (LispExpr::BoolLit(s), LispExpr::BoolLit(o)) => Ok(s == o),
@@ -244,18 +247,6 @@ pub fn new_env() -> Result<Environment, LispError> {
244 } 247 }
245 }); 248 });
246 249
247 primitive!(env, Arity::Exact(2), "cons", |args, _| {
248 if type_match!(args, 1 => LispExpr::Unit) {
249 return Ok(LispExpr::List(vec![args[0].clone()]));
250 } else if !type_match!(args, 1 => LispExpr::List(_)) {
251 return Ok(LispExpr::List(vec![args[0].clone(), args[1].clone()]));
252 } else {
253 let mut rest = args[1].unwrap_list();
254 rest.insert(0, args[0].clone());
255 return Ok(LispExpr::List(rest));
256 }
257 });
258
259 primitive!(env, Arity::Exact(0), "grid-enabled?", |_, app| { 250 primitive!(env, Arity::Exact(0), "grid-enabled?", |_, app| {
260 Ok(LispExpr::BoolLit(app.grid.enabled)) 251 Ok(LispExpr::BoolLit(app.grid.enabled))
261 }); 252 });
@@ -285,9 +276,30 @@ pub fn new_env() -> Result<Environment, LispError> {
285 return Ok(LispExpr::Unit); 276 return Ok(LispExpr::Unit);
286 }); 277 });
287 278
279 primitive!(env, Arity::Exact(2), "cons", |args, _| {
280 if type_match!(args, 1 => LispExpr::Unit) {
281 return Ok(LispExpr::List(vec![args[0].clone()]));
282 } else if type_match!(args, 1 => LispExpr::DottedList(_)) {
283 // cons of anything to an improper list is an improper list
284 let mut rest = args[1].unwrap_dotted_list();
285 rest.insert(0, args[0].clone());
286 return Ok(LispExpr::DottedList(rest));
287 } else if type_match!(args, 1 => LispExpr::List(_)) {
288 // cons of anything to a proper list is a proper list
289 let mut rest = args[1].unwrap_list();
290 rest.insert(0, args[0].clone());
291 return Ok(LispExpr::List(rest));
292 } else {
293 // attempt to cons non-lists
294 return Ok(LispExpr::DottedList(vec![args[0].clone(), args[1].clone()]));
295 }
296 });
297
288 primitive!(env, Arity::Exact(1), "car", |args, _| { 298 primitive!(env, Arity::Exact(1), "car", |args, _| {
289 if type_match!(args, 0 => LispExpr::List(_)) { 299 if type_match!(args, 0 => LispExpr::List(_)) {
290 return Ok(args[0].unwrap_list().swap_remove(0)); 300 return Ok(args[0].unwrap_list().swap_remove(0));
301 } else if type_match!(args, 0 => LispExpr::DottedList(_)) {
302 return Ok(args[0].unwrap_dotted_list().swap_remove(0));
291 } else if type_match!(args, 0 => LispExpr::Unit) { 303 } else if type_match!(args, 0 => LispExpr::Unit) {
292 return Err(EvalError::AccessEmptyList.into()); 304 return Err(EvalError::AccessEmptyList.into());
293 } else { 305 } else {
@@ -297,6 +309,7 @@ pub fn new_env() -> Result<Environment, LispError> {
297 309
298 primitive!(env, Arity::Exact(1), "cdr", |args, _| { 310 primitive!(env, Arity::Exact(1), "cdr", |args, _| {
299 if type_match!(args, 0 => LispExpr::List(_)) { 311 if type_match!(args, 0 => LispExpr::List(_)) {
312 // cdr of a proper list is a proper list
300 let mut ls = args[0].unwrap_list(); 313 let mut ls = args[0].unwrap_list();
301 if ls.len() == 0 { 314 if ls.len() == 0 {
302 return Err(EvalError::AccessEmptyList.into()); 315 return Err(EvalError::AccessEmptyList.into());
@@ -306,6 +319,15 @@ pub fn new_env() -> Result<Environment, LispError> {
306 ls.remove(0); 319 ls.remove(0);
307 return Ok(LispExpr::List(ls)); 320 return Ok(LispExpr::List(ls));
308 } 321 }
322 } else if type_match!(args, 0 => LispExpr::DottedList(_)){
323 // cdr of an improper list is an improper list or an atom
324 let ls = args[0].unwrap_dotted_list();
325 if ls.len() == 2 {
326 return Ok(ls.into_iter().last().unwrap());
327 } else {
328 // should be unreachable
329 return Err(EvalError::AccessEmptyList.into());
330 }
309 } else if type_match!(args, 0 => LispExpr::Unit) { 331 } else if type_match!(args, 0 => LispExpr::Unit) {
310 return Err(EvalError::AccessEmptyList.into()); 332 return Err(EvalError::AccessEmptyList.into());
311 } else { 333 } else {