1use crate::scheme::value::Value;
26use crate::grove::{EmptyNodeList, Node};
27
28pub type PrimitiveResult = Result<Value, String>;
30
31pub fn prim_car(args: &[Value]) -> PrimitiveResult {
41 if args.len() != 1 {
42 return Err("car requires exactly 1 argument".to_string());
43 }
44
45 if let Value::Pair(ref p) = args[0] {
46 let pair = p.borrow();
47 Ok(pair.car.clone())
48 } else {
49 Err(format!("car: not a pair: {:?}", args[0]))
50 }
51}
52
53pub fn prim_cdr(args: &[Value]) -> PrimitiveResult {
59 if args.len() != 1 {
60 return Err("cdr requires exactly 1 argument".to_string());
61 }
62
63 if let Value::Pair(ref p) = args[0] {
64 let pair = p.borrow();
65 Ok(pair.cdr.clone())
66 } else {
67 Err(format!("cdr: not a pair: {:?}", args[0]))
68 }
69}
70
71pub fn prim_cons(args: &[Value]) -> PrimitiveResult {
77 if args.len() != 2 {
78 return Err("cons requires exactly 2 arguments".to_string());
79 }
80
81 Ok(Value::cons(args[0].clone(), args[1].clone()))
82}
83
84pub fn prim_list(args: &[Value]) -> PrimitiveResult {
90 let mut result = Value::Nil;
91 for arg in args.iter().rev() {
92 result = Value::cons(arg.clone(), result);
93 }
94 Ok(result)
95}
96
97pub fn prim_null_p(args: &[Value]) -> PrimitiveResult {
103 if args.len() != 1 {
104 return Err("null? requires exactly 1 argument".to_string());
105 }
106
107 Ok(Value::bool(args[0].is_nil()))
108}
109
110pub fn prim_pair_p(args: &[Value]) -> PrimitiveResult {
116 if args.len() != 1 {
117 return Err("pair? requires exactly 1 argument".to_string());
118 }
119
120 Ok(Value::bool(args[0].is_pair()))
121}
122
123pub fn prim_list_p(args: &[Value]) -> PrimitiveResult {
129 if args.len() != 1 {
130 return Err("list? requires exactly 1 argument".to_string());
131 }
132
133 Ok(Value::bool(args[0].is_list()))
134}
135
136pub fn prim_length(args: &[Value]) -> PrimitiveResult {
142 if args.len() != 1 {
143 return Err("length requires exactly 1 argument".to_string());
144 }
145
146 let mut len = 0;
147 let mut current = args[0].clone();
148
149 loop {
150 match current {
151 Value::Nil => break,
152 Value::Pair(ref p) => {
153 len += 1;
154 let pair = p.borrow();
155 let cdr = pair.cdr.clone();
156 drop(pair);
157 current = cdr;
158 }
159 _ => return Err("length: not a proper list".to_string()),
160 }
161 }
162
163 Ok(Value::integer(len))
164}
165
166pub fn prim_append(args: &[Value]) -> PrimitiveResult {
173 if args.is_empty() {
174 return Ok(Value::Nil);
175 }
176
177 if args.len() == 1 {
178 return Ok(args[0].clone());
179 }
180
181 let mut all_elements = Vec::new();
183
184 for i in 0..args.len() - 1 {
185 let mut current = args[i].clone();
186 loop {
187 match current {
188 Value::Nil => break,
189 Value::Pair(ref p) => {
190 let pair = p.borrow();
191 all_elements.push(pair.car.clone());
192 let cdr = pair.cdr.clone();
193 drop(pair);
194 current = cdr;
195 }
196 _ => return Err("append: not a proper list".to_string()),
197 }
198 }
199 }
200
201 let mut result = args[args.len() - 1].clone();
203 for elem in all_elements.iter().rev() {
204 result = Value::cons(elem.clone(), result);
205 }
206
207 Ok(result)
208}
209
210pub fn prim_reverse(args: &[Value]) -> PrimitiveResult {
216 if args.len() != 1 {
217 return Err("reverse requires exactly 1 argument".to_string());
218 }
219
220 let mut result = Value::Nil;
221 let mut current = args[0].clone();
222
223 loop {
224 match current {
225 Value::Nil => break,
226 Value::Pair(ref p) => {
227 let pair = p.borrow();
228 result = Value::cons(pair.car.clone(), result);
229 let cdr = pair.cdr.clone();
230 drop(pair);
231 current = cdr;
232 }
233 _ => return Err("reverse: not a proper list".to_string()),
234 }
235 }
236
237 Ok(result)
238}
239
240pub fn prim_list_tail(args: &[Value]) -> PrimitiveResult {
246 if args.len() != 2 {
247 return Err("list-tail requires exactly 2 arguments".to_string());
248 }
249
250 let k = match args[1] {
251 Value::Integer(n) if n >= 0 => n as usize,
252 _ => return Err("list-tail: second argument must be a non-negative integer".to_string()),
253 };
254
255 let mut current = args[0].clone();
256 for _ in 0..k {
257 match current {
258 Value::Pair(ref p) => {
259 let pair = p.borrow();
260 let cdr = pair.cdr.clone();
261 drop(pair);
262 current = cdr;
263 }
264 _ => return Err("list-tail: list too short".to_string()),
265 }
266 }
267
268 Ok(current)
269}
270
271pub fn prim_list_ref(args: &[Value]) -> PrimitiveResult {
277 if args.len() != 2 {
278 return Err("list-ref requires exactly 2 arguments".to_string());
279 }
280
281 let k = match args[1] {
282 Value::Integer(n) if n >= 0 => n as usize,
283 _ => return Err("list-ref: second argument must be a non-negative integer".to_string()),
284 };
285
286 let mut current = args[0].clone();
287 for _ in 0..k {
288 match current {
289 Value::Pair(ref p) => {
290 let pair = p.borrow();
291 let cdr = pair.cdr.clone();
292 drop(pair);
293 current = cdr;
294 }
295 _ => return Err("list-ref: list too short".to_string()),
296 }
297 }
298
299 match current {
300 Value::Pair(ref p) => {
301 let pair = p.borrow();
302 Ok(pair.car.clone())
303 }
304 _ => Err("list-ref: index out of bounds".to_string()),
305 }
306}
307
308pub fn prim_add(args: &[Value]) -> PrimitiveResult {
318 let mut int_sum = 0i64;
319 let mut real_sum = 0.0f64;
320 let mut has_real = false;
321
322 for arg in args {
323 match arg {
324 Value::Integer(n) => {
325 int_sum += n;
326 real_sum += *n as f64;
327 }
328 Value::Real(r) => {
329 has_real = true;
330 real_sum += r;
331 }
332 _ => return Err(format!("+: not a number: {:?}", arg)),
333 }
334 }
335
336 if has_real {
337 Ok(Value::real(real_sum))
338 } else {
339 Ok(Value::integer(int_sum))
340 }
341}
342
343pub fn prim_subtract(args: &[Value]) -> PrimitiveResult {
350 if args.is_empty() {
351 return Err("-: requires at least 1 argument".to_string());
352 }
353
354 if args.len() == 1 {
355 match args[0] {
357 Value::Integer(n) => Ok(Value::integer(-n)),
358 Value::Real(r) => Ok(Value::real(-r)),
359 _ => Err(format!("-: not a number: {:?}", args[0])),
360 }
361 } else {
362 let mut result_int: i64;
364 let mut result_real: f64;
365 let mut has_real = false;
366
367 match args[0] {
369 Value::Integer(n) => {
370 result_int = n;
371 result_real = n as f64;
372 }
373 Value::Real(r) => {
374 has_real = true;
375 result_int = 0; result_real = r;
377 }
378 _ => return Err(format!("-: not a number: {:?}", args[0])),
379 }
380
381 for arg in &args[1..] {
383 match arg {
384 Value::Integer(n) => {
385 result_int -= n;
386 result_real -= *n as f64;
387 }
388 Value::Real(r) => {
389 has_real = true;
390 result_real -= r;
391 }
392 _ => return Err(format!("-: not a number: {:?}", arg)),
393 }
394 }
395
396 if has_real {
397 Ok(Value::real(result_real))
398 } else {
399 Ok(Value::integer(result_int))
400 }
401 }
402}
403
404pub fn prim_multiply(args: &[Value]) -> PrimitiveResult {
410 let mut int_product = 1i64;
411 let mut real_product = 1.0f64;
412 let mut has_real = false;
413
414 for arg in args {
415 match arg {
416 Value::Integer(n) => {
417 int_product *= n;
418 real_product *= *n as f64;
419 }
420 Value::Real(r) => {
421 has_real = true;
422 real_product *= r;
423 }
424 _ => return Err(format!("*: not a number: {:?}", arg)),
425 }
426 }
427
428 if has_real {
429 Ok(Value::real(real_product))
430 } else {
431 Ok(Value::integer(int_product))
432 }
433}
434
435pub fn prim_divide(args: &[Value]) -> PrimitiveResult {
442 if args.is_empty() {
443 return Err("/: requires at least 1 argument".to_string());
444 }
445
446 if args.len() == 1 {
447 match args[0] {
449 Value::Integer(n) => {
450 if n == 0 {
451 return Err("/: division by zero".to_string());
452 }
453 Ok(Value::real(1.0 / n as f64))
454 }
455 Value::Real(r) => {
456 if r == 0.0 {
457 return Err("/: division by zero".to_string());
458 }
459 Ok(Value::real(1.0 / r))
460 }
461 _ => Err(format!("/: not a number: {:?}", args[0])),
462 }
463 } else {
464 let mut result = match args[0] {
466 Value::Integer(n) => n as f64,
467 Value::Real(r) => r,
468 _ => return Err(format!("/: not a number: {:?}", args[0])),
469 };
470
471 for arg in &args[1..] {
472 match arg {
473 Value::Integer(n) => {
474 if *n == 0 {
475 return Err("/: division by zero".to_string());
476 }
477 result /= *n as f64;
478 }
479 Value::Real(r) => {
480 if *r == 0.0 {
481 return Err("/: division by zero".to_string());
482 }
483 result /= r;
484 }
485 _ => return Err(format!("/: not a number: {:?}", arg)),
486 }
487 }
488
489 Ok(Value::real(result))
490 }
491}
492
493pub fn prim_quotient(args: &[Value]) -> PrimitiveResult {
499 if args.len() != 2 {
500 return Err("quotient requires exactly 2 arguments".to_string());
501 }
502
503 let n1 = match args[0] {
504 Value::Integer(n) => n,
505 _ => return Err(format!("quotient: not an integer: {:?}", args[0])),
506 };
507
508 let n2 = match args[1] {
509 Value::Integer(n) => n,
510 _ => return Err(format!("quotient: not an integer: {:?}", args[1])),
511 };
512
513 if n2 == 0 {
514 return Err("quotient: division by zero".to_string());
515 }
516
517 Ok(Value::integer(n1 / n2))
518}
519
520pub fn prim_remainder(args: &[Value]) -> PrimitiveResult {
526 if args.len() != 2 {
527 return Err("remainder requires exactly 2 arguments".to_string());
528 }
529
530 let n1 = match args[0] {
531 Value::Integer(n) => n,
532 _ => return Err(format!("remainder: not an integer: {:?}", args[0])),
533 };
534
535 let n2 = match args[1] {
536 Value::Integer(n) => n,
537 _ => return Err(format!("remainder: not an integer: {:?}", args[1])),
538 };
539
540 if n2 == 0 {
541 return Err("remainder: division by zero".to_string());
542 }
543
544 Ok(Value::integer(n1 % n2))
545}
546
547pub fn prim_modulo(args: &[Value]) -> PrimitiveResult {
553 if args.len() != 2 {
554 return Err("modulo requires exactly 2 arguments".to_string());
555 }
556
557 let n1 = match args[0] {
558 Value::Integer(n) => n,
559 _ => return Err(format!("modulo: not an integer: {:?}", args[0])),
560 };
561
562 let n2 = match args[1] {
563 Value::Integer(n) => n,
564 _ => return Err(format!("modulo: not an integer: {:?}", args[1])),
565 };
566
567 if n2 == 0 {
568 return Err("modulo: division by zero".to_string());
569 }
570
571 let result = ((n1 % n2) + n2) % n2;
573 Ok(Value::integer(result))
574}
575
576pub fn prim_num_eq(args: &[Value]) -> PrimitiveResult {
582 if args.len() < 2 {
583 return Err("=: requires at least 2 arguments".to_string());
584 }
585
586 let first_val = match args[0] {
587 Value::Integer(n) => n as f64,
588 Value::Real(r) => r,
589 _ => return Err(format!("=: not a number: {:?}", args[0])),
590 };
591
592 for arg in &args[1..] {
593 let val = match arg {
594 Value::Integer(n) => *n as f64,
595 Value::Real(r) => *r,
596 _ => return Err(format!("=: not a number: {:?}", arg)),
597 };
598
599 if (first_val - val).abs() > f64::EPSILON {
600 return Ok(Value::bool(false));
601 }
602 }
603
604 Ok(Value::bool(true))
605}
606
607pub fn prim_num_lt(args: &[Value]) -> PrimitiveResult {
613 if args.len() < 2 {
614 return Err("<: requires at least 2 arguments".to_string());
615 }
616
617 for i in 0..args.len() - 1 {
618 let v1 = match args[i] {
619 Value::Integer(n) => n as f64,
620 Value::Real(r) => r,
621 _ => return Err(format!("<: not a number: {:?}", args[i])),
622 };
623
624 let v2 = match args[i + 1] {
625 Value::Integer(n) => n as f64,
626 Value::Real(r) => r,
627 _ => return Err(format!("<: not a number: {:?}", args[i + 1])),
628 };
629
630 if v1 >= v2 {
631 return Ok(Value::bool(false));
632 }
633 }
634
635 Ok(Value::bool(true))
636}
637
638pub fn prim_num_gt(args: &[Value]) -> PrimitiveResult {
644 if args.len() < 2 {
645 return Err(">: requires at least 2 arguments".to_string());
646 }
647
648 for i in 0..args.len() - 1 {
649 let v1 = match args[i] {
650 Value::Integer(n) => n as f64,
651 Value::Real(r) => r,
652 _ => return Err(format!(">: not a number: {:?}", args[i])),
653 };
654
655 let v2 = match args[i + 1] {
656 Value::Integer(n) => n as f64,
657 Value::Real(r) => r,
658 _ => return Err(format!(">: not a number: {:?}", args[i + 1])),
659 };
660
661 if v1 <= v2 {
662 return Ok(Value::bool(false));
663 }
664 }
665
666 Ok(Value::bool(true))
667}
668
669pub fn prim_num_le(args: &[Value]) -> PrimitiveResult {
675 if args.len() < 2 {
676 return Err("<=: requires at least 2 arguments".to_string());
677 }
678
679 for i in 0..args.len() - 1 {
680 let v1 = match args[i] {
681 Value::Integer(n) => n as f64,
682 Value::Real(r) => r,
683 _ => return Err(format!("<=: not a number: {:?}", args[i])),
684 };
685
686 let v2 = match args[i + 1] {
687 Value::Integer(n) => n as f64,
688 Value::Real(r) => r,
689 _ => return Err(format!("<=: not a number: {:?}", args[i + 1])),
690 };
691
692 if v1 > v2 {
693 return Ok(Value::bool(false));
694 }
695 }
696
697 Ok(Value::bool(true))
698}
699
700pub fn prim_num_ge(args: &[Value]) -> PrimitiveResult {
706 if args.len() < 2 {
707 return Err(">=: requires at least 2 arguments".to_string());
708 }
709
710 for i in 0..args.len() - 1 {
711 let v1 = match args[i] {
712 Value::Integer(n) => n as f64,
713 Value::Real(r) => r,
714 _ => return Err(format!(">=: not a number: {:?}", args[i])),
715 };
716
717 let v2 = match args[i + 1] {
718 Value::Integer(n) => n as f64,
719 Value::Real(r) => r,
720 _ => return Err(format!(">=: not a number: {:?}", args[i + 1])),
721 };
722
723 if v1 < v2 {
724 return Ok(Value::bool(false));
725 }
726 }
727
728 Ok(Value::bool(true))
729}
730
731pub fn prim_number_p(args: &[Value]) -> PrimitiveResult {
737 if args.len() != 1 {
738 return Err("number?: requires exactly 1 argument".to_string());
739 }
740
741 Ok(Value::bool(matches!(args[0], Value::Integer(_) | Value::Real(_))))
742}
743
744pub fn prim_integer_p(args: &[Value]) -> PrimitiveResult {
750 if args.len() != 1 {
751 return Err("integer?: requires exactly 1 argument".to_string());
752 }
753
754 Ok(Value::bool(matches!(args[0], Value::Integer(_))))
755}
756
757pub fn prim_real_p(args: &[Value]) -> PrimitiveResult {
763 if args.len() != 1 {
764 return Err("real?: requires exactly 1 argument".to_string());
765 }
766
767 Ok(Value::bool(matches!(args[0], Value::Real(_))))
768}
769
770pub fn prim_zero_p(args: &[Value]) -> PrimitiveResult {
776 if args.len() != 1 {
777 return Err("zero?: requires exactly 1 argument".to_string());
778 }
779
780 match args[0] {
781 Value::Integer(n) => Ok(Value::bool(n == 0)),
782 Value::Real(r) => Ok(Value::bool(r.abs() < f64::EPSILON)),
783 _ => Err(format!("zero?: not a number: {:?}", args[0])),
784 }
785}
786
787pub fn prim_positive_p(args: &[Value]) -> PrimitiveResult {
793 if args.len() != 1 {
794 return Err("positive?: requires exactly 1 argument".to_string());
795 }
796
797 match args[0] {
798 Value::Integer(n) => Ok(Value::bool(n > 0)),
799 Value::Real(r) => Ok(Value::bool(r > 0.0)),
800 _ => Err(format!("positive?: not a number: {:?}", args[0])),
801 }
802}
803
804pub fn prim_negative_p(args: &[Value]) -> PrimitiveResult {
810 if args.len() != 1 {
811 return Err("negative?: requires exactly 1 argument".to_string());
812 }
813
814 match args[0] {
815 Value::Integer(n) => Ok(Value::bool(n < 0)),
816 Value::Real(r) => Ok(Value::bool(r < 0.0)),
817 _ => Err(format!("negative?: not a number: {:?}", args[0])),
818 }
819}
820
821pub fn prim_odd_p(args: &[Value]) -> PrimitiveResult {
827 if args.len() != 1 {
828 return Err("odd?: requires exactly 1 argument".to_string());
829 }
830
831 match args[0] {
832 Value::Integer(n) => Ok(Value::bool(n % 2 != 0)),
833 _ => Err(format!("odd?: not an integer: {:?}", args[0])),
834 }
835}
836
837pub fn prim_even_p(args: &[Value]) -> PrimitiveResult {
843 if args.len() != 1 {
844 return Err("even?: requires exactly 1 argument".to_string());
845 }
846
847 match args[0] {
848 Value::Integer(n) => Ok(Value::bool(n % 2 == 0)),
849 _ => Err(format!("even?: not an integer: {:?}", args[0])),
850 }
851}
852
853pub fn prim_abs(args: &[Value]) -> PrimitiveResult {
859 if args.len() != 1 {
860 return Err("abs: requires exactly 1 argument".to_string());
861 }
862
863 match args[0] {
864 Value::Integer(n) => Ok(Value::integer(n.abs())),
865 Value::Real(r) => Ok(Value::real(r.abs())),
866 _ => Err(format!("abs: not a number: {:?}", args[0])),
867 }
868}
869
870pub fn prim_max(args: &[Value]) -> PrimitiveResult {
876 if args.is_empty() {
877 return Err("max: requires at least 1 argument".to_string());
878 }
879
880 let mut max_val = match args[0] {
881 Value::Integer(n) => n as f64,
882 Value::Real(r) => r,
883 _ => return Err(format!("max: not a number: {:?}", args[0])),
884 };
885
886 let mut has_real = matches!(args[0], Value::Real(_));
887
888 for arg in &args[1..] {
889 let val = match arg {
890 Value::Integer(n) => *n as f64,
891 Value::Real(r) => {
892 has_real = true;
893 *r
894 }
895 _ => return Err(format!("max: not a number: {:?}", arg)),
896 };
897
898 if val > max_val {
899 max_val = val;
900 }
901 }
902
903 if has_real {
904 Ok(Value::real(max_val))
905 } else {
906 Ok(Value::integer(max_val as i64))
907 }
908}
909
910pub fn prim_min(args: &[Value]) -> PrimitiveResult {
916 if args.is_empty() {
917 return Err("min: requires at least 1 argument".to_string());
918 }
919
920 let mut min_val = match args[0] {
921 Value::Integer(n) => n as f64,
922 Value::Real(r) => r,
923 _ => return Err(format!("min: not a number: {:?}", args[0])),
924 };
925
926 let mut has_real = matches!(args[0], Value::Real(_));
927
928 for arg in &args[1..] {
929 let val = match arg {
930 Value::Integer(n) => *n as f64,
931 Value::Real(r) => {
932 has_real = true;
933 *r
934 }
935 _ => return Err(format!("min: not a number: {:?}", arg)),
936 };
937
938 if val < min_val {
939 min_val = val;
940 }
941 }
942
943 if has_real {
944 Ok(Value::real(min_val))
945 } else {
946 Ok(Value::integer(min_val as i64))
947 }
948}
949
950pub fn prim_gcd(args: &[Value]) -> PrimitiveResult {
957 if args.is_empty() {
958 return Ok(Value::integer(0));
959 }
960
961 fn gcd_two(a: i64, b: i64) -> i64 {
963 let mut a = a.abs();
964 let mut b = b.abs();
965 while b != 0 {
966 let temp = b;
967 b = a % b;
968 a = temp;
969 }
970 a
971 }
972
973 let mut result = match args[0] {
974 Value::Integer(n) => n,
975 _ => return Err(format!("gcd: not an integer: {:?}", args[0])),
976 };
977
978 for arg in &args[1..] {
979 let n = match arg {
980 Value::Integer(n) => *n,
981 _ => return Err(format!("gcd: not an integer: {:?}", arg)),
982 };
983 result = gcd_two(result, n);
984 }
985
986 Ok(Value::integer(result))
987}
988
989pub fn prim_lcm(args: &[Value]) -> PrimitiveResult {
996 if args.is_empty() {
997 return Ok(Value::integer(1));
998 }
999
1000 fn gcd_two(a: i64, b: i64) -> i64 {
1002 let mut a = a.abs();
1003 let mut b = b.abs();
1004 while b != 0 {
1005 let temp = b;
1006 b = a % b;
1007 a = temp;
1008 }
1009 a
1010 }
1011
1012 fn lcm_two(a: i64, b: i64) -> i64 {
1014 if a == 0 || b == 0 {
1015 return 0;
1016 }
1017 (a.abs() / gcd_two(a, b)) * b.abs()
1018 }
1019
1020 let mut result = match args[0] {
1021 Value::Integer(n) => n,
1022 _ => return Err(format!("lcm: not an integer: {:?}", args[0])),
1023 };
1024
1025 for arg in &args[1..] {
1026 let n = match arg {
1027 Value::Integer(n) => *n,
1028 _ => return Err(format!("lcm: not an integer: {:?}", arg)),
1029 };
1030 result = lcm_two(result, n);
1031 }
1032
1033 Ok(Value::integer(result))
1034}
1035
1036pub fn prim_floor(args: &[Value]) -> PrimitiveResult {
1042 if args.len() != 1 {
1043 return Err("floor: requires exactly 1 argument".to_string());
1044 }
1045
1046 match args[0] {
1047 Value::Integer(n) => Ok(Value::integer(n)),
1048 Value::Real(r) => Ok(Value::integer(r.floor() as i64)),
1049 _ => Err(format!("floor: not a number: {:?}", args[0])),
1050 }
1051}
1052
1053pub fn prim_ceiling(args: &[Value]) -> PrimitiveResult {
1059 if args.len() != 1 {
1060 return Err("ceiling: requires exactly 1 argument".to_string());
1061 }
1062
1063 match args[0] {
1064 Value::Integer(n) => Ok(Value::integer(n)),
1065 Value::Real(r) => Ok(Value::integer(r.ceil() as i64)),
1066 _ => Err(format!("ceiling: not a number: {:?}", args[0])),
1067 }
1068}
1069
1070pub fn prim_truncate(args: &[Value]) -> PrimitiveResult {
1077 if args.len() != 1 {
1078 return Err("truncate: requires exactly 1 argument".to_string());
1079 }
1080
1081 match args[0] {
1082 Value::Integer(n) => Ok(Value::integer(n)),
1083 Value::Real(r) => Ok(Value::integer(r.trunc() as i64)),
1084 _ => Err(format!("truncate: not a number: {:?}", args[0])),
1085 }
1086}
1087
1088pub fn prim_round(args: &[Value]) -> PrimitiveResult {
1095 if args.len() != 1 {
1096 return Err("round: requires exactly 1 argument".to_string());
1097 }
1098
1099 match args[0] {
1100 Value::Integer(n) => Ok(Value::integer(n)),
1101 Value::Real(r) => Ok(Value::integer(r.round() as i64)),
1102 _ => Err(format!("round: not a number: {:?}", args[0])),
1103 }
1104}
1105
1106pub fn prim_string_length(args: &[Value]) -> PrimitiveResult {
1116 if args.len() != 1 {
1117 return Err("string-length requires exactly 1 argument".to_string());
1118 }
1119
1120 match &args[0] {
1121 Value::String(s) => Ok(Value::integer(s.chars().count() as i64)),
1122 _ => Err(format!(
1123 "argument for primitive \"string-length\" of wrong type: {:?} not a string",
1124 args[0]
1125 )),
1126 }
1127}
1128
1129pub fn prim_string_ref(args: &[Value]) -> PrimitiveResult {
1135 if args.len() != 2 {
1136 return Err("string-ref requires exactly 2 arguments".to_string());
1137 }
1138
1139 let s = match &args[0] {
1140 Value::String(s) => s,
1141 _ => return Err(format!("string-ref: not a string: {:?}", args[0])),
1142 };
1143
1144 let k = match args[1] {
1145 Value::Integer(n) if n >= 0 => n as usize,
1146 _ => return Err("string-ref: second argument must be a non-negative integer".to_string()),
1147 };
1148
1149 let chars: Vec<char> = s.chars().collect();
1150 if k >= chars.len() {
1151 return Err("string-ref: index out of bounds".to_string());
1152 }
1153
1154 Ok(Value::char(chars[k]))
1155}
1156
1157pub fn prim_string_append(args: &[Value]) -> PrimitiveResult {
1163 let mut result = String::new();
1164
1165 for (i, arg) in args.iter().enumerate() {
1166 match arg {
1167 Value::String(s) => result.push_str(s),
1168 _ => {
1169 return Err(format!(
1170 "{} argument for primitive \"string-append\" of wrong type: {:?} not a string",
1171 ordinal(i + 1),
1172 arg
1173 ))
1174 }
1175 }
1176 }
1177
1178 Ok(Value::string(result))
1179}
1180
1181fn ordinal(n: usize) -> String {
1183 let suffix = match (n % 10, n % 100) {
1184 (1, 11) => "th",
1185 (1, _) => "st",
1186 (2, 12) => "th",
1187 (2, _) => "nd",
1188 (3, 13) => "th",
1189 (3, _) => "rd",
1190 _ => "th",
1191 };
1192 format!("{}{}", n, suffix)
1193}
1194
1195pub fn prim_substring(args: &[Value]) -> PrimitiveResult {
1202 if args.len() != 3 {
1203 return Err("substring requires exactly 3 arguments".to_string());
1204 }
1205
1206 let s = match &args[0] {
1207 Value::String(s) => s,
1208 _ => {
1209 return Err(format!(
1210 "1st argument for primitive \"substring\" of wrong type: {:?} not a string",
1211 args[0]
1212 ))
1213 }
1214 };
1215
1216 let start = match args[1] {
1217 Value::Integer(n) if n >= 0 => n as usize,
1218 _ => return Err("substring: start must be a non-negative integer".to_string()),
1219 };
1220
1221 let end = match args[2] {
1222 Value::Integer(n) if n >= 0 => n as usize,
1223 _ => return Err("substring: end must be a non-negative integer".to_string()),
1224 };
1225
1226 let chars: Vec<char> = s.chars().collect();
1227 if start > end || end > chars.len() {
1228 return Err("substring: invalid range".to_string());
1229 }
1230
1231 let substring: String = chars[start..end].iter().collect();
1232 Ok(Value::string(substring))
1233}
1234
1235pub fn prim_string_eq(args: &[Value]) -> PrimitiveResult {
1241 if args.len() != 2 {
1242 return Err("string=? requires exactly 2 arguments".to_string());
1243 }
1244
1245 let s1 = match &args[0] {
1246 Value::String(s) => s,
1247 _ => return Err(format!("string=?: not a string: {:?}", args[0])),
1248 };
1249
1250 let s2 = match &args[1] {
1251 Value::String(s) => s,
1252 _ => return Err(format!("string=?: not a string: {:?}", args[1])),
1253 };
1254
1255 Ok(Value::bool(s1 == s2))
1256}
1257
1258pub fn prim_string_lt(args: &[Value]) -> PrimitiveResult {
1264 if args.len() != 2 {
1265 return Err("string<? requires exactly 2 arguments".to_string());
1266 }
1267
1268 let s1 = match &args[0] {
1269 Value::String(s) => s,
1270 _ => return Err(format!("string<?: not a string: {:?}", args[0])),
1271 };
1272
1273 let s2 = match &args[1] {
1274 Value::String(s) => s,
1275 _ => return Err(format!("string<?: not a string: {:?}", args[1])),
1276 };
1277
1278 Ok(Value::bool(s1 < s2))
1279}
1280
1281pub fn prim_string_gt(args: &[Value]) -> PrimitiveResult {
1287 if args.len() != 2 {
1288 return Err("string>? requires exactly 2 arguments".to_string());
1289 }
1290
1291 let s1 = match &args[0] {
1292 Value::String(s) => s,
1293 _ => return Err(format!("string>?: not a string: {:?}", args[0])),
1294 };
1295
1296 let s2 = match &args[1] {
1297 Value::String(s) => s,
1298 _ => return Err(format!("string>?: not a string: {:?}", args[1])),
1299 };
1300
1301 Ok(Value::bool(s1 > s2))
1302}
1303
1304pub fn prim_string_le(args: &[Value]) -> PrimitiveResult {
1310 if args.len() != 2 {
1311 return Err("string<=? requires exactly 2 arguments".to_string());
1312 }
1313
1314 let s1 = match &args[0] {
1315 Value::String(s) => s,
1316 _ => return Err(format!("string<=?: not a string: {:?}", args[0])),
1317 };
1318
1319 let s2 = match &args[1] {
1320 Value::String(s) => s,
1321 _ => return Err(format!("string<=?: not a string: {:?}", args[1])),
1322 };
1323
1324 Ok(Value::bool(s1 <= s2))
1325}
1326
1327pub fn prim_string_ge(args: &[Value]) -> PrimitiveResult {
1333 if args.len() != 2 {
1334 return Err("string>=? requires exactly 2 arguments".to_string());
1335 }
1336
1337 let s1 = match &args[0] {
1338 Value::String(s) => s,
1339 _ => return Err(format!("string>=?: not a string: {:?}", args[0])),
1340 };
1341
1342 let s2 = match &args[1] {
1343 Value::String(s) => s,
1344 _ => return Err(format!("string>=?: not a string: {:?}", args[1])),
1345 };
1346
1347 Ok(Value::bool(s1 >= s2))
1348}
1349
1350pub fn prim_string_ci_eq(args: &[Value]) -> PrimitiveResult {
1356 if args.len() != 2 {
1357 return Err("string-ci=? requires exactly 2 arguments".to_string());
1358 }
1359
1360 let s1 = match &args[0] {
1361 Value::String(s) => s.to_lowercase(),
1362 _ => return Err(format!("string-ci=?: not a string: {:?}", args[0])),
1363 };
1364
1365 let s2 = match &args[1] {
1366 Value::String(s) => s.to_lowercase(),
1367 _ => return Err(format!("string-ci=?: not a string: {:?}", args[1])),
1368 };
1369
1370 Ok(Value::bool(s1 == s2))
1371}
1372
1373pub fn prim_string_ci_lt(args: &[Value]) -> PrimitiveResult {
1379 if args.len() != 2 {
1380 return Err("string-ci<? requires exactly 2 arguments".to_string());
1381 }
1382
1383 let s1 = match &args[0] {
1384 Value::String(s) => s.to_lowercase(),
1385 _ => return Err(format!("string-ci<?: not a string: {:?}", args[0])),
1386 };
1387
1388 let s2 = match &args[1] {
1389 Value::String(s) => s.to_lowercase(),
1390 _ => return Err(format!("string-ci<?: not a string: {:?}", args[1])),
1391 };
1392
1393 Ok(Value::bool(s1 < s2))
1394}
1395
1396pub fn prim_string_ci_gt(args: &[Value]) -> PrimitiveResult {
1402 if args.len() != 2 {
1403 return Err("string-ci>? requires exactly 2 arguments".to_string());
1404 }
1405
1406 let s1 = match &args[0] {
1407 Value::String(s) => s.to_lowercase(),
1408 _ => return Err(format!("string-ci>?: not a string: {:?}", args[0])),
1409 };
1410
1411 let s2 = match &args[1] {
1412 Value::String(s) => s.to_lowercase(),
1413 _ => return Err(format!("string-ci>?: not a string: {:?}", args[1])),
1414 };
1415
1416 Ok(Value::bool(s1 > s2))
1417}
1418
1419pub fn prim_string_ci_le(args: &[Value]) -> PrimitiveResult {
1425 if args.len() != 2 {
1426 return Err("string-ci<=? requires exactly 2 arguments".to_string());
1427 }
1428
1429 let s1 = match &args[0] {
1430 Value::String(s) => s.to_lowercase(),
1431 _ => return Err(format!("string-ci<=?: not a string: {:?}", args[0])),
1432 };
1433
1434 let s2 = match &args[1] {
1435 Value::String(s) => s.to_lowercase(),
1436 _ => return Err(format!("string-ci<=?: not a string: {:?}", args[1])),
1437 };
1438
1439 Ok(Value::bool(s1 <= s2))
1440}
1441
1442pub fn prim_string_ci_ge(args: &[Value]) -> PrimitiveResult {
1448 if args.len() != 2 {
1449 return Err("string-ci>=? requires exactly 2 arguments".to_string());
1450 }
1451
1452 let s1 = match &args[0] {
1453 Value::String(s) => s.to_lowercase(),
1454 _ => return Err(format!("string-ci>=?: not a string: {:?}", args[0])),
1455 };
1456
1457 let s2 = match &args[1] {
1458 Value::String(s) => s.to_lowercase(),
1459 _ => return Err(format!("string-ci>=?: not a string: {:?}", args[1])),
1460 };
1461
1462 Ok(Value::bool(s1 >= s2))
1463}
1464
1465pub fn prim_string_p(args: &[Value]) -> PrimitiveResult {
1471 if args.len() != 1 {
1472 return Err("string? requires exactly 1 argument".to_string());
1473 }
1474
1475 Ok(Value::bool(matches!(args[0], Value::String(_))))
1476}
1477
1478pub fn prim_make_string(args: &[Value]) -> PrimitiveResult {
1486 if args.is_empty() || args.len() > 2 {
1487 return Err("make-string requires 1 or 2 arguments".to_string());
1488 }
1489
1490 let k = match args[0] {
1491 Value::Integer(n) if n >= 0 => n as usize,
1492 _ => return Err("make-string: first argument must be a non-negative integer".to_string()),
1493 };
1494
1495 let ch = if args.len() == 2 {
1496 match args[1] {
1497 Value::Char(c) => c,
1498 _ => return Err("make-string: second argument must be a character".to_string()),
1499 }
1500 } else {
1501 ' '
1502 };
1503
1504 Ok(Value::string(ch.to_string().repeat(k)))
1505}
1506
1507pub fn prim_string(args: &[Value]) -> PrimitiveResult {
1513 let mut result = String::new();
1514
1515 for arg in args {
1516 match arg {
1517 Value::Char(c) => result.push(*c),
1518 _ => return Err(format!("string: not a character: {:?}", arg)),
1519 }
1520 }
1521
1522 Ok(Value::string(result))
1523}
1524
1525pub fn prim_string_to_list(args: &[Value]) -> PrimitiveResult {
1531 if args.len() != 1 {
1532 return Err("string->list requires exactly 1 argument".to_string());
1533 }
1534
1535 let s = match &args[0] {
1536 Value::String(s) => s,
1537 _ => return Err(format!("string->list: not a string: {:?}", args[0])),
1538 };
1539
1540 let mut result = Value::Nil;
1541 for ch in s.chars().rev() {
1542 result = Value::cons(Value::char(ch), result);
1543 }
1544
1545 Ok(result)
1546}
1547
1548pub fn prim_list_to_string(args: &[Value]) -> PrimitiveResult {
1554 if args.len() != 1 {
1555 return Err("list->string requires exactly 1 argument".to_string());
1556 }
1557
1558 let mut result = String::new();
1559 let mut current = args[0].clone();
1560
1561 loop {
1562 match current {
1563 Value::Nil => break,
1564 Value::Pair(ref p) => {
1565 let pair = p.borrow();
1566 match pair.car {
1567 Value::Char(c) => result.push(c),
1568 _ => return Err("list->string: list must contain only characters".to_string()),
1569 }
1570 let cdr = pair.cdr.clone();
1571 drop(pair);
1572 current = cdr;
1573 }
1574 _ => return Err("list->string: not a proper list".to_string()),
1575 }
1576 }
1577
1578 Ok(Value::string(result))
1579}
1580
1581pub fn prim_symbol_to_string(args: &[Value]) -> PrimitiveResult {
1587 if args.len() != 1 {
1588 return Err("symbol->string requires exactly 1 argument".to_string());
1589 }
1590
1591 match &args[0] {
1592 Value::Symbol(s) => Ok(Value::string(s.to_string())),
1593 _ => Err(format!("symbol->string: not a symbol: {:?}", args[0])),
1594 }
1595}
1596
1597pub fn prim_string_to_symbol(args: &[Value]) -> PrimitiveResult {
1603 if args.len() != 1 {
1604 return Err("string->symbol requires exactly 1 argument".to_string());
1605 }
1606
1607 match &args[0] {
1608 Value::String(s) => Ok(Value::symbol(s)),
1609 _ => Err(format!("string->symbol: not a string: {:?}", args[0])),
1610 }
1611}
1612
1613pub fn prim_symbol_p(args: &[Value]) -> PrimitiveResult {
1619 if args.len() != 1 {
1620 return Err("symbol? requires exactly 1 argument".to_string());
1621 }
1622
1623 Ok(Value::bool(matches!(args[0], Value::Symbol(_))))
1624}
1625
1626pub fn prim_char_p(args: &[Value]) -> PrimitiveResult {
1632 if args.len() != 1 {
1633 return Err("char? requires exactly 1 argument".to_string());
1634 }
1635
1636 Ok(Value::bool(matches!(args[0], Value::Char(_))))
1637}
1638
1639pub fn prim_char_eq(args: &[Value]) -> PrimitiveResult {
1645 if args.len() != 2 {
1646 return Err("char=? requires exactly 2 arguments".to_string());
1647 }
1648
1649 let c1 = match args[0] {
1650 Value::Char(c) => c,
1651 _ => return Err(format!("char=?: not a character: {:?}", args[0])),
1652 };
1653
1654 let c2 = match args[1] {
1655 Value::Char(c) => c,
1656 _ => return Err(format!("char=?: not a character: {:?}", args[1])),
1657 };
1658
1659 Ok(Value::bool(c1 == c2))
1660}
1661
1662pub fn prim_char_lt(args: &[Value]) -> PrimitiveResult {
1668 if args.len() != 2 {
1669 return Err("char<? requires exactly 2 arguments".to_string());
1670 }
1671
1672 let c1 = match args[0] {
1673 Value::Char(c) => c,
1674 _ => return Err(format!("char<?: not a character: {:?}", args[0])),
1675 };
1676
1677 let c2 = match args[1] {
1678 Value::Char(c) => c,
1679 _ => return Err(format!("char<?: not a character: {:?}", args[1])),
1680 };
1681
1682 Ok(Value::bool(c1 < c2))
1683}
1684
1685pub fn prim_char_gt(args: &[Value]) -> PrimitiveResult {
1691 if args.len() != 2 {
1692 return Err("char>? requires exactly 2 arguments".to_string());
1693 }
1694
1695 let c1 = match args[0] {
1696 Value::Char(c) => c,
1697 _ => return Err(format!("char>?: not a character: {:?}", args[0])),
1698 };
1699
1700 let c2 = match args[1] {
1701 Value::Char(c) => c,
1702 _ => return Err(format!("char>?: not a character: {:?}", args[1])),
1703 };
1704
1705 Ok(Value::bool(c1 > c2))
1706}
1707
1708pub fn prim_char_upcase(args: &[Value]) -> PrimitiveResult {
1714 if args.len() != 1 {
1715 return Err("char-upcase requires exactly 1 argument".to_string());
1716 }
1717
1718 match args[0] {
1719 Value::Char(c) => Ok(Value::char(c.to_ascii_uppercase())),
1720 _ => Err(format!("char-upcase: not a character: {:?}", args[0])),
1721 }
1722}
1723
1724pub fn prim_char_downcase(args: &[Value]) -> PrimitiveResult {
1730 if args.len() != 1 {
1731 return Err("char-downcase requires exactly 1 argument".to_string());
1732 }
1733
1734 match args[0] {
1735 Value::Char(c) => Ok(Value::char(c.to_ascii_lowercase())),
1736 _ => Err(format!("char-downcase: not a character: {:?}", args[0])),
1737 }
1738}
1739
1740pub fn prim_char_le(args: &[Value]) -> PrimitiveResult {
1746 if args.len() != 2 {
1747 return Err("char<=? requires exactly 2 arguments".to_string());
1748 }
1749
1750 let c1 = match args[0] {
1751 Value::Char(c) => c,
1752 _ => return Err(format!("char<=?: not a character: {:?}", args[0])),
1753 };
1754
1755 let c2 = match args[1] {
1756 Value::Char(c) => c,
1757 _ => return Err(format!("char<=?: not a character: {:?}", args[1])),
1758 };
1759
1760 Ok(Value::bool(c1 <= c2))
1761}
1762
1763pub fn prim_char_ge(args: &[Value]) -> PrimitiveResult {
1769 if args.len() != 2 {
1770 return Err("char>=? requires exactly 2 arguments".to_string());
1771 }
1772
1773 let c1 = match args[0] {
1774 Value::Char(c) => c,
1775 _ => return Err(format!("char>=?: not a character: {:?}", args[0])),
1776 };
1777
1778 let c2 = match args[1] {
1779 Value::Char(c) => c,
1780 _ => return Err(format!("char>=?: not a character: {:?}", args[1])),
1781 };
1782
1783 Ok(Value::bool(c1 >= c2))
1784}
1785
1786pub fn prim_char_to_integer(args: &[Value]) -> PrimitiveResult {
1792 if args.len() != 1 {
1793 return Err("char->integer requires exactly 1 argument".to_string());
1794 }
1795
1796 match args[0] {
1797 Value::Char(c) => Ok(Value::integer(c as i64)),
1798 _ => Err(format!("char->integer: not a character: {:?}", args[0])),
1799 }
1800}
1801
1802pub fn prim_integer_to_char(args: &[Value]) -> PrimitiveResult {
1808 if args.len() != 1 {
1809 return Err("integer->char requires exactly 1 argument".to_string());
1810 }
1811
1812 match args[0] {
1813 Value::Integer(n) => {
1814 if n < 0 || n > 0x10FFFF {
1815 return Err(format!("integer->char: invalid code point: {}", n));
1816 }
1817 match char::from_u32(n as u32) {
1818 Some(c) => Ok(Value::char(c)),
1819 None => Err(format!("integer->char: invalid Unicode code point: {}", n)),
1820 }
1821 }
1822 _ => Err(format!("integer->char: not an integer: {:?}", args[0])),
1823 }
1824}
1825
1826pub fn prim_char_alphabetic_p(args: &[Value]) -> PrimitiveResult {
1832 if args.len() != 1 {
1833 return Err("char-alphabetic? requires exactly 1 argument".to_string());
1834 }
1835
1836 match args[0] {
1837 Value::Char(c) => Ok(Value::bool(c.is_alphabetic())),
1838 _ => Err(format!("char-alphabetic?: not a character: {:?}", args[0])),
1839 }
1840}
1841
1842pub fn prim_char_numeric_p(args: &[Value]) -> PrimitiveResult {
1848 if args.len() != 1 {
1849 return Err("char-numeric? requires exactly 1 argument".to_string());
1850 }
1851
1852 match args[0] {
1853 Value::Char(c) => Ok(Value::bool(c.is_numeric())),
1854 _ => Err(format!("char-numeric?: not a character: {:?}", args[0])),
1855 }
1856}
1857
1858pub fn prim_char_whitespace_p(args: &[Value]) -> PrimitiveResult {
1864 if args.len() != 1 {
1865 return Err("char-whitespace? requires exactly 1 argument".to_string());
1866 }
1867
1868 match args[0] {
1869 Value::Char(c) => Ok(Value::bool(c.is_whitespace())),
1870 _ => Err(format!("char-whitespace?: not a character: {:?}", args[0])),
1871 }
1872}
1873
1874pub fn prim_char_ci_eq(args: &[Value]) -> PrimitiveResult {
1880 if args.len() != 2 {
1881 return Err("char-ci=? requires exactly 2 arguments".to_string());
1882 }
1883
1884 let c1 = match args[0] {
1885 Value::Char(c) => c.to_ascii_lowercase(),
1886 _ => return Err(format!("char-ci=?: not a character: {:?}", args[0])),
1887 };
1888
1889 let c2 = match args[1] {
1890 Value::Char(c) => c.to_ascii_lowercase(),
1891 _ => return Err(format!("char-ci=?: not a character: {:?}", args[1])),
1892 };
1893
1894 Ok(Value::bool(c1 == c2))
1895}
1896
1897pub fn prim_char_ci_lt(args: &[Value]) -> PrimitiveResult {
1903 if args.len() != 2 {
1904 return Err("char-ci<? requires exactly 2 arguments".to_string());
1905 }
1906
1907 let c1 = match args[0] {
1908 Value::Char(c) => c.to_ascii_lowercase(),
1909 _ => return Err(format!("char-ci<?: not a character: {:?}", args[0])),
1910 };
1911
1912 let c2 = match args[1] {
1913 Value::Char(c) => c.to_ascii_lowercase(),
1914 _ => return Err(format!("char-ci<?: not a character: {:?}", args[1])),
1915 };
1916
1917 Ok(Value::bool(c1 < c2))
1918}
1919
1920pub fn prim_char_ci_gt(args: &[Value]) -> PrimitiveResult {
1926 if args.len() != 2 {
1927 return Err("char-ci>? requires exactly 2 arguments".to_string());
1928 }
1929
1930 let c1 = match args[0] {
1931 Value::Char(c) => c.to_ascii_lowercase(),
1932 _ => return Err(format!("char-ci>?: not a character: {:?}", args[0])),
1933 };
1934
1935 let c2 = match args[1] {
1936 Value::Char(c) => c.to_ascii_lowercase(),
1937 _ => return Err(format!("char-ci>?: not a character: {:?}", args[1])),
1938 };
1939
1940 Ok(Value::bool(c1 > c2))
1941}
1942
1943pub fn prim_char_ci_le(args: &[Value]) -> PrimitiveResult {
1949 if args.len() != 2 {
1950 return Err("char-ci<=? requires exactly 2 arguments".to_string());
1951 }
1952
1953 let c1 = match args[0] {
1954 Value::Char(c) => c.to_ascii_lowercase(),
1955 _ => return Err(format!("char-ci<=?: not a character: {:?}", args[0])),
1956 };
1957
1958 let c2 = match args[1] {
1959 Value::Char(c) => c.to_ascii_lowercase(),
1960 _ => return Err(format!("char-ci<=?: not a character: {:?}", args[1])),
1961 };
1962
1963 Ok(Value::bool(c1 <= c2))
1964}
1965
1966pub fn prim_char_ci_ge(args: &[Value]) -> PrimitiveResult {
1972 if args.len() != 2 {
1973 return Err("char-ci>=? requires exactly 2 arguments".to_string());
1974 }
1975
1976 let c1 = match args[0] {
1977 Value::Char(c) => c.to_ascii_lowercase(),
1978 _ => return Err(format!("char-ci>=?: not a character: {:?}", args[0])),
1979 };
1980
1981 let c2 = match args[1] {
1982 Value::Char(c) => c.to_ascii_lowercase(),
1983 _ => return Err(format!("char-ci>=?: not a character: {:?}", args[1])),
1984 };
1985
1986 Ok(Value::bool(c1 >= c2))
1987}
1988
1989pub fn prim_not(args: &[Value]) -> PrimitiveResult {
1999 if args.len() != 1 {
2000 return Err("not requires exactly 1 argument".to_string());
2001 }
2002
2003 Ok(Value::bool(!args[0].is_true()))
2004}
2005
2006pub fn prim_boolean_p(args: &[Value]) -> PrimitiveResult {
2012 if args.len() != 1 {
2013 return Err("boolean? requires exactly 1 argument".to_string());
2014 }
2015
2016 Ok(Value::bool(matches!(args[0], Value::Bool(_))))
2017}
2018
2019pub fn prim_equal_p(args: &[Value]) -> PrimitiveResult {
2026 if args.len() != 2 {
2027 return Err("equal? requires exactly 2 arguments".to_string());
2028 }
2029
2030 Ok(Value::bool(values_equal(&args[0], &args[1])))
2031}
2032
2033fn values_equal(v1: &Value, v2: &Value) -> bool {
2035 match (v1, v2) {
2036 (Value::Nil, Value::Nil) => true,
2037 (Value::Bool(b1), Value::Bool(b2)) => b1 == b2,
2038 (Value::Integer(n1), Value::Integer(n2)) => n1 == n2,
2039 (Value::Real(r1), Value::Real(r2)) => (r1 - r2).abs() < f64::EPSILON,
2040 (Value::Integer(n), Value::Real(r)) | (Value::Real(r), Value::Integer(n)) => {
2041 (*n as f64 - r).abs() < f64::EPSILON
2042 }
2043 (Value::Char(c1), Value::Char(c2)) => c1 == c2,
2044 (Value::String(s1), Value::String(s2)) => s1 == s2,
2045 (Value::Symbol(s1), Value::Symbol(s2)) => s1 == s2,
2046 (Value::Pair(p1), Value::Pair(p2)) => {
2047 let pair1 = p1.borrow();
2048 let pair2 = p2.borrow();
2049 values_equal(&pair1.car, &pair2.car) && values_equal(&pair1.cdr, &pair2.cdr)
2050 }
2051 _ => false,
2052 }
2053}
2054
2055pub fn prim_eqv_p(args: &[Value]) -> PrimitiveResult {
2062 if args.len() != 2 {
2063 return Err("eqv? requires exactly 2 arguments".to_string());
2064 }
2065
2066 let result = match (&args[0], &args[1]) {
2067 (Value::Nil, Value::Nil) => true,
2068 (Value::Bool(b1), Value::Bool(b2)) => b1 == b2,
2069 (Value::Integer(n1), Value::Integer(n2)) => n1 == n2,
2070 (Value::Real(r1), Value::Real(r2)) => (r1 - r2).abs() < f64::EPSILON,
2071 (Value::Char(c1), Value::Char(c2)) => c1 == c2,
2072 (Value::Symbol(s1), Value::Symbol(s2)) => s1 == s2,
2073 (Value::Pair(p1), Value::Pair(p2)) => gc::Gc::ptr_eq(p1, p2),
2075 (Value::String(s1), Value::String(s2)) => gc::Gc::ptr_eq(s1, s2),
2076 (Value::Procedure(pr1), Value::Procedure(pr2)) => gc::Gc::ptr_eq(pr1, pr2),
2077 _ => false,
2078 };
2079
2080 Ok(Value::bool(result))
2081}
2082
2083pub fn prim_eq_p(args: &[Value]) -> PrimitiveResult {
2089 if args.len() != 2 {
2090 return Err("eq? requires exactly 2 arguments".to_string());
2091 }
2092
2093 let result = match (&args[0], &args[1]) {
2094 (Value::Nil, Value::Nil) => true,
2095 (Value::Bool(b1), Value::Bool(b2)) => b1 == b2,
2096 (Value::Integer(n1), Value::Integer(n2)) => n1 == n2,
2097 (Value::Char(c1), Value::Char(c2)) => c1 == c2,
2098 (Value::Symbol(s1), Value::Symbol(s2)) => s1 == s2,
2099 (Value::Pair(p1), Value::Pair(p2)) => gc::Gc::ptr_eq(p1, p2),
2101 (Value::String(s1), Value::String(s2)) => gc::Gc::ptr_eq(s1, s2),
2102 (Value::Procedure(pr1), Value::Procedure(pr2)) => gc::Gc::ptr_eq(pr1, pr2),
2103 _ => false,
2104 };
2105
2106 Ok(Value::bool(result))
2107}
2108
2109pub fn prim_procedure_p(args: &[Value]) -> PrimitiveResult {
2115 if args.len() != 1 {
2116 return Err("procedure? requires exactly 1 argument".to_string());
2117 }
2118
2119 Ok(Value::bool(matches!(args[0], Value::Procedure(_))))
2120}
2121
2122pub fn prim_error(args: &[Value]) -> PrimitiveResult {
2133 if args.is_empty() {
2134 return Err("error: requires at least 1 argument".to_string());
2135 }
2136
2137 let message = match &args[0] {
2138 Value::String(s) => s.to_string(),
2139 Value::Symbol(s) => s.to_string(),
2140 other => format!("{:?}", other),
2141 };
2142
2143 let mut full_message = message;
2145 for arg in &args[1..] {
2146 full_message.push_str(&format!(" {:?}", arg));
2147 }
2148
2149 Err(full_message)
2150}
2151
2152pub fn prim_display(args: &[Value]) -> PrimitiveResult {
2159 if args.len() != 1 {
2160 return Err("display requires exactly 1 argument".to_string());
2161 }
2162
2163 let output = match &args[0] {
2164 Value::String(s) => s.to_string(),
2165 Value::Char(c) => c.to_string(),
2166 other => format!("{:?}", other),
2167 };
2168
2169 print!("{}", output);
2170 Ok(Value::Unspecified)
2171}
2172
2173pub fn prim_newline(args: &[Value]) -> PrimitiveResult {
2179 if !args.is_empty() {
2180 return Err("newline requires 0 arguments".to_string());
2181 }
2182
2183 println!();
2184 Ok(Value::Unspecified)
2185}
2186
2187pub fn prim_write(args: &[Value]) -> PrimitiveResult {
2193 if args.len() != 1 {
2194 return Err("write requires exactly 1 argument".to_string());
2195 }
2196
2197 print!("{:?}", args[0]);
2198 Ok(Value::Unspecified)
2199}
2200
2201pub fn prim_number_to_string(args: &[Value]) -> PrimitiveResult {
2211 if args.len() != 1 {
2212 return Err("number->string requires exactly 1 argument".to_string());
2213 }
2214
2215 match &args[0] {
2216 Value::Integer(n) => Ok(Value::string(n.to_string())),
2217 Value::Real(r) => Ok(Value::string(r.to_string())),
2218 _ => Err(format!("number->string: not a number: {:?}", args[0])),
2219 }
2220}
2221
2222pub fn prim_string_to_number(args: &[Value]) -> PrimitiveResult {
2228 if args.len() != 1 {
2229 return Err("string->number requires exactly 1 argument".to_string());
2230 }
2231
2232 let s = match &args[0] {
2233 Value::String(s) => s,
2234 _ => return Err(format!("string->number: not a string: {:?}", args[0])),
2235 };
2236
2237 if let Ok(n) = s.parse::<i64>() {
2239 return Ok(Value::integer(n));
2240 }
2241
2242 if let Ok(r) = s.parse::<f64>() {
2244 return Ok(Value::real(r));
2245 }
2246
2247 Ok(Value::bool(false))
2249}
2250
2251pub fn prim_keyword_p(args: &[Value]) -> PrimitiveResult {
2261 if args.len() != 1 {
2262 return Err("keyword? requires exactly 1 argument".to_string());
2263 }
2264
2265 Ok(Value::bool(matches!(args[0], Value::Keyword(_))))
2266}
2267
2268pub fn prim_keyword_to_string(args: &[Value]) -> PrimitiveResult {
2274 if args.len() != 1 {
2275 return Err("keyword->string requires exactly 1 argument".to_string());
2276 }
2277
2278 match &args[0] {
2279 Value::Keyword(k) => Ok(Value::string(k.to_string())),
2280 _ => Err(format!("keyword->string: not a keyword: {:?}", args[0])),
2281 }
2282}
2283
2284pub fn prim_string_to_keyword(args: &[Value]) -> PrimitiveResult {
2290 if args.len() != 1 {
2291 return Err("string->keyword requires exactly 1 argument".to_string());
2292 }
2293
2294 match &args[0] {
2295 Value::String(s) => Ok(Value::keyword(s)),
2296 _ => Err(format!("string->keyword: not a string: {:?}", args[0])),
2297 }
2298}
2299
2300pub fn prim_memq(args: &[Value]) -> PrimitiveResult {
2311 if args.len() != 2 {
2312 return Err("memq requires exactly 2 arguments".to_string());
2313 }
2314
2315 let obj = &args[0];
2316 let mut current = args[1].clone();
2317
2318 loop {
2319 match current {
2320 Value::Nil => return Ok(Value::bool(false)),
2321 Value::Pair(ref p) => {
2322 let pair = p.borrow();
2323 if obj.eq(&pair.car) {
2325 drop(pair);
2326 return Ok(current);
2327 }
2328 let cdr = pair.cdr.clone();
2329 drop(pair);
2330 current = cdr;
2331 }
2332 _ => return Err("memq: not a proper list".to_string()),
2333 }
2334 }
2335}
2336
2337pub fn prim_memv(args: &[Value]) -> PrimitiveResult {
2344 if args.len() != 2 {
2345 return Err("memv requires exactly 2 arguments".to_string());
2346 }
2347
2348 let obj = &args[0];
2349 let mut current = args[1].clone();
2350
2351 loop {
2352 match current {
2353 Value::Nil => return Ok(Value::bool(false)),
2354 Value::Pair(ref p) => {
2355 let pair = p.borrow();
2356 if obj.eqv(&pair.car) {
2358 drop(pair);
2359 return Ok(current);
2360 }
2361 let cdr = pair.cdr.clone();
2362 drop(pair);
2363 current = cdr;
2364 }
2365 _ => return Err("memv: not a proper list".to_string()),
2366 }
2367 }
2368}
2369
2370pub fn prim_member(args: &[Value]) -> PrimitiveResult {
2377 if args.len() != 2 {
2378 return Err("member requires exactly 2 arguments".to_string());
2379 }
2380
2381 let obj = &args[0];
2382 let mut current = args[1].clone();
2383
2384 loop {
2385 match current {
2386 Value::Nil => return Ok(Value::bool(false)),
2387 Value::Pair(ref p) => {
2388 let pair = p.borrow();
2389 if obj.equal(&pair.car) {
2391 drop(pair);
2392 return Ok(current);
2393 }
2394 let cdr = pair.cdr.clone();
2395 drop(pair);
2396 current = cdr;
2397 }
2398 _ => return Err("member: not a proper list".to_string()),
2399 }
2400 }
2401}
2402
2403pub fn prim_assq(args: &[Value]) -> PrimitiveResult {
2410 if args.len() != 2 {
2411 return Err("assq requires exactly 2 arguments".to_string());
2412 }
2413
2414 let obj = &args[0];
2415 let mut current = args[1].clone();
2416
2417 loop {
2418 match current {
2419 Value::Nil => return Ok(Value::bool(false)),
2420 Value::Pair(ref p) => {
2421 let pair = p.borrow();
2422 if let Value::Pair(ref inner_p) = pair.car {
2424 let inner_pair = inner_p.borrow();
2425 if obj.eq(&inner_pair.car) {
2426 drop(inner_pair);
2427 let result = pair.car.clone();
2428 drop(pair);
2429 return Ok(result);
2430 }
2431 }
2432 let cdr = pair.cdr.clone();
2433 drop(pair);
2434 current = cdr;
2435 }
2436 _ => return Err("assq: not a proper list".to_string()),
2437 }
2438 }
2439}
2440
2441pub fn prim_assv(args: &[Value]) -> PrimitiveResult {
2448 if args.len() != 2 {
2449 return Err("assv requires exactly 2 arguments".to_string());
2450 }
2451
2452 let obj = &args[0];
2453 let mut current = args[1].clone();
2454
2455 loop {
2456 match current {
2457 Value::Nil => return Ok(Value::bool(false)),
2458 Value::Pair(ref p) => {
2459 let pair = p.borrow();
2460 if let Value::Pair(ref inner_p) = pair.car {
2462 let inner_pair = inner_p.borrow();
2463 if obj.eqv(&inner_pair.car) {
2464 drop(inner_pair);
2465 let result = pair.car.clone();
2466 drop(pair);
2467 return Ok(result);
2468 }
2469 }
2470 let cdr = pair.cdr.clone();
2471 drop(pair);
2472 current = cdr;
2473 }
2474 _ => return Err("assv: not a proper list".to_string()),
2475 }
2476 }
2477}
2478
2479pub fn prim_assoc(args: &[Value]) -> PrimitiveResult {
2486 if args.len() != 2 {
2487 return Err("assoc requires exactly 2 arguments".to_string());
2488 }
2489
2490 let obj = &args[0];
2491 let mut current = args[1].clone();
2492
2493 loop {
2494 match current {
2495 Value::Nil => return Ok(Value::bool(false)),
2496 Value::Pair(ref p) => {
2497 let pair = p.borrow();
2498 if let Value::Pair(ref inner_p) = pair.car {
2500 let inner_pair = inner_p.borrow();
2501 if obj.equal(&inner_pair.car) {
2502 drop(inner_pair);
2503 let result = pair.car.clone();
2504 drop(pair);
2505 return Ok(result);
2506 }
2507 }
2508 let cdr = pair.cdr.clone();
2509 drop(pair);
2510 current = cdr;
2511 }
2512 _ => return Err("assoc: not a proper list".to_string()),
2513 }
2514 }
2515}
2516
2517pub fn prim_quantity_p(args: &[Value]) -> PrimitiveResult {
2533 if args.len() != 1 {
2534 return Err("quantity? requires exactly 1 argument".to_string());
2535 }
2536 Ok(Value::bool(false))
2538}
2539
2540pub fn prim_color_p(args: &[Value]) -> PrimitiveResult {
2546 if args.len() != 1 {
2547 return Err("color? requires exactly 1 argument".to_string());
2548 }
2549 Ok(Value::bool(false))
2551}
2552
2553pub fn prim_address_p(args: &[Value]) -> PrimitiveResult {
2559 if args.len() != 1 {
2560 return Err("address? requires exactly 1 argument".to_string());
2561 }
2562 Ok(Value::bool(false))
2564}
2565
2566pub fn prim_cadr(args: &[Value]) -> PrimitiveResult {
2576 if args.len() != 1 {
2577 return Err("cadr requires exactly 1 argument".to_string());
2578 }
2579
2580 let cdr = prim_cdr(args)?;
2582 prim_car(&[cdr])
2584}
2585
2586pub fn prim_caddr(args: &[Value]) -> PrimitiveResult {
2592 if args.len() != 1 {
2593 return Err("caddr requires exactly 1 argument".to_string());
2594 }
2595
2596 let cdr1 = prim_cdr(args)?;
2598 let cdr2 = prim_cdr(&[cdr1])?;
2599 prim_car(&[cdr2])
2601}
2602
2603pub fn prim_cadddr(args: &[Value]) -> PrimitiveResult {
2609 if args.len() != 1 {
2610 return Err("cadddr requires exactly 1 argument".to_string());
2611 }
2612
2613 let cdr1 = prim_cdr(args)?;
2615 let cdr2 = prim_cdr(&[cdr1])?;
2616 let cdr3 = prim_cdr(&[cdr2])?;
2617 prim_car(&[cdr3])
2619}
2620
2621pub fn prim_caar(args: &[Value]) -> PrimitiveResult {
2627 if args.len() != 1 {
2628 return Err("caar requires exactly 1 argument".to_string());
2629 }
2630
2631 let car = prim_car(args)?;
2632 prim_car(&[car])
2633}
2634
2635pub fn prim_cddr(args: &[Value]) -> PrimitiveResult {
2641 if args.len() != 1 {
2642 return Err("cddr requires exactly 1 argument".to_string());
2643 }
2644
2645 let cdr1 = prim_cdr(args)?;
2646 prim_cdr(&[cdr1])
2647}
2648
2649pub fn prim_cdar(args: &[Value]) -> PrimitiveResult {
2655 if args.len() != 1 {
2656 return Err("cdar requires exactly 1 argument".to_string());
2657 }
2658
2659 let car = prim_car(args)?;
2660 prim_cdr(&[car])
2661}
2662
2663pub fn prim_caaar(args: &[Value]) -> PrimitiveResult {
2669 if args.len() != 1 {
2670 return Err("caaar requires exactly 1 argument".to_string());
2671 }
2672
2673 let car1 = prim_car(args)?;
2674 let car2 = prim_car(&[car1])?;
2675 prim_car(&[car2])
2676}
2677
2678pub fn prim_cdaar(args: &[Value]) -> PrimitiveResult {
2684 if args.len() != 1 {
2685 return Err("cdaar requires exactly 1 argument".to_string());
2686 }
2687
2688 let car1 = prim_car(args)?;
2689 let car2 = prim_car(&[car1])?;
2690 prim_cdr(&[car2])
2691}
2692
2693pub fn prim_cadar(args: &[Value]) -> PrimitiveResult {
2699 if args.len() != 1 {
2700 return Err("cadar requires exactly 1 argument".to_string());
2701 }
2702
2703 let car = prim_car(args)?;
2704 let cdr = prim_cdr(&[car])?;
2705 prim_car(&[cdr])
2706}
2707
2708pub fn prim_cddar(args: &[Value]) -> PrimitiveResult {
2714 if args.len() != 1 {
2715 return Err("cddar requires exactly 1 argument".to_string());
2716 }
2717
2718 let car = prim_car(args)?;
2719 let cdr1 = prim_cdr(&[car])?;
2720 prim_cdr(&[cdr1])
2721}
2722
2723pub fn prim_caadr(args: &[Value]) -> PrimitiveResult {
2729 if args.len() != 1 {
2730 return Err("caadr requires exactly 1 argument".to_string());
2731 }
2732
2733 let cdr = prim_cdr(args)?;
2734 let car = prim_car(&[cdr])?;
2735 prim_car(&[car])
2736}
2737
2738pub fn prim_cdadr(args: &[Value]) -> PrimitiveResult {
2744 if args.len() != 1 {
2745 return Err("cdadr requires exactly 1 argument".to_string());
2746 }
2747
2748 let cdr = prim_cdr(args)?;
2749 let car = prim_car(&[cdr])?;
2750 prim_cdr(&[car])
2751}
2752
2753pub fn prim_last(args: &[Value]) -> PrimitiveResult {
2763 if args.len() != 1 {
2764 return Err("last requires exactly 1 argument".to_string());
2765 }
2766
2767 let mut current = args[0].clone();
2768 loop {
2769 match current {
2770 Value::Nil => return Err("last: empty list".to_string()),
2771 Value::Pair(ref p) => {
2772 let pair = p.borrow();
2773 match &pair.cdr {
2774 Value::Nil => {
2775 return Ok(pair.car.clone());
2777 }
2778 Value::Pair(_) => {
2779 let next = pair.cdr.clone();
2781 drop(pair);
2782 current = next;
2783 }
2784 _other => {
2785 return Ok(pair.car.clone());
2787 }
2788 }
2789 }
2790 _ => return Err(format!("last: not a list: {:?}", args[0])),
2791 }
2792 }
2793}
2794
2795pub fn prim_format_number(args: &[Value]) -> PrimitiveResult {
2818 if args.len() != 2 {
2819 return Err("format-number requires exactly 2 arguments".to_string());
2820 }
2821
2822 let n = match &args[0] {
2823 Value::Integer(i) => *i,
2824 Value::Real(r) => *r as i64,
2825 _ => return Err(format!("format-number: not a number: {:?}", args[0])),
2826 };
2827
2828 let format = match &args[1] {
2829 Value::String(s) => s.as_str(),
2830 Value::Symbol(s) => s.as_ref(),
2831 _ => return Err(format!("format-number: invalid format: {:?}", args[1])),
2832 };
2833
2834 let result = match format {
2836 "1" | "decimal" => n.to_string(),
2837 "I" | "roman-upper" => {
2838 let roman_str = match n {
2840 1 => "I",
2841 2 => "II",
2842 3 => "III",
2843 4 => "IV",
2844 5 => "V",
2845 6 => "VI",
2846 7 => "VII",
2847 8 => "VIII",
2848 9 => "IX",
2849 10 => "X",
2850 11 => "XI",
2851 12 => "XII",
2852 13 => "XIII",
2853 14 => "XIV",
2854 15 => "XV",
2855 16 => "XVI",
2856 17 => "XVII",
2857 18 => "XVIII",
2858 19 => "XIX",
2859 20 => "XX",
2860 _ => return Ok(Value::string(n.to_string())),
2861 };
2862 roman_str.to_string()
2863 }
2864 "i" | "roman-lower" => {
2865 let roman_str = match n {
2866 1 => "i",
2867 2 => "ii",
2868 3 => "iii",
2869 4 => "iv",
2870 5 => "v",
2871 6 => "vi",
2872 7 => "vii",
2873 8 => "viii",
2874 9 => "ix",
2875 10 => "x",
2876 11 => "xi",
2877 12 => "xii",
2878 13 => "xiii",
2879 14 => "xiv",
2880 15 => "xv",
2881 16 => "xvi",
2882 17 => "xvii",
2883 18 => "xviii",
2884 19 => "xix",
2885 20 => "xx",
2886 _ => return Ok(Value::string(n.to_string())),
2887 };
2888 roman_str.to_string()
2889 }
2890 "a" | "alpha-lower" => {
2891 if n >= 1 && n <= 26 {
2893 ((b'a' + (n as u8 - 1)) as char).to_string()
2894 } else {
2895 n.to_string()
2896 }
2897 }
2898 "A" | "alpha-upper" => {
2899 if n >= 1 && n <= 26 {
2901 ((b'A' + (n as u8 - 1)) as char).to_string()
2902 } else {
2903 n.to_string()
2904 }
2905 }
2906 _ => n.to_string(), };
2908
2909 Ok(Value::string(result))
2910}
2911
2912pub fn prim_format_number_list(args: &[Value]) -> PrimitiveResult {
2918 if args.is_empty() || args.len() > 2 {
2919 return Err("format-number-list requires 1 or 2 arguments".to_string());
2920 }
2921
2922 let separator = if args.len() == 2 {
2923 match &args[1] {
2924 Value::String(s) => s.as_str(),
2925 Value::Symbol(s) => s.as_ref(),
2926 _ => ".",
2927 }
2928 } else {
2929 "."
2930 };
2931
2932 let mut numbers = Vec::new();
2933 let mut current = args[0].clone();
2934
2935 loop {
2936 match current {
2937 Value::Nil => break,
2938 Value::Pair(ref p) => {
2939 let pair = p.borrow();
2940 match &pair.car {
2941 Value::Integer(n) => numbers.push(n.to_string()),
2942 Value::Real(r) => numbers.push((*r as i64).to_string()),
2943 _ => {
2944 return Err("format-number-list: list must contain only numbers".to_string())
2945 }
2946 }
2947 let cdr = pair.cdr.clone();
2948 drop(pair);
2949 current = cdr;
2950 }
2951 _ => return Err("format-number-list: not a proper list".to_string()),
2952 }
2953 }
2954
2955 Ok(Value::string(numbers.join(separator)))
2956}
2957
2958pub fn prim_current_node(args: &[Value]) -> PrimitiveResult {
2978 if !args.is_empty() {
2979 return Err("current-node requires no arguments".to_string());
2980 }
2981
2982 let ctx = crate::scheme::evaluator::get_evaluator_context()
2984 .ok_or_else(|| "current-node: no evaluator context available".to_string())?;
2985
2986 let node = ctx
2988 .current_node
2989 .ok_or_else(|| "current-node: no current node set".to_string())?;
2990
2991 Ok(Value::Node(node))
2992}
2993
2994pub fn prim_node_list_p(args: &[Value]) -> PrimitiveResult {
3000 if args.len() != 1 {
3001 return Err("node-list? requires exactly 1 argument".to_string());
3002 }
3003
3004 Ok(Value::bool(matches!(args[0], Value::NodeList(_))))
3005}
3006
3007pub fn prim_empty_node_list(args: &[Value]) -> PrimitiveResult {
3013 if !args.is_empty() {
3014 return Err("empty-node-list requires no arguments".to_string());
3015 }
3016
3017 Ok(Value::node_list(Box::new(EmptyNodeList::new())))
3018}
3019
3020pub fn prim_node_list_empty_p(args: &[Value]) -> PrimitiveResult {
3026 if args.len() != 1 {
3027 return Err("node-list-empty? requires exactly 1 argument".to_string());
3028 }
3029
3030 match &args[0] {
3031 Value::NodeList(nl) => {
3032 Ok(Value::bool(nl.is_empty()))
3034 }
3035 _ => Err(format!("node-list-empty?: not a node-list: {:?}", args[0])),
3036 }
3037}
3038
3039pub fn prim_node_list_length(args: &[Value]) -> PrimitiveResult {
3045 if args.len() != 1 {
3046 return Err("node-list-length requires exactly 1 argument".to_string());
3047 }
3048
3049 match &args[0] {
3050 Value::NodeList(nl) => {
3051 Ok(Value::integer(nl.length() as i64))
3053 }
3054 Value::Node(_) => {
3055 Ok(Value::integer(1))
3057 }
3058 _ => Err(format!("node-list-length: not a node-list: {:?}", args[0])),
3059 }
3060}
3061
3062pub fn prim_node_list_first(args: &[Value]) -> PrimitiveResult {
3069 if args.len() != 1 {
3070 return Err("node-list-first requires exactly 1 argument".to_string());
3071 }
3072
3073 match &args[0] {
3074 Value::NodeList(nl) => {
3075 if let Some(node) = nl.first() {
3077 Ok(Value::node(node))
3078 } else {
3079 Ok(Value::bool(false))
3080 }
3081 }
3082 Value::Node(_) => {
3083 Ok(args[0].clone())
3086 }
3087 _ => Err(format!("node-list-first: not a node-list: {:?}", args[0])),
3088 }
3089}
3090
3091pub fn prim_node_list_last(args: &[Value]) -> PrimitiveResult {
3098 if args.len() != 1 {
3099 return Err("node-list-last requires exactly 1 argument".to_string());
3100 }
3101
3102 match &args[0] {
3103 Value::NodeList(nl) => {
3104 let len = nl.length();
3105 if len == 0 {
3106 Ok(Value::bool(false))
3107 } else {
3108 let mut current_nl = nl.clone();
3110 let mut last_node = None;
3111
3112 while let Some(node) = current_nl.first() {
3114 last_node = Some(node);
3115 let rest = current_nl.rest();
3116 if rest.is_empty() {
3117 break;
3118 }
3119 current_nl = std::rc::Rc::new(rest);
3120 }
3121
3122 if let Some(node) = last_node {
3123 Ok(Value::node(node))
3124 } else {
3125 Ok(Value::bool(false))
3126 }
3127 }
3128 }
3129 Value::Node(_) => {
3130 Ok(args[0].clone())
3133 }
3134 _ => Err(format!("node-list-last: not a node-list: {:?}", args[0])),
3135 }
3136}
3137
3138pub fn prim_node_list_to_list(args: &[Value]) -> PrimitiveResult {
3145 if args.len() != 1 {
3146 return Err("node-list->list requires exactly 1 argument".to_string());
3147 }
3148
3149 match &args[0] {
3150 Value::NodeList(nl) => {
3151 fn build_list(nl: &std::rc::Rc<Box<dyn crate::grove::NodeList>>) -> Value {
3153 if nl.is_empty() {
3154 Value::Nil
3155 } else if let Some(first) = nl.first() {
3156 let rest_nl = nl.rest();
3157 let rest_list = build_list(&std::rc::Rc::new(rest_nl));
3158 Value::cons(Value::node(first), rest_list)
3159 } else {
3160 Value::Nil
3161 }
3162 }
3163
3164 Ok(build_list(nl))
3165 }
3166 Value::Nil => {
3167 Ok(Value::Nil)
3169 }
3170 Value::Pair(_) => {
3171 Ok(args[0].clone())
3174 }
3175 _ => Err(format!("node-list->list: not a node-list: {:?}", args[0])),
3176 }
3177}
3178
3179pub fn prim_node_list_rest(args: &[Value]) -> PrimitiveResult {
3186 if args.len() != 1 {
3187 return Err("node-list-rest requires exactly 1 argument".to_string());
3188 }
3189
3190 match &args[0] {
3191 Value::NodeList(_nl) => {
3192 let rest = _nl.rest();
3194 Ok(Value::node_list(rest))
3195 }
3196 Value::Node(_) => {
3197 Ok(Value::node_list(Box::new(EmptyNodeList::new())))
3200 }
3201 _ => Err(format!("node-list-rest: not a node-list: {:?}", args[0])),
3202 }
3203}
3204
3205pub fn prim_node_list_ref(args: &[Value]) -> PrimitiveResult {
3212 if args.len() != 2 {
3213 return Err("node-list-ref requires exactly 2 arguments".to_string());
3214 }
3215
3216 match &args[0] {
3217 Value::NodeList(nl) => {
3218 match &args[1] {
3220 Value::Integer(idx) => {
3221 if *idx < 0 {
3223 return Err("node-list-ref: index must be non-negative".to_string());
3224 }
3225 if let Some(node) = nl.get(*idx as usize) {
3226 Ok(Value::node(node))
3227 } else {
3228 Ok(Value::bool(false))
3229 }
3230 }
3231 _ => Err(format!("node-list-ref: index not an integer: {:?}", args[1])),
3232 }
3233 }
3234 _ => Err(format!("node-list-ref: not a node-list: {:?}", args[0])),
3235 }
3236}
3237
3238pub fn prim_node_list_reverse(args: &[Value]) -> PrimitiveResult {
3244 if args.len() != 1 {
3245 return Err("node-list-reverse requires exactly 1 argument".to_string());
3246 }
3247
3248 match &args[0] {
3249 Value::NodeList(nl) => {
3250 let mut nodes: Vec<Box<dyn Node>> = Vec::new();
3252 let mut current = nl.clone();
3253 while let Some(node) = current.first() {
3254 nodes.push(node);
3255 current = std::rc::Rc::new(current.rest());
3256 if current.length() == 0 {
3257 break;
3258 }
3259 }
3260 nodes.reverse();
3261
3262 use crate::grove::VecNodeList;
3264 Ok(Value::node_list(Box::new(VecNodeList::new(nodes))))
3265 }
3266 _ => Err(format!("node-list-reverse: not a node-list: {:?}", args[0])),
3267 }
3268}
3269
3270pub fn prim_node_list_remove_duplicates(args: &[Value]) -> PrimitiveResult {
3277 if args.len() != 1 {
3278 return Err("node-list-remove-duplicates requires exactly 1 argument".to_string());
3279 }
3280
3281 match &args[0] {
3282 Value::NodeList(nl) => {
3283 let mut unique_nodes = Vec::new();
3284
3285 let mut index = 0;
3287 loop {
3288 if let Some(node) = nl.get(index) {
3289 let is_duplicate = unique_nodes.iter().any(|existing: &Box<dyn crate::grove::Node>| {
3291 existing.node_eq(node.as_ref())
3292 });
3293
3294 if !is_duplicate {
3295 unique_nodes.push(node);
3296 }
3297 index += 1;
3298 } else {
3299 break;
3300 }
3301 }
3302
3303 Ok(Value::node_list(Box::new(crate::grove::VecNodeList::new(unique_nodes))))
3304 }
3305 Value::Node(_) => {
3306 Ok(args[0].clone())
3309 }
3310 _ => Err(format!(
3311 "1st argument for primitive \"node-list-remove-duplicates\" of wrong type: {:?} not a node-list",
3312 args[0]
3313 )),
3314 }
3315}
3316
3317pub fn prim_node_list_count(args: &[Value]) -> PrimitiveResult {
3324 let unique_nl = prim_node_list_remove_duplicates(args)?;
3326 prim_node_list_length(&[unique_nl])
3327}
3328
3329pub fn prim_node_list_contains_p(args: &[Value]) -> PrimitiveResult {
3336 if args.len() != 2 {
3337 return Err("node-list-contains? requires exactly 2 arguments".to_string());
3338 }
3339
3340 let search_node = match &args[1] {
3341 Value::Node(n) => n,
3342 _ => return Err(format!("node-list-contains?: second argument not a node: {:?}", args[1])),
3343 };
3344
3345 match &args[0] {
3346 Value::NodeList(nl) => {
3347 let mut index = 0;
3349 loop {
3350 if let Some(node) = nl.get(index) {
3351 if node.node_eq(search_node.as_ref().as_ref()) {
3353 return Ok(Value::bool(true));
3354 }
3355 index += 1;
3356 } else {
3357 break;
3358 }
3359 }
3360
3361 Ok(Value::bool(false))
3363 }
3364 Value::Nil => {
3365 Ok(Value::bool(false))
3367 }
3368 Value::Pair(_) => {
3369 let mut current = args[0].clone();
3371 loop {
3372 match current {
3373 Value::Nil => return Ok(Value::bool(false)),
3374 Value::Pair(ref p) => {
3375 let (car, cdr) = {
3376 let pair_data = p.borrow();
3377 (pair_data.car.clone(), pair_data.cdr.clone())
3378 };
3379
3380 if let Value::Node(ref n) = car {
3382 if n.as_ref().node_eq(search_node.as_ref().as_ref()) {
3383 return Ok(Value::bool(true));
3384 }
3385 }
3386 current = cdr;
3388 }
3389 _ => return Err(format!("node-list-contains?: malformed list: {:?}", current)),
3390 }
3391 }
3392 }
3393 _ => Err(format!("node-list-contains?: first argument not a node-list: {:?}", args[0])),
3394 }
3395}
3396
3397pub fn prim_node_p(args: &[Value]) -> PrimitiveResult {
3403 if args.len() != 1 {
3404 return Err("node? requires exactly 1 argument".to_string());
3405 }
3406
3407 Ok(Value::bool(matches!(args[0], Value::Node(_))))
3408}
3409
3410pub fn prim_gi(args: &[Value]) -> PrimitiveResult {
3417 if args.len() != 1 {
3418 return Err("gi requires exactly 1 argument".to_string());
3419 }
3420
3421 match &args[0] {
3422 Value::Bool(false) => {
3423 Ok(Value::bool(false))
3425 }
3426 Value::Node(node) => {
3427 if let Some(gi) = node.gi() {
3428 Ok(Value::string(gi))
3429 } else {
3430 Ok(Value::bool(false))
3431 }
3432 }
3433 Value::NodeList(nl) => {
3434 if nl.length() == 1 {
3436 if let Some(node) = nl.first() {
3437 if let Some(gi) = node.gi() {
3438 Ok(Value::string(gi))
3439 } else {
3440 Ok(Value::bool(false))
3441 }
3442 } else {
3443 Ok(Value::bool(false))
3444 }
3445 } else {
3446 Err(format!("gi: node-list must have exactly 1 element, got {}", nl.length()))
3447 }
3448 }
3449 _ => Err(format!(
3450 "1st argument for primitive \"gi\" of wrong type: {:?} not an optional singleton node list",
3451 args[0]
3452 )),
3453 }
3454}
3455
3456pub fn prim_data(args: &[Value]) -> PrimitiveResult {
3464 if args.len() != 1 {
3465 return Err("data requires exactly 1 argument".to_string());
3466 }
3467
3468 match &args[0] {
3469 Value::Node(node) => {
3470 if let Some(data) = node.data() {
3474 Ok(Value::string(data))
3475 } else {
3476 Ok(Value::string(String::new()))
3478 }
3479 }
3480 Value::NodeList(nl) => {
3481 let mut result = String::new();
3485 let mut current = nl.clone();
3486
3487 loop {
3488 if let Some(node) = current.first() {
3489 if let Some(data) = node.data() {
3490 result.push_str(&data);
3491 }
3492 current = std::rc::Rc::new(current.rest());
3493 if current.length() == 0 {
3494 break;
3495 }
3496 } else {
3497 break;
3498 }
3499 }
3500
3501 Ok(Value::string(result))
3504 }
3505 _ => Err(format!(
3506 "1st argument for primitive \"data\" of wrong type: {:?} not an optional singleton node list",
3507 args[0]
3508 )),
3509 }
3510}
3511
3512pub fn prim_attribute_string(args: &[Value]) -> PrimitiveResult {
3521 if args.len() != 2 {
3522 return Err("attribute-string requires exactly 2 arguments".to_string());
3523 }
3524
3525 let name = match &args[0] {
3526 Value::String(s) => s.as_str(),
3527 _ => return Err(format!("attribute-string: name not a string: {:?}", args[0])),
3528 };
3529
3530 match &args[1] {
3531 Value::Node(node) => {
3532 if let Some(value) = node.attribute_string(name) {
3533 Ok(Value::string(value))
3534 } else {
3535 Ok(Value::bool(false))
3536 }
3537 }
3538 Value::NodeList(nl) => {
3539 if nl.length() == 0 {
3542 Ok(Value::bool(false))
3543 } else if nl.length() == 1 {
3544 if let Some(node) = nl.first() {
3545 if let Some(value) = node.attribute_string(name) {
3546 Ok(Value::string(value))
3547 } else {
3548 Ok(Value::bool(false))
3549 }
3550 } else {
3551 Ok(Value::bool(false))
3552 }
3553 } else {
3554 Err(format!("attribute-string: node-list must have exactly 1 element, got {}", nl.length()))
3555 }
3556 }
3557 Value::Bool(false) => {
3558 Ok(Value::bool(false))
3561 }
3562 _ => Err(format!(
3563 "2nd argument for primitive \"attribute-string\" of wrong type: {:?} not an optional singleton node list",
3564 args[1]
3565 )),
3566 }
3567}
3568
3569pub fn prim_children(args: &[Value]) -> PrimitiveResult {
3576 if args.len() != 1 {
3577 return Err("children requires exactly 1 argument".to_string());
3578 }
3579
3580 match &args[0] {
3581 Value::Node(node) => {
3582 let children = node.children();
3583 Ok(Value::node_list(children))
3584 }
3585 Value::NodeList(nl) => {
3586 if nl.length() == 1 {
3592 if let Some(node) = nl.first() {
3594 let children = node.children();
3595 Ok(Value::node_list(children))
3596 } else {
3597 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new())))
3598 }
3599 } else {
3600 let mut all_children: Vec<Box<dyn crate::grove::Node>> = Vec::new();
3602 let mut index = 0;
3603 while let Some(node) = nl.get(index) {
3604 let children = node.children();
3605 let mut child_index = 0;
3607 while let Some(child) = children.get(child_index) {
3608 all_children.push(child);
3609 child_index += 1;
3610 }
3611 index += 1;
3612 }
3613 Ok(Value::node_list(Box::new(crate::grove::VecNodeList::new(all_children))))
3614 }
3615 }
3616 Value::Bool(false) | Value::Unspecified => {
3617 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new())))
3619 }
3620 _ => Err(format!("children: not a node or node-list: {:?}", args[0])),
3621 }
3622}
3623
3624pub fn prim_select_children(args: &[Value]) -> PrimitiveResult {
3631 if args.len() != 2 {
3632 return Err("select-children requires exactly 2 arguments".to_string());
3633 }
3634
3635 let gi_name = match &args[0] {
3636 Value::String(s) => s.as_str(),
3637 _ => return Err(format!("select-children: first argument not a string: {:?}", args[0])),
3638 };
3639
3640 match &args[1] {
3641 Value::Node(node) => {
3642 let children = node.children();
3644
3645 let mut matching = Vec::new();
3647 let mut current = children;
3648 while !current.is_empty() {
3649 if let Some(child) = current.first() {
3650 if let Some(child_gi) = child.gi() {
3651 if child_gi == gi_name {
3652 matching.push(child);
3653 }
3654 }
3655 current = current.rest();
3656 } else {
3657 break;
3658 }
3659 }
3660
3661 Ok(Value::node_list(Box::new(crate::grove::VecNodeList::new(matching))))
3662 }
3663 Value::NodeList(nl) => {
3664 if let Some(node) = nl.first() {
3667 prim_select_children(&[args[0].clone(), Value::node(node)])
3669 } else {
3670 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new())))
3672 }
3673 }
3674 _ => Err(format!(
3675 "2nd argument for primitive \"select-children\" of wrong type: {:?} not an optional singleton node list",
3676 args[1]
3677 )),
3678 }
3679}
3680
3681pub fn prim_parent(args: &[Value]) -> PrimitiveResult {
3688 if args.len() != 1 {
3689 return Err("parent requires exactly 1 argument".to_string());
3690 }
3691
3692 let node: Box<dyn crate::grove::Node> = match &args[0] {
3693 Value::Bool(false) => {
3694 return Ok(Value::bool(false));
3696 }
3697 Value::Node(n) => n.clone_node(),
3698 Value::NodeList(nl) => {
3699 if let Some(n) = nl.first() {
3701 n
3702 } else {
3703 return Ok(Value::bool(false)); }
3705 }
3706 _ => return Err(format!(
3707 "1st argument for primitive \"parent\" of wrong type: {:?} not an optional singleton node list",
3708 args[0]
3709 )),
3710 };
3711
3712 if let Some(parent) = node.parent() {
3713 Ok(Value::node(parent))
3714 } else {
3715 Ok(Value::bool(false))
3716 }
3717}
3718
3719pub fn prim_tree_root(args: &[Value]) -> PrimitiveResult {
3726 if args.len() != 1 {
3727 return Err("tree-root requires exactly 1 argument".to_string());
3728 }
3729
3730 match &args[0] {
3731 Value::Node(node) => {
3732 let mut current = node.clone_node();
3734 while let Some(parent) = current.parent() {
3735 current = parent;
3736 }
3737 Ok(Value::node(current))
3738 }
3739 _ => Err(format!(
3740 "1st argument for primitive \"tree-root\" of wrong type: {:?} not an optional singleton node list",
3741 args[0]
3742 )),
3743 }
3744}
3745
3746pub fn prim_ancestors(args: &[Value]) -> PrimitiveResult {
3754 if args.len() != 1 {
3755 return Err("ancestors requires exactly 1 argument".to_string());
3756 }
3757
3758 match &args[0] {
3759 Value::Node(node) => {
3760 let mut ancestor_nodes = Vec::new();
3762 let mut current = node.clone_node();
3763
3764 while let Some(parent) = current.parent() {
3765 ancestor_nodes.push(parent.clone_node());
3766 current = parent;
3767 }
3768
3769 Ok(Value::node_list(Box::new(crate::grove::VecNodeList::new(ancestor_nodes))))
3770 }
3771 _ => Err(format!(
3772 "1st argument for primitive \"ancestors\" of wrong type: {:?} not an optional singleton node list",
3773 args[0]
3774 )),
3775 }
3776}
3777
3778pub fn prim_id(args: &[Value]) -> PrimitiveResult {
3785 if args.len() != 1 {
3786 return Err("id requires exactly 1 argument".to_string());
3787 }
3788
3789 match &args[0] {
3790 Value::Node(node) => {
3791 if let Some(id) = node.id() {
3792 Ok(Value::string(id))
3793 } else {
3794 Ok(Value::bool(false))
3795 }
3796 }
3797 _ => Err(format!("id: not a node: {:?}", args[0])),
3798 }
3799}
3800
3801pub fn prim_ancestor(args: &[Value]) -> PrimitiveResult {
3809 if args.len() != 2 {
3810 return Err("ancestor requires exactly 2 arguments".to_string());
3811 }
3812
3813 let gi_name = match &args[0] {
3815 Value::String(s) => s.clone(),
3816 _ => return Err(format!("ancestor: first argument not a string: {:?}", args[0])),
3817 };
3818
3819 let starting_node: Box<dyn crate::grove::Node> = match &args[1] {
3821 Value::Node(n) => n.clone_node(),
3822 Value::NodeList(nl) => {
3823 if let Some(n) = nl.first() {
3825 n
3826 } else {
3827 return Ok(Value::bool(false)); }
3829 }
3830 _ => return Err(format!(
3831 "2nd argument for primitive \"ancestor\" of wrong type: {:?} not an optional singleton node list",
3832 args[1]
3833 )),
3834 };
3835
3836 let mut current = starting_node.parent();
3838 while let Some(parent_node) = current {
3839 if let Some(parent_gi) = parent_node.gi() {
3840 if parent_gi == gi_name.as_str() {
3841 return Ok(Value::node(parent_node));
3842 }
3843 }
3844 current = parent_node.parent();
3845 }
3846
3847 Ok(Value::bool(false))
3849}
3850
3851pub fn prim_descendants(args: &[Value]) -> PrimitiveResult {
3858 if args.len() != 1 {
3859 return Err("descendants requires exactly 1 argument".to_string());
3860 }
3861
3862 match &args[0] {
3863 Value::Node(node) => {
3864 let mut descendants = Vec::new();
3865 collect_descendants(node.as_ref().as_ref(), &mut descendants);
3869 Ok(Value::node_list(Box::new(crate::grove::VecNodeList::new(descendants))))
3870 }
3871 Value::NodeList(nl) => {
3872 if let Some(node) = nl.first() {
3874 let mut descendants = Vec::new();
3875 collect_descendants(&*node, &mut descendants);
3877 Ok(Value::node_list(Box::new(crate::grove::VecNodeList::new(descendants))))
3878 } else {
3879 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new())))
3880 }
3881 }
3882 _ => Err(format!("descendants: not a node or node-list: {:?}", args[0])),
3883 }
3884}
3885
3886fn collect_descendants(node: &dyn crate::grove::Node, result: &mut Vec<Box<dyn crate::grove::Node>>) {
3888 let children = node.children();
3889 let len = children.length();
3890
3891 for i in 0..len {
3892 if let Some(child) = children.get(i) {
3893 result.push(child.clone_node());
3895
3896 collect_descendants(&*child, result);
3899 }
3900 }
3901}
3902
3903pub fn prim_follow(args: &[Value]) -> PrimitiveResult {
3909 if args.len() != 1 {
3910 return Err("follow requires exactly 1 argument".to_string());
3911 }
3912
3913 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new())))
3916}
3917
3918pub fn prim_preced(args: &[Value]) -> PrimitiveResult {
3924 if args.len() != 1 {
3925 return Err("preced requires exactly 1 argument".to_string());
3926 }
3927
3928 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new())))
3931}
3932
3933pub fn prim_attributes(args: &[Value]) -> PrimitiveResult {
3939 if args.len() != 1 {
3940 return Err("attributes requires exactly 1 argument".to_string());
3941 }
3942
3943 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new())))
3946}
3947
3948pub fn prim_select_elements(args: &[Value]) -> PrimitiveResult {
3954 if args.len() != 2 {
3955 return Err("select-elements requires exactly 2 arguments".to_string());
3956 }
3957
3958 let node_list = match &args[0] {
3959 Value::NodeList(nl) => nl,
3960 _ => return Err(format!("select-elements: first argument not a node-list: {:?}", args[0])),
3961 };
3962
3963 let gi_name = match &args[1] {
3964 Value::String(s) => s.as_str(),
3965 _ => return Err(format!("select-elements: second argument not a string: {:?}", args[1])),
3966 };
3967
3968 let mut result_nodes = Vec::new();
3970
3971 let mut index = 0;
3973 loop {
3974 if let Some(node) = node_list.get(index) {
3975 if let Some(node_gi) = node.gi() {
3977 if node_gi == gi_name {
3978 result_nodes.push(node);
3979 }
3980 }
3981 index += 1;
3982 } else {
3983 break;
3984 }
3985 }
3986
3987 Ok(Value::node_list(Box::new(crate::grove::VecNodeList::new(result_nodes))))
3989}
3990
3991pub fn prim_element_with_id(args: &[Value]) -> PrimitiveResult {
3999 if args.is_empty() || args.len() > 2 {
4000 return Err("element-with-id requires 1 or 2 arguments".to_string());
4001 }
4002
4003 let id = match &args[0] {
4005 Value::String(s) => s.as_str(),
4006 _ => return Err(format!(
4007 "1st argument for primitive \"element-with-id\" of wrong type: {:?} not a string",
4008 args[0]
4009 )),
4010 };
4011
4012 let ctx = crate::scheme::evaluator::get_evaluator_context()
4014 .ok_or_else(|| "element-with-id: no evaluator context available".to_string())?;
4015
4016 let grove = ctx.grove
4017 .as_ref()
4018 .ok_or_else(|| "element-with-id: no grove available".to_string())?;
4019
4020 match grove.element_with_id(id) {
4022 Some(node) => Ok(Value::node(node)),
4023 None => Ok(Value::bool(false)),
4024 }
4025}
4026
4027pub fn prim_expt(args: &[Value]) -> PrimitiveResult {
4037 if args.len() != 2 {
4038 return Err("expt requires exactly 2 arguments".to_string());
4039 }
4040
4041 let base = match &args[0] {
4042 Value::Integer(n) => *n as f64,
4043 Value::Real(r) => *r,
4044 _ => return Err(format!("expt: not a number: {:?}", args[0])),
4045 };
4046
4047 let exponent = match &args[1] {
4048 Value::Integer(n) => *n as f64,
4049 Value::Real(r) => *r,
4050 _ => return Err(format!("expt: not a number: {:?}", args[1])),
4051 };
4052
4053 let result = base.powf(exponent);
4054
4055 if matches!(args[0], Value::Integer(_)) && matches!(args[1], Value::Integer(_)) && result.fract() == 0.0 {
4057 Ok(Value::integer(result as i64))
4058 } else {
4059 Ok(Value::real(result))
4060 }
4061}
4062
4063pub fn prim_sqrt(args: &[Value]) -> PrimitiveResult {
4069 if args.len() != 1 {
4070 return Err("sqrt requires exactly 1 argument".to_string());
4071 }
4072
4073 let n = match &args[0] {
4074 Value::Integer(i) => *i as f64,
4075 Value::Real(r) => *r,
4076 _ => return Err(format!("sqrt: not a number: {:?}", args[0])),
4077 };
4078
4079 if n < 0.0 {
4080 return Err("sqrt: negative argument".to_string());
4081 }
4082
4083 Ok(Value::real(n.sqrt()))
4084}
4085
4086pub fn prim_sin(args: &[Value]) -> PrimitiveResult {
4092 if args.len() != 1 {
4093 return Err("sin requires exactly 1 argument".to_string());
4094 }
4095
4096 let n = match &args[0] {
4097 Value::Integer(i) => *i as f64,
4098 Value::Real(r) => *r,
4099 _ => return Err(format!("sin: not a number: {:?}", args[0])),
4100 };
4101
4102 Ok(Value::real(n.sin()))
4103}
4104
4105pub fn prim_cos(args: &[Value]) -> PrimitiveResult {
4111 if args.len() != 1 {
4112 return Err("cos requires exactly 1 argument".to_string());
4113 }
4114
4115 let n = match &args[0] {
4116 Value::Integer(i) => *i as f64,
4117 Value::Real(r) => *r,
4118 _ => return Err(format!("cos: not a number: {:?}", args[0])),
4119 };
4120
4121 Ok(Value::real(n.cos()))
4122}
4123
4124pub fn prim_tan(args: &[Value]) -> PrimitiveResult {
4130 if args.len() != 1 {
4131 return Err("tan requires exactly 1 argument".to_string());
4132 }
4133
4134 let n = match &args[0] {
4135 Value::Integer(i) => *i as f64,
4136 Value::Real(r) => *r,
4137 _ => return Err(format!("tan: not a number: {:?}", args[0])),
4138 };
4139
4140 Ok(Value::real(n.tan()))
4141}
4142
4143pub fn prim_atan(args: &[Value]) -> PrimitiveResult {
4149 if args.len() != 1 {
4150 return Err("atan requires exactly 1 argument".to_string());
4151 }
4152
4153 let n = match &args[0] {
4154 Value::Integer(i) => *i as f64,
4155 Value::Real(r) => *r,
4156 _ => return Err(format!("atan: not a number: {:?}", args[0])),
4157 };
4158
4159 Ok(Value::real(n.atan()))
4160}
4161
4162pub fn prim_log(args: &[Value]) -> PrimitiveResult {
4168 if args.len() != 1 {
4169 return Err("log requires exactly 1 argument".to_string());
4170 }
4171
4172 let n = match &args[0] {
4173 Value::Integer(i) => *i as f64,
4174 Value::Real(r) => *r,
4175 _ => return Err(format!("log: not a number: {:?}", args[0])),
4176 };
4177
4178 if n <= 0.0 {
4179 return Err("log: argument must be positive".to_string());
4180 }
4181
4182 Ok(Value::real(n.ln()))
4183}
4184
4185pub fn prim_exp(args: &[Value]) -> PrimitiveResult {
4191 if args.len() != 1 {
4192 return Err("exp requires exactly 1 argument".to_string());
4193 }
4194
4195 let n = match &args[0] {
4196 Value::Integer(i) => *i as f64,
4197 Value::Real(r) => *r,
4198 _ => return Err(format!("exp: not a number: {:?}", args[0])),
4199 };
4200
4201 Ok(Value::real(n.exp()))
4202}
4203
4204pub fn prim_asin(args: &[Value]) -> PrimitiveResult {
4210 if args.len() != 1 {
4211 return Err("asin requires exactly 1 argument".to_string());
4212 }
4213
4214 let n = match &args[0] {
4215 Value::Integer(i) => *i as f64,
4216 Value::Real(r) => *r,
4217 _ => return Err(format!("asin: not a number: {:?}", args[0])),
4218 };
4219
4220 if n < -1.0 || n > 1.0 {
4221 return Err("asin: argument must be in range [-1, 1]".to_string());
4222 }
4223
4224 Ok(Value::real(n.asin()))
4225}
4226
4227pub fn prim_acos(args: &[Value]) -> PrimitiveResult {
4233 if args.len() != 1 {
4234 return Err("acos requires exactly 1 argument".to_string());
4235 }
4236
4237 let n = match &args[0] {
4238 Value::Integer(i) => *i as f64,
4239 Value::Real(r) => *r,
4240 _ => return Err(format!("acos: not a number: {:?}", args[0])),
4241 };
4242
4243 if n < -1.0 || n > 1.0 {
4244 return Err("acos: argument must be in range [-1, 1]".to_string());
4245 }
4246
4247 Ok(Value::real(n.acos()))
4248}
4249
4250pub fn prim_exact_p(args: &[Value]) -> PrimitiveResult {
4256 if args.len() != 1 {
4257 return Err("exact? requires exactly 1 argument".to_string());
4258 }
4259
4260 Ok(Value::bool(matches!(args[0], Value::Integer(_))))
4261}
4262
4263pub fn prim_inexact_p(args: &[Value]) -> PrimitiveResult {
4269 if args.len() != 1 {
4270 return Err("inexact? requires exactly 1 argument".to_string());
4271 }
4272
4273 Ok(Value::bool(matches!(args[0], Value::Real(_))))
4274}
4275
4276pub fn prim_exact_to_inexact(args: &[Value]) -> PrimitiveResult {
4282 if args.len() != 1 {
4283 return Err("exact->inexact requires exactly 1 argument".to_string());
4284 }
4285
4286 match &args[0] {
4287 Value::Integer(i) => Ok(Value::real(*i as f64)),
4288 Value::Real(r) => Ok(Value::real(*r)), _ => Err(format!("exact->inexact: not a number: {:?}", args[0])),
4290 }
4291}
4292
4293pub fn prim_inexact_to_exact(args: &[Value]) -> PrimitiveResult {
4299 if args.len() != 1 {
4300 return Err("inexact->exact requires exactly 1 argument".to_string());
4301 }
4302
4303 match &args[0] {
4304 Value::Real(r) => {
4305 if r.fract() == 0.0 && r.is_finite() {
4306 Ok(Value::integer(*r as i64))
4307 } else {
4308 Err("inexact->exact: cannot convert non-integer to exact".to_string())
4309 }
4310 }
4311 Value::Integer(i) => Ok(Value::integer(*i)), _ => Err(format!("inexact->exact: not a number: {:?}", args[0])),
4313 }
4314}
4315
4316pub fn prim_entity_system_id(_args: &[Value]) -> PrimitiveResult {
4322 Ok(Value::bool(false)) }
4324
4325pub fn prim_entity_public_id(_args: &[Value]) -> PrimitiveResult {
4327 Ok(Value::bool(false)) }
4329
4330pub fn prim_notation_system_id(_args: &[Value]) -> PrimitiveResult {
4332 Ok(Value::bool(false)) }
4334
4335pub fn prim_notation_public_id(_args: &[Value]) -> PrimitiveResult {
4337 Ok(Value::bool(false)) }
4339
4340pub fn prim_color(_args: &[Value]) -> PrimitiveResult {
4346 Ok(Value::Unspecified) }
4348
4349pub fn prim_color_space(_args: &[Value]) -> PrimitiveResult {
4351 Ok(Value::Unspecified) }
4353
4354pub fn prim_color_space_p(args: &[Value]) -> PrimitiveResult {
4356 if args.len() != 1 {
4357 return Err("color-space? requires exactly 1 argument".to_string());
4358 }
4359 Ok(Value::bool(false)) }
4361
4362pub fn prim_display_space(_args: &[Value]) -> PrimitiveResult {
4364 Ok(Value::Unspecified) }
4366
4367pub fn prim_display_space_p(args: &[Value]) -> PrimitiveResult {
4369 if args.len() != 1 {
4370 return Err("display-space? requires exactly 1 argument".to_string());
4371 }
4372 Ok(Value::bool(false)) }
4374
4375pub fn prim_inline_space(_args: &[Value]) -> PrimitiveResult {
4377 Ok(Value::Unspecified) }
4379
4380pub fn prim_inline_space_p(args: &[Value]) -> PrimitiveResult {
4382 if args.len() != 1 {
4383 return Err("inline-space? requires exactly 1 argument".to_string());
4384 }
4385 Ok(Value::bool(false)) }
4387
4388pub fn prim_glyph_id(_args: &[Value]) -> PrimitiveResult {
4390 Ok(Value::Unspecified) }
4392
4393pub fn prim_glyph_id_p(args: &[Value]) -> PrimitiveResult {
4395 if args.len() != 1 {
4396 return Err("glyph-id? requires exactly 1 argument".to_string());
4397 }
4398 Ok(Value::bool(false)) }
4400
4401pub fn prim_glyph_subst_table(_args: &[Value]) -> PrimitiveResult {
4403 Ok(Value::Unspecified) }
4405
4406pub fn prim_glyph_subst_table_p(args: &[Value]) -> PrimitiveResult {
4408 if args.len() != 1 {
4409 return Err("glyph-subst-table? requires exactly 1 argument".to_string());
4410 }
4411 Ok(Value::bool(false)) }
4413
4414pub fn prim_glyph_subst(_args: &[Value]) -> PrimitiveResult {
4416 Ok(Value::Unspecified) }
4418
4419pub fn prim_current_node_address(_args: &[Value]) -> PrimitiveResult {
4421 Ok(Value::Unspecified) }
4423
4424pub fn prim_address_local_p(args: &[Value]) -> PrimitiveResult {
4426 if args.len() != 1 {
4427 return Err("address-local? requires exactly 1 argument".to_string());
4428 }
4429 Ok(Value::bool(false)) }
4431
4432pub fn prim_address_visited_p(args: &[Value]) -> PrimitiveResult {
4434 if args.len() != 1 {
4435 return Err("address-visited? requires exactly 1 argument".to_string());
4436 }
4437 Ok(Value::bool(false)) }
4439
4440pub fn prim_node_list(_args: &[Value]) -> PrimitiveResult {
4446 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
4448
4449pub fn prim_node_list_map(_args: &[Value]) -> PrimitiveResult {
4457 Err("node-list-map should be handled as a special form in the evaluator".to_string())
4458}
4459
4460pub fn prim_node_property(_args: &[Value]) -> PrimitiveResult {
4462 Ok(Value::Unspecified) }
4464
4465pub fn prim_match_element_p(_args: &[Value]) -> PrimitiveResult {
4467 Ok(Value::bool(false)) }
4469
4470pub fn prim_named_node_list_p(args: &[Value]) -> PrimitiveResult {
4472 if args.len() != 1 {
4473 return Err("named-node-list? requires exactly 1 argument".to_string());
4474 }
4475 Ok(Value::bool(false)) }
4477
4478pub fn prim_node_list_eq(args: &[Value]) -> PrimitiveResult {
4486 if args.len() != 2 {
4487 return Err("node-list=? requires exactly 2 arguments".to_string());
4488 }
4489
4490 match (&args[0], &args[1]) {
4492 (Value::Node(n1), Value::Node(n2)) => {
4494 Ok(Value::bool(n1.as_ref().as_ref().node_eq(n2.as_ref().as_ref())))
4495 }
4496
4497 (Value::Node(n), Value::NodeList(nl)) | (Value::NodeList(nl), Value::Node(n)) => {
4499 if nl.length() != 1 {
4500 return Ok(Value::bool(false));
4501 }
4502 if let Some(nl_node) = nl.get(0) {
4503 Ok(Value::bool(n.as_ref().as_ref().node_eq(nl_node.as_ref())))
4505 } else {
4506 Ok(Value::bool(false))
4507 }
4508 }
4509
4510 (Value::NodeList(nl1), Value::NodeList(nl2)) => {
4512 let len1 = nl1.length();
4513 let len2 = nl2.length();
4514
4515 if len1 != len2 {
4517 return Ok(Value::bool(false));
4518 }
4519
4520 for i in 0..len1 {
4522 let node1 = nl1.get(i);
4523 let node2 = nl2.get(i);
4524
4525 match (node1, node2) {
4526 (Some(n1), Some(n2)) => {
4527 if !n1.node_eq(n2.as_ref()) {
4529 return Ok(Value::bool(false));
4530 }
4531 }
4532 (None, None) => continue,
4533 _ => return Ok(Value::bool(false)),
4534 }
4535 }
4536
4537 Ok(Value::bool(true))
4538 }
4539
4540 _ => Err(format!("node-list=?: arguments must be nodes or node-lists: {:?}, {:?}", args[0], args[1])),
4541 }
4542}
4543
4544pub fn prim_first_sibling_p(args: &[Value]) -> PrimitiveResult {
4555 if args.len() > 1 {
4556 return Err("first-sibling? requires 0 or 1 arguments".to_string());
4557 }
4558
4559 let node = if args.is_empty() {
4561 let ctx = crate::scheme::evaluator::get_evaluator_context()
4563 .ok_or_else(|| "first-sibling?: no evaluator context available".to_string())?;
4564 ctx.current_node
4565 .ok_or_else(|| "first-sibling?: no current node set".to_string())?
4566 } else {
4567 match &args[0] {
4568 Value::Node(n) => n.clone(),
4569 Value::NodeList(nl) => {
4570 if nl.length() != 1 {
4572 return Err("first-sibling?: argument must be a single node".to_string());
4573 }
4574 if let Some(n) = nl.first() {
4575 std::rc::Rc::new(n)
4576 } else {
4577 return Err("first-sibling?: empty node-list".to_string());
4578 }
4579 }
4580 _ => return Err(format!("first-sibling?: not a node: {:?}", args[0])),
4581 }
4582 };
4583
4584 let gi = match node.gi() {
4586 Some(g) => g,
4587 None => return Ok(Value::bool(true)), };
4589
4590 let parent = match node.parent() {
4592 Some(p) => p,
4593 None => return Ok(Value::bool(true)), };
4595
4596 let siblings = parent.children();
4598 for i in 0..siblings.length() {
4599 if let Some(sibling) = siblings.get(i) {
4600 if sibling.node_eq(node.as_ref().as_ref()) {
4602 return Ok(Value::bool(true));
4603 }
4604
4605 if let Some(sibling_gi) = sibling.gi() {
4607 if sibling_gi == gi {
4608 return Ok(Value::bool(false));
4609 }
4610 }
4611 }
4612 }
4613
4614 Ok(Value::bool(true))
4616}
4617
4618pub fn prim_last_sibling_p(args: &[Value]) -> PrimitiveResult {
4626 if args.len() > 1 {
4627 return Err("last-sibling? requires 0 or 1 arguments".to_string());
4628 }
4629
4630 let node = if args.is_empty() {
4631 return Err("last-sibling? with no arguments requires current-node context (not yet implemented)".to_string());
4633 } else {
4634 match &args[0] {
4635 Value::Node(n) => n.clone(),
4636 Value::NodeList(nl) => {
4637 if let Some(node) = nl.first() {
4638 if nl.length() != 1 {
4639 return Err(format!("last-sibling?: node-list must have exactly 1 element, got {}", nl.length()));
4640 }
4641 std::rc::Rc::new(node)
4642 } else {
4643 return Ok(Value::bool(false)); }
4645 }
4646 _ => return Err("last-sibling? requires node or singleton node-list".to_string()),
4647 }
4648 };
4649
4650 if let Some(parent) = node.parent() {
4652 let my_gi = node.gi();
4653
4654 let siblings = parent.children();
4656 let mut current_nl = siblings;
4657 let mut last_with_same_gi: Option<Box<dyn crate::grove::Node>> = None;
4658
4659 loop {
4661 if let Some(child) = current_nl.first() {
4662 if child.gi() == my_gi {
4663 last_with_same_gi = Some(child);
4664 }
4665 current_nl = current_nl.rest();
4666 } else {
4667 break;
4668 }
4669 }
4670
4671 if let Some(last) = last_with_same_gi {
4673 Ok(Value::bool(node.node_eq(last.as_ref())))
4674 } else {
4675 Ok(Value::bool(false))
4676 }
4677 } else {
4678 Ok(Value::bool(false))
4680 }
4681}
4682
4683pub fn prim_child_number(args: &[Value]) -> PrimitiveResult {
4691 if args.is_empty() || args.len() > 1 {
4692 return Err("child-number requires 0 or 1 arguments".to_string());
4693 }
4694
4695 let node = if args.is_empty() {
4696 return Err("child-number with no arguments requires current-node context (not yet implemented)".to_string());
4698 } else {
4699 match &args[0] {
4700 Value::Node(n) => n.clone(),
4701 Value::NodeList(nl) => {
4702 if let Some(node) = nl.first() {
4703 if nl.length() != 1 {
4704 return Err(format!("child-number: node-list must have exactly 1 element, got {}", nl.length()));
4705 }
4706 std::rc::Rc::new(node)
4707 } else {
4708 return Err("child-number: empty node-list".to_string());
4709 }
4710 }
4711 _ => return Err(format!("child-number: not a node: {:?}", args[0])),
4712 }
4713 };
4714
4715 let gi = match node.gi() {
4717 Some(name) => name.to_string(),
4718 None => return Ok(Value::bool(false)), };
4720
4721 let parent = match node.parent() {
4723 Some(p) => p,
4724 None => return Ok(Value::integer(1)), };
4726
4727 let mut count = 0;
4729 let mut current = parent.children();
4730
4731 loop {
4732 if let Some(sibling) = current.first() {
4733 if sibling.node_eq(&**node) {
4735 return Ok(Value::integer((count + 1) as i64));
4737 }
4738
4739 if let Some(sibling_gi) = sibling.gi() {
4741 if sibling_gi == gi {
4742 count += 1;
4743 }
4744 }
4745
4746 current = current.rest();
4748 if current.length() == 0 {
4749 break;
4750 }
4751 } else {
4752 break;
4753 }
4754 }
4755
4756 Err("child-number: node not found among siblings".to_string())
4758}
4759
4760pub fn prim_element_number(_args: &[Value]) -> PrimitiveResult {
4762 Ok(Value::integer(0)) }
4764
4765pub fn prim_inherited_attribute_string(_args: &[Value]) -> PrimitiveResult {
4767 Ok(Value::bool(false)) }
4769
4770pub fn prim_absolute_first_sibling_p(_args: &[Value]) -> PrimitiveResult {
4772 Ok(Value::bool(false)) }
4774
4775pub fn prim_absolute_last_sibling_p(_args: &[Value]) -> PrimitiveResult {
4777 Ok(Value::bool(false)) }
4779
4780pub fn prim_ancestor_child_number(_args: &[Value]) -> PrimitiveResult {
4782 Ok(Value::integer(0)) }
4784
4785pub fn prim_element_number_list(_args: &[Value]) -> PrimitiveResult {
4787 Ok(Value::Nil) }
4789
4790pub fn prim_hierarchical_number(_args: &[Value]) -> PrimitiveResult {
4792 Ok(Value::string("1".to_string())) }
4794
4795pub fn prim_hierarchical_number_recursive(_args: &[Value]) -> PrimitiveResult {
4797 Ok(Value::string("1".to_string())) }
4799
4800pub fn prim_have_ancestor_p(_args: &[Value]) -> PrimitiveResult {
4802 Ok(Value::bool(false)) }
4804
4805pub fn prim_all_element_number(_args: &[Value]) -> PrimitiveResult {
4807 Ok(Value::integer(0)) }
4809
4810pub fn prim_char_property(_args: &[Value]) -> PrimitiveResult {
4816 Ok(Value::Unspecified) }
4818
4819pub fn prim_char_script_case(_args: &[Value]) -> PrimitiveResult {
4821 Ok(Value::Char('a')) }
4823
4824pub fn prim_language(_args: &[Value]) -> PrimitiveResult {
4826 Ok(Value::Unspecified) }
4828
4829pub fn prim_with_language(_args: &[Value]) -> PrimitiveResult {
4831 Ok(Value::Unspecified) }
4833
4834pub fn prim_first_child_gi(_args: &[Value]) -> PrimitiveResult {
4840 Ok(Value::bool(false)) }
4842
4843pub fn prim_inherited_element_attribute_string(_args: &[Value]) -> PrimitiveResult {
4845 Ok(Value::bool(false)) }
4847
4848pub fn prim_debug(args: &[Value]) -> PrimitiveResult {
4854 if args.is_empty() {
4855 return Err("debug requires at least 1 argument".to_string());
4856 }
4857
4858 match &args[0] {
4861 Value::String(s) => {
4862 println!("{}", s);
4863 }
4864 other => {
4865 println!("{:?}", other);
4867 }
4868 }
4869
4870 Ok(args[0].clone())
4871}
4872
4873pub fn prim_external_procedure(_args: &[Value]) -> PrimitiveResult {
4875 Ok(Value::Unspecified) }
4877
4878pub fn prim_read_entity(_args: &[Value]) -> PrimitiveResult {
4880 Ok(Value::string("".to_string())) }
4882
4883pub fn prim_entity_address(_args: &[Value]) -> PrimitiveResult {
4889 Ok(Value::Unspecified) }
4891
4892pub fn prim_entity_attribute_string(_args: &[Value]) -> PrimitiveResult {
4894 Ok(Value::bool(false)) }
4896
4897pub fn prim_entity_generated_system_id(_args: &[Value]) -> PrimitiveResult {
4899 Ok(Value::bool(false)) }
4901
4902pub fn prim_entity_name_normalize(_args: &[Value]) -> PrimitiveResult {
4904 Ok(Value::string("".to_string())) }
4906
4907pub fn prim_entity_notation(_args: &[Value]) -> PrimitiveResult {
4909 Ok(Value::bool(false)) }
4911
4912pub fn prim_entity_text(_args: &[Value]) -> PrimitiveResult {
4914 Ok(Value::bool(false)) }
4916
4917pub fn prim_entity_type(_args: &[Value]) -> PrimitiveResult {
4919 Ok(Value::symbol("unknown")) }
4921
4922pub fn prim_notation_generated_system_id(_args: &[Value]) -> PrimitiveResult {
4924 Ok(Value::bool(false)) }
4926
4927pub fn prim_general_name_normalize(_args: &[Value]) -> PrimitiveResult {
4929 Ok(Value::string("".to_string())) }
4931
4932pub fn prim_sgml_document_address(_args: &[Value]) -> PrimitiveResult {
4934 Ok(Value::Unspecified) }
4936
4937pub fn prim_declaration(_args: &[Value]) -> PrimitiveResult {
4939 Ok(Value::bool(false)) }
4941
4942pub fn prim_dtd(_args: &[Value]) -> PrimitiveResult {
4944 Ok(Value::bool(false)) }
4946
4947pub fn prim_sgml_declaration(_args: &[Value]) -> PrimitiveResult {
4949 Ok(Value::bool(false)) }
4951
4952pub fn prim_document_element(_args: &[Value]) -> PrimitiveResult {
4954 Ok(Value::bool(false)) }
4956
4957pub fn prim_prolog(_args: &[Value]) -> PrimitiveResult {
4959 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
4961
4962pub fn prim_epilog(_args: &[Value]) -> PrimitiveResult {
4964 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
4966
4967pub fn prim_declare_default_language(_args: &[Value]) -> PrimitiveResult {
4971 Ok(Value::Unspecified)
4972}
4973
4974pub fn prim_declare_characteristic(_args: &[Value]) -> PrimitiveResult {
4978 Ok(Value::Unspecified)
4979}
4980
4981pub fn prim_origin_to_subnode_rel_forest_addr(_args: &[Value]) -> PrimitiveResult {
4983 Ok(Value::Unspecified) }
4985
4986pub fn prim_named_node(_args: &[Value]) -> PrimitiveResult {
4992 Ok(Value::bool(false)) }
4994
4995pub fn prim_named_node_list_names(_args: &[Value]) -> PrimitiveResult {
4997 Ok(Value::Nil) }
4999
5000pub fn prim_named_node_list_normalize(_args: &[Value]) -> PrimitiveResult {
5002 Ok(Value::Unspecified) }
5004
5005pub fn prim_node_list_address(_args: &[Value]) -> PrimitiveResult {
5007 Ok(Value::Unspecified) }
5009
5010pub fn prim_node_list_error(_args: &[Value]) -> PrimitiveResult {
5012 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
5014
5015pub fn prim_node_list_no_order(_args: &[Value]) -> PrimitiveResult {
5017 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
5019
5020pub fn prim_select_by_class(_args: &[Value]) -> PrimitiveResult {
5022 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
5024
5025pub fn prim_node_list_union(args: &[Value]) -> PrimitiveResult {
5033 if args.is_empty() {
5034 return Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new())));
5035 }
5036
5037 let mut seen_ids = std::collections::HashSet::new();
5039 let mut result_nodes = Vec::new();
5040
5041 for arg in args {
5042 match arg {
5043 Value::NodeList(nl) => {
5044 for i in 0..nl.length() {
5046 if let Some(node) = nl.get(i) {
5047 let node_id = node.node_id();
5048 if !seen_ids.contains(&node_id) {
5050 seen_ids.insert(node_id);
5051 result_nodes.push(node);
5052 }
5053 }
5054 }
5055 }
5056 Value::Node(n) => {
5057 let node_id = n.as_ref().node_id();
5059 if !seen_ids.contains(&node_id) {
5060 seen_ids.insert(node_id);
5061 result_nodes.push(n.as_ref().clone_node());
5062 }
5063 }
5064 Value::Pair(_) => {
5065 let mut current = arg.clone();
5067 loop {
5068 match current {
5069 Value::Nil => break,
5070 Value::Pair(ref p) => {
5071 let (car, cdr) = {
5072 let pair_data = p.borrow();
5073 (pair_data.car.clone(), pair_data.cdr.clone())
5074 };
5075
5076 match car {
5078 Value::Node(ref n) => {
5079 let node_id = n.as_ref().node_id();
5080 if !seen_ids.contains(&node_id) {
5081 seen_ids.insert(node_id);
5082 result_nodes.push(n.as_ref().clone_node());
5083 }
5084 }
5085 _ => return Err(format!("node-list-union: list contains non-node: {:?}", car)),
5086 }
5087
5088 current = cdr;
5089 }
5090 _ => return Err(format!("node-list-union: malformed list: {:?}", current)),
5091 }
5092 }
5093 }
5094 Value::Nil => {
5095 }
5097 _ => return Err(format!("node-list-union: argument not a node-list: {:?}", arg)),
5098 }
5099 }
5100
5101 Ok(Value::node_list(Box::new(crate::grove::VecNodeList::new(result_nodes))))
5102}
5103
5104pub fn prim_node_list_intersection(_args: &[Value]) -> PrimitiveResult {
5106 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
5108
5109pub fn prim_node_list_difference(_args: &[Value]) -> PrimitiveResult {
5111 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
5113
5114pub fn prim_node_list_symmetrical_difference(_args: &[Value]) -> PrimitiveResult {
5116 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
5118
5119pub fn prim_node_list_union_map(_args: &[Value]) -> PrimitiveResult {
5121 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
5123
5124pub fn prim_process_children_trim(_args: &[Value]) -> PrimitiveResult {
5130 Ok(Value::Sosofo) }
5132
5133pub fn prim_process_element_with_id(_args: &[Value]) -> PrimitiveResult {
5135 Ok(Value::Sosofo) }
5137
5138pub fn prim_process_first_descendant(_args: &[Value]) -> PrimitiveResult {
5140 Ok(Value::Sosofo) }
5142
5143pub fn prim_process_matching_children(_args: &[Value]) -> PrimitiveResult {
5145 Ok(Value::Sosofo) }
5147
5148pub fn prim_merge_style(_args: &[Value]) -> PrimitiveResult {
5150 Ok(Value::Unspecified) }
5152
5153pub fn prim_map_constructor(_args: &[Value]) -> PrimitiveResult {
5155 Ok(Value::Unspecified) }
5157
5158pub fn prim_with_mode(_args: &[Value]) -> PrimitiveResult {
5160 Ok(Value::Sosofo) }
5162
5163pub fn prim_current_mode(_args: &[Value]) -> PrimitiveResult {
5165 Ok(Value::bool(false)) }
5167
5168pub fn prim_current_node_page_number_sosofo(_args: &[Value]) -> PrimitiveResult {
5174 Ok(Value::Sosofo) }
5176
5177pub fn prim_page_number_sosofo(_args: &[Value]) -> PrimitiveResult {
5179 Ok(Value::Sosofo) }
5181
5182pub fn prim_sosofo_discard_labeled(_args: &[Value]) -> PrimitiveResult {
5184 Ok(Value::Sosofo) }
5186
5187pub fn prim_sosofo_label(_args: &[Value]) -> PrimitiveResult {
5189 Ok(Value::Sosofo) }
5191
5192pub fn prim_idref_address(_args: &[Value]) -> PrimitiveResult {
5194 Ok(Value::Unspecified) }
5196
5197pub fn prim_hytime_linkend(_args: &[Value]) -> PrimitiveResult {
5199 Ok(Value::bool(false)) }
5201
5202pub fn prim_if_first_page(_args: &[Value]) -> PrimitiveResult {
5204 Ok(Value::Sosofo) }
5206
5207pub fn prim_if_front_page(_args: &[Value]) -> PrimitiveResult {
5209 Ok(Value::Sosofo) }
5211
5212pub fn prim_sosofo_contains_node_p(_args: &[Value]) -> PrimitiveResult {
5214 Ok(Value::bool(false)) }
5216
5217pub fn prim_set_visited(_args: &[Value]) -> PrimitiveResult {
5219 Ok(Value::Unspecified) }
5221
5222pub fn prim_label_length(_args: &[Value]) -> PrimitiveResult {
5224 Ok(Value::integer(0)) }
5226
5227pub fn prim_label_distance(_args: &[Value]) -> PrimitiveResult {
5229 Ok(Value::integer(0)) }
5231
5232pub fn prim_quantity_to_number(_args: &[Value]) -> PrimitiveResult {
5238 Ok(Value::integer(0)) }
5240
5241pub fn prim_number_to_quantity(_args: &[Value]) -> PrimitiveResult {
5243 Ok(Value::Unspecified) }
5245
5246pub fn prim_quantity_convert(_args: &[Value]) -> PrimitiveResult {
5248 Ok(Value::Unspecified) }
5250
5251pub fn prim_device_length(_args: &[Value]) -> PrimitiveResult {
5253 Ok(Value::integer(0)) }
5255
5256pub fn prim_quantity_to_string(_args: &[Value]) -> PrimitiveResult {
5258 Ok(Value::string("0pt".to_string())) }
5260
5261pub fn prim_table_unit(_args: &[Value]) -> PrimitiveResult {
5263 Ok(Value::Unspecified) }
5265
5266pub fn prim_display_size(_args: &[Value]) -> PrimitiveResult {
5268 Ok(Value::Unspecified) }
5271
5272pub fn prim_sgml_parse(_args: &[Value]) -> PrimitiveResult {
5278 Ok(Value::Unspecified) }
5280
5281pub fn prim_time_lt(_args: &[Value]) -> PrimitiveResult {
5287 Ok(Value::bool(false)) }
5289
5290pub fn prim_time_le(_args: &[Value]) -> PrimitiveResult {
5292 Ok(Value::bool(false)) }
5294
5295pub fn prim_time_gt(_args: &[Value]) -> PrimitiveResult {
5297 Ok(Value::bool(false)) }
5299
5300pub fn prim_time_ge(_args: &[Value]) -> PrimitiveResult {
5302 Ok(Value::bool(false)) }
5304
5305pub fn prim_next_match(_args: &[Value]) -> PrimitiveResult {
5311 Ok(Value::Sosofo) }
5313
5314pub fn prim_style_p(args: &[Value]) -> PrimitiveResult {
5316 if args.len() != 1 {
5317 return Err("style? requires exactly 1 argument".to_string());
5318 }
5319 Ok(Value::bool(false)) }
5321
5322pub fn prim_sosofo_p(args: &[Value]) -> PrimitiveResult {
5338 if args.len() != 1 {
5339 return Err("sosofo? requires exactly 1 argument".to_string());
5340 }
5341
5342 Ok(Value::bool(matches!(args[0], Value::Sosofo)))
5343}
5344
5345pub fn prim_empty_sosofo(args: &[Value]) -> PrimitiveResult {
5351 if !args.is_empty() {
5352 return Err("empty-sosofo requires no arguments".to_string());
5353 }
5354
5355 Ok(Value::Sosofo)
5356}
5357
5358pub fn prim_literal(args: &[Value]) -> PrimitiveResult {
5365 if args.len() != 1 {
5366 return Err("literal requires exactly 1 argument".to_string());
5367 }
5368
5369 match &args[0] {
5370 Value::String(s) => {
5371 if let Some(ctx) = crate::scheme::evaluator::get_evaluator_context() {
5373 if let Some(ref backend) = ctx.backend {
5374 backend.borrow_mut()
5375 .formatting_instruction(s)
5376 .map_err(|e| format!("literal: backend error: {}", e))?;
5377 }
5378 }
5379 Ok(Value::Sosofo)
5380 }
5381 _ => Err(format!("literal: not a string: {:?}", args[0])),
5382 }
5383}
5384
5385pub fn prim_sosofo_append(args: &[Value]) -> PrimitiveResult {
5391 for arg in args {
5393 if !matches!(arg, Value::Sosofo | Value::Unspecified) {
5394 return Err(format!("sosofo-append: not a sosofo: {:?}", arg));
5395 }
5396 }
5397
5398 Ok(Value::Sosofo)
5401}
5402
5403pub fn prim_process_children(args: &[Value]) -> PrimitiveResult {
5423 if !args.is_empty() {
5424 return Err("process-children requires no arguments".to_string());
5425 }
5426
5427 Ok(Value::Sosofo)
5436}
5437
5438pub fn prim_process_node_list(args: &[Value]) -> PrimitiveResult {
5451 if args.len() != 1 {
5452 return Err("process-node-list requires exactly 1 argument".to_string());
5453 }
5454
5455 if !matches!(args[0], Value::NodeList(_)) {
5457 return Err(format!("process-node-list: not a node-list: {:?}", args[0]));
5458 }
5459
5460 Ok(Value::Sosofo)
5469}
5470
5471pub fn prim_make(args: &[Value]) -> PrimitiveResult {
5494 if args.is_empty() {
5495 return Err("make requires at least a flow object type".to_string());
5496 }
5497
5498 match &args[0] {
5500 Value::Symbol(fo_type) => {
5501 match fo_type.as_ref() {
5510 "entity" | "formatting-instruction" | "sequence" | "paragraph" => {
5511 Ok(Value::Sosofo)
5512 }
5513 _ => Err(format!("make: unknown flow object type: {}", fo_type)),
5514 }
5515 }
5516 _ => Err(format!("make: first argument must be a symbol: {:?}", args[0])),
5517 }
5518}
5519
5520pub fn prim_string_equiv_p(args: &[Value]) -> PrimitiveResult {
5531 if args.len() != 2 {
5532 return Err("string-equiv? requires exactly 2 arguments".to_string());
5533 }
5534
5535 let s1 = match &args[0] {
5536 Value::String(s) => s.to_lowercase(),
5537 _ => return Err(format!("string-equiv?: not a string: {:?}", args[0])),
5538 };
5539
5540 let s2 = match &args[1] {
5541 Value::String(s) => s.to_lowercase(),
5542 _ => return Err(format!("string-equiv?: not a string: {:?}", args[1])),
5543 };
5544
5545 Ok(Value::bool(s1 == s2))
5546}
5547
5548pub fn prim_time(args: &[Value]) -> PrimitiveResult {
5561 if !args.is_empty() {
5562 return Err("time requires no arguments".to_string());
5563 }
5564
5565 Ok(Value::Unspecified)
5568}
5569
5570pub fn prim_time_to_string(args: &[Value]) -> PrimitiveResult {
5577 if args.len() != 2 {
5578 return Err("time->string requires exactly 2 arguments".to_string());
5579 }
5580
5581 Ok(Value::string("".to_string()))
5583}
5584
5585pub fn prim_language_p(args: &[Value]) -> PrimitiveResult {
5599 if args.len() != 1 {
5600 return Err("language? requires exactly 1 argument".to_string());
5601 }
5602
5603 Ok(Value::bool(false))
5605}
5606
5607pub fn prim_current_language(args: &[Value]) -> PrimitiveResult {
5614 if !args.is_empty() {
5615 return Err("current-language requires no arguments".to_string());
5616 }
5617
5618 Ok(Value::Unspecified)
5620}
5621
5622pub fn register_list_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5628 env.define("car", Value::primitive("car", prim_car));
5629 env.define("cdr", Value::primitive("cdr", prim_cdr));
5630 env.define("cons", Value::primitive("cons", prim_cons));
5631 env.define("list", Value::primitive("list", prim_list));
5632 env.define("null?", Value::primitive("null?", prim_null_p));
5633 env.define("pair?", Value::primitive("pair?", prim_pair_p));
5634 env.define("list?", Value::primitive("list?", prim_list_p));
5635 env.define("length", Value::primitive("length", prim_length));
5636 env.define("append", Value::primitive("append", prim_append));
5637 env.define("reverse", Value::primitive("reverse", prim_reverse));
5638 env.define("list-tail", Value::primitive("list-tail", prim_list_tail));
5639 env.define("list-ref", Value::primitive("list-ref", prim_list_ref));
5640 env.define("memq", Value::primitive("memq", prim_memq));
5641 env.define("memv", Value::primitive("memv", prim_memv));
5642 env.define("member", Value::primitive("member", prim_member));
5643 env.define("assq", Value::primitive("assq", prim_assq));
5644 env.define("assv", Value::primitive("assv", prim_assv));
5645 env.define("assoc", Value::primitive("assoc", prim_assoc));
5646 env.define("cadr", Value::primitive("cadr", prim_cadr));
5648 env.define("caddr", Value::primitive("caddr", prim_caddr));
5649 env.define("cadddr", Value::primitive("cadddr", prim_cadddr));
5650 env.define("caar", Value::primitive("caar", prim_caar));
5651 env.define("cddr", Value::primitive("cddr", prim_cddr));
5652 env.define("cdar", Value::primitive("cdar", prim_cdar));
5653 env.define("caaar", Value::primitive("caaar", prim_caaar));
5654 env.define("cdaar", Value::primitive("cdaar", prim_cdaar));
5655 env.define("cadar", Value::primitive("cadar", prim_cadar));
5656 env.define("cddar", Value::primitive("cddar", prim_cddar));
5657 env.define("caadr", Value::primitive("caadr", prim_caadr));
5658 env.define("cdadr", Value::primitive("cdadr", prim_cdadr));
5659 env.define("last", Value::primitive("last", prim_last));
5661}
5662
5663pub fn register_number_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5665 env.define("+", Value::primitive("+", prim_add));
5667 env.define("-", Value::primitive("-", prim_subtract));
5668 env.define("*", Value::primitive("*", prim_multiply));
5669 env.define("/", Value::primitive("/", prim_divide));
5670 env.define("quotient", Value::primitive("quotient", prim_quotient));
5671 env.define("remainder", Value::primitive("remainder", prim_remainder));
5672 env.define("modulo", Value::primitive("modulo", prim_modulo));
5673
5674 env.define("=", Value::primitive("=", prim_num_eq));
5676 env.define("<", Value::primitive("<", prim_num_lt));
5677 env.define(">", Value::primitive(">", prim_num_gt));
5678 env.define("<=", Value::primitive("<=", prim_num_le));
5679 env.define(">=", Value::primitive(">=", prim_num_ge));
5680
5681 env.define("number?", Value::primitive("number?", prim_number_p));
5683 env.define("integer?", Value::primitive("integer?", prim_integer_p));
5684 env.define("real?", Value::primitive("real?", prim_real_p));
5685 env.define("zero?", Value::primitive("zero?", prim_zero_p));
5686 env.define("positive?", Value::primitive("positive?", prim_positive_p));
5687 env.define("negative?", Value::primitive("negative?", prim_negative_p));
5688 env.define("odd?", Value::primitive("odd?", prim_odd_p));
5689 env.define("even?", Value::primitive("even?", prim_even_p));
5690
5691 env.define("abs", Value::primitive("abs", prim_abs));
5693 env.define("max", Value::primitive("max", prim_max));
5694 env.define("min", Value::primitive("min", prim_min));
5695 env.define("gcd", Value::primitive("gcd", prim_gcd));
5696 env.define("lcm", Value::primitive("lcm", prim_lcm));
5697 env.define("floor", Value::primitive("floor", prim_floor));
5698 env.define("ceiling", Value::primitive("ceiling", prim_ceiling));
5699 env.define("truncate", Value::primitive("truncate", prim_truncate));
5700 env.define("round", Value::primitive("round", prim_round));
5701
5702 env.define("expt", Value::primitive("expt", prim_expt));
5704 env.define("sqrt", Value::primitive("sqrt", prim_sqrt));
5705 env.define("sin", Value::primitive("sin", prim_sin));
5706 env.define("cos", Value::primitive("cos", prim_cos));
5707 env.define("tan", Value::primitive("tan", prim_tan));
5708 env.define("atan", Value::primitive("atan", prim_atan));
5709 env.define("asin", Value::primitive("asin", prim_asin));
5710 env.define("acos", Value::primitive("acos", prim_acos));
5711 env.define("log", Value::primitive("log", prim_log));
5712 env.define("exp", Value::primitive("exp", prim_exp));
5713
5714 env.define("exact?", Value::primitive("exact?", prim_exact_p));
5716 env.define("inexact?", Value::primitive("inexact?", prim_inexact_p));
5717 env.define("exact->inexact", Value::primitive("exact->inexact", prim_exact_to_inexact));
5718 env.define("inexact->exact", Value::primitive("inexact->exact", prim_inexact_to_exact));
5719}
5720
5721pub fn register_string_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5723 env.define("string-length", Value::primitive("string-length", prim_string_length));
5725 env.define("string-ref", Value::primitive("string-ref", prim_string_ref));
5726 env.define("string-append", Value::primitive("string-append", prim_string_append));
5727 env.define("substring", Value::primitive("substring", prim_substring));
5728 env.define("make-string", Value::primitive("make-string", prim_make_string));
5729 env.define("string", Value::primitive("string", prim_string));
5730
5731 env.define("string=?", Value::primitive("string=?", prim_string_eq));
5733 env.define("string<?", Value::primitive("string<?", prim_string_lt));
5734 env.define("string>?", Value::primitive("string>?", prim_string_gt));
5735 env.define("string<=?", Value::primitive("string<=?", prim_string_le));
5736 env.define("string>=?", Value::primitive("string>=?", prim_string_ge));
5737
5738 env.define("string-ci=?", Value::primitive("string-ci=?", prim_string_ci_eq));
5740 env.define("string-ci<?", Value::primitive("string-ci<?", prim_string_ci_lt));
5741 env.define("string-ci>?", Value::primitive("string-ci>?", prim_string_ci_gt));
5742 env.define("string-ci<=?", Value::primitive("string-ci<=?", prim_string_ci_le));
5743 env.define("string-ci>=?", Value::primitive("string-ci>=?", prim_string_ci_ge));
5744
5745 env.define("string->list", Value::primitive("string->list", prim_string_to_list));
5747 env.define("list->string", Value::primitive("list->string", prim_list_to_string));
5748 env.define("string->symbol", Value::primitive("string->symbol", prim_string_to_symbol));
5749 env.define("symbol->string", Value::primitive("symbol->string", prim_symbol_to_string));
5750
5751 env.define("string?", Value::primitive("string?", prim_string_p));
5753 env.define("symbol?", Value::primitive("symbol?", prim_symbol_p));
5754 env.define("char?", Value::primitive("char?", prim_char_p));
5755
5756 env.define("char=?", Value::primitive("char=?", prim_char_eq));
5758 env.define("char<?", Value::primitive("char<?", prim_char_lt));
5759 env.define("char>?", Value::primitive("char>?", prim_char_gt));
5760 env.define("char<=?", Value::primitive("char<=?", prim_char_le));
5761 env.define("char>=?", Value::primitive("char>=?", prim_char_ge));
5762 env.define("char-upcase", Value::primitive("char-upcase", prim_char_upcase));
5763 env.define("char-downcase", Value::primitive("char-downcase", prim_char_downcase));
5764 env.define("char->integer", Value::primitive("char->integer", prim_char_to_integer));
5765 env.define("integer->char", Value::primitive("integer->char", prim_integer_to_char));
5766 env.define("char-alphabetic?", Value::primitive("char-alphabetic?", prim_char_alphabetic_p));
5767 env.define("char-numeric?", Value::primitive("char-numeric?", prim_char_numeric_p));
5768 env.define("char-whitespace?", Value::primitive("char-whitespace?", prim_char_whitespace_p));
5769
5770 env.define("char-ci=?", Value::primitive("char-ci=?", prim_char_ci_eq));
5772 env.define("char-ci<?", Value::primitive("char-ci<?", prim_char_ci_lt));
5773 env.define("char-ci>?", Value::primitive("char-ci>?", prim_char_ci_gt));
5774 env.define("char-ci<=?", Value::primitive("char-ci<=?", prim_char_ci_le));
5775 env.define("char-ci>=?", Value::primitive("char-ci>=?", prim_char_ci_ge));
5776}
5777
5778pub fn register_boolean_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5780 env.define("not", Value::primitive("not", prim_not));
5781 env.define("boolean?", Value::primitive("boolean?", prim_boolean_p));
5782 env.define("equal?", Value::primitive("equal?", prim_equal_p));
5783 env.define("eqv?", Value::primitive("eqv?", prim_eqv_p));
5784 env.define("eq?", Value::primitive("eq?", prim_eq_p));
5785 env.define("procedure?", Value::primitive("procedure?", prim_procedure_p));
5786}
5787
5788pub fn register_io_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5790 env.define("error", Value::primitive("error", prim_error));
5791 env.define("display", Value::primitive("display", prim_display));
5792 env.define("newline", Value::primitive("newline", prim_newline));
5793 env.define("write", Value::primitive("write", prim_write));
5794}
5795
5796pub fn register_conversion_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5798 env.define("number->string", Value::primitive("number->string", prim_number_to_string));
5799 env.define("string->number", Value::primitive("string->number", prim_string_to_number));
5800}
5801
5802pub fn register_keyword_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5804 env.define("keyword?", Value::primitive("keyword?", prim_keyword_p));
5805 env.define("keyword->string", Value::primitive("keyword->string", prim_keyword_to_string));
5806 env.define("string->keyword", Value::primitive("string->keyword", prim_string_to_keyword));
5807}
5808
5809pub fn register_dsssl_type_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5811 env.define("quantity?", Value::primitive("quantity?", prim_quantity_p));
5812 env.define("color?", Value::primitive("color?", prim_color_p));
5813 env.define("address?", Value::primitive("address?", prim_address_p));
5814
5815 env.define("color", Value::primitive("color", prim_color));
5817 env.define("color-space", Value::primitive("color-space", prim_color_space));
5818 env.define("color-space?", Value::primitive("color-space?", prim_color_space_p));
5819
5820 env.define("display-space", Value::primitive("display-space", prim_display_space));
5822 env.define("display-space?", Value::primitive("display-space?", prim_display_space_p));
5823 env.define("inline-space", Value::primitive("inline-space", prim_inline_space));
5824 env.define("inline-space?", Value::primitive("inline-space?", prim_inline_space_p));
5825
5826 env.define("glyph-id", Value::primitive("glyph-id", prim_glyph_id));
5828 env.define("glyph-id?", Value::primitive("glyph-id?", prim_glyph_id_p));
5829 env.define("glyph-subst-table", Value::primitive("glyph-subst-table", prim_glyph_subst_table));
5830 env.define("glyph-subst-table?", Value::primitive("glyph-subst-table?", prim_glyph_subst_table_p));
5831 env.define("glyph-subst", Value::primitive("glyph-subst", prim_glyph_subst));
5832
5833 env.define("address-local?", Value::primitive("address-local?", prim_address_local_p));
5835
5836 env.define("quantity->number", Value::primitive("quantity->number", prim_quantity_to_number));
5838 env.define("number->quantity", Value::primitive("number->quantity", prim_number_to_quantity));
5839 env.define("quantity-convert", Value::primitive("quantity-convert", prim_quantity_convert));
5840 env.define("device-length", Value::primitive("device-length", prim_device_length));
5841}
5842
5843pub fn register_format_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5845 env.define("format-number", Value::primitive("format-number", prim_format_number));
5846 env.define("format-number-list", Value::primitive("format-number-list", prim_format_number_list));
5847}
5848
5849pub fn register_grove_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5851 env.define("current-node", Value::primitive("current-node", prim_current_node));
5853
5854 env.define("node?", Value::primitive("node?", prim_node_p));
5856 env.define("gi", Value::primitive("gi", prim_gi));
5857 env.define("data", Value::primitive("data", prim_data));
5858 env.define("id", Value::primitive("id", prim_id));
5859 env.define("attribute-string", Value::primitive("attribute-string", prim_attribute_string));
5860 env.define("children", Value::primitive("children", prim_children));
5861 env.define("select-children", Value::primitive("select-children", prim_select_children));
5862 env.define("parent", Value::primitive("parent", prim_parent));
5863 env.define("tree-root", Value::primitive("tree-root", prim_tree_root));
5864 env.define("ancestors", Value::primitive("ancestors", prim_ancestors));
5865
5866 env.define("ancestor", Value::primitive("ancestor", prim_ancestor));
5868 env.define("descendants", Value::primitive("descendants", prim_descendants));
5869 env.define("follow", Value::primitive("follow", prim_follow));
5870 env.define("preced", Value::primitive("preced", prim_preced));
5871 env.define("attributes", Value::primitive("attributes", prim_attributes));
5872 env.define("select-elements", Value::primitive("select-elements", prim_select_elements));
5873 env.define("element-with-id", Value::primitive("element-with-id", prim_element_with_id));
5874
5875 env.define("node-list?", Value::primitive("node-list?", prim_node_list_p));
5877 env.define("empty-node-list", Value::primitive("empty-node-list", prim_empty_node_list));
5878 env.define("node-list-empty?", Value::primitive("node-list-empty?", prim_node_list_empty_p));
5879 env.define("node-list-length", Value::primitive("node-list-length", prim_node_list_length));
5880 env.define("node-list-remove-duplicates", Value::primitive("node-list-remove-duplicates", prim_node_list_remove_duplicates));
5881 env.define("node-list-first", Value::primitive("node-list-first", prim_node_list_first));
5882 env.define("node-list-last", Value::primitive("node-list-last", prim_node_list_last));
5883 env.define("node-list-rest", Value::primitive("node-list-rest", prim_node_list_rest));
5884 env.define("node-list-ref", Value::primitive("node-list-ref", prim_node_list_ref));
5885 env.define("node-list-reverse", Value::primitive("node-list-reverse", prim_node_list_reverse));
5886 env.define("node-list->list", Value::primitive("node-list->list", prim_node_list_to_list));
5887 env.define("node-list-contains?", Value::primitive("node-list-contains?", prim_node_list_contains_p));
5888
5889 env.define("node-list", Value::primitive("node-list", prim_node_list));
5891 env.define("node-list-map", Value::primitive("node-list-map", prim_node_list_map));
5892 env.define("node-property", Value::primitive("node-property", prim_node_property));
5893 env.define("match-element?", Value::primitive("match-element?", prim_match_element_p));
5894 env.define("named-node-list?", Value::primitive("named-node-list?", prim_named_node_list_p));
5895 env.define("node-list=?", Value::primitive("node-list=?", prim_node_list_eq));
5896
5897 env.define("first-sibling?", Value::primitive("first-sibling?", prim_first_sibling_p));
5899 env.define("last-sibling?", Value::primitive("last-sibling?", prim_last_sibling_p));
5900 env.define("child-number", Value::primitive("child-number", prim_child_number));
5901 env.define("element-number", Value::primitive("element-number", prim_element_number));
5902 env.define("inherited-attribute-string", Value::primitive("inherited-attribute-string", prim_inherited_attribute_string));
5903
5904 env.define("entity-system-id", Value::primitive("entity-system-id", prim_entity_system_id));
5906 env.define("entity-public-id", Value::primitive("entity-public-id", prim_entity_public_id));
5907 env.define("notation-system-id", Value::primitive("notation-system-id", prim_notation_system_id));
5908 env.define("notation-public-id", Value::primitive("notation-public-id", prim_notation_public_id));
5909
5910 env.define("absolute-first-sibling?", Value::primitive("absolute-first-sibling?", prim_absolute_first_sibling_p));
5912 env.define("absolute-last-sibling?", Value::primitive("absolute-last-sibling?", prim_absolute_last_sibling_p));
5913 env.define("ancestor-child-number", Value::primitive("ancestor-child-number", prim_ancestor_child_number));
5914 env.define("element-number-list", Value::primitive("element-number-list", prim_element_number_list));
5915 env.define("hierarchical-number", Value::primitive("hierarchical-number", prim_hierarchical_number));
5916 env.define("hierarchical-number-recursive", Value::primitive("hierarchical-number-recursive", prim_hierarchical_number_recursive));
5917 env.define("have-ancestor?", Value::primitive("have-ancestor?", prim_have_ancestor_p));
5918 env.define("all-element-number", Value::primitive("all-element-number", prim_all_element_number));
5919
5920 env.define("first-child-gi", Value::primitive("first-child-gi", prim_first_child_gi));
5922 env.define("inherited-element-attribute-string", Value::primitive("inherited-element-attribute-string", prim_inherited_element_attribute_string));
5923
5924 env.define("entity-address", Value::primitive("entity-address", prim_entity_address));
5926 env.define("entity-generated-system-id", Value::primitive("entity-generated-system-id", prim_entity_generated_system_id));
5927 env.define("entity-type", Value::primitive("entity-type", prim_entity_type));
5928 env.define("declaration", Value::primitive("declaration", prim_declaration));
5929 env.define("dtd", Value::primitive("dtd", prim_dtd));
5930 env.define("sgml-declaration", Value::primitive("sgml-declaration", prim_sgml_declaration));
5931 env.define("document-element", Value::primitive("document-element", prim_document_element));
5932 env.define("prolog", Value::primitive("prolog", prim_prolog));
5933 env.define("epilog", Value::primitive("epilog", prim_epilog));
5934
5935 env.define("declare-default-language", Value::primitive("declare-default-language", prim_declare_default_language));
5937 env.define("declare-characteristic", Value::primitive("declare-characteristic", prim_declare_characteristic));
5938 env.define("origin-to-subnode-rel-forest-addr", Value::primitive("origin-to-subnode-rel-forest-addr", prim_origin_to_subnode_rel_forest_addr));
5939
5940 env.define("named-node", Value::primitive("named-node", prim_named_node));
5942 env.define("named-node-list-names", Value::primitive("named-node-list-names", prim_named_node_list_names));
5943 env.define("node-list-union", Value::primitive("node-list-union", prim_node_list_union));
5944 env.define("node-list-intersection", Value::primitive("node-list-intersection", prim_node_list_intersection));
5945 env.define("node-list-difference", Value::primitive("node-list-difference", prim_node_list_difference));
5946 env.define("node-list-symmetrical-difference", Value::primitive("node-list-symmetrical-difference", prim_node_list_symmetrical_difference));
5947 env.define("node-list-union-map", Value::primitive("node-list-union-map", prim_node_list_union_map));
5948
5949 env.define("node-list-count", Value::primitive("node-list-count", prim_node_list_count));
5951}
5952
5953pub fn register_sosofo_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5955 env.define("sosofo?", Value::primitive("sosofo?", prim_sosofo_p));
5957 env.define("style?", Value::primitive("style?", prim_style_p));
5958 env.define("next-match", Value::primitive("next-match", prim_next_match));
5959 env.define("empty-sosofo", Value::primitive("empty-sosofo", prim_empty_sosofo));
5960 env.define("literal", Value::primitive("literal", prim_literal));
5961 env.define("sosofo-append", Value::primitive("sosofo-append", prim_sosofo_append));
5962
5963 env.define("process-children", Value::primitive("process-children", prim_process_children));
5965 env.define("process-node-list", Value::primitive("process-node-list", prim_process_node_list));
5966 env.define("make", Value::primitive("make", prim_make));
5967
5968 env.define("process-children-trim", Value::primitive("process-children-trim", prim_process_children_trim));
5970 env.define("process-first-descendant", Value::primitive("process-first-descendant", prim_process_first_descendant));
5971 env.define("process-matching-children", Value::primitive("process-matching-children", prim_process_matching_children));
5972 env.define("process-element-with-id", Value::primitive("process-element-with-id", prim_process_element_with_id));
5973 env.define("with-mode", Value::primitive("with-mode", prim_with_mode));
5974 env.define("current-mode", Value::primitive("current-mode", prim_current_mode));
5975
5976 env.define("current-node-page-number-sosofo", Value::primitive("current-node-page-number-sosofo", prim_current_node_page_number_sosofo));
5978 env.define("page-number-sosofo", Value::primitive("page-number-sosofo", prim_page_number_sosofo));
5979 env.define("sosofo-contains-node?", Value::primitive("sosofo-contains-node?", prim_sosofo_contains_node_p));
5980 env.define("current-node-address", Value::primitive("current-node-address", prim_current_node_address));
5981 env.define("address-visited?", Value::primitive("address-visited?", prim_address_visited_p));
5982 env.define("set-visited!", Value::primitive("set-visited!", prim_set_visited));
5983 env.define("label-length", Value::primitive("label-length", prim_label_length));
5984 env.define("label-distance", Value::primitive("label-distance", prim_label_distance));
5985}
5986
5987pub fn register_utility_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5989 env.define("string-equiv?", Value::primitive("string-equiv?", prim_string_equiv_p));
5991
5992 env.define("time", Value::primitive("time", prim_time));
5994 env.define("time->string", Value::primitive("time->string", prim_time_to_string));
5995 env.define("time<?", Value::primitive("time<?", prim_time_lt));
5996 env.define("time<=?", Value::primitive("time<=?", prim_time_le));
5997 env.define("time>?", Value::primitive("time>?", prim_time_gt));
5998 env.define("time>=?", Value::primitive("time>=?", prim_time_ge));
5999
6000 env.define("language?", Value::primitive("language?", prim_language_p));
6002 env.define("current-language", Value::primitive("current-language", prim_current_language));
6003
6004 env.define("char-property", Value::primitive("char-property", prim_char_property));
6006 env.define("char-script-case", Value::primitive("char-script-case", prim_char_script_case));
6007 env.define("language", Value::primitive("language", prim_language));
6008 env.define("with-language", Value::primitive("with-language", prim_with_language));
6009
6010 env.define("debug", Value::primitive("debug", prim_debug));
6012 env.define("external-procedure", Value::primitive("external-procedure", prim_external_procedure));
6013 env.define("read-entity", Value::primitive("read-entity", prim_read_entity));
6014
6015 env.define("sgml-parse", Value::primitive("sgml-parse", prim_sgml_parse));
6017}
6018
6019pub fn register_all_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
6024 register_list_primitives(env);
6025 register_number_primitives(env);
6026 register_string_primitives(env);
6027 register_boolean_primitives(env);
6028 register_io_primitives(env);
6029 register_conversion_primitives(env);
6030 register_keyword_primitives(env);
6031 register_dsssl_type_primitives(env);
6032 register_format_primitives(env);
6033 register_grove_primitives(env);
6034 register_sosofo_primitives(env);
6035 register_utility_primitives(env);
6036}
6037
6038#[cfg(test)]
6043mod tests {
6044 use super::*;
6045
6046 #[test]
6047 fn test_car() {
6048 let pair = Value::cons(Value::integer(1), Value::integer(2));
6049 let result = prim_car(&[pair]).unwrap();
6050 assert!(matches!(result, Value::Integer(1)));
6051 }
6052
6053 #[test]
6054 fn test_cdr() {
6055 let pair = Value::cons(Value::integer(1), Value::integer(2));
6056 let result = prim_cdr(&[pair]).unwrap();
6057 assert!(matches!(result, Value::Integer(2)));
6058 }
6059
6060 #[test]
6061 fn test_cons() {
6062 let result = prim_cons(&[Value::integer(1), Value::integer(2)]).unwrap();
6063 assert!(result.is_pair());
6064 }
6065
6066 #[test]
6067 fn test_list() {
6068 let result = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
6069 assert!(result.is_list());
6070
6071 let len = prim_length(&[result]).unwrap();
6073 assert!(matches!(len, Value::Integer(3)));
6074 }
6075
6076 #[test]
6077 fn test_null_p() {
6078 assert!(matches!(prim_null_p(&[Value::Nil]).unwrap(), Value::Bool(true)));
6079 assert!(matches!(
6080 prim_null_p(&[Value::integer(1)]).unwrap(),
6081 Value::Bool(false)
6082 ));
6083 }
6084
6085 #[test]
6086 fn test_pair_p() {
6087 let pair = Value::cons(Value::integer(1), Value::integer(2));
6088 assert!(matches!(prim_pair_p(&[pair]).unwrap(), Value::Bool(true)));
6089 assert!(matches!(
6090 prim_pair_p(&[Value::Nil]).unwrap(),
6091 Value::Bool(false)
6092 ));
6093 }
6094
6095 #[test]
6096 fn test_length() {
6097 let list = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
6098 let result = prim_length(&[list]).unwrap();
6099 assert!(matches!(result, Value::Integer(3)));
6100
6101 let empty = prim_length(&[Value::Nil]).unwrap();
6102 assert!(matches!(empty, Value::Integer(0)));
6103 }
6104
6105 #[test]
6106 fn test_append() {
6107 let list1 = prim_list(&[Value::integer(1), Value::integer(2)]).unwrap();
6108 let list2 = prim_list(&[Value::integer(3), Value::integer(4)]).unwrap();
6109 let result = prim_append(&[list1, list2]).unwrap();
6110
6111 let len = prim_length(&[result]).unwrap();
6112 assert!(matches!(len, Value::Integer(4)));
6113 }
6114
6115 #[test]
6116 fn test_reverse() {
6117 let list = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
6118 let result = prim_reverse(&[list]).unwrap();
6119
6120 let first = prim_car(&[result]).unwrap();
6122 assert!(matches!(first, Value::Integer(3)));
6123 }
6124
6125 #[test]
6126 fn test_list_ref() {
6127 let list = prim_list(&[Value::integer(10), Value::integer(20), Value::integer(30)]).unwrap();
6128
6129 let result = prim_list_ref(&[list.clone(), Value::integer(0)]).unwrap();
6130 assert!(matches!(result, Value::Integer(10)));
6131
6132 let result = prim_list_ref(&[list.clone(), Value::integer(1)]).unwrap();
6133 assert!(matches!(result, Value::Integer(20)));
6134
6135 let result = prim_list_ref(&[list, Value::integer(2)]).unwrap();
6136 assert!(matches!(result, Value::Integer(30)));
6137 }
6138
6139 #[test]
6140 fn test_list_tail() {
6141 let list = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
6142
6143 let result = prim_list_tail(&[list, Value::integer(2)]).unwrap();
6144 let len = prim_length(&[result]).unwrap();
6145 assert!(matches!(len, Value::Integer(1)));
6146 }
6147
6148 #[test]
6153 fn test_add() {
6154 let result = prim_add(&[]).unwrap();
6155 assert!(matches!(result, Value::Integer(0)));
6156
6157 let result = prim_add(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
6158 assert!(matches!(result, Value::Integer(6)));
6159
6160 let result = prim_add(&[Value::integer(1), Value::real(2.5)]).unwrap();
6161 assert!(matches!(result, Value::Real(r) if (r - 3.5).abs() < f64::EPSILON));
6162 }
6163
6164 #[test]
6165 fn test_subtract() {
6166 let result = prim_subtract(&[Value::integer(5)]).unwrap();
6167 assert!(matches!(result, Value::Integer(-5)));
6168
6169 let result = prim_subtract(&[Value::integer(10), Value::integer(3), Value::integer(2)]).unwrap();
6170 assert!(matches!(result, Value::Integer(5)));
6171
6172 let result = prim_subtract(&[Value::real(10.5), Value::integer(2)]).unwrap();
6173 assert!(matches!(result, Value::Real(r) if (r - 8.5).abs() < f64::EPSILON));
6174 }
6175
6176 #[test]
6177 fn test_multiply() {
6178 let result = prim_multiply(&[]).unwrap();
6179 assert!(matches!(result, Value::Integer(1)));
6180
6181 let result = prim_multiply(&[Value::integer(2), Value::integer(3), Value::integer(4)]).unwrap();
6182 assert!(matches!(result, Value::Integer(24)));
6183
6184 let result = prim_multiply(&[Value::integer(2), Value::real(1.5)]).unwrap();
6185 assert!(matches!(result, Value::Real(r) if (r - 3.0).abs() < f64::EPSILON));
6186 }
6187
6188 #[test]
6189 fn test_divide() {
6190 let result = prim_divide(&[Value::integer(2)]).unwrap();
6191 assert!(matches!(result, Value::Real(r) if (r - 0.5).abs() < f64::EPSILON));
6192
6193 let result = prim_divide(&[Value::integer(10), Value::integer(2)]).unwrap();
6194 assert!(matches!(result, Value::Real(r) if (r - 5.0).abs() < f64::EPSILON));
6195
6196 assert!(prim_divide(&[Value::integer(1), Value::integer(0)]).is_err());
6198 }
6199
6200 #[test]
6201 fn test_quotient() {
6202 let result = prim_quotient(&[Value::integer(10), Value::integer(3)]).unwrap();
6203 assert!(matches!(result, Value::Integer(3)));
6204
6205 let result = prim_quotient(&[Value::integer(-10), Value::integer(3)]).unwrap();
6206 assert!(matches!(result, Value::Integer(-3)));
6207 }
6208
6209 #[test]
6210 fn test_remainder() {
6211 let result = prim_remainder(&[Value::integer(10), Value::integer(3)]).unwrap();
6212 assert!(matches!(result, Value::Integer(1)));
6213
6214 let result = prim_remainder(&[Value::integer(-10), Value::integer(3)]).unwrap();
6215 assert!(matches!(result, Value::Integer(-1)));
6216 }
6217
6218 #[test]
6219 fn test_modulo() {
6220 let result = prim_modulo(&[Value::integer(10), Value::integer(3)]).unwrap();
6221 assert!(matches!(result, Value::Integer(1)));
6222
6223 let result = prim_modulo(&[Value::integer(-10), Value::integer(3)]).unwrap();
6224 assert!(matches!(result, Value::Integer(2))); }
6226
6227 #[test]
6228 fn test_num_eq() {
6229 let result = prim_num_eq(&[Value::integer(5), Value::integer(5)]).unwrap();
6230 assert!(matches!(result, Value::Bool(true)));
6231
6232 let result = prim_num_eq(&[Value::integer(5), Value::integer(6)]).unwrap();
6233 assert!(matches!(result, Value::Bool(false)));
6234
6235 let result = prim_num_eq(&[Value::integer(5), Value::real(5.0)]).unwrap();
6236 assert!(matches!(result, Value::Bool(true)));
6237 }
6238
6239 #[test]
6240 fn test_num_lt() {
6241 let result = prim_num_lt(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
6242 assert!(matches!(result, Value::Bool(true)));
6243
6244 let result = prim_num_lt(&[Value::integer(1), Value::integer(3), Value::integer(2)]).unwrap();
6245 assert!(matches!(result, Value::Bool(false)));
6246 }
6247
6248 #[test]
6249 fn test_num_gt() {
6250 let result = prim_num_gt(&[Value::integer(3), Value::integer(2), Value::integer(1)]).unwrap();
6251 assert!(matches!(result, Value::Bool(true)));
6252
6253 let result = prim_num_gt(&[Value::integer(3), Value::integer(1), Value::integer(2)]).unwrap();
6254 assert!(matches!(result, Value::Bool(false)));
6255 }
6256
6257 #[test]
6258 fn test_num_le() {
6259 let result = prim_num_le(&[Value::integer(1), Value::integer(2), Value::integer(2)]).unwrap();
6260 assert!(matches!(result, Value::Bool(true)));
6261
6262 let result = prim_num_le(&[Value::integer(2), Value::integer(1)]).unwrap();
6263 assert!(matches!(result, Value::Bool(false)));
6264 }
6265
6266 #[test]
6267 fn test_num_ge() {
6268 let result = prim_num_ge(&[Value::integer(3), Value::integer(2), Value::integer(2)]).unwrap();
6269 assert!(matches!(result, Value::Bool(true)));
6270
6271 let result = prim_num_ge(&[Value::integer(1), Value::integer(2)]).unwrap();
6272 assert!(matches!(result, Value::Bool(false)));
6273 }
6274
6275 #[test]
6276 fn test_number_p() {
6277 assert!(matches!(prim_number_p(&[Value::integer(42)]).unwrap(), Value::Bool(true)));
6278 assert!(matches!(prim_number_p(&[Value::real(3.14)]).unwrap(), Value::Bool(true)));
6279 assert!(matches!(prim_number_p(&[Value::string("hello".to_string())]).unwrap(), Value::Bool(false)));
6280 }
6281
6282 #[test]
6283 fn test_integer_p() {
6284 assert!(matches!(prim_integer_p(&[Value::integer(42)]).unwrap(), Value::Bool(true)));
6285 assert!(matches!(prim_integer_p(&[Value::real(3.14)]).unwrap(), Value::Bool(false)));
6286 }
6287
6288 #[test]
6289 fn test_real_p() {
6290 assert!(matches!(prim_real_p(&[Value::real(3.14)]).unwrap(), Value::Bool(true)));
6291 assert!(matches!(prim_real_p(&[Value::integer(42)]).unwrap(), Value::Bool(false)));
6292 }
6293
6294 #[test]
6295 fn test_zero_p() {
6296 assert!(matches!(prim_zero_p(&[Value::integer(0)]).unwrap(), Value::Bool(true)));
6297 assert!(matches!(prim_zero_p(&[Value::integer(1)]).unwrap(), Value::Bool(false)));
6298 assert!(matches!(prim_zero_p(&[Value::real(0.0)]).unwrap(), Value::Bool(true)));
6299 }
6300
6301 #[test]
6302 fn test_positive_p() {
6303 assert!(matches!(prim_positive_p(&[Value::integer(5)]).unwrap(), Value::Bool(true)));
6304 assert!(matches!(prim_positive_p(&[Value::integer(-5)]).unwrap(), Value::Bool(false)));
6305 assert!(matches!(prim_positive_p(&[Value::integer(0)]).unwrap(), Value::Bool(false)));
6306 }
6307
6308 #[test]
6309 fn test_negative_p() {
6310 assert!(matches!(prim_negative_p(&[Value::integer(-5)]).unwrap(), Value::Bool(true)));
6311 assert!(matches!(prim_negative_p(&[Value::integer(5)]).unwrap(), Value::Bool(false)));
6312 assert!(matches!(prim_negative_p(&[Value::integer(0)]).unwrap(), Value::Bool(false)));
6313 }
6314
6315 #[test]
6316 fn test_odd_p() {
6317 assert!(matches!(prim_odd_p(&[Value::integer(3)]).unwrap(), Value::Bool(true)));
6318 assert!(matches!(prim_odd_p(&[Value::integer(4)]).unwrap(), Value::Bool(false)));
6319 }
6320
6321 #[test]
6322 fn test_even_p() {
6323 assert!(matches!(prim_even_p(&[Value::integer(4)]).unwrap(), Value::Bool(true)));
6324 assert!(matches!(prim_even_p(&[Value::integer(3)]).unwrap(), Value::Bool(false)));
6325 }
6326
6327 #[test]
6328 fn test_abs() {
6329 let result = prim_abs(&[Value::integer(-5)]).unwrap();
6330 assert!(matches!(result, Value::Integer(5)));
6331
6332 let result = prim_abs(&[Value::real(-3.14)]).unwrap();
6333 assert!(matches!(result, Value::Real(r) if (r - 3.14).abs() < f64::EPSILON));
6334 }
6335
6336 #[test]
6337 fn test_max() {
6338 let result = prim_max(&[Value::integer(1), Value::integer(5), Value::integer(3)]).unwrap();
6339 assert!(matches!(result, Value::Integer(5)));
6340
6341 let result = prim_max(&[Value::integer(1), Value::real(5.5), Value::integer(3)]).unwrap();
6342 assert!(matches!(result, Value::Real(r) if (r - 5.5).abs() < f64::EPSILON));
6343 }
6344
6345 #[test]
6346 fn test_min() {
6347 let result = prim_min(&[Value::integer(5), Value::integer(1), Value::integer(3)]).unwrap();
6348 assert!(matches!(result, Value::Integer(1)));
6349
6350 let result = prim_min(&[Value::integer(5), Value::real(0.5), Value::integer(3)]).unwrap();
6351 assert!(matches!(result, Value::Real(r) if (r - 0.5).abs() < f64::EPSILON));
6352 }
6353
6354 #[test]
6355 fn test_gcd() {
6356 let result = prim_gcd(&[Value::integer(12), Value::integer(8)]).unwrap();
6358 assert!(matches!(result, Value::Integer(4)));
6359
6360 let result = prim_gcd(&[Value::integer(12), Value::integer(18), Value::integer(24)]).unwrap();
6362 assert!(matches!(result, Value::Integer(6)));
6363
6364 let result = prim_gcd(&[Value::integer(-12), Value::integer(8)]).unwrap();
6366 assert!(matches!(result, Value::Integer(4)));
6367
6368 let result = prim_gcd(&[Value::integer(0), Value::integer(5)]).unwrap();
6370 assert!(matches!(result, Value::Integer(5)));
6371
6372 let result = prim_gcd(&[]).unwrap();
6374 assert!(matches!(result, Value::Integer(0)));
6375
6376 assert!(prim_gcd(&[Value::real(12.5), Value::integer(8)]).is_err());
6378 }
6379
6380 #[test]
6381 fn test_lcm() {
6382 let result = prim_lcm(&[Value::integer(4), Value::integer(6)]).unwrap();
6384 assert!(matches!(result, Value::Integer(12)));
6385
6386 let result = prim_lcm(&[Value::integer(2), Value::integer(3), Value::integer(4)]).unwrap();
6388 assert!(matches!(result, Value::Integer(12)));
6389
6390 let result = prim_lcm(&[Value::integer(-4), Value::integer(6)]).unwrap();
6392 assert!(matches!(result, Value::Integer(12)));
6393
6394 let result = prim_lcm(&[Value::integer(0), Value::integer(5)]).unwrap();
6396 assert!(matches!(result, Value::Integer(0)));
6397
6398 let result = prim_lcm(&[]).unwrap();
6400 assert!(matches!(result, Value::Integer(1)));
6401
6402 assert!(prim_lcm(&[Value::real(4.5), Value::integer(6)]).is_err());
6404 }
6405
6406 #[test]
6407 fn test_floor() {
6408 let result = prim_floor(&[Value::real(3.7)]).unwrap();
6409 assert!(matches!(result, Value::Integer(3)));
6410
6411 let result = prim_floor(&[Value::real(-3.7)]).unwrap();
6412 assert!(matches!(result, Value::Integer(-4)));
6413 }
6414
6415 #[test]
6416 fn test_ceiling() {
6417 let result = prim_ceiling(&[Value::real(3.2)]).unwrap();
6418 assert!(matches!(result, Value::Integer(4)));
6419
6420 let result = prim_ceiling(&[Value::real(-3.2)]).unwrap();
6421 assert!(matches!(result, Value::Integer(-3)));
6422 }
6423
6424 #[test]
6425 fn test_truncate() {
6426 let result = prim_truncate(&[Value::real(3.7)]).unwrap();
6427 assert!(matches!(result, Value::Integer(3)));
6428
6429 let result = prim_truncate(&[Value::real(-3.7)]).unwrap();
6430 assert!(matches!(result, Value::Integer(-3)));
6431 }
6432
6433 #[test]
6434 fn test_round() {
6435 let result = prim_round(&[Value::real(3.5)]).unwrap();
6436 assert!(matches!(result, Value::Integer(4)));
6437
6438 let result = prim_round(&[Value::real(3.4)]).unwrap();
6439 assert!(matches!(result, Value::Integer(3)));
6440 }
6441
6442 #[test]
6447 fn test_string_length() {
6448 let s = Value::string("hello".to_string());
6449 let result = prim_string_length(&[s]).unwrap();
6450 assert!(matches!(result, Value::Integer(5)));
6451
6452 let empty = Value::string(String::new());
6453 let result = prim_string_length(&[empty]).unwrap();
6454 assert!(matches!(result, Value::Integer(0)));
6455 }
6456
6457 #[test]
6458 fn test_string_ref() {
6459 let s = Value::string("hello".to_string());
6460 let result = prim_string_ref(&[s.clone(), Value::integer(0)]).unwrap();
6461 assert!(matches!(result, Value::Char('h')));
6462
6463 let result = prim_string_ref(&[s, Value::integer(4)]).unwrap();
6464 assert!(matches!(result, Value::Char('o')));
6465 }
6466
6467 #[test]
6468 fn test_string_append() {
6469 let s1 = Value::string("hello".to_string());
6470 let s2 = Value::string(" ".to_string());
6471 let s3 = Value::string("world".to_string());
6472 let result = prim_string_append(&[s1, s2, s3]).unwrap();
6473
6474 if let Value::String(ref s) = result {
6475 assert_eq!(&**s, "hello world");
6476 } else {
6477 panic!("Expected string");
6478 }
6479 }
6480
6481 #[test]
6482 fn test_substring() {
6483 let s = Value::string("hello".to_string());
6484 let result = prim_substring(&[s, Value::integer(1), Value::integer(4)]).unwrap();
6485
6486 if let Value::String(ref s) = result {
6487 assert_eq!(&**s, "ell");
6488 } else {
6489 panic!("Expected string");
6490 }
6491 }
6492
6493 #[test]
6494 fn test_string_eq() {
6495 let s1 = Value::string("hello".to_string());
6496 let s2 = Value::string("hello".to_string());
6497 let s3 = Value::string("world".to_string());
6498
6499 let result = prim_string_eq(&[s1.clone(), s2]).unwrap();
6500 assert!(matches!(result, Value::Bool(true)));
6501
6502 let result = prim_string_eq(&[s1, s3]).unwrap();
6503 assert!(matches!(result, Value::Bool(false)));
6504 }
6505
6506 #[test]
6507 fn test_string_lt() {
6508 let s1 = Value::string("abc".to_string());
6509 let s2 = Value::string("def".to_string());
6510
6511 let result = prim_string_lt(&[s1.clone(), s2.clone()]).unwrap();
6512 assert!(matches!(result, Value::Bool(true)));
6513
6514 let result = prim_string_lt(&[s2, s1]).unwrap();
6515 assert!(matches!(result, Value::Bool(false)));
6516 }
6517
6518 #[test]
6519 fn test_string_ci_eq() {
6520 let result = prim_string_ci_eq(&[
6522 Value::string("Hello".to_string()),
6523 Value::string("hello".to_string()),
6524 ]).unwrap();
6525 assert!(matches!(result, Value::Bool(true)));
6526
6527 let result = prim_string_ci_eq(&[
6528 Value::string("WORLD".to_string()),
6529 Value::string("world".to_string()),
6530 ]).unwrap();
6531 assert!(matches!(result, Value::Bool(true)));
6532
6533 let result = prim_string_ci_eq(&[
6534 Value::string("hello".to_string()),
6535 Value::string("world".to_string()),
6536 ]).unwrap();
6537 assert!(matches!(result, Value::Bool(false)));
6538 }
6539
6540 #[test]
6541 fn test_string_ci_lt() {
6542 let result = prim_string_ci_lt(&[
6544 Value::string("ABC".to_string()),
6545 Value::string("def".to_string()),
6546 ]).unwrap();
6547 assert!(matches!(result, Value::Bool(true)));
6548
6549 let result = prim_string_ci_lt(&[
6550 Value::string("abc".to_string()),
6551 Value::string("DEF".to_string()),
6552 ]).unwrap();
6553 assert!(matches!(result, Value::Bool(true)));
6554
6555 let result = prim_string_ci_lt(&[
6556 Value::string("def".to_string()),
6557 Value::string("ABC".to_string()),
6558 ]).unwrap();
6559 assert!(matches!(result, Value::Bool(false)));
6560 }
6561
6562 #[test]
6563 fn test_string_ci_gt() {
6564 let result = prim_string_ci_gt(&[
6566 Value::string("DEF".to_string()),
6567 Value::string("abc".to_string()),
6568 ]).unwrap();
6569 assert!(matches!(result, Value::Bool(true)));
6570
6571 let result = prim_string_ci_gt(&[
6572 Value::string("def".to_string()),
6573 Value::string("ABC".to_string()),
6574 ]).unwrap();
6575 assert!(matches!(result, Value::Bool(true)));
6576
6577 let result = prim_string_ci_gt(&[
6578 Value::string("ABC".to_string()),
6579 Value::string("def".to_string()),
6580 ]).unwrap();
6581 assert!(matches!(result, Value::Bool(false)));
6582 }
6583
6584 #[test]
6585 fn test_string_ci_le() {
6586 let result = prim_string_ci_le(&[
6588 Value::string("ABC".to_string()),
6589 Value::string("def".to_string()),
6590 ]).unwrap();
6591 assert!(matches!(result, Value::Bool(true)));
6592
6593 let result = prim_string_ci_le(&[
6594 Value::string("Hello".to_string()),
6595 Value::string("hello".to_string()),
6596 ]).unwrap();
6597 assert!(matches!(result, Value::Bool(true)));
6598
6599 let result = prim_string_ci_le(&[
6600 Value::string("def".to_string()),
6601 Value::string("ABC".to_string()),
6602 ]).unwrap();
6603 assert!(matches!(result, Value::Bool(false)));
6604 }
6605
6606 #[test]
6607 fn test_string_ci_ge() {
6608 let result = prim_string_ci_ge(&[
6610 Value::string("DEF".to_string()),
6611 Value::string("abc".to_string()),
6612 ]).unwrap();
6613 assert!(matches!(result, Value::Bool(true)));
6614
6615 let result = prim_string_ci_ge(&[
6616 Value::string("Hello".to_string()),
6617 Value::string("hello".to_string()),
6618 ]).unwrap();
6619 assert!(matches!(result, Value::Bool(true)));
6620
6621 let result = prim_string_ci_ge(&[
6622 Value::string("ABC".to_string()),
6623 Value::string("def".to_string()),
6624 ]).unwrap();
6625 assert!(matches!(result, Value::Bool(false)));
6626 }
6627
6628 #[test]
6629 fn test_make_string() {
6630 let result = prim_make_string(&[Value::integer(5), Value::char('a')]).unwrap();
6631
6632 if let Value::String(ref s) = result {
6633 assert_eq!(&**s, "aaaaa");
6634 } else {
6635 panic!("Expected string");
6636 }
6637 }
6638
6639 #[test]
6640 fn test_string() {
6641 let result = prim_string(&[
6642 Value::char('h'),
6643 Value::char('i'),
6644 ]).unwrap();
6645
6646 if let Value::String(ref s) = result {
6647 assert_eq!(&**s, "hi");
6648 } else {
6649 panic!("Expected string");
6650 }
6651 }
6652
6653 #[test]
6654 fn test_string_to_list() {
6655 let s = Value::string("hi".to_string());
6656 let result = prim_string_to_list(&[s]).unwrap();
6657
6658 let len = prim_length(&[result.clone()]).unwrap();
6660 assert!(matches!(len, Value::Integer(2)));
6661
6662 let first = prim_car(&[result]).unwrap();
6663 assert!(matches!(first, Value::Char('h')));
6664 }
6665
6666 #[test]
6667 fn test_list_to_string() {
6668 let list = prim_list(&[
6669 Value::char('h'),
6670 Value::char('i'),
6671 ]).unwrap();
6672
6673 let result = prim_list_to_string(&[list]).unwrap();
6674
6675 if let Value::String(ref s) = result {
6676 assert_eq!(&**s, "hi");
6677 } else {
6678 panic!("Expected string");
6679 }
6680 }
6681
6682 #[test]
6683 fn test_symbol_to_string() {
6684 let sym = Value::symbol("foo");
6685 let result = prim_symbol_to_string(&[sym]).unwrap();
6686
6687 if let Value::String(ref s) = result {
6688 assert_eq!(&**s, "foo");
6689 } else {
6690 panic!("Expected string");
6691 }
6692 }
6693
6694 #[test]
6695 fn test_string_to_symbol() {
6696 let s = Value::string("foo".to_string());
6697 let result = prim_string_to_symbol(&[s]).unwrap();
6698
6699 assert!(matches!(result, Value::Symbol(_)));
6700 }
6701
6702 #[test]
6703 fn test_string_p() {
6704 assert!(matches!(prim_string_p(&[Value::string("hello".to_string())]).unwrap(), Value::Bool(true)));
6705 assert!(matches!(prim_string_p(&[Value::integer(42)]).unwrap(), Value::Bool(false)));
6706 }
6707
6708 #[test]
6709 fn test_symbol_p() {
6710 assert!(matches!(prim_symbol_p(&[Value::symbol("foo")]).unwrap(), Value::Bool(true)));
6711 assert!(matches!(prim_symbol_p(&[Value::string("foo".to_string())]).unwrap(), Value::Bool(false)));
6712 }
6713
6714 #[test]
6715 fn test_char_p() {
6716 assert!(matches!(prim_char_p(&[Value::char('a')]).unwrap(), Value::Bool(true)));
6717 assert!(matches!(prim_char_p(&[Value::integer(65)]).unwrap(), Value::Bool(false)));
6718 }
6719
6720 #[test]
6721 fn test_char_eq() {
6722 let result = prim_char_eq(&[Value::char('a'), Value::char('a')]).unwrap();
6723 assert!(matches!(result, Value::Bool(true)));
6724
6725 let result = prim_char_eq(&[Value::char('a'), Value::char('b')]).unwrap();
6726 assert!(matches!(result, Value::Bool(false)));
6727 }
6728
6729 #[test]
6730 fn test_char_lt() {
6731 let result = prim_char_lt(&[Value::char('a'), Value::char('b')]).unwrap();
6732 assert!(matches!(result, Value::Bool(true)));
6733
6734 let result = prim_char_lt(&[Value::char('b'), Value::char('a')]).unwrap();
6735 assert!(matches!(result, Value::Bool(false)));
6736 }
6737
6738 #[test]
6739 fn test_char_upcase() {
6740 let result = prim_char_upcase(&[Value::char('a')]).unwrap();
6741 assert!(matches!(result, Value::Char('A')));
6742 }
6743
6744 #[test]
6745 fn test_char_downcase() {
6746 let result = prim_char_downcase(&[Value::char('Z')]).unwrap();
6747 assert!(matches!(result, Value::Char('z')));
6748 }
6749
6750 #[test]
6751 fn test_char_le() {
6752 let result = prim_char_le(&[Value::char('a'), Value::char('b')]).unwrap();
6753 assert!(matches!(result, Value::Bool(true)));
6754
6755 let result = prim_char_le(&[Value::char('a'), Value::char('a')]).unwrap();
6756 assert!(matches!(result, Value::Bool(true)));
6757
6758 let result = prim_char_le(&[Value::char('b'), Value::char('a')]).unwrap();
6759 assert!(matches!(result, Value::Bool(false)));
6760 }
6761
6762 #[test]
6763 fn test_char_ge() {
6764 let result = prim_char_ge(&[Value::char('b'), Value::char('a')]).unwrap();
6765 assert!(matches!(result, Value::Bool(true)));
6766
6767 let result = prim_char_ge(&[Value::char('a'), Value::char('a')]).unwrap();
6768 assert!(matches!(result, Value::Bool(true)));
6769
6770 let result = prim_char_ge(&[Value::char('a'), Value::char('b')]).unwrap();
6771 assert!(matches!(result, Value::Bool(false)));
6772 }
6773
6774 #[test]
6775 fn test_char_to_integer() {
6776 let result = prim_char_to_integer(&[Value::char('A')]).unwrap();
6777 assert!(matches!(result, Value::Integer(65)));
6778
6779 let result = prim_char_to_integer(&[Value::char('a')]).unwrap();
6780 assert!(matches!(result, Value::Integer(97)));
6781
6782 let result = prim_char_to_integer(&[Value::char('0')]).unwrap();
6783 assert!(matches!(result, Value::Integer(48)));
6784
6785 assert!(prim_char_to_integer(&[Value::integer(65)]).is_err());
6787 }
6788
6789 #[test]
6790 fn test_integer_to_char() {
6791 let result = prim_integer_to_char(&[Value::integer(65)]).unwrap();
6792 assert!(matches!(result, Value::Char('A')));
6793
6794 let result = prim_integer_to_char(&[Value::integer(97)]).unwrap();
6795 assert!(matches!(result, Value::Char('a')));
6796
6797 let result = prim_integer_to_char(&[Value::integer(48)]).unwrap();
6798 assert!(matches!(result, Value::Char('0')));
6799
6800 assert!(prim_integer_to_char(&[Value::integer(-1)]).is_err());
6802 assert!(prim_integer_to_char(&[Value::integer(0x200000)]).is_err());
6803
6804 assert!(prim_integer_to_char(&[Value::char('A')]).is_err());
6806 }
6807
6808 #[test]
6809 fn test_char_alphabetic_p() {
6810 let result = prim_char_alphabetic_p(&[Value::char('a')]).unwrap();
6811 assert!(matches!(result, Value::Bool(true)));
6812
6813 let result = prim_char_alphabetic_p(&[Value::char('Z')]).unwrap();
6814 assert!(matches!(result, Value::Bool(true)));
6815
6816 let result = prim_char_alphabetic_p(&[Value::char('5')]).unwrap();
6817 assert!(matches!(result, Value::Bool(false)));
6818
6819 let result = prim_char_alphabetic_p(&[Value::char(' ')]).unwrap();
6820 assert!(matches!(result, Value::Bool(false)));
6821
6822 assert!(prim_char_alphabetic_p(&[Value::integer(97)]).is_err());
6824 }
6825
6826 #[test]
6827 fn test_char_numeric_p() {
6828 let result = prim_char_numeric_p(&[Value::char('5')]).unwrap();
6829 assert!(matches!(result, Value::Bool(true)));
6830
6831 let result = prim_char_numeric_p(&[Value::char('0')]).unwrap();
6832 assert!(matches!(result, Value::Bool(true)));
6833
6834 let result = prim_char_numeric_p(&[Value::char('a')]).unwrap();
6835 assert!(matches!(result, Value::Bool(false)));
6836
6837 let result = prim_char_numeric_p(&[Value::char(' ')]).unwrap();
6838 assert!(matches!(result, Value::Bool(false)));
6839
6840 assert!(prim_char_numeric_p(&[Value::integer(5)]).is_err());
6842 }
6843
6844 #[test]
6845 fn test_char_whitespace_p() {
6846 let result = prim_char_whitespace_p(&[Value::char(' ')]).unwrap();
6847 assert!(matches!(result, Value::Bool(true)));
6848
6849 let result = prim_char_whitespace_p(&[Value::char('\t')]).unwrap();
6850 assert!(matches!(result, Value::Bool(true)));
6851
6852 let result = prim_char_whitespace_p(&[Value::char('\n')]).unwrap();
6853 assert!(matches!(result, Value::Bool(true)));
6854
6855 let result = prim_char_whitespace_p(&[Value::char('a')]).unwrap();
6856 assert!(matches!(result, Value::Bool(false)));
6857
6858 let result = prim_char_whitespace_p(&[Value::char('5')]).unwrap();
6859 assert!(matches!(result, Value::Bool(false)));
6860
6861 assert!(prim_char_whitespace_p(&[Value::integer(32)]).is_err());
6863 }
6864
6865 #[test]
6866 fn test_char_ci_eq() {
6867 let result = prim_char_ci_eq(&[Value::char('a'), Value::char('A')]).unwrap();
6869 assert!(matches!(result, Value::Bool(true)));
6870
6871 let result = prim_char_ci_eq(&[Value::char('Z'), Value::char('z')]).unwrap();
6872 assert!(matches!(result, Value::Bool(true)));
6873
6874 let result = prim_char_ci_eq(&[Value::char('a'), Value::char('b')]).unwrap();
6875 assert!(matches!(result, Value::Bool(false)));
6876
6877 assert!(prim_char_ci_eq(&[Value::integer(97), Value::char('a')]).is_err());
6879 }
6880
6881 #[test]
6882 fn test_char_ci_lt() {
6883 let result = prim_char_ci_lt(&[Value::char('A'), Value::char('b')]).unwrap();
6885 assert!(matches!(result, Value::Bool(true)));
6886
6887 let result = prim_char_ci_lt(&[Value::char('a'), Value::char('B')]).unwrap();
6888 assert!(matches!(result, Value::Bool(true)));
6889
6890 let result = prim_char_ci_lt(&[Value::char('B'), Value::char('a')]).unwrap();
6891 assert!(matches!(result, Value::Bool(false)));
6892
6893 let result = prim_char_ci_lt(&[Value::char('A'), Value::char('a')]).unwrap();
6894 assert!(matches!(result, Value::Bool(false)));
6895 }
6896
6897 #[test]
6898 fn test_char_ci_gt() {
6899 let result = prim_char_ci_gt(&[Value::char('B'), Value::char('a')]).unwrap();
6901 assert!(matches!(result, Value::Bool(true)));
6902
6903 let result = prim_char_ci_gt(&[Value::char('b'), Value::char('A')]).unwrap();
6904 assert!(matches!(result, Value::Bool(true)));
6905
6906 let result = prim_char_ci_gt(&[Value::char('A'), Value::char('b')]).unwrap();
6907 assert!(matches!(result, Value::Bool(false)));
6908
6909 let result = prim_char_ci_gt(&[Value::char('A'), Value::char('a')]).unwrap();
6910 assert!(matches!(result, Value::Bool(false)));
6911 }
6912
6913 #[test]
6914 fn test_char_ci_le() {
6915 let result = prim_char_ci_le(&[Value::char('A'), Value::char('b')]).unwrap();
6917 assert!(matches!(result, Value::Bool(true)));
6918
6919 let result = prim_char_ci_le(&[Value::char('A'), Value::char('a')]).unwrap();
6920 assert!(matches!(result, Value::Bool(true)));
6921
6922 let result = prim_char_ci_le(&[Value::char('B'), Value::char('a')]).unwrap();
6923 assert!(matches!(result, Value::Bool(false)));
6924 }
6925
6926 #[test]
6927 fn test_char_ci_ge() {
6928 let result = prim_char_ci_ge(&[Value::char('B'), Value::char('a')]).unwrap();
6930 assert!(matches!(result, Value::Bool(true)));
6931
6932 let result = prim_char_ci_ge(&[Value::char('A'), Value::char('a')]).unwrap();
6933 assert!(matches!(result, Value::Bool(true)));
6934
6935 let result = prim_char_ci_ge(&[Value::char('A'), Value::char('b')]).unwrap();
6936 assert!(matches!(result, Value::Bool(false)));
6937 }
6938
6939 #[test]
6944 fn test_not() {
6945 let result = prim_not(&[Value::bool(true)]).unwrap();
6946 assert!(matches!(result, Value::Bool(false)));
6947
6948 let result = prim_not(&[Value::bool(false)]).unwrap();
6949 assert!(matches!(result, Value::Bool(true)));
6950
6951 let result = prim_not(&[Value::integer(0)]).unwrap();
6953 assert!(matches!(result, Value::Bool(false)));
6954 }
6955
6956 #[test]
6957 fn test_boolean_p() {
6958 assert!(matches!(prim_boolean_p(&[Value::bool(true)]).unwrap(), Value::Bool(true)));
6959 assert!(matches!(prim_boolean_p(&[Value::bool(false)]).unwrap(), Value::Bool(true)));
6960 assert!(matches!(prim_boolean_p(&[Value::integer(1)]).unwrap(), Value::Bool(false)));
6961 assert!(matches!(prim_boolean_p(&[Value::Nil]).unwrap(), Value::Bool(false)));
6962 }
6963
6964 #[test]
6965 fn test_equal_p() {
6966 let result = prim_equal_p(&[Value::integer(42), Value::integer(42)]).unwrap();
6968 assert!(matches!(result, Value::Bool(true)));
6969
6970 let result = prim_equal_p(&[Value::integer(42), Value::integer(43)]).unwrap();
6971 assert!(matches!(result, Value::Bool(false)));
6972
6973 let result = prim_equal_p(&[Value::string("hello".to_string()), Value::string("hello".to_string())]).unwrap();
6975 assert!(matches!(result, Value::Bool(true)));
6976
6977 let list1 = prim_list(&[Value::integer(1), Value::integer(2)]).unwrap();
6979 let list2 = prim_list(&[Value::integer(1), Value::integer(2)]).unwrap();
6980 let result = prim_equal_p(&[list1, list2]).unwrap();
6981 assert!(matches!(result, Value::Bool(true)));
6982 }
6983
6984 #[test]
6985 fn test_eqv_p() {
6986 let result = prim_eqv_p(&[Value::integer(42), Value::integer(42)]).unwrap();
6988 assert!(matches!(result, Value::Bool(true)));
6989
6990 let sym1 = Value::symbol("foo");
6992 let sym2 = Value::symbol("foo");
6993 let result = prim_eqv_p(&[sym1, sym2]).unwrap();
6994 assert!(matches!(result, Value::Bool(true)));
6995
6996 let result = prim_eqv_p(&[Value::integer(42), Value::string("42".to_string())]).unwrap();
6998 assert!(matches!(result, Value::Bool(false)));
6999 }
7000
7001 #[test]
7002 fn test_eq_p() {
7003 let result = prim_eq_p(&[Value::integer(42), Value::integer(42)]).unwrap();
7005 assert!(matches!(result, Value::Bool(true)));
7006
7007 let sym1 = Value::symbol("foo");
7009 let sym2 = Value::symbol("foo");
7010 let result = prim_eq_p(&[sym1, sym2]).unwrap();
7011 assert!(matches!(result, Value::Bool(true)));
7012
7013 let pair = Value::cons(Value::integer(1), Value::integer(2));
7015 let result = prim_eq_p(&[pair.clone(), pair]).unwrap();
7016 assert!(matches!(result, Value::Bool(true)));
7017 }
7018
7019 #[test]
7020 fn test_procedure_p() {
7021 let proc = Value::primitive("+", prim_add);
7023 assert!(matches!(prim_procedure_p(&[proc]).unwrap(), Value::Bool(true)));
7024
7025 assert!(matches!(prim_procedure_p(&[Value::integer(42)]).unwrap(), Value::Bool(false)));
7027 assert!(matches!(prim_procedure_p(&[Value::string("hello".to_string())]).unwrap(), Value::Bool(false)));
7028 }
7029
7030 #[test]
7035 fn test_error() {
7036 let result = prim_error(&[Value::string("test error".to_string())]);
7038 assert!(result.is_err());
7039 assert_eq!(result.unwrap_err(), "test error");
7040
7041 let result = prim_error(&[Value::symbol("error-symbol")]);
7043 assert!(result.is_err());
7044 assert!(result.unwrap_err().contains("error-symbol"));
7045
7046 let result = prim_error(&[
7048 Value::string("error:".to_string()),
7049 Value::integer(42),
7050 Value::string("foo".to_string()),
7051 ]);
7052 assert!(result.is_err());
7053 let msg = result.unwrap_err();
7054 assert!(msg.contains("error:"));
7055 assert!(msg.contains("42"));
7056 }
7057
7058 #[test]
7059 fn test_display() {
7060 let result = prim_display(&[Value::string("test".to_string())]).unwrap();
7062 assert!(matches!(result, Value::Unspecified));
7063
7064 let result = prim_display(&[Value::integer(42)]).unwrap();
7065 assert!(matches!(result, Value::Unspecified));
7066
7067 let result = prim_display(&[Value::Char('x')]).unwrap();
7068 assert!(matches!(result, Value::Unspecified));
7069 }
7070
7071 #[test]
7072 fn test_newline() {
7073 let result = prim_newline(&[]).unwrap();
7074 assert!(matches!(result, Value::Unspecified));
7075
7076 let result = prim_newline(&[Value::integer(1)]);
7078 assert!(result.is_err());
7079 }
7080
7081 #[test]
7082 fn test_write() {
7083 let result = prim_write(&[Value::string("test".to_string())]).unwrap();
7084 assert!(matches!(result, Value::Unspecified));
7085
7086 let result = prim_write(&[Value::integer(42)]).unwrap();
7087 assert!(matches!(result, Value::Unspecified));
7088 }
7089
7090 #[test]
7095 fn test_number_to_string() {
7096 let result = prim_number_to_string(&[Value::integer(42)]).unwrap();
7097 if let Value::String(ref s) = result {
7098 assert_eq!(&***s, "42");
7099 } else {
7100 panic!("Expected string");
7101 }
7102
7103 let result = prim_number_to_string(&[Value::real(3.14)]).unwrap();
7104 if let Value::String(ref s) = result {
7105 assert!(s.starts_with("3.14"));
7106 } else {
7107 panic!("Expected string");
7108 }
7109 }
7110
7111 #[test]
7112 fn test_string_to_number() {
7113 let result = prim_string_to_number(&[Value::string("42".to_string())]).unwrap();
7114 assert!(matches!(result, Value::Integer(42)));
7115
7116 let result = prim_string_to_number(&[Value::string("3.14".to_string())]).unwrap();
7117 assert!(matches!(result, Value::Real(_)));
7118
7119 let result = prim_string_to_number(&[Value::string("not-a-number".to_string())]).unwrap();
7121 assert!(matches!(result, Value::Bool(false)));
7122 }
7123
7124 #[test]
7129 fn test_keyword_p() {
7130 let kw = Value::keyword("test");
7131 assert!(matches!(prim_keyword_p(&[kw]).unwrap(), Value::Bool(true)));
7132
7133 assert!(matches!(prim_keyword_p(&[Value::symbol("test")]).unwrap(), Value::Bool(false)));
7134 assert!(matches!(prim_keyword_p(&[Value::string("test".to_string())]).unwrap(), Value::Bool(false)));
7135 }
7136
7137 #[test]
7138 fn test_keyword_to_string() {
7139 let kw = Value::keyword("test");
7140 let result = prim_keyword_to_string(&[kw]).unwrap();
7141 if let Value::String(ref s) = result {
7142 assert_eq!(&***s, "test");
7143 } else {
7144 panic!("Expected string");
7145 }
7146 }
7147
7148 #[test]
7149 fn test_string_to_keyword() {
7150 let result = prim_string_to_keyword(&[Value::string("test".to_string())]).unwrap();
7151 assert!(matches!(result, Value::Keyword(_)));
7152 }
7153
7154 #[test]
7159 fn test_memq() {
7160 let list = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
7161 let result = prim_memq(&[Value::integer(2), list.clone()]).unwrap();
7162 assert!(result.is_list());
7163
7164 let result = prim_memq(&[Value::integer(99), list]).unwrap();
7166 assert!(matches!(result, Value::Bool(false)));
7167 }
7168
7169 #[test]
7170 fn test_memv() {
7171 let list = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
7172 let result = prim_memv(&[Value::integer(2), list.clone()]).unwrap();
7173 assert!(result.is_list());
7174
7175 let result = prim_memv(&[Value::integer(99), list]).unwrap();
7177 assert!(matches!(result, Value::Bool(false)));
7178 }
7179
7180 #[test]
7181 fn test_member() {
7182 let list = prim_list(&[
7183 Value::string("a".to_string()),
7184 Value::string("b".to_string()),
7185 Value::string("c".to_string()),
7186 ])
7187 .unwrap();
7188 let result = prim_member(&[Value::string("b".to_string()), list.clone()]).unwrap();
7189 assert!(result.is_list());
7190
7191 let result = prim_member(&[Value::string("z".to_string()), list]).unwrap();
7193 assert!(matches!(result, Value::Bool(false)));
7194 }
7195
7196 #[test]
7197 fn test_assq() {
7198 let pair1 = Value::cons(Value::symbol("a"), Value::integer(1));
7200 let pair2 = Value::cons(Value::symbol("b"), Value::integer(2));
7201 let pair3 = Value::cons(Value::symbol("c"), Value::integer(3));
7202 let alist = prim_list(&[pair1, pair2, pair3]).unwrap();
7203
7204 let result = prim_assq(&[Value::symbol("b"), alist.clone()]).unwrap();
7205 assert!(result.is_pair());
7206
7207 let result = prim_assq(&[Value::symbol("z"), alist]).unwrap();
7209 assert!(matches!(result, Value::Bool(false)));
7210 }
7211
7212 #[test]
7213 fn test_assv() {
7214 let pair1 = Value::cons(Value::integer(1), Value::symbol("a"));
7216 let pair2 = Value::cons(Value::integer(2), Value::symbol("b"));
7217 let pair3 = Value::cons(Value::integer(3), Value::symbol("c"));
7218 let alist = prim_list(&[pair1, pair2, pair3]).unwrap();
7219
7220 let result = prim_assv(&[Value::integer(2), alist.clone()]).unwrap();
7221 assert!(result.is_pair());
7222
7223 let result = prim_assv(&[Value::integer(99), alist]).unwrap();
7225 assert!(matches!(result, Value::Bool(false)));
7226 }
7227
7228 #[test]
7229 fn test_assoc() {
7230 let pair1 = Value::cons(Value::string("a".to_string()), Value::integer(1));
7232 let pair2 = Value::cons(Value::string("b".to_string()), Value::integer(2));
7233 let pair3 = Value::cons(Value::string("c".to_string()), Value::integer(3));
7234 let alist = prim_list(&[pair1, pair2, pair3]).unwrap();
7235
7236 let result = prim_assoc(&[Value::string("b".to_string()), alist.clone()]).unwrap();
7237 assert!(result.is_pair());
7238
7239 let result = prim_assoc(&[Value::string("z".to_string()), alist]).unwrap();
7241 assert!(matches!(result, Value::Bool(false)));
7242 }
7243
7244 #[test]
7249 fn test_cadr() {
7250 let list = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
7252 let result = prim_cadr(&[list]).unwrap();
7253 assert!(matches!(result, Value::Integer(2)));
7254 }
7255
7256 #[test]
7257 fn test_caddr() {
7258 let list = prim_list(&[
7260 Value::integer(1),
7261 Value::integer(2),
7262 Value::integer(3),
7263 Value::integer(4),
7264 ])
7265 .unwrap();
7266 let result = prim_caddr(&[list]).unwrap();
7267 assert!(matches!(result, Value::Integer(3)));
7268 }
7269
7270 #[test]
7271 fn test_cadddr() {
7272 let list = prim_list(&[
7274 Value::integer(1),
7275 Value::integer(2),
7276 Value::integer(3),
7277 Value::integer(4),
7278 Value::integer(5),
7279 ])
7280 .unwrap();
7281 let result = prim_cadddr(&[list]).unwrap();
7282 assert!(matches!(result, Value::Integer(4)));
7283 }
7284
7285 #[test]
7286 fn test_caar() {
7287 let inner = prim_list(&[Value::integer(1), Value::integer(2)]).unwrap();
7289 let outer = prim_list(&[inner, Value::integer(3)]).unwrap();
7290 let result = prim_caar(&[outer]).unwrap();
7291 assert!(matches!(result, Value::Integer(1)));
7292 }
7293
7294 #[test]
7295 fn test_cddr() {
7296 let list = prim_list(&[
7298 Value::integer(1),
7299 Value::integer(2),
7300 Value::integer(3),
7301 Value::integer(4),
7302 ])
7303 .unwrap();
7304 let result = prim_cddr(&[list]).unwrap();
7305 assert!(result.is_list());
7306 let first = prim_car(&[result.clone()]).unwrap();
7308 assert!(matches!(first, Value::Integer(3)));
7309 }
7310
7311 #[test]
7312 fn test_cdar() {
7313 let inner = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
7315 let outer = prim_list(&[inner, Value::integer(4)]).unwrap();
7316 let result = prim_cdar(&[outer]).unwrap();
7317 assert!(result.is_list());
7318 let first = prim_car(&[result]).unwrap();
7319 assert!(matches!(first, Value::Integer(2)));
7320 }
7321
7322 #[test]
7323 fn test_caaar() {
7324 let innermost = prim_list(&[Value::integer(1), Value::integer(2)]).unwrap();
7326 let middle = prim_list(&[innermost, Value::integer(3)]).unwrap();
7327 let outer = prim_list(&[middle, Value::integer(4)]).unwrap();
7328 let result = prim_caaar(&[outer]).unwrap();
7329 assert!(matches!(result, Value::Integer(1)));
7330 }
7331
7332 #[test]
7333 fn test_cdaar() {
7334 let innermost = prim_list(&[Value::integer(1), Value::integer(2)]).unwrap();
7336 let middle = prim_list(&[innermost, Value::integer(3)]).unwrap();
7337 let outer = prim_list(&[middle, Value::integer(4)]).unwrap();
7338 let result = prim_cdaar(&[outer]).unwrap();
7339 assert!(result.is_list());
7340 let first = prim_car(&[result]).unwrap();
7341 assert!(matches!(first, Value::Integer(2)));
7342 }
7343
7344 #[test]
7345 fn test_cadar() {
7346 let inner = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
7348 let outer = prim_list(&[inner, Value::integer(4)]).unwrap();
7349 let result = prim_cadar(&[outer]).unwrap();
7350 assert!(matches!(result, Value::Integer(2)));
7351 }
7352
7353 #[test]
7354 fn test_cddar() {
7355 let inner = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3), Value::integer(4)]).unwrap();
7357 let outer = prim_list(&[inner, Value::integer(5)]).unwrap();
7358 let result = prim_cddar(&[outer]).unwrap();
7359 assert!(result.is_list());
7360 let first = prim_car(&[result]).unwrap();
7361 assert!(matches!(first, Value::Integer(3)));
7362 }
7363
7364 #[test]
7365 fn test_caadr() {
7366 let inner = prim_list(&[Value::integer(2), Value::integer(3)]).unwrap();
7368 let outer = prim_list(&[Value::integer(1), inner, Value::integer(4)]).unwrap();
7369 let result = prim_caadr(&[outer]).unwrap();
7370 assert!(matches!(result, Value::Integer(2)));
7371 }
7372
7373 #[test]
7374 fn test_cdadr() {
7375 let inner = prim_list(&[Value::integer(2), Value::integer(3), Value::integer(4)]).unwrap();
7377 let outer = prim_list(&[Value::integer(1), inner, Value::integer(5)]).unwrap();
7378 let result = prim_cdadr(&[outer]).unwrap();
7379 assert!(result.is_list());
7380 let first = prim_car(&[result]).unwrap();
7381 assert!(matches!(first, Value::Integer(3)));
7382 }
7383
7384 #[test]
7385 fn test_last() {
7386 let list = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3), Value::integer(4)]).unwrap();
7388 let result = prim_last(&[list]).unwrap();
7389 assert!(matches!(result, Value::Integer(4)));
7390
7391 let single = prim_list(&[Value::integer(1)]).unwrap();
7393 let result = prim_last(&[single]).unwrap();
7394 assert!(matches!(result, Value::Integer(1)));
7395
7396 assert!(prim_last(&[Value::Nil]).is_err());
7398 }
7399
7400 #[test]
7405 fn test_quantity_p() {
7406 assert!(matches!(prim_quantity_p(&[Value::integer(1)]).unwrap(), Value::Bool(false)));
7408 assert!(matches!(prim_quantity_p(&[Value::string("10pt".to_string())]).unwrap(), Value::Bool(false)));
7409 assert!(matches!(prim_quantity_p(&[Value::symbol("quantity")]).unwrap(), Value::Bool(false)));
7410 }
7411
7412 #[test]
7413 fn test_color_p() {
7414 assert!(matches!(prim_color_p(&[Value::string("red".to_string())]).unwrap(), Value::Bool(false)));
7416 assert!(matches!(prim_color_p(&[Value::integer(0)]).unwrap(), Value::Bool(false)));
7417 assert!(matches!(prim_color_p(&[Value::symbol("color")]).unwrap(), Value::Bool(false)));
7418 }
7419
7420 #[test]
7421 fn test_address_p() {
7422 assert!(matches!(prim_address_p(&[Value::string("addr".to_string())]).unwrap(), Value::Bool(false)));
7424 assert!(matches!(prim_address_p(&[Value::integer(0)]).unwrap(), Value::Bool(false)));
7425 assert!(matches!(prim_address_p(&[Value::symbol("address")]).unwrap(), Value::Bool(false)));
7426 }
7427
7428 #[test]
7433 fn test_format_number_decimal() {
7434 let result = prim_format_number(&[Value::integer(42), Value::string("1".to_string())]).unwrap();
7435 if let Value::String(ref s) = result {
7436 assert_eq!(&***s, "42");
7437 } else {
7438 panic!("Expected string");
7439 }
7440 }
7441
7442 #[test]
7443 fn test_format_number_roman_upper() {
7444 let result = prim_format_number(&[Value::integer(5), Value::string("I".to_string())]).unwrap();
7445 if let Value::String(ref s) = result {
7446 assert_eq!(&***s, "V");
7447 } else {
7448 panic!("Expected string");
7449 }
7450
7451 let result = prim_format_number(&[Value::integer(10), Value::string("I".to_string())]).unwrap();
7452 if let Value::String(ref s) = result {
7453 assert_eq!(&***s, "X");
7454 } else {
7455 panic!("Expected string");
7456 }
7457 }
7458
7459 #[test]
7460 fn test_format_number_roman_lower() {
7461 let result = prim_format_number(&[Value::integer(3), Value::string("i".to_string())]).unwrap();
7462 if let Value::String(ref s) = result {
7463 assert_eq!(&***s, "iii");
7464 } else {
7465 panic!("Expected string");
7466 }
7467 }
7468
7469 #[test]
7470 fn test_format_number_alpha_upper() {
7471 let result = prim_format_number(&[Value::integer(1), Value::string("A".to_string())]).unwrap();
7472 if let Value::String(ref s) = result {
7473 assert_eq!(&***s, "A");
7474 } else {
7475 panic!("Expected string");
7476 }
7477
7478 let result = prim_format_number(&[Value::integer(26), Value::string("A".to_string())]).unwrap();
7479 if let Value::String(ref s) = result {
7480 assert_eq!(&***s, "Z");
7481 } else {
7482 panic!("Expected string");
7483 }
7484 }
7485
7486 #[test]
7487 fn test_format_number_alpha_lower() {
7488 let result = prim_format_number(&[Value::integer(1), Value::string("a".to_string())]).unwrap();
7489 if let Value::String(ref s) = result {
7490 assert_eq!(&***s, "a");
7491 } else {
7492 panic!("Expected string");
7493 }
7494
7495 let result = prim_format_number(&[Value::integer(3), Value::string("a".to_string())]).unwrap();
7496 if let Value::String(ref s) = result {
7497 assert_eq!(&***s, "c");
7498 } else {
7499 panic!("Expected string");
7500 }
7501 }
7502
7503 #[test]
7504 fn test_format_number_list() {
7505 let nums = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
7506 let result = prim_format_number_list(&[nums.clone()]).unwrap();
7507 if let Value::String(ref s) = result {
7508 assert_eq!(&***s, "1.2.3");
7509 } else {
7510 panic!("Expected string");
7511 }
7512
7513 let result = prim_format_number_list(&[nums, Value::string("-".to_string())]).unwrap();
7515 if let Value::String(ref s) = result {
7516 assert_eq!(&***s, "1-2-3");
7517 } else {
7518 panic!("Expected string");
7519 }
7520 }
7521
7522 #[test]
7527 fn test_node_list_p() {
7528 let nl = prim_empty_node_list(&[]).unwrap();
7530 assert!(matches!(prim_node_list_p(&[nl]).unwrap(), Value::Bool(true)));
7531
7532 assert!(matches!(prim_node_list_p(&[Value::integer(1)]).unwrap(), Value::Bool(false)));
7534 assert!(matches!(prim_node_list_p(&[Value::string("test".to_string())]).unwrap(), Value::Bool(false)));
7535 assert!(matches!(prim_node_list_p(&[Value::Nil]).unwrap(), Value::Bool(false)));
7536 }
7537
7538 #[test]
7539 fn test_empty_node_list() {
7540 let result = prim_empty_node_list(&[]).unwrap();
7541 assert!(matches!(result, Value::NodeList(_)));
7542 }
7543
7544 #[test]
7545 fn test_node_list_empty_p() {
7546 let nl = prim_empty_node_list(&[]).unwrap();
7548 let result = prim_node_list_empty_p(&[nl]).unwrap();
7549 assert!(matches!(result, Value::Bool(true)));
7550
7551 assert!(prim_node_list_empty_p(&[Value::integer(1)]).is_err());
7553 }
7554
7555 #[test]
7556 fn test_node_list_length() {
7557 let nl = prim_empty_node_list(&[]).unwrap();
7559 let result = prim_node_list_length(&[nl]).unwrap();
7560 assert!(matches!(result, Value::Integer(0)));
7561
7562 assert!(prim_node_list_length(&[Value::integer(1)]).is_err());
7564 }
7565
7566 #[test]
7567 fn test_node_list_first() {
7568 let nl = prim_empty_node_list(&[]).unwrap();
7570 let result = prim_node_list_first(&[nl]).unwrap();
7571 assert!(matches!(result, Value::Bool(false)));
7572
7573 assert!(prim_node_list_first(&[Value::integer(1)]).is_err());
7575 }
7576
7577 #[test]
7578 fn test_node_list_rest() {
7579 let nl = prim_empty_node_list(&[]).unwrap();
7581 let result = prim_node_list_rest(&[nl]).unwrap();
7582 assert!(matches!(result, Value::NodeList(_)));
7583
7584 assert!(prim_node_list_rest(&[Value::integer(1)]).is_err());
7586 }
7587
7588 #[test]
7589 fn test_node_list_ref() {
7590 let nl = prim_empty_node_list(&[]).unwrap();
7592 let result = prim_node_list_ref(&[nl, Value::integer(0)]).unwrap();
7593 assert!(matches!(result, Value::Bool(false)));
7594
7595 assert!(prim_node_list_ref(&[Value::integer(1), Value::integer(0)]).is_err());
7597
7598 let nl = prim_empty_node_list(&[]).unwrap();
7600 assert!(prim_node_list_ref(&[nl, Value::string("x".to_string())]).is_err());
7601 }
7602
7603 #[test]
7604 fn test_node_list_reverse() {
7605 let nl = prim_empty_node_list(&[]).unwrap();
7607 let result = prim_node_list_reverse(&[nl]).unwrap();
7608 assert!(matches!(result, Value::NodeList(_)));
7609
7610 assert!(prim_node_list_reverse(&[Value::integer(1)]).is_err());
7612 }
7613
7614 #[test]
7619 fn test_expt() {
7620 let result = prim_expt(&[Value::integer(2), Value::integer(3)]).unwrap();
7622 assert!(matches!(result, Value::Integer(8)));
7623
7624 let result = prim_expt(&[Value::real(2.0), Value::integer(3)]).unwrap();
7626 assert!(matches!(result, Value::Real(r) if (r - 8.0).abs() < 0.001));
7627
7628 let result = prim_expt(&[Value::integer(4), Value::real(0.5)]).unwrap();
7630 assert!(matches!(result, Value::Real(r) if (r - 2.0).abs() < 0.001));
7631
7632 assert!(prim_expt(&[Value::string("x".to_string()), Value::integer(2)]).is_err());
7634 }
7635
7636 #[test]
7637 fn test_sqrt() {
7638 let result = prim_sqrt(&[Value::integer(16)]).unwrap();
7640 assert!(matches!(result, Value::Real(r) if (r - 4.0).abs() < 0.001));
7641
7642 let result = prim_sqrt(&[Value::real(2.0)]).unwrap();
7644 assert!(matches!(result, Value::Real(r) if (r - 1.414).abs() < 0.01));
7645
7646 assert!(prim_sqrt(&[Value::integer(-1)]).is_err());
7648
7649 assert!(prim_sqrt(&[Value::string("x".to_string())]).is_err());
7651 }
7652
7653 #[test]
7654 fn test_sin() {
7655 let result = prim_sin(&[Value::integer(0)]).unwrap();
7657 assert!(matches!(result, Value::Real(r) if r.abs() < 0.001));
7658
7659 let result = prim_sin(&[Value::real(std::f64::consts::PI / 2.0)]).unwrap();
7661 assert!(matches!(result, Value::Real(r) if (r - 1.0).abs() < 0.001));
7662
7663 assert!(prim_sin(&[Value::string("x".to_string())]).is_err());
7665 }
7666
7667 #[test]
7668 fn test_cos() {
7669 let result = prim_cos(&[Value::integer(0)]).unwrap();
7671 assert!(matches!(result, Value::Real(r) if (r - 1.0).abs() < 0.001));
7672
7673 let result = prim_cos(&[Value::real(std::f64::consts::PI)]).unwrap();
7675 assert!(matches!(result, Value::Real(r) if (r + 1.0).abs() < 0.001));
7676
7677 assert!(prim_cos(&[Value::string("x".to_string())]).is_err());
7679 }
7680
7681 #[test]
7682 fn test_tan() {
7683 let result = prim_tan(&[Value::integer(0)]).unwrap();
7685 assert!(matches!(result, Value::Real(r) if r.abs() < 0.001));
7686
7687 let result = prim_tan(&[Value::real(std::f64::consts::PI / 4.0)]).unwrap();
7689 assert!(matches!(result, Value::Real(r) if (r - 1.0).abs() < 0.001));
7690
7691 assert!(prim_tan(&[Value::string("x".to_string())]).is_err());
7693 }
7694
7695 #[test]
7696 fn test_atan() {
7697 let result = prim_atan(&[Value::integer(0)]).unwrap();
7699 assert!(matches!(result, Value::Real(r) if r.abs() < 0.001));
7700
7701 let result = prim_atan(&[Value::integer(1)]).unwrap();
7703 assert!(matches!(result, Value::Real(r) if (r - std::f64::consts::PI / 4.0).abs() < 0.001));
7704
7705 assert!(prim_atan(&[Value::string("x".to_string())]).is_err());
7707 }
7708
7709 #[test]
7710 fn test_log() {
7711 let result = prim_log(&[Value::real(std::f64::consts::E)]).unwrap();
7713 assert!(matches!(result, Value::Real(r) if (r - 1.0).abs() < 0.001));
7714
7715 let result = prim_log(&[Value::integer(1)]).unwrap();
7717 assert!(matches!(result, Value::Real(r) if r.abs() < 0.001));
7718
7719 assert!(prim_log(&[Value::integer(-1)]).is_err());
7721
7722 assert!(prim_log(&[Value::string("x".to_string())]).is_err());
7724 }
7725
7726 #[test]
7727 fn test_exp() {
7728 let result = prim_exp(&[Value::integer(0)]).unwrap();
7730 assert!(matches!(result, Value::Real(r) if (r - 1.0).abs() < 0.001));
7731
7732 let result = prim_exp(&[Value::integer(1)]).unwrap();
7734 assert!(matches!(result, Value::Real(r) if (r - std::f64::consts::E).abs() < 0.001));
7735
7736 assert!(prim_exp(&[Value::string("x".to_string())]).is_err());
7738 }
7739
7740 #[test]
7745 fn test_sosofo_p() {
7746 assert!(matches!(prim_sosofo_p(&[Value::Sosofo]).unwrap(), Value::Bool(true)));
7748
7749 assert!(matches!(prim_sosofo_p(&[Value::integer(1)]).unwrap(), Value::Bool(false)));
7751 assert!(matches!(prim_sosofo_p(&[Value::string("test".to_string())]).unwrap(), Value::Bool(false)));
7752 let nl = prim_empty_node_list(&[]).unwrap();
7753 assert!(matches!(prim_sosofo_p(&[nl]).unwrap(), Value::Bool(false)));
7754 }
7755
7756 #[test]
7757 fn test_empty_sosofo() {
7758 let result = prim_empty_sosofo(&[]).unwrap();
7759 assert!(matches!(result, Value::Sosofo));
7760 }
7761
7762 #[test]
7763 fn test_literal() {
7764 let result = prim_literal(&[Value::string("hello".to_string())]).unwrap();
7765 assert!(matches!(result, Value::Sosofo));
7766
7767 assert!(prim_literal(&[Value::integer(1)]).is_err());
7769 }
7770
7771 #[test]
7772 fn test_sosofo_append() {
7773 let s1 = prim_empty_sosofo(&[]).unwrap();
7775 let s2 = prim_empty_sosofo(&[]).unwrap();
7776 let result = prim_sosofo_append(&[s1, s2]).unwrap();
7777 assert!(matches!(result, Value::Sosofo));
7778
7779 assert!(prim_sosofo_append(&[Value::Sosofo, Value::integer(1)]).is_err());
7781 }
7782
7783 #[test]
7788 fn test_string_equiv_p() {
7789 let result = prim_string_equiv_p(&[
7791 Value::string("Hello".to_string()),
7792 Value::string("hello".to_string()),
7793 ])
7794 .unwrap();
7795 assert!(matches!(result, Value::Bool(true)));
7796
7797 let result = prim_string_equiv_p(&[
7798 Value::string("HELLO".to_string()),
7799 Value::string("hello".to_string()),
7800 ])
7801 .unwrap();
7802 assert!(matches!(result, Value::Bool(true)));
7803
7804 let result = prim_string_equiv_p(&[
7805 Value::string("hello".to_string()),
7806 Value::string("world".to_string()),
7807 ])
7808 .unwrap();
7809 assert!(matches!(result, Value::Bool(false)));
7810
7811 assert!(prim_string_equiv_p(&[Value::integer(1), Value::string("test".to_string())]).is_err());
7813 }
7814
7815 #[test]
7820 fn test_time() {
7821 let result = prim_time(&[]).unwrap();
7823 assert!(matches!(result, Value::Unspecified));
7824 }
7825
7826 #[test]
7827 fn test_time_to_string() {
7828 let result = prim_time_to_string(&[Value::Unspecified, Value::string("".to_string())]).unwrap();
7830 if let Value::String(ref s) = result {
7831 assert_eq!(&***s, "");
7832 } else {
7833 panic!("Expected string");
7834 }
7835 }
7836
7837 #[test]
7842 fn test_language_p() {
7843 assert!(matches!(prim_language_p(&[Value::Unspecified]).unwrap(), Value::Bool(false)));
7845 assert!(matches!(prim_language_p(&[Value::string("en".to_string())]).unwrap(), Value::Bool(false)));
7846 }
7847
7848 #[test]
7849 fn test_current_language() {
7850 let result = prim_current_language(&[]).unwrap();
7852 assert!(matches!(result, Value::Unspecified));
7853 }
7854}