1use std::time::{SystemTime, UNIX_EPOCH, Duration};
2use crate::lisp::{
3 add_builtin, eval, to_num, to_qexpr, to_str, to_sym, Lenv, Lerr, LerrType, Llambda, Lval,
4};
5
6pub fn init_builtins(env: &mut Lenv) {
7 add_builtin(env, "!", builtin_not);
8 add_builtin(env, "+", builtin_add);
9 add_builtin(env, "-", builtin_sub);
10 add_builtin(env, "*", builtin_mul);
11 add_builtin(env, "/", builtin_div);
12 add_builtin(env, "%", builtin_mod);
13
14 add_builtin(env, "head", builtin_head);
15 add_builtin(env, "tail", builtin_tail);
16 add_builtin(env, "list", builtin_list);
17 add_builtin(env, "eval", builtin_eval);
18 add_builtin(env, "join", builtin_join);
19 add_builtin(env, "concat", builtin_concat);
20
21 add_builtin(env, "\\", builtin_lambda);
22 add_builtin(env, "def", builtin_def);
23 add_builtin(env, "=", builtin_var);
24
25 add_builtin(env, "if", builtin_if);
26 add_builtin(env, "echo", builtin_echo);
27 add_builtin(env, "rand", builtin_rand);
28
29 add_builtin(env, "die", builtin_err);
30
31 add_builtin(env, "<", builtin_lt);
32 add_builtin(env, ">", builtin_gt);
33 add_builtin(env, ">=", builtin_gte);
34 add_builtin(env, "<=", builtin_lte);
35 add_builtin(env, "==", builtin_eq);
36 add_builtin(env, "!=", builtin_ne);
37 add_builtin(env, "&&", builtin_and);
38 add_builtin(env, "||", builtin_or);
39}
40
41fn builtin_op(sym: &str, operands: Vec<Lval>) -> Result<Lval, Lerr> {
42 let numbers = operands
44 .into_iter()
45 .map(to_num)
46 .collect::<Option<Vec<f64>>>()
47 .ok_or(Lerr::new(
48 LerrType::BadNum,
49 format!("Function {} can operate only on numbers", sym),
50 ))?;
51
52 if numbers.len() == 1 {
54 if "-" == sym {
55 return Ok(Lval::Num(-numbers[0]));
56 } else if "!" == sym {
57 let n = if numbers[0] == 0_f64 { 1_f64 } else { 0_f64 };
58 return Ok(Lval::Num(n));
59 } else {
60 return Ok(Lval::Num(numbers[0]));
61 }
62 }
63
64 let mut x = numbers[0];
65 let mut i = 1;
66
67 while i < numbers.len() {
69 let y = numbers[i];
70 match sym {
71 "-" => x -= y,
72 "*" => x *= y,
73 "%" => x %= y,
74 "/" => {
75 if y == 0_f64 {
76 return Err(Lerr::new(
77 LerrType::DivZero,
78 format!("You cannot divide {}, or any number, by 0", x),
79 ));
80 } else {
81 x /= y;
82 }
83 }
84 _ => x += y,
85 }
86 i += 1;
87 }
88
89 Ok(Lval::Num(x))
90}
91
92fn builtin_ord(sym: &str, operands: Vec<Lval>) -> Result<Lval, Lerr> {
93 if operands.len() != 2 {
95 return Err(Lerr::new(
96 LerrType::IncorrectParamCount,
97 format!(
98 "Function {} needed 2 args but was given {}",
99 sym,
100 operands.len()
101 ),
102 ));
103 }
104
105 let numbers = operands
107 .into_iter()
108 .map(to_num)
109 .collect::<Option<Vec<f64>>>()
110 .ok_or(Lerr::new(
111 LerrType::BadNum,
112 format!("Function {} can operate only on numbers", sym),
113 ))?;
114
115 let x = numbers[0];
116 let y = numbers[1];
117
118 let a = if x == 0_f64 { false } else { true };
120 let b = if y == 0_f64 { false } else { true };
121
122 let r = match sym {
123 ">" => x > y,
124 "<" => x < y,
125 ">=" => x >= y,
126 "<=" => x <= y,
127 "&&" => a && b,
128 "||" => a || b,
129 _ => false,
130 };
131
132 if r {
133 Ok(Lval::Num(1_f64))
134 } else {
135 Ok(Lval::Num(0_f64))
136 }
137}
138
139fn builtin_eq(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
140 if operands.len() != 2 {
142 return Err(Lerr::new(
143 LerrType::IncorrectParamCount,
144 format!("Function eq needed 2 arg but was given {}", operands.len()),
145 ));
146 }
147
148 if operands[0] == operands[1] {
149 Ok(Lval::Num(1_f64))
150 } else {
151 Ok(Lval::Num(0_f64))
152 }
153}
154
155fn builtin_ne(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
156 if operands.len() != 2 {
158 return Err(Lerr::new(
159 LerrType::IncorrectParamCount,
160 format!("Function eq needed 2 arg but was given {}", operands.len()),
161 ));
162 }
163
164 if operands[0] == operands[1] {
165 Ok(Lval::Num(0_f64))
166 } else {
167 Ok(Lval::Num(1_f64))
168 }
169}
170
171fn builtin_gt(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
172 builtin_ord(">", operands)
173}
174
175fn builtin_lt(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
176 builtin_ord("<", operands)
177}
178
179fn builtin_gte(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
180 builtin_ord(">=", operands)
181}
182
183fn builtin_lte(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
184 builtin_ord("<=", operands)
185}
186
187fn builtin_and(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
188 builtin_ord("&&", operands)
189}
190
191fn builtin_or(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
192 builtin_ord("||", operands)
193}
194
195fn builtin_not(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
196 builtin_op("!", operands)
197}
198
199fn builtin_add(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
200 builtin_op("+", operands)
201}
202
203fn builtin_sub(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
204 builtin_op("-", operands)
205}
206
207fn builtin_mul(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
208 builtin_op("*", operands)
209}
210
211fn builtin_mod(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
212 builtin_op("%", operands)
213}
214
215fn builtin_div(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
216 builtin_op("/", operands)
217}
218
219fn builtin_rand(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
220 if operands.len() != 0 {
221 return Err(Lerr::new(
222 LerrType::IncorrectParamCount,
223 format!("Function if needed 0 arg but was given {}", operands.len()),
224 ));
225 }
226
227 let nanos = SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or(Duration::from_nanos(12345)).subsec_nanos();
228 Ok(Lval::Num(nanos as f64))
229}
230
231fn builtin_if(env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
232 if operands.len() != 3 {
233 return Err(Lerr::new(
234 LerrType::IncorrectParamCount,
235 format!("Function if needed 3 arg but was given {}", operands.len()),
236 ));
237 }
238
239 let conditional = to_num(operands[0].clone()).ok_or(Lerr::new(
240 LerrType::WrongType,
241 format!(
242 "Function if needed conditional but was given {:?}",
243 operands[0]
244 ),
245 ))?;
246
247 let then = to_qexpr(operands[1].clone()).ok_or(Lerr::new(
248 LerrType::WrongType,
249 format!(
250 "Function if needed qexpr for Then but was given {:?}",
251 operands[1]
252 ),
253 ))?;
254
255 let els = to_qexpr(operands[2].clone()).ok_or(Lerr::new(
256 LerrType::WrongType,
257 format!(
258 "Function if needed qexpr for Else but was given {:?}",
259 operands[2]
260 ),
261 ))?;
262
263 if conditional == 0_f64 {
264 eval::eval(env, Lval::Sexpr(els))
265 } else {
266 eval::eval(env, Lval::Sexpr(then))
267 }
268}
269
270fn builtin_err(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
271 let err = to_str(operands[0].clone()).ok_or(Lerr::new(
272 LerrType::WrongType,
273 format!(
274 "Function die needed qexpr for Else but was given {:?}",
275 operands[0]
276 ),
277 ))?;
278
279 Err(Lerr::new(LerrType::Interrupt, err))
280}
281
282fn builtin_head(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
283 if operands.len() != 1 {
285 return Err(Lerr::new(
286 LerrType::IncorrectParamCount,
287 format!(
288 "Function head needed 1 arg but was given {}",
289 operands.len()
290 ),
291 ));
292 }
293
294 let arg = &operands[0];
295 match arg {
297 Lval::Qexpr(qexpr) => {
298 if qexpr.len() == 0 {
299 Err(Lerr::new(
300 LerrType::EmptyList,
301 format!("Function head was given empty list"),
302 ))
303 } else {
304 Ok(qexpr[0].clone())
305 }
306 }
307 _ => Err(Lerr::new(
308 LerrType::WrongType,
309 format!("Function head needed Qexpr but was given {:?}", arg),
310 )),
311 }
312}
313
314fn builtin_tail(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
315 if operands.len() != 1 {
317 return Err(Lerr::new(
318 LerrType::IncorrectParamCount,
319 format!(
320 "Function tail needed 1 arg but was given {}",
321 operands.len()
322 ),
323 ));
324 }
325
326 let arg = &operands[0];
327 match arg {
329 Lval::Qexpr(qexpr) => {
330 if qexpr.len() == 0 {
331 Err(Lerr::new(
332 LerrType::EmptyList,
333 format!("Function tail was given empty list"),
334 ))
335 } else {
336 Ok(Lval::Qexpr(qexpr[1..].to_vec()))
337 }
338 }
339 _ => Err(Lerr::new(
340 LerrType::WrongType,
341 format!("Function tail needed Qexpr but was given {:?}", arg),
342 )),
343 }
344}
345
346fn builtin_list(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
347 Ok(Lval::Qexpr(operands))
348}
349
350fn builtin_eval(env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
351 if operands.len() != 1 {
353 return Err(Lerr::new(
354 LerrType::IncorrectParamCount,
355 format!(
356 "Function eval needed 1 arg but was given {}",
357 operands.len()
358 ),
359 ));
360 }
361
362 let arg = &operands[0];
363 match arg {
364 Lval::Qexpr(qexpr) => eval::eval(env, Lval::Sexpr(qexpr[..].to_vec())),
365 _ => eval::eval(env, arg.clone()),
366 }
367}
368
369fn builtin_echo(env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
370 if operands.len() != 1 {
372 return Err(Lerr::new(
373 LerrType::IncorrectParamCount,
374 format!(
375 "Function echo needed 1 arg but was given {}",
376 operands.len()
377 ),
378 ));
379 }
380
381 let arg = &operands[0];
382 Ok(Lval::Str(format!("\"{:?}\"", arg)))
383}
384
385fn builtin_join(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
386 if operands.len() < 2 {
388 return Err(Lerr::new(
389 LerrType::IncorrectParamCount,
390 format!(
391 "Function join needed 2 arg but was given {}",
392 operands.len()
393 ),
394 ));
395 }
396
397 let qexprs = operands
399 .into_iter()
400 .map(to_qexpr)
401 .collect::<Option<Vec<_>>>()
402 .ok_or(Lerr::new(
403 LerrType::WrongType,
404 format!("Function join needed Qexpr but was given"),
405 ))?;
406
407 let mut joined = vec![];
409 for qexp in qexprs {
410 for item in qexp {
411 joined.push(item);
412 }
413 }
414
415 Ok(Lval::Qexpr(joined))
416}
417
418fn builtin_concat(_env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
419 if operands.len() < 1 {
421 return Err(Lerr::new(
422 LerrType::IncorrectParamCount,
423 format!(
424 "Function concat needed >= 1 arg but was given {}",
425 operands.len()
426 ),
427 ));
428 }
429
430 let strings = operands
432 .into_iter()
433 .map(to_str)
434 .collect::<Option<Vec<_>>>()
435 .ok_or(Lerr::new(
436 LerrType::WrongType,
437 format!("Function concat needed Strings but was given"),
438 ))?;
439
440 let mut concatted = String::from("");
442 for string in strings {
443 concatted = format!("{}{}", concatted, string);
444 }
445
446 Ok(Lval::Str(concatted))
447}
448
449fn builtin_def(env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
450 builtin_assign("def", env, operands)
451}
452
453fn builtin_var(env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
454 builtin_assign("=", env, operands)
455}
456
457fn builtin_assign(sym: &str, env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
458 if operands.len() < 2 {
460 return Err(Lerr::new(
461 LerrType::IncorrectParamCount,
462 format!(
463 "Function def needed 2 args but was given {}",
464 operands.len()
465 ),
466 ));
467 }
468
469 let args = operands[0].clone();
470
471 let args = to_qexpr(args)
473 .ok_or(Lerr::new(
474 LerrType::WrongType,
475 format!("Function def needed Qexpr but was given {:?}", operands[0]),
476 ))?
477 .into_iter()
478 .map(to_sym)
479 .collect::<Option<Vec<String>>>()
480 .ok_or(Lerr::new(
481 LerrType::WrongType,
482 format!("Function def needed a param list of all Symbols"),
483 ))?;
484
485 if args.len() != operands.len() - 1 {
487 return Err(Lerr::new(
488 LerrType::IncorrectParamCount,
489 format!(
490 "Function def needed to assign {} values but was passed {}",
491 args.len(),
492 operands.len() - 1
493 ),
494 ));
495 }
496
497 for (i, arg) in args.into_iter().enumerate() {
499 if sym == "def" {
500 env.insert_last(&arg, operands[i + 1].clone());
501 } else {
502 env.insert(&arg, operands[i + 1].clone());
503 }
504 }
505
506 Ok(Lval::Str(String::from("")))
507}
508
509fn builtin_lambda(env: &mut Lenv, operands: Vec<Lval>) -> Result<Lval, Lerr> {
510 if operands.len() != 2 {
511 return Err(Lerr::new(
512 LerrType::IncorrectParamCount,
513 format!("Function \\ needed 2 arg but was given {}", operands.len()),
514 ));
515 }
516
517 let results = operands
519 .into_iter()
520 .map(to_qexpr)
521 .collect::<Option<Vec<_>>>()
522 .ok_or(Lerr::new(
523 LerrType::WrongType,
524 format!("Function \\ needed a Qexpr for arguments and a Qexpr for body"),
525 ))?;
526
527 let args = results[0].clone();
528 let args = args
530 .into_iter()
531 .map(to_sym)
532 .collect::<Option<Vec<String>>>()
533 .ok_or(Lerr::new(
534 LerrType::WrongType,
535 format!("Function \\ needed a param list of all Symbols"),
536 ))?;
537
538 let body = results[1].clone();
539 let new_env = env.peek().unwrap().clone();
540 let lambda = Llambda::new(args, body, new_env);
541
542 Ok(Lval::Lambda(lambda))
543}
544
545#[cfg(test)]
546mod tests {
547 use super::*;
548 use crate::lisp::{env::init_env, to_lambda};
549
550 fn empty_fun(_env: &mut Lenv, _operands: Vec<Lval>) -> Result<Lval, Lerr> {
551 Ok(Lval::Sexpr(vec![]))
552 }
553
554 #[test]
555 fn it_correctly_uses_head() {
556 let env = &mut init_env();
557 let expr = Lval::Qexpr(vec![
558 Lval::Sym(String::from("+")),
559 Lval::Num(1_f64),
560 Lval::Sexpr(vec![
561 Lval::Sym(String::from("+")),
562 Lval::Num(1_f64),
563 Lval::Num(1_f64),
564 ]),
565 ]);
566 assert_eq!(
567 builtin_head(env, vec![expr.clone()]).unwrap(),
568 Lval::Sym(String::from("+"))
569 );
570
571 let _ = builtin_head(env, vec![])
572 .map_err(|err| assert_eq!(err.etype, LerrType::IncorrectParamCount));
573
574 let _ = builtin_head(env, vec![Lval::Sym(String::from("+"))])
575 .map_err(|err| assert_eq!(err.etype, LerrType::WrongType));
576
577 let _ = builtin_head(env, vec![Lval::Qexpr(vec![])])
578 .map_err(|err| assert_eq!(err.etype, LerrType::EmptyList));
579 }
580
581 #[test]
582 fn it_correctly_uses_tail() {
583 let env = &mut init_env();
584 let expr = Lval::Qexpr(vec![
585 Lval::Sym(String::from("+")),
586 Lval::Num(1_f64),
587 Lval::Sexpr(vec![
588 Lval::Sym(String::from("+")),
589 Lval::Num(1_f64),
590 Lval::Num(1_f64),
591 ]),
592 ]);
593 assert_eq!(
594 builtin_tail(env, vec![expr.clone()]).unwrap(),
595 Lval::Qexpr(vec![
596 Lval::Num(1_f64),
597 Lval::Sexpr(vec![
598 Lval::Sym(String::from("+")),
599 Lval::Num(1_f64),
600 Lval::Num(1_f64),
601 ])
602 ])
603 );
604 let _ = builtin_tail(env, vec![])
605 .map_err(|err| assert_eq!(err.etype, LerrType::IncorrectParamCount));
606
607 let _ = builtin_tail(env, vec![Lval::Sym(String::from("+"))])
608 .map_err(|err| assert_eq!(err.etype, LerrType::WrongType));
609
610 let _ = builtin_tail(env, vec![Lval::Qexpr(vec![])])
611 .map_err(|err| assert_eq!(err.etype, LerrType::EmptyList));
612 }
613
614 #[test]
615 fn it_correctly_uses_list() {
616 let env = &mut init_env();
617 let expr = vec![
618 Lval::Sym(String::from("+")),
619 Lval::Num(1_f64),
620 Lval::Sexpr(vec![
621 Lval::Sym(String::from("+")),
622 Lval::Num(1_f64),
623 Lval::Num(1_f64),
624 ]),
625 ];
626 assert_eq!(
627 builtin_list(env, expr.clone()).unwrap(),
628 Lval::Qexpr(vec![
629 Lval::Sym(String::from("+")),
630 Lval::Num(1_f64),
631 Lval::Sexpr(vec![
632 Lval::Sym(String::from("+")),
633 Lval::Num(1_f64),
634 Lval::Num(1_f64),
635 ])
636 ])
637 );
638 assert_eq!(
639 builtin_list(
640 env,
641 vec![
642 Lval::Sym(String::from("+")),
643 Lval::Num(1_f64),
644 Lval::Num(1_f64),
645 ]
646 )
647 .unwrap(),
648 Lval::Qexpr(vec![
649 Lval::Sym(String::from("+")),
650 Lval::Num(1_f64),
651 Lval::Num(1_f64),
652 ])
653 );
654 assert_eq!(builtin_list(env, vec![]).unwrap(), Lval::Qexpr(vec![]));
655 assert_eq!(
656 builtin_list(env, vec![Lval::Sym(String::from("+"))]).unwrap(),
657 Lval::Qexpr(vec![Lval::Sym(String::from("+")),])
658 );
659 assert_eq!(
660 builtin_list(env, vec![Lval::Sexpr(vec![])]).unwrap(),
661 Lval::Qexpr(vec![Lval::Sexpr(vec![]),])
662 );
663 }
664
665 #[test]
666 fn it_correctly_uses_eval() {
667 let env = &mut init_env();
668 let expr = Lval::Qexpr(vec![
669 Lval::Sym(String::from("+")),
670 Lval::Num(1_f64),
671 Lval::Sexpr(vec![
672 Lval::Sym(String::from("+")),
673 Lval::Num(1_f64),
674 Lval::Num(1_f64),
675 ]),
676 ]);
677 assert_eq!(
678 builtin_eval(env, vec![expr.clone()]).unwrap(),
679 Lval::Num(3_f64)
680 );
681
682 let _ = builtin_eval(env, vec![expr.clone(), expr.clone()])
683 .map_err(|err| assert_eq!(err.etype, LerrType::IncorrectParamCount));
684
685 let _ = builtin_eval(env, vec![])
686 .map_err(|err| assert_eq!(err.etype, LerrType::IncorrectParamCount));
687
688 assert_eq!(
689 builtin_eval(env, vec![Lval::Sym(String::from("-"))]).unwrap(),
690 Lval::Fun(empty_fun)
691 );
692 assert_eq!(
693 builtin_eval(env, vec![Lval::Sexpr(vec![Lval::Sym(String::from("-"))])]).unwrap(),
694 Lval::Fun(empty_fun)
695 );
696 assert_eq!(
697 builtin_eval(env, vec![Lval::Qexpr(vec![])]).unwrap(),
698 Lval::Sexpr(vec![])
699 );
700 }
701
702 #[test]
703 fn it_correctly_uses_join() {
704 let env = &mut init_env();
705 let expr = Lval::Qexpr(vec![
706 Lval::Sym(String::from("+")),
707 Lval::Num(1_f64),
708 Lval::Sexpr(vec![
709 Lval::Sym(String::from("+")),
710 Lval::Num(1_f64),
711 Lval::Num(1_f64),
712 ]),
713 ]);
714 assert_eq!(
715 builtin_join(env, vec![expr.clone(), expr.clone()]).unwrap(),
716 Lval::Qexpr(vec![
717 Lval::Sym(String::from("+")),
718 Lval::Num(1_f64),
719 Lval::Sexpr(vec![
720 Lval::Sym(String::from("+")),
721 Lval::Num(1_f64),
722 Lval::Num(1_f64),
723 ]),
724 Lval::Sym(String::from("+")),
725 Lval::Num(1_f64),
726 Lval::Sexpr(vec![
727 Lval::Sym(String::from("+")),
728 Lval::Num(1_f64),
729 Lval::Num(1_f64),
730 ]),
731 ])
732 );
733
734 let _ = builtin_join(env, vec![expr.clone()])
735 .map_err(|err| assert_eq!(err.etype, LerrType::IncorrectParamCount));
736
737 let _ = builtin_join(env, vec![])
738 .map_err(|err| assert_eq!(err.etype, LerrType::IncorrectParamCount));
739
740 let _ = builtin_join(env, vec![expr.clone(), Lval::Sym(String::from("+"))])
741 .map_err(|err| assert_eq!(err.etype, LerrType::WrongType));
742
743 assert_eq!(
744 builtin_join(env, vec![expr.clone(), Lval::Qexpr(vec![])]).unwrap(),
745 Lval::Qexpr(vec![
746 Lval::Sym(String::from("+")),
747 Lval::Num(1_f64),
748 Lval::Sexpr(vec![
749 Lval::Sym(String::from("+")),
750 Lval::Num(1_f64),
751 Lval::Num(1_f64),
752 ]),
753 ])
754 );
755 }
756
757 #[test]
758 fn it_correctly_uses_concat() {
759 let env = &mut init_env();
760 assert_eq!(
761 builtin_concat(
762 env,
763 vec![
764 Lval::Str(String::from("ceci")),
765 Lval::Str(String::from(" n'est")),
766 Lval::Str(String::from(" pas")),
767 Lval::Str(String::from(" une")),
768 Lval::Str(String::from(" pipe"))
769 ]
770 )
771 .unwrap(),
772 Lval::Str(String::from("ceci n'est pas une pipe"))
773 );
774 }
775
776 #[test]
777 fn it_correctly_uses_define() {
778 let env = &mut init_env();
779 assert_eq!(
780 builtin_def(
781 env,
782 vec![
783 Lval::Qexpr(vec![
784 Lval::Sym(String::from("a")),
785 Lval::Sym(String::from("b")),
786 Lval::Sym(String::from("c"))
787 ]),
788 Lval::Num(1_f64),
789 Lval::Sym(String::from("+")),
790 Lval::Sexpr(vec![]),
791 ]
792 )
793 .unwrap(),
794 Lval::Sexpr(vec![])
795 );
796 assert_eq!(
797 crate::lisp::eval::eval(env, Lval::Sym(String::from("a"))).unwrap(),
798 Lval::Num(1_f64)
799 );
800 assert_eq!(
801 crate::lisp::eval::eval(env, Lval::Sym(String::from("b"))).unwrap(),
802 Lval::Sym(String::from("+"))
803 );
804 assert_eq!(
805 crate::lisp::eval::eval(env, Lval::Sym(String::from("c"))).unwrap(),
806 Lval::Sexpr(vec![])
807 );
808 let _ = builtin_def(
809 env,
810 vec![Lval::Qexpr(vec![
811 Lval::Sym(String::from("a")),
812 Lval::Sym(String::from("b")),
813 Lval::Sym(String::from("c")),
814 ])],
815 )
816 .map_err(|err| assert_eq!(err.etype, LerrType::IncorrectParamCount));
817
818 let _ = builtin_def(
819 env,
820 vec![
821 Lval::Qexpr(vec![
822 Lval::Sym(String::from("a")),
823 Lval::Sym(String::from("b")),
824 ]),
825 Lval::Num(1_f64),
826 Lval::Sym(String::from("+")),
827 Lval::Sym(String::from("+")),
828 ],
829 )
830 .map_err(|err| assert_eq!(err.etype, LerrType::IncorrectParamCount));
831 let _ = builtin_def(
832 env,
833 vec![Lval::Qexpr(vec![Lval::Num(1_f64)]), Lval::Num(1_f64)],
834 )
835 .map_err(|err| assert_eq!(err.etype, LerrType::WrongType));
836 }
837
838 #[test]
840 fn it_correctly_uses_lambda() {
841 let env = &mut init_env();
842 assert!(to_lambda(
843 &builtin_lambda(
844 env,
845 vec![
846 Lval::Qexpr(vec![
847 Lval::Sym(String::from("a")),
848 Lval::Sym(String::from("b")),
849 ]),
850 Lval::Qexpr(vec![
851 Lval::Sym(String::from("+")),
852 Lval::Sym(String::from("a")),
853 Lval::Sym(String::from("b")),
854 ]),
855 ]
856 )
857 .unwrap()
858 )
859 .is_some());
860
861 let expr = Lval::Sexpr(vec![
862 Lval::Sexpr(vec![
863 Lval::Sym(String::from("\\")),
864 Lval::Qexpr(vec![
865 Lval::Sym(String::from("a")),
866 Lval::Sym(String::from("b")),
867 ]),
868 Lval::Qexpr(vec![
869 Lval::Sym(String::from("+")),
870 Lval::Sym(String::from("a")),
871 Lval::Sym(String::from("b")),
872 ]),
873 ]),
874 Lval::Num(2_f64),
875 Lval::Num(2_f64),
876 ]);
877 assert_eq!(eval::eval(env, expr).unwrap(), Lval::Num(4_f64));
878 }
879
880 #[test]
881 fn it_correctly_uses_ord() {
882 let env = &mut init_env();
883 assert_eq!(
884 builtin_lt(env, vec![Lval::Num(1_f64), Lval::Num(2_f64)]).unwrap(),
885 Lval::Num(1_f64)
886 );
887 assert_eq!(
888 builtin_lt(env, vec![Lval::Num(2_f64), Lval::Num(1_f64)]).unwrap(),
889 Lval::Num(0_f64)
890 );
891
892 assert_eq!(
893 builtin_gt(env, vec![Lval::Num(1_f64), Lval::Num(2_f64)]).unwrap(),
894 Lval::Num(0_f64)
895 );
896 assert_eq!(
897 builtin_gt(env, vec![Lval::Num(2_f64), Lval::Num(1_f64)]).unwrap(),
898 Lval::Num(1_f64)
899 );
900
901 assert_eq!(
902 builtin_gte(env, vec![Lval::Num(1_f64), Lval::Num(2_f64)]).unwrap(),
903 Lval::Num(0_f64)
904 );
905 assert_eq!(
906 builtin_gte(env, vec![Lval::Num(2_f64), Lval::Num(1_f64)]).unwrap(),
907 Lval::Num(1_f64)
908 );
909 assert_eq!(
910 builtin_gte(env, vec![Lval::Num(2_f64), Lval::Num(2_f64)]).unwrap(),
911 Lval::Num(1_f64)
912 );
913
914 assert_eq!(
915 builtin_lte(env, vec![Lval::Num(1_f64), Lval::Num(2_f64)]).unwrap(),
916 Lval::Num(1_f64)
917 );
918 assert_eq!(
919 builtin_lte(env, vec![Lval::Num(2_f64), Lval::Num(1_f64)]).unwrap(),
920 Lval::Num(0_f64)
921 );
922 assert_eq!(
923 builtin_lte(env, vec![Lval::Num(2_f64), Lval::Num(2_f64)]).unwrap(),
924 Lval::Num(1_f64)
925 );
926 }
927
928 #[test]
929 fn it_correctly_uses_if() {
930 let env = &mut init_env();
931 assert_eq!(
932 builtin_if(
933 env,
934 vec![
935 Lval::Num(1_f64),
936 Lval::Qexpr(vec![Lval::Num(6_f64)]),
937 Lval::Qexpr(vec![Lval::Num(9_f64)])
938 ]
939 )
940 .unwrap(),
941 Lval::Num(6_f64)
942 );
943 assert_eq!(
944 builtin_if(
945 env,
946 vec![
947 Lval::Num(0_f64),
948 Lval::Qexpr(vec![Lval::Num(6_f64)]),
949 Lval::Qexpr(vec![Lval::Num(9_f64)])
950 ]
951 )
952 .unwrap(),
953 Lval::Num(9_f64)
954 );
955 }
956}