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 Value::Bool(false) => {
1123 Ok(Value::integer(0))
1125 }
1126 Value::Unspecified => {
1127 Ok(Value::integer(0))
1130 }
1131 _ => Err(format!("string-length: not a string: {:?}", args[0])),
1132 }
1133}
1134
1135pub fn prim_string_ref(args: &[Value]) -> PrimitiveResult {
1141 if args.len() != 2 {
1142 return Err("string-ref requires exactly 2 arguments".to_string());
1143 }
1144
1145 let s = match &args[0] {
1146 Value::String(s) => s,
1147 _ => return Err(format!("string-ref: not a string: {:?}", args[0])),
1148 };
1149
1150 let k = match args[1] {
1151 Value::Integer(n) if n >= 0 => n as usize,
1152 _ => return Err("string-ref: second argument must be a non-negative integer".to_string()),
1153 };
1154
1155 let chars: Vec<char> = s.chars().collect();
1156 if k >= chars.len() {
1157 return Err("string-ref: index out of bounds".to_string());
1158 }
1159
1160 Ok(Value::char(chars[k]))
1161}
1162
1163pub fn prim_string_append(args: &[Value]) -> PrimitiveResult {
1169 let mut result = String::new();
1170
1171 for arg in args {
1172 match arg {
1173 Value::String(s) => result.push_str(s),
1174 Value::Unspecified => {
1175 }
1178 Value::Bool(false) => {
1179 }
1182 _ => return Err(format!("string-append: not a string: {:?}", arg)),
1183 }
1184 }
1185
1186 Ok(Value::string(result))
1187}
1188
1189pub fn prim_substring(args: &[Value]) -> PrimitiveResult {
1196 if args.len() != 3 {
1197 return Err("substring requires exactly 3 arguments".to_string());
1198 }
1199
1200 let s = match &args[0] {
1201 Value::String(s) => s,
1202 Value::Bool(false) => {
1203 return Err("substring: first argument is #f (expected string)".to_string());
1204 }
1205 Value::Unspecified => {
1206 return Ok(Value::string(String::new()));
1208 }
1209 _ => return Err(format!("substring: not a string: {:?}", args[0])),
1210 };
1211
1212 let start = match args[1] {
1213 Value::Integer(n) if n >= 0 => n as usize,
1214 _ => return Err("substring: start must be a non-negative integer".to_string()),
1215 };
1216
1217 let end = match args[2] {
1218 Value::Integer(n) if n >= 0 => n as usize,
1219 _ => return Err("substring: end must be a non-negative integer".to_string()),
1220 };
1221
1222 let chars: Vec<char> = s.chars().collect();
1223 if start > end || end > chars.len() {
1224 return Err("substring: invalid range".to_string());
1225 }
1226
1227 let substring: String = chars[start..end].iter().collect();
1228 Ok(Value::string(substring))
1229}
1230
1231pub fn prim_string_eq(args: &[Value]) -> PrimitiveResult {
1237 if args.len() != 2 {
1238 return Err("string=? requires exactly 2 arguments".to_string());
1239 }
1240
1241 let s1 = match &args[0] {
1242 Value::String(s) => s,
1243 _ => return Err(format!("string=?: not a string: {:?}", args[0])),
1244 };
1245
1246 let s2 = match &args[1] {
1247 Value::String(s) => s,
1248 _ => return Err(format!("string=?: not a string: {:?}", args[1])),
1249 };
1250
1251 Ok(Value::bool(s1 == s2))
1252}
1253
1254pub fn prim_string_lt(args: &[Value]) -> PrimitiveResult {
1260 if args.len() != 2 {
1261 return Err("string<? requires exactly 2 arguments".to_string());
1262 }
1263
1264 let s1 = match &args[0] {
1265 Value::String(s) => s,
1266 _ => return Err(format!("string<?: not a string: {:?}", args[0])),
1267 };
1268
1269 let s2 = match &args[1] {
1270 Value::String(s) => s,
1271 _ => return Err(format!("string<?: not a string: {:?}", args[1])),
1272 };
1273
1274 Ok(Value::bool(s1 < s2))
1275}
1276
1277pub fn prim_string_gt(args: &[Value]) -> PrimitiveResult {
1283 if args.len() != 2 {
1284 return Err("string>? requires exactly 2 arguments".to_string());
1285 }
1286
1287 let s1 = match &args[0] {
1288 Value::String(s) => s,
1289 _ => return Err(format!("string>?: not a string: {:?}", args[0])),
1290 };
1291
1292 let s2 = match &args[1] {
1293 Value::String(s) => s,
1294 _ => return Err(format!("string>?: not a string: {:?}", args[1])),
1295 };
1296
1297 Ok(Value::bool(s1 > s2))
1298}
1299
1300pub fn prim_string_le(args: &[Value]) -> PrimitiveResult {
1306 if args.len() != 2 {
1307 return Err("string<=? requires exactly 2 arguments".to_string());
1308 }
1309
1310 let s1 = match &args[0] {
1311 Value::String(s) => s,
1312 _ => return Err(format!("string<=?: not a string: {:?}", args[0])),
1313 };
1314
1315 let s2 = match &args[1] {
1316 Value::String(s) => s,
1317 _ => return Err(format!("string<=?: not a string: {:?}", args[1])),
1318 };
1319
1320 Ok(Value::bool(s1 <= s2))
1321}
1322
1323pub fn prim_string_ge(args: &[Value]) -> PrimitiveResult {
1329 if args.len() != 2 {
1330 return Err("string>=? requires exactly 2 arguments".to_string());
1331 }
1332
1333 let s1 = match &args[0] {
1334 Value::String(s) => s,
1335 _ => return Err(format!("string>=?: not a string: {:?}", args[0])),
1336 };
1337
1338 let s2 = match &args[1] {
1339 Value::String(s) => s,
1340 _ => return Err(format!("string>=?: not a string: {:?}", args[1])),
1341 };
1342
1343 Ok(Value::bool(s1 >= s2))
1344}
1345
1346pub fn prim_string_ci_eq(args: &[Value]) -> PrimitiveResult {
1352 if args.len() != 2 {
1353 return Err("string-ci=? requires exactly 2 arguments".to_string());
1354 }
1355
1356 let s1 = match &args[0] {
1357 Value::String(s) => s.to_lowercase(),
1358 _ => return Err(format!("string-ci=?: not a string: {:?}", args[0])),
1359 };
1360
1361 let s2 = match &args[1] {
1362 Value::String(s) => s.to_lowercase(),
1363 _ => return Err(format!("string-ci=?: not a string: {:?}", args[1])),
1364 };
1365
1366 Ok(Value::bool(s1 == s2))
1367}
1368
1369pub fn prim_string_ci_lt(args: &[Value]) -> PrimitiveResult {
1375 if args.len() != 2 {
1376 return Err("string-ci<? requires exactly 2 arguments".to_string());
1377 }
1378
1379 let s1 = match &args[0] {
1380 Value::String(s) => s.to_lowercase(),
1381 _ => return Err(format!("string-ci<?: not a string: {:?}", args[0])),
1382 };
1383
1384 let s2 = match &args[1] {
1385 Value::String(s) => s.to_lowercase(),
1386 _ => return Err(format!("string-ci<?: not a string: {:?}", args[1])),
1387 };
1388
1389 Ok(Value::bool(s1 < s2))
1390}
1391
1392pub fn prim_string_ci_gt(args: &[Value]) -> PrimitiveResult {
1398 if args.len() != 2 {
1399 return Err("string-ci>? requires exactly 2 arguments".to_string());
1400 }
1401
1402 let s1 = match &args[0] {
1403 Value::String(s) => s.to_lowercase(),
1404 _ => return Err(format!("string-ci>?: not a string: {:?}", args[0])),
1405 };
1406
1407 let s2 = match &args[1] {
1408 Value::String(s) => s.to_lowercase(),
1409 _ => return Err(format!("string-ci>?: not a string: {:?}", args[1])),
1410 };
1411
1412 Ok(Value::bool(s1 > s2))
1413}
1414
1415pub fn prim_string_ci_le(args: &[Value]) -> PrimitiveResult {
1421 if args.len() != 2 {
1422 return Err("string-ci<=? requires exactly 2 arguments".to_string());
1423 }
1424
1425 let s1 = match &args[0] {
1426 Value::String(s) => s.to_lowercase(),
1427 _ => return Err(format!("string-ci<=?: not a string: {:?}", args[0])),
1428 };
1429
1430 let s2 = match &args[1] {
1431 Value::String(s) => s.to_lowercase(),
1432 _ => return Err(format!("string-ci<=?: not a string: {:?}", args[1])),
1433 };
1434
1435 Ok(Value::bool(s1 <= s2))
1436}
1437
1438pub fn prim_string_ci_ge(args: &[Value]) -> PrimitiveResult {
1444 if args.len() != 2 {
1445 return Err("string-ci>=? requires exactly 2 arguments".to_string());
1446 }
1447
1448 let s1 = match &args[0] {
1449 Value::String(s) => s.to_lowercase(),
1450 _ => return Err(format!("string-ci>=?: not a string: {:?}", args[0])),
1451 };
1452
1453 let s2 = match &args[1] {
1454 Value::String(s) => s.to_lowercase(),
1455 _ => return Err(format!("string-ci>=?: not a string: {:?}", args[1])),
1456 };
1457
1458 Ok(Value::bool(s1 >= s2))
1459}
1460
1461pub fn prim_string_p(args: &[Value]) -> PrimitiveResult {
1467 if args.len() != 1 {
1468 return Err("string? requires exactly 1 argument".to_string());
1469 }
1470
1471 Ok(Value::bool(matches!(args[0], Value::String(_))))
1472}
1473
1474pub fn prim_make_string(args: &[Value]) -> PrimitiveResult {
1482 if args.is_empty() || args.len() > 2 {
1483 return Err("make-string requires 1 or 2 arguments".to_string());
1484 }
1485
1486 let k = match args[0] {
1487 Value::Integer(n) if n >= 0 => n as usize,
1488 _ => return Err("make-string: first argument must be a non-negative integer".to_string()),
1489 };
1490
1491 let ch = if args.len() == 2 {
1492 match args[1] {
1493 Value::Char(c) => c,
1494 _ => return Err("make-string: second argument must be a character".to_string()),
1495 }
1496 } else {
1497 ' '
1498 };
1499
1500 Ok(Value::string(ch.to_string().repeat(k)))
1501}
1502
1503pub fn prim_string(args: &[Value]) -> PrimitiveResult {
1509 let mut result = String::new();
1510
1511 for arg in args {
1512 match arg {
1513 Value::Char(c) => result.push(*c),
1514 _ => return Err(format!("string: not a character: {:?}", arg)),
1515 }
1516 }
1517
1518 Ok(Value::string(result))
1519}
1520
1521pub fn prim_string_to_list(args: &[Value]) -> PrimitiveResult {
1527 if args.len() != 1 {
1528 return Err("string->list requires exactly 1 argument".to_string());
1529 }
1530
1531 let s = match &args[0] {
1532 Value::String(s) => s,
1533 _ => return Err(format!("string->list: not a string: {:?}", args[0])),
1534 };
1535
1536 let mut result = Value::Nil;
1537 for ch in s.chars().rev() {
1538 result = Value::cons(Value::char(ch), result);
1539 }
1540
1541 Ok(result)
1542}
1543
1544pub fn prim_list_to_string(args: &[Value]) -> PrimitiveResult {
1550 if args.len() != 1 {
1551 return Err("list->string requires exactly 1 argument".to_string());
1552 }
1553
1554 let mut result = String::new();
1555 let mut current = args[0].clone();
1556
1557 loop {
1558 match current {
1559 Value::Nil => break,
1560 Value::Pair(ref p) => {
1561 let pair = p.borrow();
1562 match pair.car {
1563 Value::Char(c) => result.push(c),
1564 _ => return Err("list->string: list must contain only characters".to_string()),
1565 }
1566 let cdr = pair.cdr.clone();
1567 drop(pair);
1568 current = cdr;
1569 }
1570 _ => return Err("list->string: not a proper list".to_string()),
1571 }
1572 }
1573
1574 Ok(Value::string(result))
1575}
1576
1577pub fn prim_symbol_to_string(args: &[Value]) -> PrimitiveResult {
1583 if args.len() != 1 {
1584 return Err("symbol->string requires exactly 1 argument".to_string());
1585 }
1586
1587 match &args[0] {
1588 Value::Symbol(s) => Ok(Value::string(s.to_string())),
1589 _ => Err(format!("symbol->string: not a symbol: {:?}", args[0])),
1590 }
1591}
1592
1593pub fn prim_string_to_symbol(args: &[Value]) -> PrimitiveResult {
1599 if args.len() != 1 {
1600 return Err("string->symbol requires exactly 1 argument".to_string());
1601 }
1602
1603 match &args[0] {
1604 Value::String(s) => Ok(Value::symbol(s)),
1605 _ => Err(format!("string->symbol: not a string: {:?}", args[0])),
1606 }
1607}
1608
1609pub fn prim_symbol_p(args: &[Value]) -> PrimitiveResult {
1615 if args.len() != 1 {
1616 return Err("symbol? requires exactly 1 argument".to_string());
1617 }
1618
1619 Ok(Value::bool(matches!(args[0], Value::Symbol(_))))
1620}
1621
1622pub fn prim_char_p(args: &[Value]) -> PrimitiveResult {
1628 if args.len() != 1 {
1629 return Err("char? requires exactly 1 argument".to_string());
1630 }
1631
1632 Ok(Value::bool(matches!(args[0], Value::Char(_))))
1633}
1634
1635pub fn prim_char_eq(args: &[Value]) -> PrimitiveResult {
1641 if args.len() != 2 {
1642 return Err("char=? requires exactly 2 arguments".to_string());
1643 }
1644
1645 let c1 = match args[0] {
1646 Value::Char(c) => c,
1647 _ => return Err(format!("char=?: not a character: {:?}", args[0])),
1648 };
1649
1650 let c2 = match args[1] {
1651 Value::Char(c) => c,
1652 _ => return Err(format!("char=?: not a character: {:?}", args[1])),
1653 };
1654
1655 Ok(Value::bool(c1 == c2))
1656}
1657
1658pub fn prim_char_lt(args: &[Value]) -> PrimitiveResult {
1664 if args.len() != 2 {
1665 return Err("char<? requires exactly 2 arguments".to_string());
1666 }
1667
1668 let c1 = match args[0] {
1669 Value::Char(c) => c,
1670 _ => return Err(format!("char<?: not a character: {:?}", args[0])),
1671 };
1672
1673 let c2 = match args[1] {
1674 Value::Char(c) => c,
1675 _ => return Err(format!("char<?: not a character: {:?}", args[1])),
1676 };
1677
1678 Ok(Value::bool(c1 < c2))
1679}
1680
1681pub fn prim_char_gt(args: &[Value]) -> PrimitiveResult {
1687 if args.len() != 2 {
1688 return Err("char>? requires exactly 2 arguments".to_string());
1689 }
1690
1691 let c1 = match args[0] {
1692 Value::Char(c) => c,
1693 _ => return Err(format!("char>?: not a character: {:?}", args[0])),
1694 };
1695
1696 let c2 = match args[1] {
1697 Value::Char(c) => c,
1698 _ => return Err(format!("char>?: not a character: {:?}", args[1])),
1699 };
1700
1701 Ok(Value::bool(c1 > c2))
1702}
1703
1704pub fn prim_char_upcase(args: &[Value]) -> PrimitiveResult {
1710 if args.len() != 1 {
1711 return Err("char-upcase requires exactly 1 argument".to_string());
1712 }
1713
1714 match args[0] {
1715 Value::Char(c) => Ok(Value::char(c.to_ascii_uppercase())),
1716 _ => Err(format!("char-upcase: not a character: {:?}", args[0])),
1717 }
1718}
1719
1720pub fn prim_char_downcase(args: &[Value]) -> PrimitiveResult {
1726 if args.len() != 1 {
1727 return Err("char-downcase requires exactly 1 argument".to_string());
1728 }
1729
1730 match args[0] {
1731 Value::Char(c) => Ok(Value::char(c.to_ascii_lowercase())),
1732 _ => Err(format!("char-downcase: not a character: {:?}", args[0])),
1733 }
1734}
1735
1736pub fn prim_char_le(args: &[Value]) -> PrimitiveResult {
1742 if args.len() != 2 {
1743 return Err("char<=? requires exactly 2 arguments".to_string());
1744 }
1745
1746 let c1 = match args[0] {
1747 Value::Char(c) => c,
1748 _ => return Err(format!("char<=?: not a character: {:?}", args[0])),
1749 };
1750
1751 let c2 = match args[1] {
1752 Value::Char(c) => c,
1753 _ => return Err(format!("char<=?: not a character: {:?}", args[1])),
1754 };
1755
1756 Ok(Value::bool(c1 <= c2))
1757}
1758
1759pub fn prim_char_ge(args: &[Value]) -> PrimitiveResult {
1765 if args.len() != 2 {
1766 return Err("char>=? requires exactly 2 arguments".to_string());
1767 }
1768
1769 let c1 = match args[0] {
1770 Value::Char(c) => c,
1771 _ => return Err(format!("char>=?: not a character: {:?}", args[0])),
1772 };
1773
1774 let c2 = match args[1] {
1775 Value::Char(c) => c,
1776 _ => return Err(format!("char>=?: not a character: {:?}", args[1])),
1777 };
1778
1779 Ok(Value::bool(c1 >= c2))
1780}
1781
1782pub fn prim_char_to_integer(args: &[Value]) -> PrimitiveResult {
1788 if args.len() != 1 {
1789 return Err("char->integer requires exactly 1 argument".to_string());
1790 }
1791
1792 match args[0] {
1793 Value::Char(c) => Ok(Value::integer(c as i64)),
1794 _ => Err(format!("char->integer: not a character: {:?}", args[0])),
1795 }
1796}
1797
1798pub fn prim_integer_to_char(args: &[Value]) -> PrimitiveResult {
1804 if args.len() != 1 {
1805 return Err("integer->char requires exactly 1 argument".to_string());
1806 }
1807
1808 match args[0] {
1809 Value::Integer(n) => {
1810 if n < 0 || n > 0x10FFFF {
1811 return Err(format!("integer->char: invalid code point: {}", n));
1812 }
1813 match char::from_u32(n as u32) {
1814 Some(c) => Ok(Value::char(c)),
1815 None => Err(format!("integer->char: invalid Unicode code point: {}", n)),
1816 }
1817 }
1818 _ => Err(format!("integer->char: not an integer: {:?}", args[0])),
1819 }
1820}
1821
1822pub fn prim_char_alphabetic_p(args: &[Value]) -> PrimitiveResult {
1828 if args.len() != 1 {
1829 return Err("char-alphabetic? requires exactly 1 argument".to_string());
1830 }
1831
1832 match args[0] {
1833 Value::Char(c) => Ok(Value::bool(c.is_alphabetic())),
1834 _ => Err(format!("char-alphabetic?: not a character: {:?}", args[0])),
1835 }
1836}
1837
1838pub fn prim_char_numeric_p(args: &[Value]) -> PrimitiveResult {
1844 if args.len() != 1 {
1845 return Err("char-numeric? requires exactly 1 argument".to_string());
1846 }
1847
1848 match args[0] {
1849 Value::Char(c) => Ok(Value::bool(c.is_numeric())),
1850 _ => Err(format!("char-numeric?: not a character: {:?}", args[0])),
1851 }
1852}
1853
1854pub fn prim_char_whitespace_p(args: &[Value]) -> PrimitiveResult {
1860 if args.len() != 1 {
1861 return Err("char-whitespace? requires exactly 1 argument".to_string());
1862 }
1863
1864 match args[0] {
1865 Value::Char(c) => Ok(Value::bool(c.is_whitespace())),
1866 _ => Err(format!("char-whitespace?: not a character: {:?}", args[0])),
1867 }
1868}
1869
1870pub fn prim_char_ci_eq(args: &[Value]) -> PrimitiveResult {
1876 if args.len() != 2 {
1877 return Err("char-ci=? requires exactly 2 arguments".to_string());
1878 }
1879
1880 let c1 = match args[0] {
1881 Value::Char(c) => c.to_ascii_lowercase(),
1882 _ => return Err(format!("char-ci=?: not a character: {:?}", args[0])),
1883 };
1884
1885 let c2 = match args[1] {
1886 Value::Char(c) => c.to_ascii_lowercase(),
1887 _ => return Err(format!("char-ci=?: not a character: {:?}", args[1])),
1888 };
1889
1890 Ok(Value::bool(c1 == c2))
1891}
1892
1893pub fn prim_char_ci_lt(args: &[Value]) -> PrimitiveResult {
1899 if args.len() != 2 {
1900 return Err("char-ci<? requires exactly 2 arguments".to_string());
1901 }
1902
1903 let c1 = match args[0] {
1904 Value::Char(c) => c.to_ascii_lowercase(),
1905 _ => return Err(format!("char-ci<?: not a character: {:?}", args[0])),
1906 };
1907
1908 let c2 = match args[1] {
1909 Value::Char(c) => c.to_ascii_lowercase(),
1910 _ => return Err(format!("char-ci<?: not a character: {:?}", args[1])),
1911 };
1912
1913 Ok(Value::bool(c1 < c2))
1914}
1915
1916pub fn prim_char_ci_gt(args: &[Value]) -> PrimitiveResult {
1922 if args.len() != 2 {
1923 return Err("char-ci>? requires exactly 2 arguments".to_string());
1924 }
1925
1926 let c1 = match args[0] {
1927 Value::Char(c) => c.to_ascii_lowercase(),
1928 _ => return Err(format!("char-ci>?: not a character: {:?}", args[0])),
1929 };
1930
1931 let c2 = match args[1] {
1932 Value::Char(c) => c.to_ascii_lowercase(),
1933 _ => return Err(format!("char-ci>?: not a character: {:?}", args[1])),
1934 };
1935
1936 Ok(Value::bool(c1 > c2))
1937}
1938
1939pub fn prim_char_ci_le(args: &[Value]) -> PrimitiveResult {
1945 if args.len() != 2 {
1946 return Err("char-ci<=? requires exactly 2 arguments".to_string());
1947 }
1948
1949 let c1 = match args[0] {
1950 Value::Char(c) => c.to_ascii_lowercase(),
1951 _ => return Err(format!("char-ci<=?: not a character: {:?}", args[0])),
1952 };
1953
1954 let c2 = match args[1] {
1955 Value::Char(c) => c.to_ascii_lowercase(),
1956 _ => return Err(format!("char-ci<=?: not a character: {:?}", args[1])),
1957 };
1958
1959 Ok(Value::bool(c1 <= c2))
1960}
1961
1962pub fn prim_char_ci_ge(args: &[Value]) -> PrimitiveResult {
1968 if args.len() != 2 {
1969 return Err("char-ci>=? requires exactly 2 arguments".to_string());
1970 }
1971
1972 let c1 = match args[0] {
1973 Value::Char(c) => c.to_ascii_lowercase(),
1974 _ => return Err(format!("char-ci>=?: not a character: {:?}", args[0])),
1975 };
1976
1977 let c2 = match args[1] {
1978 Value::Char(c) => c.to_ascii_lowercase(),
1979 _ => return Err(format!("char-ci>=?: not a character: {:?}", args[1])),
1980 };
1981
1982 Ok(Value::bool(c1 >= c2))
1983}
1984
1985pub fn prim_not(args: &[Value]) -> PrimitiveResult {
1995 if args.len() != 1 {
1996 return Err("not requires exactly 1 argument".to_string());
1997 }
1998
1999 Ok(Value::bool(!args[0].is_true()))
2000}
2001
2002pub fn prim_boolean_p(args: &[Value]) -> PrimitiveResult {
2008 if args.len() != 1 {
2009 return Err("boolean? requires exactly 1 argument".to_string());
2010 }
2011
2012 Ok(Value::bool(matches!(args[0], Value::Bool(_))))
2013}
2014
2015pub fn prim_equal_p(args: &[Value]) -> PrimitiveResult {
2022 if args.len() != 2 {
2023 return Err("equal? requires exactly 2 arguments".to_string());
2024 }
2025
2026 Ok(Value::bool(values_equal(&args[0], &args[1])))
2027}
2028
2029fn values_equal(v1: &Value, v2: &Value) -> bool {
2031 match (v1, v2) {
2032 (Value::Nil, Value::Nil) => true,
2033 (Value::Bool(b1), Value::Bool(b2)) => b1 == b2,
2034 (Value::Integer(n1), Value::Integer(n2)) => n1 == n2,
2035 (Value::Real(r1), Value::Real(r2)) => (r1 - r2).abs() < f64::EPSILON,
2036 (Value::Integer(n), Value::Real(r)) | (Value::Real(r), Value::Integer(n)) => {
2037 (*n as f64 - r).abs() < f64::EPSILON
2038 }
2039 (Value::Char(c1), Value::Char(c2)) => c1 == c2,
2040 (Value::String(s1), Value::String(s2)) => s1 == s2,
2041 (Value::Symbol(s1), Value::Symbol(s2)) => s1 == s2,
2042 (Value::Pair(p1), Value::Pair(p2)) => {
2043 let pair1 = p1.borrow();
2044 let pair2 = p2.borrow();
2045 values_equal(&pair1.car, &pair2.car) && values_equal(&pair1.cdr, &pair2.cdr)
2046 }
2047 _ => false,
2048 }
2049}
2050
2051pub fn prim_eqv_p(args: &[Value]) -> PrimitiveResult {
2058 if args.len() != 2 {
2059 return Err("eqv? requires exactly 2 arguments".to_string());
2060 }
2061
2062 let result = match (&args[0], &args[1]) {
2063 (Value::Nil, Value::Nil) => true,
2064 (Value::Bool(b1), Value::Bool(b2)) => b1 == b2,
2065 (Value::Integer(n1), Value::Integer(n2)) => n1 == n2,
2066 (Value::Real(r1), Value::Real(r2)) => (r1 - r2).abs() < f64::EPSILON,
2067 (Value::Char(c1), Value::Char(c2)) => c1 == c2,
2068 (Value::Symbol(s1), Value::Symbol(s2)) => s1 == s2,
2069 (Value::Pair(p1), Value::Pair(p2)) => gc::Gc::ptr_eq(p1, p2),
2071 (Value::String(s1), Value::String(s2)) => gc::Gc::ptr_eq(s1, s2),
2072 (Value::Procedure(pr1), Value::Procedure(pr2)) => gc::Gc::ptr_eq(pr1, pr2),
2073 _ => false,
2074 };
2075
2076 Ok(Value::bool(result))
2077}
2078
2079pub fn prim_eq_p(args: &[Value]) -> PrimitiveResult {
2085 if args.len() != 2 {
2086 return Err("eq? requires exactly 2 arguments".to_string());
2087 }
2088
2089 let result = match (&args[0], &args[1]) {
2090 (Value::Nil, Value::Nil) => true,
2091 (Value::Bool(b1), Value::Bool(b2)) => b1 == b2,
2092 (Value::Integer(n1), Value::Integer(n2)) => n1 == n2,
2093 (Value::Char(c1), Value::Char(c2)) => c1 == c2,
2094 (Value::Symbol(s1), Value::Symbol(s2)) => s1 == s2,
2095 (Value::Pair(p1), Value::Pair(p2)) => gc::Gc::ptr_eq(p1, p2),
2097 (Value::String(s1), Value::String(s2)) => gc::Gc::ptr_eq(s1, s2),
2098 (Value::Procedure(pr1), Value::Procedure(pr2)) => gc::Gc::ptr_eq(pr1, pr2),
2099 _ => false,
2100 };
2101
2102 Ok(Value::bool(result))
2103}
2104
2105pub fn prim_procedure_p(args: &[Value]) -> PrimitiveResult {
2111 if args.len() != 1 {
2112 return Err("procedure? requires exactly 1 argument".to_string());
2113 }
2114
2115 Ok(Value::bool(matches!(args[0], Value::Procedure(_))))
2116}
2117
2118pub fn prim_error(args: &[Value]) -> PrimitiveResult {
2129 if args.is_empty() {
2130 return Err("error: requires at least 1 argument".to_string());
2131 }
2132
2133 let message = match &args[0] {
2134 Value::String(s) => s.to_string(),
2135 Value::Symbol(s) => s.to_string(),
2136 other => format!("{:?}", other),
2137 };
2138
2139 let mut full_message = message;
2141 for arg in &args[1..] {
2142 full_message.push_str(&format!(" {:?}", arg));
2143 }
2144
2145 Err(full_message)
2146}
2147
2148pub fn prim_display(args: &[Value]) -> PrimitiveResult {
2155 if args.len() != 1 {
2156 return Err("display requires exactly 1 argument".to_string());
2157 }
2158
2159 let output = match &args[0] {
2160 Value::String(s) => s.to_string(),
2161 Value::Char(c) => c.to_string(),
2162 other => format!("{:?}", other),
2163 };
2164
2165 print!("{}", output);
2166 Ok(Value::Unspecified)
2167}
2168
2169pub fn prim_newline(args: &[Value]) -> PrimitiveResult {
2175 if !args.is_empty() {
2176 return Err("newline requires 0 arguments".to_string());
2177 }
2178
2179 println!();
2180 Ok(Value::Unspecified)
2181}
2182
2183pub fn prim_write(args: &[Value]) -> PrimitiveResult {
2189 if args.len() != 1 {
2190 return Err("write requires exactly 1 argument".to_string());
2191 }
2192
2193 print!("{:?}", args[0]);
2194 Ok(Value::Unspecified)
2195}
2196
2197pub fn prim_number_to_string(args: &[Value]) -> PrimitiveResult {
2207 if args.len() != 1 {
2208 return Err("number->string requires exactly 1 argument".to_string());
2209 }
2210
2211 match &args[0] {
2212 Value::Integer(n) => Ok(Value::string(n.to_string())),
2213 Value::Real(r) => Ok(Value::string(r.to_string())),
2214 _ => Err(format!("number->string: not a number: {:?}", args[0])),
2215 }
2216}
2217
2218pub fn prim_string_to_number(args: &[Value]) -> PrimitiveResult {
2224 if args.len() != 1 {
2225 return Err("string->number requires exactly 1 argument".to_string());
2226 }
2227
2228 let s = match &args[0] {
2229 Value::String(s) => s,
2230 _ => return Err(format!("string->number: not a string: {:?}", args[0])),
2231 };
2232
2233 if let Ok(n) = s.parse::<i64>() {
2235 return Ok(Value::integer(n));
2236 }
2237
2238 if let Ok(r) = s.parse::<f64>() {
2240 return Ok(Value::real(r));
2241 }
2242
2243 Ok(Value::bool(false))
2245}
2246
2247pub fn prim_keyword_p(args: &[Value]) -> PrimitiveResult {
2257 if args.len() != 1 {
2258 return Err("keyword? requires exactly 1 argument".to_string());
2259 }
2260
2261 Ok(Value::bool(matches!(args[0], Value::Keyword(_))))
2262}
2263
2264pub fn prim_keyword_to_string(args: &[Value]) -> PrimitiveResult {
2270 if args.len() != 1 {
2271 return Err("keyword->string requires exactly 1 argument".to_string());
2272 }
2273
2274 match &args[0] {
2275 Value::Keyword(k) => Ok(Value::string(k.to_string())),
2276 _ => Err(format!("keyword->string: not a keyword: {:?}", args[0])),
2277 }
2278}
2279
2280pub fn prim_string_to_keyword(args: &[Value]) -> PrimitiveResult {
2286 if args.len() != 1 {
2287 return Err("string->keyword requires exactly 1 argument".to_string());
2288 }
2289
2290 match &args[0] {
2291 Value::String(s) => Ok(Value::keyword(s)),
2292 _ => Err(format!("string->keyword: not a string: {:?}", args[0])),
2293 }
2294}
2295
2296pub fn prim_memq(args: &[Value]) -> PrimitiveResult {
2307 if args.len() != 2 {
2308 return Err("memq requires exactly 2 arguments".to_string());
2309 }
2310
2311 let obj = &args[0];
2312 let mut current = args[1].clone();
2313
2314 loop {
2315 match current {
2316 Value::Nil => return Ok(Value::bool(false)),
2317 Value::Pair(ref p) => {
2318 let pair = p.borrow();
2319 if obj.eq(&pair.car) {
2321 drop(pair);
2322 return Ok(current);
2323 }
2324 let cdr = pair.cdr.clone();
2325 drop(pair);
2326 current = cdr;
2327 }
2328 _ => return Err("memq: not a proper list".to_string()),
2329 }
2330 }
2331}
2332
2333pub fn prim_memv(args: &[Value]) -> PrimitiveResult {
2340 if args.len() != 2 {
2341 return Err("memv requires exactly 2 arguments".to_string());
2342 }
2343
2344 let obj = &args[0];
2345 let mut current = args[1].clone();
2346
2347 loop {
2348 match current {
2349 Value::Nil => return Ok(Value::bool(false)),
2350 Value::Pair(ref p) => {
2351 let pair = p.borrow();
2352 if obj.eqv(&pair.car) {
2354 drop(pair);
2355 return Ok(current);
2356 }
2357 let cdr = pair.cdr.clone();
2358 drop(pair);
2359 current = cdr;
2360 }
2361 _ => return Err("memv: not a proper list".to_string()),
2362 }
2363 }
2364}
2365
2366pub fn prim_member(args: &[Value]) -> PrimitiveResult {
2373 if args.len() != 2 {
2374 return Err("member requires exactly 2 arguments".to_string());
2375 }
2376
2377 let obj = &args[0];
2378 let mut current = args[1].clone();
2379
2380 loop {
2381 match current {
2382 Value::Nil => return Ok(Value::bool(false)),
2383 Value::Pair(ref p) => {
2384 let pair = p.borrow();
2385 if obj.equal(&pair.car) {
2387 drop(pair);
2388 return Ok(current);
2389 }
2390 let cdr = pair.cdr.clone();
2391 drop(pair);
2392 current = cdr;
2393 }
2394 _ => return Err("member: not a proper list".to_string()),
2395 }
2396 }
2397}
2398
2399pub fn prim_assq(args: &[Value]) -> PrimitiveResult {
2406 if args.len() != 2 {
2407 return Err("assq requires exactly 2 arguments".to_string());
2408 }
2409
2410 let obj = &args[0];
2411 let mut current = args[1].clone();
2412
2413 loop {
2414 match current {
2415 Value::Nil => return Ok(Value::bool(false)),
2416 Value::Pair(ref p) => {
2417 let pair = p.borrow();
2418 if let Value::Pair(ref inner_p) = pair.car {
2420 let inner_pair = inner_p.borrow();
2421 if obj.eq(&inner_pair.car) {
2422 drop(inner_pair);
2423 let result = pair.car.clone();
2424 drop(pair);
2425 return Ok(result);
2426 }
2427 }
2428 let cdr = pair.cdr.clone();
2429 drop(pair);
2430 current = cdr;
2431 }
2432 _ => return Err("assq: not a proper list".to_string()),
2433 }
2434 }
2435}
2436
2437pub fn prim_assv(args: &[Value]) -> PrimitiveResult {
2444 if args.len() != 2 {
2445 return Err("assv requires exactly 2 arguments".to_string());
2446 }
2447
2448 let obj = &args[0];
2449 let mut current = args[1].clone();
2450
2451 loop {
2452 match current {
2453 Value::Nil => return Ok(Value::bool(false)),
2454 Value::Pair(ref p) => {
2455 let pair = p.borrow();
2456 if let Value::Pair(ref inner_p) = pair.car {
2458 let inner_pair = inner_p.borrow();
2459 if obj.eqv(&inner_pair.car) {
2460 drop(inner_pair);
2461 let result = pair.car.clone();
2462 drop(pair);
2463 return Ok(result);
2464 }
2465 }
2466 let cdr = pair.cdr.clone();
2467 drop(pair);
2468 current = cdr;
2469 }
2470 _ => return Err("assv: not a proper list".to_string()),
2471 }
2472 }
2473}
2474
2475pub fn prim_assoc(args: &[Value]) -> PrimitiveResult {
2482 if args.len() != 2 {
2483 return Err("assoc requires exactly 2 arguments".to_string());
2484 }
2485
2486 let obj = &args[0];
2487 let mut current = args[1].clone();
2488
2489 loop {
2490 match current {
2491 Value::Nil => return Ok(Value::bool(false)),
2492 Value::Pair(ref p) => {
2493 let pair = p.borrow();
2494 if let Value::Pair(ref inner_p) = pair.car {
2496 let inner_pair = inner_p.borrow();
2497 if obj.equal(&inner_pair.car) {
2498 drop(inner_pair);
2499 let result = pair.car.clone();
2500 drop(pair);
2501 return Ok(result);
2502 }
2503 }
2504 let cdr = pair.cdr.clone();
2505 drop(pair);
2506 current = cdr;
2507 }
2508 _ => return Err("assoc: not a proper list".to_string()),
2509 }
2510 }
2511}
2512
2513pub fn prim_quantity_p(args: &[Value]) -> PrimitiveResult {
2529 if args.len() != 1 {
2530 return Err("quantity? requires exactly 1 argument".to_string());
2531 }
2532 Ok(Value::bool(false))
2534}
2535
2536pub fn prim_color_p(args: &[Value]) -> PrimitiveResult {
2542 if args.len() != 1 {
2543 return Err("color? requires exactly 1 argument".to_string());
2544 }
2545 Ok(Value::bool(false))
2547}
2548
2549pub fn prim_address_p(args: &[Value]) -> PrimitiveResult {
2555 if args.len() != 1 {
2556 return Err("address? requires exactly 1 argument".to_string());
2557 }
2558 Ok(Value::bool(false))
2560}
2561
2562pub fn prim_cadr(args: &[Value]) -> PrimitiveResult {
2572 if args.len() != 1 {
2573 return Err("cadr requires exactly 1 argument".to_string());
2574 }
2575
2576 let cdr = prim_cdr(args)?;
2578 prim_car(&[cdr])
2580}
2581
2582pub fn prim_caddr(args: &[Value]) -> PrimitiveResult {
2588 if args.len() != 1 {
2589 return Err("caddr requires exactly 1 argument".to_string());
2590 }
2591
2592 let cdr1 = prim_cdr(args)?;
2594 let cdr2 = prim_cdr(&[cdr1])?;
2595 prim_car(&[cdr2])
2597}
2598
2599pub fn prim_cadddr(args: &[Value]) -> PrimitiveResult {
2605 if args.len() != 1 {
2606 return Err("cadddr requires exactly 1 argument".to_string());
2607 }
2608
2609 let cdr1 = prim_cdr(args)?;
2611 let cdr2 = prim_cdr(&[cdr1])?;
2612 let cdr3 = prim_cdr(&[cdr2])?;
2613 prim_car(&[cdr3])
2615}
2616
2617pub fn prim_caar(args: &[Value]) -> PrimitiveResult {
2623 if args.len() != 1 {
2624 return Err("caar requires exactly 1 argument".to_string());
2625 }
2626
2627 let car = prim_car(args)?;
2628 prim_car(&[car])
2629}
2630
2631pub fn prim_cddr(args: &[Value]) -> PrimitiveResult {
2637 if args.len() != 1 {
2638 return Err("cddr requires exactly 1 argument".to_string());
2639 }
2640
2641 let cdr1 = prim_cdr(args)?;
2642 prim_cdr(&[cdr1])
2643}
2644
2645pub fn prim_cdar(args: &[Value]) -> PrimitiveResult {
2651 if args.len() != 1 {
2652 return Err("cdar requires exactly 1 argument".to_string());
2653 }
2654
2655 let car = prim_car(args)?;
2656 prim_cdr(&[car])
2657}
2658
2659pub fn prim_caaar(args: &[Value]) -> PrimitiveResult {
2665 if args.len() != 1 {
2666 return Err("caaar requires exactly 1 argument".to_string());
2667 }
2668
2669 let car1 = prim_car(args)?;
2670 let car2 = prim_car(&[car1])?;
2671 prim_car(&[car2])
2672}
2673
2674pub fn prim_cdaar(args: &[Value]) -> PrimitiveResult {
2680 if args.len() != 1 {
2681 return Err("cdaar requires exactly 1 argument".to_string());
2682 }
2683
2684 let car1 = prim_car(args)?;
2685 let car2 = prim_car(&[car1])?;
2686 prim_cdr(&[car2])
2687}
2688
2689pub fn prim_cadar(args: &[Value]) -> PrimitiveResult {
2695 if args.len() != 1 {
2696 return Err("cadar requires exactly 1 argument".to_string());
2697 }
2698
2699 let car = prim_car(args)?;
2700 let cdr = prim_cdr(&[car])?;
2701 prim_car(&[cdr])
2702}
2703
2704pub fn prim_cddar(args: &[Value]) -> PrimitiveResult {
2710 if args.len() != 1 {
2711 return Err("cddar requires exactly 1 argument".to_string());
2712 }
2713
2714 let car = prim_car(args)?;
2715 let cdr1 = prim_cdr(&[car])?;
2716 prim_cdr(&[cdr1])
2717}
2718
2719pub fn prim_caadr(args: &[Value]) -> PrimitiveResult {
2725 if args.len() != 1 {
2726 return Err("caadr requires exactly 1 argument".to_string());
2727 }
2728
2729 let cdr = prim_cdr(args)?;
2730 let car = prim_car(&[cdr])?;
2731 prim_car(&[car])
2732}
2733
2734pub fn prim_cdadr(args: &[Value]) -> PrimitiveResult {
2740 if args.len() != 1 {
2741 return Err("cdadr requires exactly 1 argument".to_string());
2742 }
2743
2744 let cdr = prim_cdr(args)?;
2745 let car = prim_car(&[cdr])?;
2746 prim_cdr(&[car])
2747}
2748
2749pub fn prim_last(args: &[Value]) -> PrimitiveResult {
2759 if args.len() != 1 {
2760 return Err("last requires exactly 1 argument".to_string());
2761 }
2762
2763 let mut current = args[0].clone();
2764 loop {
2765 match current {
2766 Value::Nil => return Err("last: empty list".to_string()),
2767 Value::Pair(ref p) => {
2768 let pair = p.borrow();
2769 match &pair.cdr {
2770 Value::Nil => {
2771 return Ok(pair.car.clone());
2773 }
2774 Value::Pair(_) => {
2775 let next = pair.cdr.clone();
2777 drop(pair);
2778 current = next;
2779 }
2780 _other => {
2781 return Ok(pair.car.clone());
2783 }
2784 }
2785 }
2786 _ => return Err(format!("last: not a list: {:?}", args[0])),
2787 }
2788 }
2789}
2790
2791pub fn prim_format_number(args: &[Value]) -> PrimitiveResult {
2814 if args.len() != 2 {
2815 return Err("format-number requires exactly 2 arguments".to_string());
2816 }
2817
2818 let n = match &args[0] {
2819 Value::Integer(i) => *i,
2820 Value::Real(r) => *r as i64,
2821 _ => return Err(format!("format-number: not a number: {:?}", args[0])),
2822 };
2823
2824 let format = match &args[1] {
2825 Value::String(s) => s.as_str(),
2826 Value::Symbol(s) => s.as_ref(),
2827 _ => return Err(format!("format-number: invalid format: {:?}", args[1])),
2828 };
2829
2830 let result = match format {
2832 "1" | "decimal" => n.to_string(),
2833 "I" | "roman-upper" => {
2834 let roman_str = match n {
2836 1 => "I",
2837 2 => "II",
2838 3 => "III",
2839 4 => "IV",
2840 5 => "V",
2841 6 => "VI",
2842 7 => "VII",
2843 8 => "VIII",
2844 9 => "IX",
2845 10 => "X",
2846 11 => "XI",
2847 12 => "XII",
2848 13 => "XIII",
2849 14 => "XIV",
2850 15 => "XV",
2851 16 => "XVI",
2852 17 => "XVII",
2853 18 => "XVIII",
2854 19 => "XIX",
2855 20 => "XX",
2856 _ => return Ok(Value::string(n.to_string())),
2857 };
2858 roman_str.to_string()
2859 }
2860 "i" | "roman-lower" => {
2861 let roman_str = match n {
2862 1 => "i",
2863 2 => "ii",
2864 3 => "iii",
2865 4 => "iv",
2866 5 => "v",
2867 6 => "vi",
2868 7 => "vii",
2869 8 => "viii",
2870 9 => "ix",
2871 10 => "x",
2872 11 => "xi",
2873 12 => "xii",
2874 13 => "xiii",
2875 14 => "xiv",
2876 15 => "xv",
2877 16 => "xvi",
2878 17 => "xvii",
2879 18 => "xviii",
2880 19 => "xix",
2881 20 => "xx",
2882 _ => return Ok(Value::string(n.to_string())),
2883 };
2884 roman_str.to_string()
2885 }
2886 "a" | "alpha-lower" => {
2887 if n >= 1 && n <= 26 {
2889 ((b'a' + (n as u8 - 1)) as char).to_string()
2890 } else {
2891 n.to_string()
2892 }
2893 }
2894 "A" | "alpha-upper" => {
2895 if n >= 1 && n <= 26 {
2897 ((b'A' + (n as u8 - 1)) as char).to_string()
2898 } else {
2899 n.to_string()
2900 }
2901 }
2902 _ => n.to_string(), };
2904
2905 Ok(Value::string(result))
2906}
2907
2908pub fn prim_format_number_list(args: &[Value]) -> PrimitiveResult {
2914 if args.is_empty() || args.len() > 2 {
2915 return Err("format-number-list requires 1 or 2 arguments".to_string());
2916 }
2917
2918 let separator = if args.len() == 2 {
2919 match &args[1] {
2920 Value::String(s) => s.as_str(),
2921 Value::Symbol(s) => s.as_ref(),
2922 _ => ".",
2923 }
2924 } else {
2925 "."
2926 };
2927
2928 let mut numbers = Vec::new();
2929 let mut current = args[0].clone();
2930
2931 loop {
2932 match current {
2933 Value::Nil => break,
2934 Value::Pair(ref p) => {
2935 let pair = p.borrow();
2936 match &pair.car {
2937 Value::Integer(n) => numbers.push(n.to_string()),
2938 Value::Real(r) => numbers.push((*r as i64).to_string()),
2939 _ => {
2940 return Err("format-number-list: list must contain only numbers".to_string())
2941 }
2942 }
2943 let cdr = pair.cdr.clone();
2944 drop(pair);
2945 current = cdr;
2946 }
2947 _ => return Err("format-number-list: not a proper list".to_string()),
2948 }
2949 }
2950
2951 Ok(Value::string(numbers.join(separator)))
2952}
2953
2954pub fn prim_current_node(args: &[Value]) -> PrimitiveResult {
2974 if !args.is_empty() {
2975 return Err("current-node requires no arguments".to_string());
2976 }
2977
2978 let ctx = crate::scheme::evaluator::get_evaluator_context()
2980 .ok_or_else(|| "current-node: no evaluator context available".to_string())?;
2981
2982 let node = ctx
2984 .current_node
2985 .ok_or_else(|| "current-node: no current node set".to_string())?;
2986
2987 Ok(Value::Node(node))
2988}
2989
2990pub fn prim_node_list_p(args: &[Value]) -> PrimitiveResult {
2996 if args.len() != 1 {
2997 return Err("node-list? requires exactly 1 argument".to_string());
2998 }
2999
3000 Ok(Value::bool(matches!(args[0], Value::NodeList(_))))
3001}
3002
3003pub fn prim_empty_node_list(args: &[Value]) -> PrimitiveResult {
3009 if !args.is_empty() {
3010 return Err("empty-node-list requires no arguments".to_string());
3011 }
3012
3013 Ok(Value::node_list(Box::new(EmptyNodeList::new())))
3014}
3015
3016pub fn prim_node_list_empty_p(args: &[Value]) -> PrimitiveResult {
3022 if args.len() != 1 {
3023 return Err("node-list-empty? requires exactly 1 argument".to_string());
3024 }
3025
3026 match &args[0] {
3027 Value::NodeList(nl) => {
3028 Ok(Value::bool(nl.is_empty()))
3030 }
3031 _ => Err(format!("node-list-empty?: not a node-list: {:?}", args[0])),
3032 }
3033}
3034
3035pub fn prim_node_list_length(args: &[Value]) -> PrimitiveResult {
3041 if args.len() != 1 {
3042 return Err("node-list-length requires exactly 1 argument".to_string());
3043 }
3044
3045 match &args[0] {
3046 Value::NodeList(nl) => {
3047 Ok(Value::integer(nl.length() as i64))
3049 }
3050 Value::Node(_) => {
3051 Ok(Value::integer(1))
3053 }
3054 _ => Err(format!("node-list-length: not a node-list: {:?}", args[0])),
3055 }
3056}
3057
3058pub fn prim_node_list_first(args: &[Value]) -> PrimitiveResult {
3065 if args.len() != 1 {
3066 return Err("node-list-first requires exactly 1 argument".to_string());
3067 }
3068
3069 match &args[0] {
3070 Value::NodeList(nl) => {
3071 if let Some(node) = nl.first() {
3073 Ok(Value::node(node))
3074 } else {
3075 Ok(Value::bool(false))
3076 }
3077 }
3078 Value::Node(_) => {
3079 Ok(args[0].clone())
3082 }
3083 _ => Err(format!("node-list-first: not a node-list: {:?}", args[0])),
3084 }
3085}
3086
3087pub fn prim_node_list_last(args: &[Value]) -> PrimitiveResult {
3094 if args.len() != 1 {
3095 return Err("node-list-last requires exactly 1 argument".to_string());
3096 }
3097
3098 match &args[0] {
3099 Value::NodeList(nl) => {
3100 let len = nl.length();
3101 if len == 0 {
3102 Ok(Value::bool(false))
3103 } else {
3104 let mut current_nl = nl.clone();
3106 let mut last_node = None;
3107
3108 while let Some(node) = current_nl.first() {
3110 last_node = Some(node);
3111 let rest = current_nl.rest();
3112 if rest.is_empty() {
3113 break;
3114 }
3115 current_nl = std::rc::Rc::new(rest);
3116 }
3117
3118 if let Some(node) = last_node {
3119 Ok(Value::node(node))
3120 } else {
3121 Ok(Value::bool(false))
3122 }
3123 }
3124 }
3125 Value::Node(_) => {
3126 Ok(args[0].clone())
3129 }
3130 _ => Err(format!("node-list-last: not a node-list: {:?}", args[0])),
3131 }
3132}
3133
3134pub fn prim_node_list_to_list(args: &[Value]) -> PrimitiveResult {
3141 if args.len() != 1 {
3142 return Err("node-list->list requires exactly 1 argument".to_string());
3143 }
3144
3145 match &args[0] {
3146 Value::NodeList(nl) => {
3147 fn build_list(nl: &std::rc::Rc<Box<dyn crate::grove::NodeList>>) -> Value {
3149 if nl.is_empty() {
3150 Value::Nil
3151 } else if let Some(first) = nl.first() {
3152 let rest_nl = nl.rest();
3153 let rest_list = build_list(&std::rc::Rc::new(rest_nl));
3154 Value::cons(Value::node(first), rest_list)
3155 } else {
3156 Value::Nil
3157 }
3158 }
3159
3160 Ok(build_list(nl))
3161 }
3162 Value::Nil => {
3163 Ok(Value::Nil)
3165 }
3166 Value::Pair(_) => {
3167 Ok(args[0].clone())
3170 }
3171 _ => Err(format!("node-list->list: not a node-list: {:?}", args[0])),
3172 }
3173}
3174
3175pub fn prim_node_list_rest(args: &[Value]) -> PrimitiveResult {
3182 if args.len() != 1 {
3183 return Err("node-list-rest requires exactly 1 argument".to_string());
3184 }
3185
3186 match &args[0] {
3187 Value::NodeList(_nl) => {
3188 let rest = _nl.rest();
3190 Ok(Value::node_list(rest))
3191 }
3192 Value::Node(_) => {
3193 Ok(Value::node_list(Box::new(EmptyNodeList::new())))
3196 }
3197 _ => Err(format!("node-list-rest: not a node-list: {:?}", args[0])),
3198 }
3199}
3200
3201pub fn prim_node_list_ref(args: &[Value]) -> PrimitiveResult {
3208 if args.len() != 2 {
3209 return Err("node-list-ref requires exactly 2 arguments".to_string());
3210 }
3211
3212 match &args[0] {
3213 Value::NodeList(nl) => {
3214 match &args[1] {
3216 Value::Integer(idx) => {
3217 if *idx < 0 {
3219 return Err("node-list-ref: index must be non-negative".to_string());
3220 }
3221 if let Some(node) = nl.get(*idx as usize) {
3222 Ok(Value::node(node))
3223 } else {
3224 Ok(Value::bool(false))
3225 }
3226 }
3227 _ => Err(format!("node-list-ref: index not an integer: {:?}", args[1])),
3228 }
3229 }
3230 _ => Err(format!("node-list-ref: not a node-list: {:?}", args[0])),
3231 }
3232}
3233
3234pub fn prim_node_list_reverse(args: &[Value]) -> PrimitiveResult {
3240 if args.len() != 1 {
3241 return Err("node-list-reverse requires exactly 1 argument".to_string());
3242 }
3243
3244 match &args[0] {
3245 Value::NodeList(nl) => {
3246 let mut nodes: Vec<Box<dyn Node>> = Vec::new();
3248 let mut current = nl.clone();
3249 while let Some(node) = current.first() {
3250 nodes.push(node);
3251 current = std::rc::Rc::new(current.rest());
3252 if current.length() == 0 {
3253 break;
3254 }
3255 }
3256 nodes.reverse();
3257
3258 use crate::grove::VecNodeList;
3260 Ok(Value::node_list(Box::new(VecNodeList::new(nodes))))
3261 }
3262 _ => Err(format!("node-list-reverse: not a node-list: {:?}", args[0])),
3263 }
3264}
3265
3266pub fn prim_node_list_remove_duplicates(args: &[Value]) -> PrimitiveResult {
3273 if args.len() != 1 {
3274 return Err("node-list-remove-duplicates requires exactly 1 argument".to_string());
3275 }
3276
3277 match &args[0] {
3278 Value::NodeList(nl) => {
3279 let mut unique_nodes = Vec::new();
3280
3281 let mut index = 0;
3283 loop {
3284 if let Some(node) = nl.get(index) {
3285 let is_duplicate = unique_nodes.iter().any(|existing: &Box<dyn crate::grove::Node>| {
3287 existing.node_eq(node.as_ref())
3288 });
3289
3290 if !is_duplicate {
3291 unique_nodes.push(node);
3292 }
3293 index += 1;
3294 } else {
3295 break;
3296 }
3297 }
3298
3299 Ok(Value::node_list(Box::new(crate::grove::VecNodeList::new(unique_nodes))))
3300 }
3301 Value::Node(_) => {
3302 Ok(args[0].clone())
3305 }
3306 Value::Bool(false) => {
3307 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new())))
3309 }
3310 _ => Err(format!("node-list-remove-duplicates: not a node-list: {:?}", args[0])),
3311 }
3312}
3313
3314pub fn prim_node_list_count(args: &[Value]) -> PrimitiveResult {
3321 let unique_nl = prim_node_list_remove_duplicates(args)?;
3323 prim_node_list_length(&[unique_nl])
3324}
3325
3326pub fn prim_node_list_contains_p(args: &[Value]) -> PrimitiveResult {
3333 if args.len() != 2 {
3334 return Err("node-list-contains? requires exactly 2 arguments".to_string());
3335 }
3336
3337 let search_node = match &args[1] {
3338 Value::Node(n) => n,
3339 _ => return Err(format!("node-list-contains?: second argument not a node: {:?}", args[1])),
3340 };
3341
3342 match &args[0] {
3343 Value::NodeList(nl) => {
3344 let mut index = 0;
3346 loop {
3347 if let Some(node) = nl.get(index) {
3348 if node.node_eq(search_node.as_ref().as_ref()) {
3350 return Ok(Value::bool(true));
3351 }
3352 index += 1;
3353 } else {
3354 break;
3355 }
3356 }
3357
3358 Ok(Value::bool(false))
3360 }
3361 Value::Nil => {
3362 Ok(Value::bool(false))
3364 }
3365 Value::Pair(_) => {
3366 let mut current = args[0].clone();
3368 loop {
3369 match current {
3370 Value::Nil => return Ok(Value::bool(false)),
3371 Value::Pair(ref p) => {
3372 let (car, cdr) = {
3373 let pair_data = p.borrow();
3374 (pair_data.car.clone(), pair_data.cdr.clone())
3375 };
3376
3377 if let Value::Node(ref n) = car {
3379 if n.as_ref().node_eq(search_node.as_ref().as_ref()) {
3380 return Ok(Value::bool(true));
3381 }
3382 }
3383 current = cdr;
3385 }
3386 _ => return Err(format!("node-list-contains?: malformed list: {:?}", current)),
3387 }
3388 }
3389 }
3390 _ => Err(format!("node-list-contains?: first argument not a node-list: {:?}", args[0])),
3391 }
3392}
3393
3394pub fn prim_node_p(args: &[Value]) -> PrimitiveResult {
3400 if args.len() != 1 {
3401 return Err("node? requires exactly 1 argument".to_string());
3402 }
3403
3404 Ok(Value::bool(matches!(args[0], Value::Node(_))))
3405}
3406
3407pub fn prim_gi(args: &[Value]) -> PrimitiveResult {
3414 if args.len() != 1 {
3415 return Err("gi requires exactly 1 argument".to_string());
3416 }
3417
3418 match &args[0] {
3419 Value::Node(node) => {
3420 if let Some(gi) = node.gi() {
3421 Ok(Value::string(gi))
3422 } else {
3423 Ok(Value::bool(false))
3424 }
3425 }
3426 Value::NodeList(nl) => {
3427 if nl.length() == 1 {
3429 if let Some(node) = nl.first() {
3430 if let Some(gi) = node.gi() {
3431 Ok(Value::string(gi))
3432 } else {
3433 Ok(Value::bool(false))
3434 }
3435 } else {
3436 Ok(Value::bool(false))
3437 }
3438 } else {
3439 Err(format!("gi: node-list must have exactly 1 element, got {}", nl.length()))
3440 }
3441 }
3442 Value::Bool(false) => Ok(Value::bool(false)), _ => Err(format!("gi: not a node: {:?}", args[0])),
3444 }
3445}
3446
3447pub fn prim_data(args: &[Value]) -> PrimitiveResult {
3455 if args.len() != 1 {
3456 return Err("data requires exactly 1 argument".to_string());
3457 }
3458
3459 match &args[0] {
3460 Value::Node(node) => {
3461 if let Some(data) = node.data() {
3462 if data.is_empty() {
3465 Ok(Value::bool(false))
3466 } else {
3467 Ok(Value::string(data))
3468 }
3469 } else {
3470 Ok(Value::bool(false))
3471 }
3472 }
3473 Value::NodeList(nl) => {
3474 let mut result = String::new();
3478 let mut current = nl.clone();
3479
3480 loop {
3481 if let Some(node) = current.first() {
3482 if let Some(data) = node.data() {
3483 result.push_str(&data);
3484 }
3485 current = std::rc::Rc::new(current.rest());
3486 if current.length() == 0 {
3487 break;
3488 }
3489 } else {
3490 break;
3491 }
3492 }
3493
3494 if result.is_empty() {
3495 Ok(Value::bool(false))
3496 } else {
3497 Ok(Value::string(result))
3499 }
3500 }
3501 Value::Bool(false) => Ok(Value::bool(false)), _ => Err(format!("data: not a node: {:?}", args[0])),
3503 }
3504}
3505
3506pub fn prim_attribute_string(args: &[Value]) -> PrimitiveResult {
3515 if args.len() != 2 {
3516 return Err("attribute-string requires exactly 2 arguments".to_string());
3517 }
3518
3519 let name = match &args[0] {
3520 Value::String(s) => s.as_str(),
3521 _ => return Err(format!("attribute-string: name not a string: {:?}", args[0])),
3522 };
3523
3524 match &args[1] {
3525 Value::Node(node) => {
3526 if let Some(value) = node.attribute_string(name) {
3527 Ok(Value::string(value))
3528 } else {
3529 Ok(Value::bool(false))
3530 }
3531 }
3532 Value::NodeList(nl) => {
3533 if nl.length() == 0 {
3536 Ok(Value::bool(false))
3537 } else if nl.length() == 1 {
3538 if let Some(node) = nl.first() {
3539 if let Some(value) = node.attribute_string(name) {
3540 Ok(Value::string(value))
3541 } else {
3542 Ok(Value::bool(false))
3543 }
3544 } else {
3545 Ok(Value::bool(false))
3546 }
3547 } else {
3548 Err(format!("attribute-string: node-list must have exactly 1 element, got {}", nl.length()))
3549 }
3550 }
3551 Value::Bool(false) => Ok(Value::bool(false)), _ => Err(format!("attribute-string: not a node: {:?}", args[1])),
3553 }
3554}
3555
3556pub fn prim_children(args: &[Value]) -> PrimitiveResult {
3563 if args.len() != 1 {
3564 return Err("children requires exactly 1 argument".to_string());
3565 }
3566
3567 match &args[0] {
3568 Value::Node(node) => {
3569 let children = node.children();
3570 Ok(Value::node_list(children))
3571 }
3572 Value::NodeList(nl) => {
3573 if nl.length() == 1 {
3579 if let Some(node) = nl.first() {
3581 let children = node.children();
3582 Ok(Value::node_list(children))
3583 } else {
3584 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new())))
3585 }
3586 } else {
3587 let mut all_children: Vec<Box<dyn crate::grove::Node>> = Vec::new();
3589 let mut index = 0;
3590 while let Some(node) = nl.get(index) {
3591 let children = node.children();
3592 let mut child_index = 0;
3594 while let Some(child) = children.get(child_index) {
3595 all_children.push(child);
3596 child_index += 1;
3597 }
3598 index += 1;
3599 }
3600 Ok(Value::node_list(Box::new(crate::grove::VecNodeList::new(all_children))))
3601 }
3602 }
3603 Value::Bool(false) | Value::Unspecified => {
3604 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new())))
3606 }
3607 _ => Err(format!("children: not a node or node-list: {:?}", args[0])),
3608 }
3609}
3610
3611pub fn prim_select_children(args: &[Value]) -> PrimitiveResult {
3618 if args.len() != 2 {
3619 return Err("select-children requires exactly 2 arguments".to_string());
3620 }
3621
3622 let gi_name = match &args[0] {
3623 Value::String(s) => s.as_str(),
3624 _ => return Err(format!("select-children: first argument not a string: {:?}", args[0])),
3625 };
3626
3627 match &args[1] {
3628 Value::Node(node) => {
3629 let children = node.children();
3631
3632 let mut matching = Vec::new();
3634 let mut current = children;
3635 while !current.is_empty() {
3636 if let Some(child) = current.first() {
3637 if let Some(child_gi) = child.gi() {
3638 if child_gi == gi_name {
3639 matching.push(child);
3640 }
3641 }
3642 current = current.rest();
3643 } else {
3644 break;
3645 }
3646 }
3647
3648 Ok(Value::node_list(Box::new(crate::grove::VecNodeList::new(matching))))
3649 }
3650 Value::NodeList(nl) => {
3651 if let Some(node) = nl.first() {
3654 prim_select_children(&[args[0].clone(), Value::node(node)])
3656 } else {
3657 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new())))
3659 }
3660 }
3661 Value::Bool(false) => {
3662 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new())))
3664 }
3665 _ => Err(format!("select-children: second argument not a node or node-list: {:?}", args[1])),
3666 }
3667}
3668
3669pub fn prim_parent(args: &[Value]) -> PrimitiveResult {
3676 if args.len() != 1 {
3677 return Err("parent requires exactly 1 argument".to_string());
3678 }
3679
3680 let node: Box<dyn crate::grove::Node> = match &args[0] {
3681 Value::Node(n) => n.clone_node(),
3682 Value::NodeList(nl) => {
3683 if let Some(n) = nl.first() {
3685 n
3686 } else {
3687 return Ok(Value::bool(false)); }
3689 }
3690 Value::Bool(false) => return Ok(Value::bool(false)), _ => return Err(format!("parent: not a node or node-list: {:?}", args[0])),
3692 };
3693
3694 if let Some(parent) = node.parent() {
3695 Ok(Value::node(parent))
3696 } else {
3697 Ok(Value::bool(false))
3698 }
3699}
3700
3701pub fn prim_tree_root(args: &[Value]) -> PrimitiveResult {
3708 if args.len() != 1 {
3709 return Err("tree-root requires exactly 1 argument".to_string());
3710 }
3711
3712 match &args[0] {
3713 Value::Node(node) => {
3714 let mut current = node.clone_node();
3716 while let Some(parent) = current.parent() {
3717 current = parent;
3718 }
3719 Ok(Value::node(current))
3720 }
3721 Value::Bool(false) => Ok(Value::bool(false)), _ => Err(format!("tree-root: not a node: {:?}", args[0])),
3723 }
3724}
3725
3726pub fn prim_ancestors(args: &[Value]) -> PrimitiveResult {
3734 if args.len() != 1 {
3735 return Err("ancestors requires exactly 1 argument".to_string());
3736 }
3737
3738 match &args[0] {
3739 Value::Node(node) => {
3740 let mut ancestor_nodes = Vec::new();
3742 let mut current = node.clone_node();
3743
3744 while let Some(parent) = current.parent() {
3745 ancestor_nodes.push(parent.clone_node());
3746 current = parent;
3747 }
3748
3749 Ok(Value::node_list(Box::new(crate::grove::VecNodeList::new(ancestor_nodes))))
3750 }
3751 Value::Bool(false) => Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))), _ => Err(format!("ancestors: not a node: {:?}", args[0])),
3753 }
3754}
3755
3756pub fn prim_id(args: &[Value]) -> PrimitiveResult {
3763 if args.len() != 1 {
3764 return Err("id requires exactly 1 argument".to_string());
3765 }
3766
3767 match &args[0] {
3768 Value::Node(node) => {
3769 if let Some(id) = node.id() {
3770 Ok(Value::string(id))
3771 } else {
3772 Ok(Value::bool(false))
3773 }
3774 }
3775 _ => Err(format!("id: not a node: {:?}", args[0])),
3776 }
3777}
3778
3779pub fn prim_ancestor(args: &[Value]) -> PrimitiveResult {
3787 if args.len() != 2 {
3788 return Err("ancestor requires exactly 2 arguments".to_string());
3789 }
3790
3791 let gi_name = match &args[0] {
3793 Value::String(s) => s.clone(),
3794 _ => return Err(format!("ancestor: first argument not a string: {:?}", args[0])),
3795 };
3796
3797 let starting_node: Box<dyn crate::grove::Node> = match &args[1] {
3799 Value::Node(n) => n.clone_node(),
3800 Value::NodeList(nl) => {
3801 if let Some(n) = nl.first() {
3803 n
3804 } else {
3805 return Ok(Value::bool(false)); }
3807 }
3808 Value::Bool(false) => return Ok(Value::bool(false)), _ => return Err(format!("ancestor: second argument not a node or node-list: {:?}", args[1])),
3810 };
3811
3812 let mut current = starting_node.parent();
3814 while let Some(parent_node) = current {
3815 if let Some(parent_gi) = parent_node.gi() {
3816 if parent_gi == gi_name.as_str() {
3817 return Ok(Value::node(parent_node));
3818 }
3819 }
3820 current = parent_node.parent();
3821 }
3822
3823 Ok(Value::bool(false))
3825}
3826
3827pub fn prim_descendants(args: &[Value]) -> PrimitiveResult {
3834 if args.len() != 1 {
3835 return Err("descendants requires exactly 1 argument".to_string());
3836 }
3837
3838 match &args[0] {
3839 Value::Node(node) => {
3840 let mut descendants = Vec::new();
3841 collect_descendants(node.as_ref().as_ref(), &mut descendants);
3845 Ok(Value::node_list(Box::new(crate::grove::VecNodeList::new(descendants))))
3846 }
3847 Value::NodeList(nl) => {
3848 if let Some(node) = nl.first() {
3850 let mut descendants = Vec::new();
3851 collect_descendants(&*node, &mut descendants);
3853 Ok(Value::node_list(Box::new(crate::grove::VecNodeList::new(descendants))))
3854 } else {
3855 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new())))
3856 }
3857 }
3858 _ => Err(format!("descendants: not a node or node-list: {:?}", args[0])),
3859 }
3860}
3861
3862fn collect_descendants(node: &dyn crate::grove::Node, result: &mut Vec<Box<dyn crate::grove::Node>>) {
3864 let children = node.children();
3865 let len = children.length();
3866
3867 for i in 0..len {
3868 if let Some(child) = children.get(i) {
3869 result.push(child.clone_node());
3871
3872 collect_descendants(&*child, result);
3875 }
3876 }
3877}
3878
3879pub fn prim_follow(args: &[Value]) -> PrimitiveResult {
3885 if args.len() != 1 {
3886 return Err("follow requires exactly 1 argument".to_string());
3887 }
3888
3889 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new())))
3892}
3893
3894pub fn prim_preced(args: &[Value]) -> PrimitiveResult {
3900 if args.len() != 1 {
3901 return Err("preced requires exactly 1 argument".to_string());
3902 }
3903
3904 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new())))
3907}
3908
3909pub fn prim_attributes(args: &[Value]) -> PrimitiveResult {
3915 if args.len() != 1 {
3916 return Err("attributes requires exactly 1 argument".to_string());
3917 }
3918
3919 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new())))
3922}
3923
3924pub fn prim_select_elements(args: &[Value]) -> PrimitiveResult {
3930 if args.len() != 2 {
3931 return Err("select-elements requires exactly 2 arguments".to_string());
3932 }
3933
3934 let node_list = match &args[0] {
3935 Value::NodeList(nl) => nl,
3936 _ => return Err(format!("select-elements: first argument not a node-list: {:?}", args[0])),
3937 };
3938
3939 let gi_name = match &args[1] {
3940 Value::String(s) => s.as_str(),
3941 _ => return Err(format!("select-elements: second argument not a string: {:?}", args[1])),
3942 };
3943
3944 let mut result_nodes = Vec::new();
3946
3947 let mut index = 0;
3949 loop {
3950 if let Some(node) = node_list.get(index) {
3951 if let Some(node_gi) = node.gi() {
3953 if node_gi == gi_name {
3954 result_nodes.push(node);
3955 }
3956 }
3957 index += 1;
3958 } else {
3959 break;
3960 }
3961 }
3962
3963 Ok(Value::node_list(Box::new(crate::grove::VecNodeList::new(result_nodes))))
3965}
3966
3967pub fn prim_element_with_id(args: &[Value]) -> PrimitiveResult {
3975 if args.is_empty() || args.len() > 2 {
3976 return Err("element-with-id requires 1 or 2 arguments".to_string());
3977 }
3978
3979 let id = match &args[0] {
3981 Value::String(s) => s.as_str(),
3982 Value::Bool(false) => return Ok(Value::bool(false)), _ => return Err(format!("element-with-id: first argument not a string: {:?}", args[0])),
3984 };
3985
3986 let ctx = crate::scheme::evaluator::get_evaluator_context()
3988 .ok_or_else(|| "element-with-id: no evaluator context available".to_string())?;
3989
3990 let grove = ctx.grove
3991 .as_ref()
3992 .ok_or_else(|| "element-with-id: no grove available".to_string())?;
3993
3994 match grove.element_with_id(id) {
3996 Some(node) => Ok(Value::node(node)),
3997 None => Ok(Value::bool(false)),
3998 }
3999}
4000
4001pub fn prim_expt(args: &[Value]) -> PrimitiveResult {
4011 if args.len() != 2 {
4012 return Err("expt requires exactly 2 arguments".to_string());
4013 }
4014
4015 let base = match &args[0] {
4016 Value::Integer(n) => *n as f64,
4017 Value::Real(r) => *r,
4018 _ => return Err(format!("expt: not a number: {:?}", args[0])),
4019 };
4020
4021 let exponent = match &args[1] {
4022 Value::Integer(n) => *n as f64,
4023 Value::Real(r) => *r,
4024 _ => return Err(format!("expt: not a number: {:?}", args[1])),
4025 };
4026
4027 let result = base.powf(exponent);
4028
4029 if matches!(args[0], Value::Integer(_)) && matches!(args[1], Value::Integer(_)) && result.fract() == 0.0 {
4031 Ok(Value::integer(result as i64))
4032 } else {
4033 Ok(Value::real(result))
4034 }
4035}
4036
4037pub fn prim_sqrt(args: &[Value]) -> PrimitiveResult {
4043 if args.len() != 1 {
4044 return Err("sqrt requires exactly 1 argument".to_string());
4045 }
4046
4047 let n = match &args[0] {
4048 Value::Integer(i) => *i as f64,
4049 Value::Real(r) => *r,
4050 _ => return Err(format!("sqrt: not a number: {:?}", args[0])),
4051 };
4052
4053 if n < 0.0 {
4054 return Err("sqrt: negative argument".to_string());
4055 }
4056
4057 Ok(Value::real(n.sqrt()))
4058}
4059
4060pub fn prim_sin(args: &[Value]) -> PrimitiveResult {
4066 if args.len() != 1 {
4067 return Err("sin requires exactly 1 argument".to_string());
4068 }
4069
4070 let n = match &args[0] {
4071 Value::Integer(i) => *i as f64,
4072 Value::Real(r) => *r,
4073 _ => return Err(format!("sin: not a number: {:?}", args[0])),
4074 };
4075
4076 Ok(Value::real(n.sin()))
4077}
4078
4079pub fn prim_cos(args: &[Value]) -> PrimitiveResult {
4085 if args.len() != 1 {
4086 return Err("cos requires exactly 1 argument".to_string());
4087 }
4088
4089 let n = match &args[0] {
4090 Value::Integer(i) => *i as f64,
4091 Value::Real(r) => *r,
4092 _ => return Err(format!("cos: not a number: {:?}", args[0])),
4093 };
4094
4095 Ok(Value::real(n.cos()))
4096}
4097
4098pub fn prim_tan(args: &[Value]) -> PrimitiveResult {
4104 if args.len() != 1 {
4105 return Err("tan requires exactly 1 argument".to_string());
4106 }
4107
4108 let n = match &args[0] {
4109 Value::Integer(i) => *i as f64,
4110 Value::Real(r) => *r,
4111 _ => return Err(format!("tan: not a number: {:?}", args[0])),
4112 };
4113
4114 Ok(Value::real(n.tan()))
4115}
4116
4117pub fn prim_atan(args: &[Value]) -> PrimitiveResult {
4123 if args.len() != 1 {
4124 return Err("atan requires exactly 1 argument".to_string());
4125 }
4126
4127 let n = match &args[0] {
4128 Value::Integer(i) => *i as f64,
4129 Value::Real(r) => *r,
4130 _ => return Err(format!("atan: not a number: {:?}", args[0])),
4131 };
4132
4133 Ok(Value::real(n.atan()))
4134}
4135
4136pub fn prim_log(args: &[Value]) -> PrimitiveResult {
4142 if args.len() != 1 {
4143 return Err("log requires exactly 1 argument".to_string());
4144 }
4145
4146 let n = match &args[0] {
4147 Value::Integer(i) => *i as f64,
4148 Value::Real(r) => *r,
4149 _ => return Err(format!("log: not a number: {:?}", args[0])),
4150 };
4151
4152 if n <= 0.0 {
4153 return Err("log: argument must be positive".to_string());
4154 }
4155
4156 Ok(Value::real(n.ln()))
4157}
4158
4159pub fn prim_exp(args: &[Value]) -> PrimitiveResult {
4165 if args.len() != 1 {
4166 return Err("exp requires exactly 1 argument".to_string());
4167 }
4168
4169 let n = match &args[0] {
4170 Value::Integer(i) => *i as f64,
4171 Value::Real(r) => *r,
4172 _ => return Err(format!("exp: not a number: {:?}", args[0])),
4173 };
4174
4175 Ok(Value::real(n.exp()))
4176}
4177
4178pub fn prim_asin(args: &[Value]) -> PrimitiveResult {
4184 if args.len() != 1 {
4185 return Err("asin requires exactly 1 argument".to_string());
4186 }
4187
4188 let n = match &args[0] {
4189 Value::Integer(i) => *i as f64,
4190 Value::Real(r) => *r,
4191 _ => return Err(format!("asin: not a number: {:?}", args[0])),
4192 };
4193
4194 if n < -1.0 || n > 1.0 {
4195 return Err("asin: argument must be in range [-1, 1]".to_string());
4196 }
4197
4198 Ok(Value::real(n.asin()))
4199}
4200
4201pub fn prim_acos(args: &[Value]) -> PrimitiveResult {
4207 if args.len() != 1 {
4208 return Err("acos requires exactly 1 argument".to_string());
4209 }
4210
4211 let n = match &args[0] {
4212 Value::Integer(i) => *i as f64,
4213 Value::Real(r) => *r,
4214 _ => return Err(format!("acos: not a number: {:?}", args[0])),
4215 };
4216
4217 if n < -1.0 || n > 1.0 {
4218 return Err("acos: argument must be in range [-1, 1]".to_string());
4219 }
4220
4221 Ok(Value::real(n.acos()))
4222}
4223
4224pub fn prim_exact_p(args: &[Value]) -> PrimitiveResult {
4230 if args.len() != 1 {
4231 return Err("exact? requires exactly 1 argument".to_string());
4232 }
4233
4234 Ok(Value::bool(matches!(args[0], Value::Integer(_))))
4235}
4236
4237pub fn prim_inexact_p(args: &[Value]) -> PrimitiveResult {
4243 if args.len() != 1 {
4244 return Err("inexact? requires exactly 1 argument".to_string());
4245 }
4246
4247 Ok(Value::bool(matches!(args[0], Value::Real(_))))
4248}
4249
4250pub fn prim_exact_to_inexact(args: &[Value]) -> PrimitiveResult {
4256 if args.len() != 1 {
4257 return Err("exact->inexact requires exactly 1 argument".to_string());
4258 }
4259
4260 match &args[0] {
4261 Value::Integer(i) => Ok(Value::real(*i as f64)),
4262 Value::Real(r) => Ok(Value::real(*r)), _ => Err(format!("exact->inexact: not a number: {:?}", args[0])),
4264 }
4265}
4266
4267pub fn prim_inexact_to_exact(args: &[Value]) -> PrimitiveResult {
4273 if args.len() != 1 {
4274 return Err("inexact->exact requires exactly 1 argument".to_string());
4275 }
4276
4277 match &args[0] {
4278 Value::Real(r) => {
4279 if r.fract() == 0.0 && r.is_finite() {
4280 Ok(Value::integer(*r as i64))
4281 } else {
4282 Err("inexact->exact: cannot convert non-integer to exact".to_string())
4283 }
4284 }
4285 Value::Integer(i) => Ok(Value::integer(*i)), _ => Err(format!("inexact->exact: not a number: {:?}", args[0])),
4287 }
4288}
4289
4290pub fn prim_entity_system_id(_args: &[Value]) -> PrimitiveResult {
4296 Ok(Value::bool(false)) }
4298
4299pub fn prim_entity_public_id(_args: &[Value]) -> PrimitiveResult {
4301 Ok(Value::bool(false)) }
4303
4304pub fn prim_notation_system_id(_args: &[Value]) -> PrimitiveResult {
4306 Ok(Value::bool(false)) }
4308
4309pub fn prim_notation_public_id(_args: &[Value]) -> PrimitiveResult {
4311 Ok(Value::bool(false)) }
4313
4314pub fn prim_color(_args: &[Value]) -> PrimitiveResult {
4320 Ok(Value::Unspecified) }
4322
4323pub fn prim_color_space(_args: &[Value]) -> PrimitiveResult {
4325 Ok(Value::Unspecified) }
4327
4328pub fn prim_color_space_p(args: &[Value]) -> PrimitiveResult {
4330 if args.len() != 1 {
4331 return Err("color-space? requires exactly 1 argument".to_string());
4332 }
4333 Ok(Value::bool(false)) }
4335
4336pub fn prim_display_space(_args: &[Value]) -> PrimitiveResult {
4338 Ok(Value::Unspecified) }
4340
4341pub fn prim_display_space_p(args: &[Value]) -> PrimitiveResult {
4343 if args.len() != 1 {
4344 return Err("display-space? requires exactly 1 argument".to_string());
4345 }
4346 Ok(Value::bool(false)) }
4348
4349pub fn prim_inline_space(_args: &[Value]) -> PrimitiveResult {
4351 Ok(Value::Unspecified) }
4353
4354pub fn prim_inline_space_p(args: &[Value]) -> PrimitiveResult {
4356 if args.len() != 1 {
4357 return Err("inline-space? requires exactly 1 argument".to_string());
4358 }
4359 Ok(Value::bool(false)) }
4361
4362pub fn prim_glyph_id(_args: &[Value]) -> PrimitiveResult {
4364 Ok(Value::Unspecified) }
4366
4367pub fn prim_glyph_id_p(args: &[Value]) -> PrimitiveResult {
4369 if args.len() != 1 {
4370 return Err("glyph-id? requires exactly 1 argument".to_string());
4371 }
4372 Ok(Value::bool(false)) }
4374
4375pub fn prim_glyph_subst_table(_args: &[Value]) -> PrimitiveResult {
4377 Ok(Value::Unspecified) }
4379
4380pub fn prim_glyph_subst_table_p(args: &[Value]) -> PrimitiveResult {
4382 if args.len() != 1 {
4383 return Err("glyph-subst-table? requires exactly 1 argument".to_string());
4384 }
4385 Ok(Value::bool(false)) }
4387
4388pub fn prim_glyph_subst(_args: &[Value]) -> PrimitiveResult {
4390 Ok(Value::Unspecified) }
4392
4393pub fn prim_current_node_address(_args: &[Value]) -> PrimitiveResult {
4395 Ok(Value::Unspecified) }
4397
4398pub fn prim_address_local_p(args: &[Value]) -> PrimitiveResult {
4400 if args.len() != 1 {
4401 return Err("address-local? requires exactly 1 argument".to_string());
4402 }
4403 Ok(Value::bool(false)) }
4405
4406pub fn prim_address_visited_p(args: &[Value]) -> PrimitiveResult {
4408 if args.len() != 1 {
4409 return Err("address-visited? requires exactly 1 argument".to_string());
4410 }
4411 Ok(Value::bool(false)) }
4413
4414pub fn prim_node_list(_args: &[Value]) -> PrimitiveResult {
4420 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
4422
4423pub fn prim_node_list_map(_args: &[Value]) -> PrimitiveResult {
4431 Err("node-list-map should be handled as a special form in the evaluator".to_string())
4432}
4433
4434pub fn prim_node_property(_args: &[Value]) -> PrimitiveResult {
4436 Ok(Value::Unspecified) }
4438
4439pub fn prim_match_element_p(_args: &[Value]) -> PrimitiveResult {
4441 Ok(Value::bool(false)) }
4443
4444pub fn prim_named_node_list_p(args: &[Value]) -> PrimitiveResult {
4446 if args.len() != 1 {
4447 return Err("named-node-list? requires exactly 1 argument".to_string());
4448 }
4449 Ok(Value::bool(false)) }
4451
4452pub fn prim_node_list_eq(args: &[Value]) -> PrimitiveResult {
4460 if args.len() != 2 {
4461 return Err("node-list=? requires exactly 2 arguments".to_string());
4462 }
4463
4464 match (&args[0], &args[1]) {
4466 (Value::Node(n1), Value::Node(n2)) => {
4468 Ok(Value::bool(n1.as_ref().as_ref().node_eq(n2.as_ref().as_ref())))
4469 }
4470
4471 (Value::Node(n), Value::NodeList(nl)) | (Value::NodeList(nl), Value::Node(n)) => {
4473 if nl.length() != 1 {
4474 return Ok(Value::bool(false));
4475 }
4476 if let Some(nl_node) = nl.get(0) {
4477 Ok(Value::bool(n.as_ref().as_ref().node_eq(nl_node.as_ref())))
4479 } else {
4480 Ok(Value::bool(false))
4481 }
4482 }
4483
4484 (Value::NodeList(nl1), Value::NodeList(nl2)) => {
4486 let len1 = nl1.length();
4487 let len2 = nl2.length();
4488
4489 if len1 != len2 {
4491 return Ok(Value::bool(false));
4492 }
4493
4494 for i in 0..len1 {
4496 let node1 = nl1.get(i);
4497 let node2 = nl2.get(i);
4498
4499 match (node1, node2) {
4500 (Some(n1), Some(n2)) => {
4501 if !n1.node_eq(n2.as_ref()) {
4503 return Ok(Value::bool(false));
4504 }
4505 }
4506 (None, None) => continue,
4507 _ => return Ok(Value::bool(false)),
4508 }
4509 }
4510
4511 Ok(Value::bool(true))
4512 }
4513
4514 _ => Err(format!("node-list=?: arguments must be nodes or node-lists: {:?}, {:?}", args[0], args[1])),
4515 }
4516}
4517
4518pub fn prim_first_sibling_p(args: &[Value]) -> PrimitiveResult {
4529 if args.len() > 1 {
4530 return Err("first-sibling? requires 0 or 1 arguments".to_string());
4531 }
4532
4533 let node = if args.is_empty() {
4535 let ctx = crate::scheme::evaluator::get_evaluator_context()
4537 .ok_or_else(|| "first-sibling?: no evaluator context available".to_string())?;
4538 ctx.current_node
4539 .ok_or_else(|| "first-sibling?: no current node set".to_string())?
4540 } else {
4541 match &args[0] {
4542 Value::Node(n) => n.clone(),
4543 Value::NodeList(nl) => {
4544 if nl.length() != 1 {
4546 return Err("first-sibling?: argument must be a single node".to_string());
4547 }
4548 if let Some(n) = nl.first() {
4549 std::rc::Rc::new(n)
4550 } else {
4551 return Err("first-sibling?: empty node-list".to_string());
4552 }
4553 }
4554 _ => return Err(format!("first-sibling?: not a node: {:?}", args[0])),
4555 }
4556 };
4557
4558 let gi = match node.gi() {
4560 Some(g) => g,
4561 None => return Ok(Value::bool(true)), };
4563
4564 let parent = match node.parent() {
4566 Some(p) => p,
4567 None => return Ok(Value::bool(true)), };
4569
4570 let siblings = parent.children();
4572 for i in 0..siblings.length() {
4573 if let Some(sibling) = siblings.get(i) {
4574 if sibling.node_eq(node.as_ref().as_ref()) {
4576 return Ok(Value::bool(true));
4577 }
4578
4579 if let Some(sibling_gi) = sibling.gi() {
4581 if sibling_gi == gi {
4582 return Ok(Value::bool(false));
4583 }
4584 }
4585 }
4586 }
4587
4588 Ok(Value::bool(true))
4590}
4591
4592pub fn prim_last_sibling_p(args: &[Value]) -> PrimitiveResult {
4600 if args.len() > 1 {
4601 return Err("last-sibling? requires 0 or 1 arguments".to_string());
4602 }
4603
4604 let node = if args.is_empty() {
4605 return Err("last-sibling? with no arguments requires current-node context (not yet implemented)".to_string());
4607 } else {
4608 match &args[0] {
4609 Value::Node(n) => n.clone(),
4610 Value::NodeList(nl) => {
4611 if let Some(node) = nl.first() {
4612 if nl.length() != 1 {
4613 return Err(format!("last-sibling?: node-list must have exactly 1 element, got {}", nl.length()));
4614 }
4615 std::rc::Rc::new(node)
4616 } else {
4617 return Ok(Value::bool(false)); }
4619 }
4620 _ => return Err("last-sibling? requires node or singleton node-list".to_string()),
4621 }
4622 };
4623
4624 if let Some(parent) = node.parent() {
4626 let my_gi = node.gi();
4627
4628 let siblings = parent.children();
4630 let mut current_nl = siblings;
4631 let mut last_with_same_gi: Option<Box<dyn crate::grove::Node>> = None;
4632
4633 loop {
4635 if let Some(child) = current_nl.first() {
4636 if child.gi() == my_gi {
4637 last_with_same_gi = Some(child);
4638 }
4639 current_nl = current_nl.rest();
4640 } else {
4641 break;
4642 }
4643 }
4644
4645 if let Some(last) = last_with_same_gi {
4647 Ok(Value::bool(node.node_eq(last.as_ref())))
4648 } else {
4649 Ok(Value::bool(false))
4650 }
4651 } else {
4652 Ok(Value::bool(false))
4654 }
4655}
4656
4657pub fn prim_child_number(args: &[Value]) -> PrimitiveResult {
4665 if args.is_empty() || args.len() > 1 {
4666 return Err("child-number requires 0 or 1 arguments".to_string());
4667 }
4668
4669 let node = if args.is_empty() {
4670 return Err("child-number with no arguments requires current-node context (not yet implemented)".to_string());
4672 } else {
4673 match &args[0] {
4674 Value::Node(n) => n.clone(),
4675 Value::NodeList(nl) => {
4676 if let Some(node) = nl.first() {
4677 if nl.length() != 1 {
4678 return Err(format!("child-number: node-list must have exactly 1 element, got {}", nl.length()));
4679 }
4680 std::rc::Rc::new(node)
4681 } else {
4682 return Err("child-number: empty node-list".to_string());
4683 }
4684 }
4685 _ => return Err(format!("child-number: not a node: {:?}", args[0])),
4686 }
4687 };
4688
4689 let gi = match node.gi() {
4691 Some(name) => name.to_string(),
4692 None => return Ok(Value::bool(false)), };
4694
4695 let parent = match node.parent() {
4697 Some(p) => p,
4698 None => return Ok(Value::integer(1)), };
4700
4701 let mut count = 0;
4703 let mut current = parent.children();
4704
4705 loop {
4706 if let Some(sibling) = current.first() {
4707 if sibling.node_eq(&**node) {
4709 return Ok(Value::integer((count + 1) as i64));
4711 }
4712
4713 if let Some(sibling_gi) = sibling.gi() {
4715 if sibling_gi == gi {
4716 count += 1;
4717 }
4718 }
4719
4720 current = current.rest();
4722 if current.length() == 0 {
4723 break;
4724 }
4725 } else {
4726 break;
4727 }
4728 }
4729
4730 Err("child-number: node not found among siblings".to_string())
4732}
4733
4734pub fn prim_element_number(_args: &[Value]) -> PrimitiveResult {
4736 Ok(Value::integer(0)) }
4738
4739pub fn prim_inherited_attribute_string(_args: &[Value]) -> PrimitiveResult {
4741 Ok(Value::bool(false)) }
4743
4744pub fn prim_absolute_first_sibling_p(_args: &[Value]) -> PrimitiveResult {
4746 Ok(Value::bool(false)) }
4748
4749pub fn prim_absolute_last_sibling_p(_args: &[Value]) -> PrimitiveResult {
4751 Ok(Value::bool(false)) }
4753
4754pub fn prim_ancestor_child_number(_args: &[Value]) -> PrimitiveResult {
4756 Ok(Value::integer(0)) }
4758
4759pub fn prim_element_number_list(_args: &[Value]) -> PrimitiveResult {
4761 Ok(Value::Nil) }
4763
4764pub fn prim_hierarchical_number(_args: &[Value]) -> PrimitiveResult {
4766 Ok(Value::string("1".to_string())) }
4768
4769pub fn prim_hierarchical_number_recursive(_args: &[Value]) -> PrimitiveResult {
4771 Ok(Value::string("1".to_string())) }
4773
4774pub fn prim_have_ancestor_p(_args: &[Value]) -> PrimitiveResult {
4776 Ok(Value::bool(false)) }
4778
4779pub fn prim_all_element_number(_args: &[Value]) -> PrimitiveResult {
4781 Ok(Value::integer(0)) }
4783
4784pub fn prim_char_property(_args: &[Value]) -> PrimitiveResult {
4790 Ok(Value::Unspecified) }
4792
4793pub fn prim_char_script_case(_args: &[Value]) -> PrimitiveResult {
4795 Ok(Value::Char('a')) }
4797
4798pub fn prim_language(_args: &[Value]) -> PrimitiveResult {
4800 Ok(Value::Unspecified) }
4802
4803pub fn prim_with_language(_args: &[Value]) -> PrimitiveResult {
4805 Ok(Value::Unspecified) }
4807
4808pub fn prim_first_child_gi(_args: &[Value]) -> PrimitiveResult {
4814 Ok(Value::bool(false)) }
4816
4817pub fn prim_inherited_element_attribute_string(_args: &[Value]) -> PrimitiveResult {
4819 Ok(Value::bool(false)) }
4821
4822pub fn prim_debug(args: &[Value]) -> PrimitiveResult {
4828 if args.is_empty() {
4829 return Err("debug requires at least 1 argument".to_string());
4830 }
4831
4832 match &args[0] {
4835 Value::String(s) => {
4836 println!("{}", s);
4837 }
4838 other => {
4839 println!("{:?}", other);
4841 }
4842 }
4843
4844 Ok(args[0].clone())
4845}
4846
4847pub fn prim_external_procedure(_args: &[Value]) -> PrimitiveResult {
4849 Ok(Value::Unspecified) }
4851
4852pub fn prim_read_entity(_args: &[Value]) -> PrimitiveResult {
4854 Ok(Value::string("".to_string())) }
4856
4857pub fn prim_entity_address(_args: &[Value]) -> PrimitiveResult {
4863 Ok(Value::Unspecified) }
4865
4866pub fn prim_entity_attribute_string(_args: &[Value]) -> PrimitiveResult {
4868 Ok(Value::bool(false)) }
4870
4871pub fn prim_entity_generated_system_id(_args: &[Value]) -> PrimitiveResult {
4873 Ok(Value::bool(false)) }
4875
4876pub fn prim_entity_name_normalize(_args: &[Value]) -> PrimitiveResult {
4878 Ok(Value::string("".to_string())) }
4880
4881pub fn prim_entity_notation(_args: &[Value]) -> PrimitiveResult {
4883 Ok(Value::bool(false)) }
4885
4886pub fn prim_entity_text(_args: &[Value]) -> PrimitiveResult {
4888 Ok(Value::bool(false)) }
4890
4891pub fn prim_entity_type(_args: &[Value]) -> PrimitiveResult {
4893 Ok(Value::symbol("unknown")) }
4895
4896pub fn prim_notation_generated_system_id(_args: &[Value]) -> PrimitiveResult {
4898 Ok(Value::bool(false)) }
4900
4901pub fn prim_general_name_normalize(_args: &[Value]) -> PrimitiveResult {
4903 Ok(Value::string("".to_string())) }
4905
4906pub fn prim_sgml_document_address(_args: &[Value]) -> PrimitiveResult {
4908 Ok(Value::Unspecified) }
4910
4911pub fn prim_declaration(_args: &[Value]) -> PrimitiveResult {
4913 Ok(Value::bool(false)) }
4915
4916pub fn prim_dtd(_args: &[Value]) -> PrimitiveResult {
4918 Ok(Value::bool(false)) }
4920
4921pub fn prim_sgml_declaration(_args: &[Value]) -> PrimitiveResult {
4923 Ok(Value::bool(false)) }
4925
4926pub fn prim_document_element(_args: &[Value]) -> PrimitiveResult {
4928 Ok(Value::bool(false)) }
4930
4931pub fn prim_prolog(_args: &[Value]) -> PrimitiveResult {
4933 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
4935
4936pub fn prim_epilog(_args: &[Value]) -> PrimitiveResult {
4938 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
4940
4941pub fn prim_declare_default_language(_args: &[Value]) -> PrimitiveResult {
4945 Ok(Value::Unspecified)
4946}
4947
4948pub fn prim_declare_characteristic(_args: &[Value]) -> PrimitiveResult {
4952 Ok(Value::Unspecified)
4953}
4954
4955pub fn prim_origin_to_subnode_rel_forest_addr(_args: &[Value]) -> PrimitiveResult {
4957 Ok(Value::Unspecified) }
4959
4960pub fn prim_named_node(_args: &[Value]) -> PrimitiveResult {
4966 Ok(Value::bool(false)) }
4968
4969pub fn prim_named_node_list_names(_args: &[Value]) -> PrimitiveResult {
4971 Ok(Value::Nil) }
4973
4974pub fn prim_named_node_list_normalize(_args: &[Value]) -> PrimitiveResult {
4976 Ok(Value::Unspecified) }
4978
4979pub fn prim_node_list_address(_args: &[Value]) -> PrimitiveResult {
4981 Ok(Value::Unspecified) }
4983
4984pub fn prim_node_list_error(_args: &[Value]) -> PrimitiveResult {
4986 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
4988
4989pub fn prim_node_list_no_order(_args: &[Value]) -> PrimitiveResult {
4991 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
4993
4994pub fn prim_select_by_class(_args: &[Value]) -> PrimitiveResult {
4996 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
4998
4999pub fn prim_node_list_union(args: &[Value]) -> PrimitiveResult {
5007 if args.is_empty() {
5008 return Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new())));
5009 }
5010
5011 let mut seen_ids = std::collections::HashSet::new();
5013 let mut result_nodes = Vec::new();
5014
5015 for arg in args {
5016 match arg {
5017 Value::NodeList(nl) => {
5018 for i in 0..nl.length() {
5020 if let Some(node) = nl.get(i) {
5021 let node_id = node.node_id();
5022 if !seen_ids.contains(&node_id) {
5024 seen_ids.insert(node_id);
5025 result_nodes.push(node);
5026 }
5027 }
5028 }
5029 }
5030 Value::Node(n) => {
5031 let node_id = n.as_ref().node_id();
5033 if !seen_ids.contains(&node_id) {
5034 seen_ids.insert(node_id);
5035 result_nodes.push(n.as_ref().clone_node());
5036 }
5037 }
5038 Value::Pair(_) => {
5039 let mut current = arg.clone();
5041 loop {
5042 match current {
5043 Value::Nil => break,
5044 Value::Pair(ref p) => {
5045 let (car, cdr) = {
5046 let pair_data = p.borrow();
5047 (pair_data.car.clone(), pair_data.cdr.clone())
5048 };
5049
5050 match car {
5052 Value::Node(ref n) => {
5053 let node_id = n.as_ref().node_id();
5054 if !seen_ids.contains(&node_id) {
5055 seen_ids.insert(node_id);
5056 result_nodes.push(n.as_ref().clone_node());
5057 }
5058 }
5059 Value::Bool(false) => {
5060 }
5062 _ => return Err(format!("node-list-union: list contains non-node: {:?}", car)),
5063 }
5064
5065 current = cdr;
5066 }
5067 _ => return Err(format!("node-list-union: malformed list: {:?}", current)),
5068 }
5069 }
5070 }
5071 Value::Nil => {
5072 }
5074 _ => return Err(format!("node-list-union: argument not a node-list: {:?}", arg)),
5075 }
5076 }
5077
5078 Ok(Value::node_list(Box::new(crate::grove::VecNodeList::new(result_nodes))))
5079}
5080
5081pub fn prim_node_list_intersection(_args: &[Value]) -> PrimitiveResult {
5083 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
5085
5086pub fn prim_node_list_difference(_args: &[Value]) -> PrimitiveResult {
5088 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
5090
5091pub fn prim_node_list_symmetrical_difference(_args: &[Value]) -> PrimitiveResult {
5093 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
5095
5096pub fn prim_node_list_union_map(_args: &[Value]) -> PrimitiveResult {
5098 Ok(Value::node_list(Box::new(crate::grove::EmptyNodeList::new()))) }
5100
5101pub fn prim_process_children_trim(_args: &[Value]) -> PrimitiveResult {
5107 Ok(Value::Sosofo) }
5109
5110pub fn prim_process_element_with_id(_args: &[Value]) -> PrimitiveResult {
5112 Ok(Value::Sosofo) }
5114
5115pub fn prim_process_first_descendant(_args: &[Value]) -> PrimitiveResult {
5117 Ok(Value::Sosofo) }
5119
5120pub fn prim_process_matching_children(_args: &[Value]) -> PrimitiveResult {
5122 Ok(Value::Sosofo) }
5124
5125pub fn prim_merge_style(_args: &[Value]) -> PrimitiveResult {
5127 Ok(Value::Unspecified) }
5129
5130pub fn prim_map_constructor(_args: &[Value]) -> PrimitiveResult {
5132 Ok(Value::Unspecified) }
5134
5135pub fn prim_with_mode(_args: &[Value]) -> PrimitiveResult {
5137 Ok(Value::Sosofo) }
5139
5140pub fn prim_current_mode(_args: &[Value]) -> PrimitiveResult {
5142 Ok(Value::bool(false)) }
5144
5145pub fn prim_current_node_page_number_sosofo(_args: &[Value]) -> PrimitiveResult {
5151 Ok(Value::Sosofo) }
5153
5154pub fn prim_page_number_sosofo(_args: &[Value]) -> PrimitiveResult {
5156 Ok(Value::Sosofo) }
5158
5159pub fn prim_sosofo_discard_labeled(_args: &[Value]) -> PrimitiveResult {
5161 Ok(Value::Sosofo) }
5163
5164pub fn prim_sosofo_label(_args: &[Value]) -> PrimitiveResult {
5166 Ok(Value::Sosofo) }
5168
5169pub fn prim_idref_address(_args: &[Value]) -> PrimitiveResult {
5171 Ok(Value::Unspecified) }
5173
5174pub fn prim_hytime_linkend(_args: &[Value]) -> PrimitiveResult {
5176 Ok(Value::bool(false)) }
5178
5179pub fn prim_if_first_page(_args: &[Value]) -> PrimitiveResult {
5181 Ok(Value::Sosofo) }
5183
5184pub fn prim_if_front_page(_args: &[Value]) -> PrimitiveResult {
5186 Ok(Value::Sosofo) }
5188
5189pub fn prim_sosofo_contains_node_p(_args: &[Value]) -> PrimitiveResult {
5191 Ok(Value::bool(false)) }
5193
5194pub fn prim_set_visited(_args: &[Value]) -> PrimitiveResult {
5196 Ok(Value::Unspecified) }
5198
5199pub fn prim_label_length(_args: &[Value]) -> PrimitiveResult {
5201 Ok(Value::integer(0)) }
5203
5204pub fn prim_label_distance(_args: &[Value]) -> PrimitiveResult {
5206 Ok(Value::integer(0)) }
5208
5209pub fn prim_quantity_to_number(_args: &[Value]) -> PrimitiveResult {
5215 Ok(Value::integer(0)) }
5217
5218pub fn prim_number_to_quantity(_args: &[Value]) -> PrimitiveResult {
5220 Ok(Value::Unspecified) }
5222
5223pub fn prim_quantity_convert(_args: &[Value]) -> PrimitiveResult {
5225 Ok(Value::Unspecified) }
5227
5228pub fn prim_device_length(_args: &[Value]) -> PrimitiveResult {
5230 Ok(Value::integer(0)) }
5232
5233pub fn prim_quantity_to_string(_args: &[Value]) -> PrimitiveResult {
5235 Ok(Value::string("0pt".to_string())) }
5237
5238pub fn prim_table_unit(_args: &[Value]) -> PrimitiveResult {
5240 Ok(Value::Unspecified) }
5242
5243pub fn prim_display_size(_args: &[Value]) -> PrimitiveResult {
5245 Ok(Value::Unspecified) }
5248
5249pub fn prim_sgml_parse(_args: &[Value]) -> PrimitiveResult {
5255 Ok(Value::Unspecified) }
5257
5258pub fn prim_time_lt(_args: &[Value]) -> PrimitiveResult {
5264 Ok(Value::bool(false)) }
5266
5267pub fn prim_time_le(_args: &[Value]) -> PrimitiveResult {
5269 Ok(Value::bool(false)) }
5271
5272pub fn prim_time_gt(_args: &[Value]) -> PrimitiveResult {
5274 Ok(Value::bool(false)) }
5276
5277pub fn prim_time_ge(_args: &[Value]) -> PrimitiveResult {
5279 Ok(Value::bool(false)) }
5281
5282pub fn prim_next_match(_args: &[Value]) -> PrimitiveResult {
5288 Ok(Value::Sosofo) }
5290
5291pub fn prim_style_p(args: &[Value]) -> PrimitiveResult {
5293 if args.len() != 1 {
5294 return Err("style? requires exactly 1 argument".to_string());
5295 }
5296 Ok(Value::bool(false)) }
5298
5299pub fn prim_sosofo_p(args: &[Value]) -> PrimitiveResult {
5315 if args.len() != 1 {
5316 return Err("sosofo? requires exactly 1 argument".to_string());
5317 }
5318
5319 Ok(Value::bool(matches!(args[0], Value::Sosofo)))
5320}
5321
5322pub fn prim_empty_sosofo(args: &[Value]) -> PrimitiveResult {
5328 if !args.is_empty() {
5329 return Err("empty-sosofo requires no arguments".to_string());
5330 }
5331
5332 Ok(Value::Sosofo)
5333}
5334
5335pub fn prim_literal(args: &[Value]) -> PrimitiveResult {
5342 if args.len() != 1 {
5343 return Err("literal requires exactly 1 argument".to_string());
5344 }
5345
5346 match &args[0] {
5347 Value::String(s) => {
5348 if let Some(ctx) = crate::scheme::evaluator::get_evaluator_context() {
5350 if let Some(ref backend) = ctx.backend {
5351 backend.borrow_mut()
5352 .formatting_instruction(s)
5353 .map_err(|e| format!("literal: backend error: {}", e))?;
5354 }
5355 }
5356 Ok(Value::Sosofo)
5357 }
5358 _ => Err(format!("literal: not a string: {:?}", args[0])),
5359 }
5360}
5361
5362pub fn prim_sosofo_append(args: &[Value]) -> PrimitiveResult {
5368 for arg in args {
5370 if !matches!(arg, Value::Sosofo | Value::Unspecified) {
5371 return Err(format!("sosofo-append: not a sosofo: {:?}", arg));
5372 }
5373 }
5374
5375 Ok(Value::Sosofo)
5378}
5379
5380pub fn prim_process_children(args: &[Value]) -> PrimitiveResult {
5400 if !args.is_empty() {
5401 return Err("process-children requires no arguments".to_string());
5402 }
5403
5404 Ok(Value::Sosofo)
5413}
5414
5415pub fn prim_process_node_list(args: &[Value]) -> PrimitiveResult {
5428 if args.len() != 1 {
5429 return Err("process-node-list requires exactly 1 argument".to_string());
5430 }
5431
5432 if !matches!(args[0], Value::NodeList(_)) {
5434 return Err(format!("process-node-list: not a node-list: {:?}", args[0]));
5435 }
5436
5437 Ok(Value::Sosofo)
5446}
5447
5448pub fn prim_make(args: &[Value]) -> PrimitiveResult {
5471 if args.is_empty() {
5472 return Err("make requires at least a flow object type".to_string());
5473 }
5474
5475 match &args[0] {
5477 Value::Symbol(fo_type) => {
5478 match fo_type.as_ref() {
5487 "entity" | "formatting-instruction" | "sequence" | "paragraph" => {
5488 Ok(Value::Sosofo)
5489 }
5490 _ => Err(format!("make: unknown flow object type: {}", fo_type)),
5491 }
5492 }
5493 _ => Err(format!("make: first argument must be a symbol: {:?}", args[0])),
5494 }
5495}
5496
5497pub fn prim_string_equiv_p(args: &[Value]) -> PrimitiveResult {
5508 if args.len() != 2 {
5509 return Err("string-equiv? requires exactly 2 arguments".to_string());
5510 }
5511
5512 let s1 = match &args[0] {
5513 Value::String(s) => s.to_lowercase(),
5514 _ => return Err(format!("string-equiv?: not a string: {:?}", args[0])),
5515 };
5516
5517 let s2 = match &args[1] {
5518 Value::String(s) => s.to_lowercase(),
5519 _ => return Err(format!("string-equiv?: not a string: {:?}", args[1])),
5520 };
5521
5522 Ok(Value::bool(s1 == s2))
5523}
5524
5525pub fn prim_time(args: &[Value]) -> PrimitiveResult {
5538 if !args.is_empty() {
5539 return Err("time requires no arguments".to_string());
5540 }
5541
5542 Ok(Value::Unspecified)
5545}
5546
5547pub fn prim_time_to_string(args: &[Value]) -> PrimitiveResult {
5554 if args.len() != 2 {
5555 return Err("time->string requires exactly 2 arguments".to_string());
5556 }
5557
5558 Ok(Value::string("".to_string()))
5560}
5561
5562pub fn prim_language_p(args: &[Value]) -> PrimitiveResult {
5576 if args.len() != 1 {
5577 return Err("language? requires exactly 1 argument".to_string());
5578 }
5579
5580 Ok(Value::bool(false))
5582}
5583
5584pub fn prim_current_language(args: &[Value]) -> PrimitiveResult {
5591 if !args.is_empty() {
5592 return Err("current-language requires no arguments".to_string());
5593 }
5594
5595 Ok(Value::Unspecified)
5597}
5598
5599pub fn register_list_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5605 env.define("car", Value::primitive("car", prim_car));
5606 env.define("cdr", Value::primitive("cdr", prim_cdr));
5607 env.define("cons", Value::primitive("cons", prim_cons));
5608 env.define("list", Value::primitive("list", prim_list));
5609 env.define("null?", Value::primitive("null?", prim_null_p));
5610 env.define("pair?", Value::primitive("pair?", prim_pair_p));
5611 env.define("list?", Value::primitive("list?", prim_list_p));
5612 env.define("length", Value::primitive("length", prim_length));
5613 env.define("append", Value::primitive("append", prim_append));
5614 env.define("reverse", Value::primitive("reverse", prim_reverse));
5615 env.define("list-tail", Value::primitive("list-tail", prim_list_tail));
5616 env.define("list-ref", Value::primitive("list-ref", prim_list_ref));
5617 env.define("memq", Value::primitive("memq", prim_memq));
5618 env.define("memv", Value::primitive("memv", prim_memv));
5619 env.define("member", Value::primitive("member", prim_member));
5620 env.define("assq", Value::primitive("assq", prim_assq));
5621 env.define("assv", Value::primitive("assv", prim_assv));
5622 env.define("assoc", Value::primitive("assoc", prim_assoc));
5623 env.define("cadr", Value::primitive("cadr", prim_cadr));
5625 env.define("caddr", Value::primitive("caddr", prim_caddr));
5626 env.define("cadddr", Value::primitive("cadddr", prim_cadddr));
5627 env.define("caar", Value::primitive("caar", prim_caar));
5628 env.define("cddr", Value::primitive("cddr", prim_cddr));
5629 env.define("cdar", Value::primitive("cdar", prim_cdar));
5630 env.define("caaar", Value::primitive("caaar", prim_caaar));
5631 env.define("cdaar", Value::primitive("cdaar", prim_cdaar));
5632 env.define("cadar", Value::primitive("cadar", prim_cadar));
5633 env.define("cddar", Value::primitive("cddar", prim_cddar));
5634 env.define("caadr", Value::primitive("caadr", prim_caadr));
5635 env.define("cdadr", Value::primitive("cdadr", prim_cdadr));
5636 env.define("last", Value::primitive("last", prim_last));
5638}
5639
5640pub fn register_number_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5642 env.define("+", Value::primitive("+", prim_add));
5644 env.define("-", Value::primitive("-", prim_subtract));
5645 env.define("*", Value::primitive("*", prim_multiply));
5646 env.define("/", Value::primitive("/", prim_divide));
5647 env.define("quotient", Value::primitive("quotient", prim_quotient));
5648 env.define("remainder", Value::primitive("remainder", prim_remainder));
5649 env.define("modulo", Value::primitive("modulo", prim_modulo));
5650
5651 env.define("=", Value::primitive("=", prim_num_eq));
5653 env.define("<", Value::primitive("<", prim_num_lt));
5654 env.define(">", Value::primitive(">", prim_num_gt));
5655 env.define("<=", Value::primitive("<=", prim_num_le));
5656 env.define(">=", Value::primitive(">=", prim_num_ge));
5657
5658 env.define("number?", Value::primitive("number?", prim_number_p));
5660 env.define("integer?", Value::primitive("integer?", prim_integer_p));
5661 env.define("real?", Value::primitive("real?", prim_real_p));
5662 env.define("zero?", Value::primitive("zero?", prim_zero_p));
5663 env.define("positive?", Value::primitive("positive?", prim_positive_p));
5664 env.define("negative?", Value::primitive("negative?", prim_negative_p));
5665 env.define("odd?", Value::primitive("odd?", prim_odd_p));
5666 env.define("even?", Value::primitive("even?", prim_even_p));
5667
5668 env.define("abs", Value::primitive("abs", prim_abs));
5670 env.define("max", Value::primitive("max", prim_max));
5671 env.define("min", Value::primitive("min", prim_min));
5672 env.define("gcd", Value::primitive("gcd", prim_gcd));
5673 env.define("lcm", Value::primitive("lcm", prim_lcm));
5674 env.define("floor", Value::primitive("floor", prim_floor));
5675 env.define("ceiling", Value::primitive("ceiling", prim_ceiling));
5676 env.define("truncate", Value::primitive("truncate", prim_truncate));
5677 env.define("round", Value::primitive("round", prim_round));
5678
5679 env.define("expt", Value::primitive("expt", prim_expt));
5681 env.define("sqrt", Value::primitive("sqrt", prim_sqrt));
5682 env.define("sin", Value::primitive("sin", prim_sin));
5683 env.define("cos", Value::primitive("cos", prim_cos));
5684 env.define("tan", Value::primitive("tan", prim_tan));
5685 env.define("atan", Value::primitive("atan", prim_atan));
5686 env.define("asin", Value::primitive("asin", prim_asin));
5687 env.define("acos", Value::primitive("acos", prim_acos));
5688 env.define("log", Value::primitive("log", prim_log));
5689 env.define("exp", Value::primitive("exp", prim_exp));
5690
5691 env.define("exact?", Value::primitive("exact?", prim_exact_p));
5693 env.define("inexact?", Value::primitive("inexact?", prim_inexact_p));
5694 env.define("exact->inexact", Value::primitive("exact->inexact", prim_exact_to_inexact));
5695 env.define("inexact->exact", Value::primitive("inexact->exact", prim_inexact_to_exact));
5696}
5697
5698pub fn register_string_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5700 env.define("string-length", Value::primitive("string-length", prim_string_length));
5702 env.define("string-ref", Value::primitive("string-ref", prim_string_ref));
5703 env.define("string-append", Value::primitive("string-append", prim_string_append));
5704 env.define("substring", Value::primitive("substring", prim_substring));
5705 env.define("make-string", Value::primitive("make-string", prim_make_string));
5706 env.define("string", Value::primitive("string", prim_string));
5707
5708 env.define("string=?", Value::primitive("string=?", prim_string_eq));
5710 env.define("string<?", Value::primitive("string<?", prim_string_lt));
5711 env.define("string>?", Value::primitive("string>?", prim_string_gt));
5712 env.define("string<=?", Value::primitive("string<=?", prim_string_le));
5713 env.define("string>=?", Value::primitive("string>=?", prim_string_ge));
5714
5715 env.define("string-ci=?", Value::primitive("string-ci=?", prim_string_ci_eq));
5717 env.define("string-ci<?", Value::primitive("string-ci<?", prim_string_ci_lt));
5718 env.define("string-ci>?", Value::primitive("string-ci>?", prim_string_ci_gt));
5719 env.define("string-ci<=?", Value::primitive("string-ci<=?", prim_string_ci_le));
5720 env.define("string-ci>=?", Value::primitive("string-ci>=?", prim_string_ci_ge));
5721
5722 env.define("string->list", Value::primitive("string->list", prim_string_to_list));
5724 env.define("list->string", Value::primitive("list->string", prim_list_to_string));
5725 env.define("string->symbol", Value::primitive("string->symbol", prim_string_to_symbol));
5726 env.define("symbol->string", Value::primitive("symbol->string", prim_symbol_to_string));
5727
5728 env.define("string?", Value::primitive("string?", prim_string_p));
5730 env.define("symbol?", Value::primitive("symbol?", prim_symbol_p));
5731 env.define("char?", Value::primitive("char?", prim_char_p));
5732
5733 env.define("char=?", Value::primitive("char=?", prim_char_eq));
5735 env.define("char<?", Value::primitive("char<?", prim_char_lt));
5736 env.define("char>?", Value::primitive("char>?", prim_char_gt));
5737 env.define("char<=?", Value::primitive("char<=?", prim_char_le));
5738 env.define("char>=?", Value::primitive("char>=?", prim_char_ge));
5739 env.define("char-upcase", Value::primitive("char-upcase", prim_char_upcase));
5740 env.define("char-downcase", Value::primitive("char-downcase", prim_char_downcase));
5741 env.define("char->integer", Value::primitive("char->integer", prim_char_to_integer));
5742 env.define("integer->char", Value::primitive("integer->char", prim_integer_to_char));
5743 env.define("char-alphabetic?", Value::primitive("char-alphabetic?", prim_char_alphabetic_p));
5744 env.define("char-numeric?", Value::primitive("char-numeric?", prim_char_numeric_p));
5745 env.define("char-whitespace?", Value::primitive("char-whitespace?", prim_char_whitespace_p));
5746
5747 env.define("char-ci=?", Value::primitive("char-ci=?", prim_char_ci_eq));
5749 env.define("char-ci<?", Value::primitive("char-ci<?", prim_char_ci_lt));
5750 env.define("char-ci>?", Value::primitive("char-ci>?", prim_char_ci_gt));
5751 env.define("char-ci<=?", Value::primitive("char-ci<=?", prim_char_ci_le));
5752 env.define("char-ci>=?", Value::primitive("char-ci>=?", prim_char_ci_ge));
5753}
5754
5755pub fn register_boolean_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5757 env.define("not", Value::primitive("not", prim_not));
5758 env.define("boolean?", Value::primitive("boolean?", prim_boolean_p));
5759 env.define("equal?", Value::primitive("equal?", prim_equal_p));
5760 env.define("eqv?", Value::primitive("eqv?", prim_eqv_p));
5761 env.define("eq?", Value::primitive("eq?", prim_eq_p));
5762 env.define("procedure?", Value::primitive("procedure?", prim_procedure_p));
5763}
5764
5765pub fn register_io_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5767 env.define("error", Value::primitive("error", prim_error));
5768 env.define("display", Value::primitive("display", prim_display));
5769 env.define("newline", Value::primitive("newline", prim_newline));
5770 env.define("write", Value::primitive("write", prim_write));
5771}
5772
5773pub fn register_conversion_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5775 env.define("number->string", Value::primitive("number->string", prim_number_to_string));
5776 env.define("string->number", Value::primitive("string->number", prim_string_to_number));
5777}
5778
5779pub fn register_keyword_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5781 env.define("keyword?", Value::primitive("keyword?", prim_keyword_p));
5782 env.define("keyword->string", Value::primitive("keyword->string", prim_keyword_to_string));
5783 env.define("string->keyword", Value::primitive("string->keyword", prim_string_to_keyword));
5784}
5785
5786pub fn register_dsssl_type_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5788 env.define("quantity?", Value::primitive("quantity?", prim_quantity_p));
5789 env.define("color?", Value::primitive("color?", prim_color_p));
5790 env.define("address?", Value::primitive("address?", prim_address_p));
5791
5792 env.define("color", Value::primitive("color", prim_color));
5794 env.define("color-space", Value::primitive("color-space", prim_color_space));
5795 env.define("color-space?", Value::primitive("color-space?", prim_color_space_p));
5796
5797 env.define("display-space", Value::primitive("display-space", prim_display_space));
5799 env.define("display-space?", Value::primitive("display-space?", prim_display_space_p));
5800 env.define("inline-space", Value::primitive("inline-space", prim_inline_space));
5801 env.define("inline-space?", Value::primitive("inline-space?", prim_inline_space_p));
5802
5803 env.define("glyph-id", Value::primitive("glyph-id", prim_glyph_id));
5805 env.define("glyph-id?", Value::primitive("glyph-id?", prim_glyph_id_p));
5806 env.define("glyph-subst-table", Value::primitive("glyph-subst-table", prim_glyph_subst_table));
5807 env.define("glyph-subst-table?", Value::primitive("glyph-subst-table?", prim_glyph_subst_table_p));
5808 env.define("glyph-subst", Value::primitive("glyph-subst", prim_glyph_subst));
5809
5810 env.define("address-local?", Value::primitive("address-local?", prim_address_local_p));
5812
5813 env.define("quantity->number", Value::primitive("quantity->number", prim_quantity_to_number));
5815 env.define("number->quantity", Value::primitive("number->quantity", prim_number_to_quantity));
5816 env.define("quantity-convert", Value::primitive("quantity-convert", prim_quantity_convert));
5817 env.define("device-length", Value::primitive("device-length", prim_device_length));
5818}
5819
5820pub fn register_format_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5822 env.define("format-number", Value::primitive("format-number", prim_format_number));
5823 env.define("format-number-list", Value::primitive("format-number-list", prim_format_number_list));
5824}
5825
5826pub fn register_grove_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5828 env.define("current-node", Value::primitive("current-node", prim_current_node));
5830
5831 env.define("node?", Value::primitive("node?", prim_node_p));
5833 env.define("gi", Value::primitive("gi", prim_gi));
5834 env.define("data", Value::primitive("data", prim_data));
5835 env.define("id", Value::primitive("id", prim_id));
5836 env.define("attribute-string", Value::primitive("attribute-string", prim_attribute_string));
5837 env.define("children", Value::primitive("children", prim_children));
5838 env.define("select-children", Value::primitive("select-children", prim_select_children));
5839 env.define("parent", Value::primitive("parent", prim_parent));
5840 env.define("tree-root", Value::primitive("tree-root", prim_tree_root));
5841 env.define("ancestors", Value::primitive("ancestors", prim_ancestors));
5842
5843 env.define("ancestor", Value::primitive("ancestor", prim_ancestor));
5845 env.define("descendants", Value::primitive("descendants", prim_descendants));
5846 env.define("follow", Value::primitive("follow", prim_follow));
5847 env.define("preced", Value::primitive("preced", prim_preced));
5848 env.define("attributes", Value::primitive("attributes", prim_attributes));
5849 env.define("select-elements", Value::primitive("select-elements", prim_select_elements));
5850 env.define("element-with-id", Value::primitive("element-with-id", prim_element_with_id));
5851
5852 env.define("node-list?", Value::primitive("node-list?", prim_node_list_p));
5854 env.define("empty-node-list", Value::primitive("empty-node-list", prim_empty_node_list));
5855 env.define("node-list-empty?", Value::primitive("node-list-empty?", prim_node_list_empty_p));
5856 env.define("node-list-length", Value::primitive("node-list-length", prim_node_list_length));
5857 env.define("node-list-remove-duplicates", Value::primitive("node-list-remove-duplicates", prim_node_list_remove_duplicates));
5858 env.define("node-list-first", Value::primitive("node-list-first", prim_node_list_first));
5859 env.define("node-list-last", Value::primitive("node-list-last", prim_node_list_last));
5860 env.define("node-list-rest", Value::primitive("node-list-rest", prim_node_list_rest));
5861 env.define("node-list-ref", Value::primitive("node-list-ref", prim_node_list_ref));
5862 env.define("node-list-reverse", Value::primitive("node-list-reverse", prim_node_list_reverse));
5863 env.define("node-list->list", Value::primitive("node-list->list", prim_node_list_to_list));
5864 env.define("node-list-contains?", Value::primitive("node-list-contains?", prim_node_list_contains_p));
5865
5866 env.define("node-list", Value::primitive("node-list", prim_node_list));
5868 env.define("node-list-map", Value::primitive("node-list-map", prim_node_list_map));
5869 env.define("node-property", Value::primitive("node-property", prim_node_property));
5870 env.define("match-element?", Value::primitive("match-element?", prim_match_element_p));
5871 env.define("named-node-list?", Value::primitive("named-node-list?", prim_named_node_list_p));
5872 env.define("node-list=?", Value::primitive("node-list=?", prim_node_list_eq));
5873
5874 env.define("first-sibling?", Value::primitive("first-sibling?", prim_first_sibling_p));
5876 env.define("last-sibling?", Value::primitive("last-sibling?", prim_last_sibling_p));
5877 env.define("child-number", Value::primitive("child-number", prim_child_number));
5878 env.define("element-number", Value::primitive("element-number", prim_element_number));
5879 env.define("inherited-attribute-string", Value::primitive("inherited-attribute-string", prim_inherited_attribute_string));
5880
5881 env.define("entity-system-id", Value::primitive("entity-system-id", prim_entity_system_id));
5883 env.define("entity-public-id", Value::primitive("entity-public-id", prim_entity_public_id));
5884 env.define("notation-system-id", Value::primitive("notation-system-id", prim_notation_system_id));
5885 env.define("notation-public-id", Value::primitive("notation-public-id", prim_notation_public_id));
5886
5887 env.define("absolute-first-sibling?", Value::primitive("absolute-first-sibling?", prim_absolute_first_sibling_p));
5889 env.define("absolute-last-sibling?", Value::primitive("absolute-last-sibling?", prim_absolute_last_sibling_p));
5890 env.define("ancestor-child-number", Value::primitive("ancestor-child-number", prim_ancestor_child_number));
5891 env.define("element-number-list", Value::primitive("element-number-list", prim_element_number_list));
5892 env.define("hierarchical-number", Value::primitive("hierarchical-number", prim_hierarchical_number));
5893 env.define("hierarchical-number-recursive", Value::primitive("hierarchical-number-recursive", prim_hierarchical_number_recursive));
5894 env.define("have-ancestor?", Value::primitive("have-ancestor?", prim_have_ancestor_p));
5895 env.define("all-element-number", Value::primitive("all-element-number", prim_all_element_number));
5896
5897 env.define("first-child-gi", Value::primitive("first-child-gi", prim_first_child_gi));
5899 env.define("inherited-element-attribute-string", Value::primitive("inherited-element-attribute-string", prim_inherited_element_attribute_string));
5900
5901 env.define("entity-address", Value::primitive("entity-address", prim_entity_address));
5903 env.define("entity-generated-system-id", Value::primitive("entity-generated-system-id", prim_entity_generated_system_id));
5904 env.define("entity-type", Value::primitive("entity-type", prim_entity_type));
5905 env.define("declaration", Value::primitive("declaration", prim_declaration));
5906 env.define("dtd", Value::primitive("dtd", prim_dtd));
5907 env.define("sgml-declaration", Value::primitive("sgml-declaration", prim_sgml_declaration));
5908 env.define("document-element", Value::primitive("document-element", prim_document_element));
5909 env.define("prolog", Value::primitive("prolog", prim_prolog));
5910 env.define("epilog", Value::primitive("epilog", prim_epilog));
5911
5912 env.define("declare-default-language", Value::primitive("declare-default-language", prim_declare_default_language));
5914 env.define("declare-characteristic", Value::primitive("declare-characteristic", prim_declare_characteristic));
5915 env.define("origin-to-subnode-rel-forest-addr", Value::primitive("origin-to-subnode-rel-forest-addr", prim_origin_to_subnode_rel_forest_addr));
5916
5917 env.define("named-node", Value::primitive("named-node", prim_named_node));
5919 env.define("named-node-list-names", Value::primitive("named-node-list-names", prim_named_node_list_names));
5920 env.define("node-list-union", Value::primitive("node-list-union", prim_node_list_union));
5921 env.define("node-list-intersection", Value::primitive("node-list-intersection", prim_node_list_intersection));
5922 env.define("node-list-difference", Value::primitive("node-list-difference", prim_node_list_difference));
5923 env.define("node-list-symmetrical-difference", Value::primitive("node-list-symmetrical-difference", prim_node_list_symmetrical_difference));
5924 env.define("node-list-union-map", Value::primitive("node-list-union-map", prim_node_list_union_map));
5925
5926 env.define("node-list-count", Value::primitive("node-list-count", prim_node_list_count));
5928}
5929
5930pub fn register_sosofo_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5932 env.define("sosofo?", Value::primitive("sosofo?", prim_sosofo_p));
5934 env.define("style?", Value::primitive("style?", prim_style_p));
5935 env.define("next-match", Value::primitive("next-match", prim_next_match));
5936 env.define("empty-sosofo", Value::primitive("empty-sosofo", prim_empty_sosofo));
5937 env.define("literal", Value::primitive("literal", prim_literal));
5938 env.define("sosofo-append", Value::primitive("sosofo-append", prim_sosofo_append));
5939
5940 env.define("process-children", Value::primitive("process-children", prim_process_children));
5942 env.define("process-node-list", Value::primitive("process-node-list", prim_process_node_list));
5943 env.define("make", Value::primitive("make", prim_make));
5944
5945 env.define("process-children-trim", Value::primitive("process-children-trim", prim_process_children_trim));
5947 env.define("process-first-descendant", Value::primitive("process-first-descendant", prim_process_first_descendant));
5948 env.define("process-matching-children", Value::primitive("process-matching-children", prim_process_matching_children));
5949 env.define("process-element-with-id", Value::primitive("process-element-with-id", prim_process_element_with_id));
5950 env.define("with-mode", Value::primitive("with-mode", prim_with_mode));
5951 env.define("current-mode", Value::primitive("current-mode", prim_current_mode));
5952
5953 env.define("current-node-page-number-sosofo", Value::primitive("current-node-page-number-sosofo", prim_current_node_page_number_sosofo));
5955 env.define("page-number-sosofo", Value::primitive("page-number-sosofo", prim_page_number_sosofo));
5956 env.define("sosofo-contains-node?", Value::primitive("sosofo-contains-node?", prim_sosofo_contains_node_p));
5957 env.define("current-node-address", Value::primitive("current-node-address", prim_current_node_address));
5958 env.define("address-visited?", Value::primitive("address-visited?", prim_address_visited_p));
5959 env.define("set-visited!", Value::primitive("set-visited!", prim_set_visited));
5960 env.define("label-length", Value::primitive("label-length", prim_label_length));
5961 env.define("label-distance", Value::primitive("label-distance", prim_label_distance));
5962}
5963
5964pub fn register_utility_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
5966 env.define("string-equiv?", Value::primitive("string-equiv?", prim_string_equiv_p));
5968
5969 env.define("time", Value::primitive("time", prim_time));
5971 env.define("time->string", Value::primitive("time->string", prim_time_to_string));
5972 env.define("time<?", Value::primitive("time<?", prim_time_lt));
5973 env.define("time<=?", Value::primitive("time<=?", prim_time_le));
5974 env.define("time>?", Value::primitive("time>?", prim_time_gt));
5975 env.define("time>=?", Value::primitive("time>=?", prim_time_ge));
5976
5977 env.define("language?", Value::primitive("language?", prim_language_p));
5979 env.define("current-language", Value::primitive("current-language", prim_current_language));
5980
5981 env.define("char-property", Value::primitive("char-property", prim_char_property));
5983 env.define("char-script-case", Value::primitive("char-script-case", prim_char_script_case));
5984 env.define("language", Value::primitive("language", prim_language));
5985 env.define("with-language", Value::primitive("with-language", prim_with_language));
5986
5987 env.define("debug", Value::primitive("debug", prim_debug));
5989 env.define("external-procedure", Value::primitive("external-procedure", prim_external_procedure));
5990 env.define("read-entity", Value::primitive("read-entity", prim_read_entity));
5991
5992 env.define("sgml-parse", Value::primitive("sgml-parse", prim_sgml_parse));
5994}
5995
5996pub fn register_all_primitives(env: &gc::Gc<crate::scheme::environment::Environment>) {
6001 register_list_primitives(env);
6002 register_number_primitives(env);
6003 register_string_primitives(env);
6004 register_boolean_primitives(env);
6005 register_io_primitives(env);
6006 register_conversion_primitives(env);
6007 register_keyword_primitives(env);
6008 register_dsssl_type_primitives(env);
6009 register_format_primitives(env);
6010 register_grove_primitives(env);
6011 register_sosofo_primitives(env);
6012 register_utility_primitives(env);
6013}
6014
6015#[cfg(test)]
6020mod tests {
6021 use super::*;
6022
6023 #[test]
6024 fn test_car() {
6025 let pair = Value::cons(Value::integer(1), Value::integer(2));
6026 let result = prim_car(&[pair]).unwrap();
6027 assert!(matches!(result, Value::Integer(1)));
6028 }
6029
6030 #[test]
6031 fn test_cdr() {
6032 let pair = Value::cons(Value::integer(1), Value::integer(2));
6033 let result = prim_cdr(&[pair]).unwrap();
6034 assert!(matches!(result, Value::Integer(2)));
6035 }
6036
6037 #[test]
6038 fn test_cons() {
6039 let result = prim_cons(&[Value::integer(1), Value::integer(2)]).unwrap();
6040 assert!(result.is_pair());
6041 }
6042
6043 #[test]
6044 fn test_list() {
6045 let result = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
6046 assert!(result.is_list());
6047
6048 let len = prim_length(&[result]).unwrap();
6050 assert!(matches!(len, Value::Integer(3)));
6051 }
6052
6053 #[test]
6054 fn test_null_p() {
6055 assert!(matches!(prim_null_p(&[Value::Nil]).unwrap(), Value::Bool(true)));
6056 assert!(matches!(
6057 prim_null_p(&[Value::integer(1)]).unwrap(),
6058 Value::Bool(false)
6059 ));
6060 }
6061
6062 #[test]
6063 fn test_pair_p() {
6064 let pair = Value::cons(Value::integer(1), Value::integer(2));
6065 assert!(matches!(prim_pair_p(&[pair]).unwrap(), Value::Bool(true)));
6066 assert!(matches!(
6067 prim_pair_p(&[Value::Nil]).unwrap(),
6068 Value::Bool(false)
6069 ));
6070 }
6071
6072 #[test]
6073 fn test_length() {
6074 let list = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
6075 let result = prim_length(&[list]).unwrap();
6076 assert!(matches!(result, Value::Integer(3)));
6077
6078 let empty = prim_length(&[Value::Nil]).unwrap();
6079 assert!(matches!(empty, Value::Integer(0)));
6080 }
6081
6082 #[test]
6083 fn test_append() {
6084 let list1 = prim_list(&[Value::integer(1), Value::integer(2)]).unwrap();
6085 let list2 = prim_list(&[Value::integer(3), Value::integer(4)]).unwrap();
6086 let result = prim_append(&[list1, list2]).unwrap();
6087
6088 let len = prim_length(&[result]).unwrap();
6089 assert!(matches!(len, Value::Integer(4)));
6090 }
6091
6092 #[test]
6093 fn test_reverse() {
6094 let list = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
6095 let result = prim_reverse(&[list]).unwrap();
6096
6097 let first = prim_car(&[result]).unwrap();
6099 assert!(matches!(first, Value::Integer(3)));
6100 }
6101
6102 #[test]
6103 fn test_list_ref() {
6104 let list = prim_list(&[Value::integer(10), Value::integer(20), Value::integer(30)]).unwrap();
6105
6106 let result = prim_list_ref(&[list.clone(), Value::integer(0)]).unwrap();
6107 assert!(matches!(result, Value::Integer(10)));
6108
6109 let result = prim_list_ref(&[list.clone(), Value::integer(1)]).unwrap();
6110 assert!(matches!(result, Value::Integer(20)));
6111
6112 let result = prim_list_ref(&[list, Value::integer(2)]).unwrap();
6113 assert!(matches!(result, Value::Integer(30)));
6114 }
6115
6116 #[test]
6117 fn test_list_tail() {
6118 let list = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
6119
6120 let result = prim_list_tail(&[list, Value::integer(2)]).unwrap();
6121 let len = prim_length(&[result]).unwrap();
6122 assert!(matches!(len, Value::Integer(1)));
6123 }
6124
6125 #[test]
6130 fn test_add() {
6131 let result = prim_add(&[]).unwrap();
6132 assert!(matches!(result, Value::Integer(0)));
6133
6134 let result = prim_add(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
6135 assert!(matches!(result, Value::Integer(6)));
6136
6137 let result = prim_add(&[Value::integer(1), Value::real(2.5)]).unwrap();
6138 assert!(matches!(result, Value::Real(r) if (r - 3.5).abs() < f64::EPSILON));
6139 }
6140
6141 #[test]
6142 fn test_subtract() {
6143 let result = prim_subtract(&[Value::integer(5)]).unwrap();
6144 assert!(matches!(result, Value::Integer(-5)));
6145
6146 let result = prim_subtract(&[Value::integer(10), Value::integer(3), Value::integer(2)]).unwrap();
6147 assert!(matches!(result, Value::Integer(5)));
6148
6149 let result = prim_subtract(&[Value::real(10.5), Value::integer(2)]).unwrap();
6150 assert!(matches!(result, Value::Real(r) if (r - 8.5).abs() < f64::EPSILON));
6151 }
6152
6153 #[test]
6154 fn test_multiply() {
6155 let result = prim_multiply(&[]).unwrap();
6156 assert!(matches!(result, Value::Integer(1)));
6157
6158 let result = prim_multiply(&[Value::integer(2), Value::integer(3), Value::integer(4)]).unwrap();
6159 assert!(matches!(result, Value::Integer(24)));
6160
6161 let result = prim_multiply(&[Value::integer(2), Value::real(1.5)]).unwrap();
6162 assert!(matches!(result, Value::Real(r) if (r - 3.0).abs() < f64::EPSILON));
6163 }
6164
6165 #[test]
6166 fn test_divide() {
6167 let result = prim_divide(&[Value::integer(2)]).unwrap();
6168 assert!(matches!(result, Value::Real(r) if (r - 0.5).abs() < f64::EPSILON));
6169
6170 let result = prim_divide(&[Value::integer(10), Value::integer(2)]).unwrap();
6171 assert!(matches!(result, Value::Real(r) if (r - 5.0).abs() < f64::EPSILON));
6172
6173 assert!(prim_divide(&[Value::integer(1), Value::integer(0)]).is_err());
6175 }
6176
6177 #[test]
6178 fn test_quotient() {
6179 let result = prim_quotient(&[Value::integer(10), Value::integer(3)]).unwrap();
6180 assert!(matches!(result, Value::Integer(3)));
6181
6182 let result = prim_quotient(&[Value::integer(-10), Value::integer(3)]).unwrap();
6183 assert!(matches!(result, Value::Integer(-3)));
6184 }
6185
6186 #[test]
6187 fn test_remainder() {
6188 let result = prim_remainder(&[Value::integer(10), Value::integer(3)]).unwrap();
6189 assert!(matches!(result, Value::Integer(1)));
6190
6191 let result = prim_remainder(&[Value::integer(-10), Value::integer(3)]).unwrap();
6192 assert!(matches!(result, Value::Integer(-1)));
6193 }
6194
6195 #[test]
6196 fn test_modulo() {
6197 let result = prim_modulo(&[Value::integer(10), Value::integer(3)]).unwrap();
6198 assert!(matches!(result, Value::Integer(1)));
6199
6200 let result = prim_modulo(&[Value::integer(-10), Value::integer(3)]).unwrap();
6201 assert!(matches!(result, Value::Integer(2))); }
6203
6204 #[test]
6205 fn test_num_eq() {
6206 let result = prim_num_eq(&[Value::integer(5), Value::integer(5)]).unwrap();
6207 assert!(matches!(result, Value::Bool(true)));
6208
6209 let result = prim_num_eq(&[Value::integer(5), Value::integer(6)]).unwrap();
6210 assert!(matches!(result, Value::Bool(false)));
6211
6212 let result = prim_num_eq(&[Value::integer(5), Value::real(5.0)]).unwrap();
6213 assert!(matches!(result, Value::Bool(true)));
6214 }
6215
6216 #[test]
6217 fn test_num_lt() {
6218 let result = prim_num_lt(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
6219 assert!(matches!(result, Value::Bool(true)));
6220
6221 let result = prim_num_lt(&[Value::integer(1), Value::integer(3), Value::integer(2)]).unwrap();
6222 assert!(matches!(result, Value::Bool(false)));
6223 }
6224
6225 #[test]
6226 fn test_num_gt() {
6227 let result = prim_num_gt(&[Value::integer(3), Value::integer(2), Value::integer(1)]).unwrap();
6228 assert!(matches!(result, Value::Bool(true)));
6229
6230 let result = prim_num_gt(&[Value::integer(3), Value::integer(1), Value::integer(2)]).unwrap();
6231 assert!(matches!(result, Value::Bool(false)));
6232 }
6233
6234 #[test]
6235 fn test_num_le() {
6236 let result = prim_num_le(&[Value::integer(1), Value::integer(2), Value::integer(2)]).unwrap();
6237 assert!(matches!(result, Value::Bool(true)));
6238
6239 let result = prim_num_le(&[Value::integer(2), Value::integer(1)]).unwrap();
6240 assert!(matches!(result, Value::Bool(false)));
6241 }
6242
6243 #[test]
6244 fn test_num_ge() {
6245 let result = prim_num_ge(&[Value::integer(3), Value::integer(2), Value::integer(2)]).unwrap();
6246 assert!(matches!(result, Value::Bool(true)));
6247
6248 let result = prim_num_ge(&[Value::integer(1), Value::integer(2)]).unwrap();
6249 assert!(matches!(result, Value::Bool(false)));
6250 }
6251
6252 #[test]
6253 fn test_number_p() {
6254 assert!(matches!(prim_number_p(&[Value::integer(42)]).unwrap(), Value::Bool(true)));
6255 assert!(matches!(prim_number_p(&[Value::real(3.14)]).unwrap(), Value::Bool(true)));
6256 assert!(matches!(prim_number_p(&[Value::string("hello".to_string())]).unwrap(), Value::Bool(false)));
6257 }
6258
6259 #[test]
6260 fn test_integer_p() {
6261 assert!(matches!(prim_integer_p(&[Value::integer(42)]).unwrap(), Value::Bool(true)));
6262 assert!(matches!(prim_integer_p(&[Value::real(3.14)]).unwrap(), Value::Bool(false)));
6263 }
6264
6265 #[test]
6266 fn test_real_p() {
6267 assert!(matches!(prim_real_p(&[Value::real(3.14)]).unwrap(), Value::Bool(true)));
6268 assert!(matches!(prim_real_p(&[Value::integer(42)]).unwrap(), Value::Bool(false)));
6269 }
6270
6271 #[test]
6272 fn test_zero_p() {
6273 assert!(matches!(prim_zero_p(&[Value::integer(0)]).unwrap(), Value::Bool(true)));
6274 assert!(matches!(prim_zero_p(&[Value::integer(1)]).unwrap(), Value::Bool(false)));
6275 assert!(matches!(prim_zero_p(&[Value::real(0.0)]).unwrap(), Value::Bool(true)));
6276 }
6277
6278 #[test]
6279 fn test_positive_p() {
6280 assert!(matches!(prim_positive_p(&[Value::integer(5)]).unwrap(), Value::Bool(true)));
6281 assert!(matches!(prim_positive_p(&[Value::integer(-5)]).unwrap(), Value::Bool(false)));
6282 assert!(matches!(prim_positive_p(&[Value::integer(0)]).unwrap(), Value::Bool(false)));
6283 }
6284
6285 #[test]
6286 fn test_negative_p() {
6287 assert!(matches!(prim_negative_p(&[Value::integer(-5)]).unwrap(), Value::Bool(true)));
6288 assert!(matches!(prim_negative_p(&[Value::integer(5)]).unwrap(), Value::Bool(false)));
6289 assert!(matches!(prim_negative_p(&[Value::integer(0)]).unwrap(), Value::Bool(false)));
6290 }
6291
6292 #[test]
6293 fn test_odd_p() {
6294 assert!(matches!(prim_odd_p(&[Value::integer(3)]).unwrap(), Value::Bool(true)));
6295 assert!(matches!(prim_odd_p(&[Value::integer(4)]).unwrap(), Value::Bool(false)));
6296 }
6297
6298 #[test]
6299 fn test_even_p() {
6300 assert!(matches!(prim_even_p(&[Value::integer(4)]).unwrap(), Value::Bool(true)));
6301 assert!(matches!(prim_even_p(&[Value::integer(3)]).unwrap(), Value::Bool(false)));
6302 }
6303
6304 #[test]
6305 fn test_abs() {
6306 let result = prim_abs(&[Value::integer(-5)]).unwrap();
6307 assert!(matches!(result, Value::Integer(5)));
6308
6309 let result = prim_abs(&[Value::real(-3.14)]).unwrap();
6310 assert!(matches!(result, Value::Real(r) if (r - 3.14).abs() < f64::EPSILON));
6311 }
6312
6313 #[test]
6314 fn test_max() {
6315 let result = prim_max(&[Value::integer(1), Value::integer(5), Value::integer(3)]).unwrap();
6316 assert!(matches!(result, Value::Integer(5)));
6317
6318 let result = prim_max(&[Value::integer(1), Value::real(5.5), Value::integer(3)]).unwrap();
6319 assert!(matches!(result, Value::Real(r) if (r - 5.5).abs() < f64::EPSILON));
6320 }
6321
6322 #[test]
6323 fn test_min() {
6324 let result = prim_min(&[Value::integer(5), Value::integer(1), Value::integer(3)]).unwrap();
6325 assert!(matches!(result, Value::Integer(1)));
6326
6327 let result = prim_min(&[Value::integer(5), Value::real(0.5), Value::integer(3)]).unwrap();
6328 assert!(matches!(result, Value::Real(r) if (r - 0.5).abs() < f64::EPSILON));
6329 }
6330
6331 #[test]
6332 fn test_gcd() {
6333 let result = prim_gcd(&[Value::integer(12), Value::integer(8)]).unwrap();
6335 assert!(matches!(result, Value::Integer(4)));
6336
6337 let result = prim_gcd(&[Value::integer(12), Value::integer(18), Value::integer(24)]).unwrap();
6339 assert!(matches!(result, Value::Integer(6)));
6340
6341 let result = prim_gcd(&[Value::integer(-12), Value::integer(8)]).unwrap();
6343 assert!(matches!(result, Value::Integer(4)));
6344
6345 let result = prim_gcd(&[Value::integer(0), Value::integer(5)]).unwrap();
6347 assert!(matches!(result, Value::Integer(5)));
6348
6349 let result = prim_gcd(&[]).unwrap();
6351 assert!(matches!(result, Value::Integer(0)));
6352
6353 assert!(prim_gcd(&[Value::real(12.5), Value::integer(8)]).is_err());
6355 }
6356
6357 #[test]
6358 fn test_lcm() {
6359 let result = prim_lcm(&[Value::integer(4), Value::integer(6)]).unwrap();
6361 assert!(matches!(result, Value::Integer(12)));
6362
6363 let result = prim_lcm(&[Value::integer(2), Value::integer(3), Value::integer(4)]).unwrap();
6365 assert!(matches!(result, Value::Integer(12)));
6366
6367 let result = prim_lcm(&[Value::integer(-4), Value::integer(6)]).unwrap();
6369 assert!(matches!(result, Value::Integer(12)));
6370
6371 let result = prim_lcm(&[Value::integer(0), Value::integer(5)]).unwrap();
6373 assert!(matches!(result, Value::Integer(0)));
6374
6375 let result = prim_lcm(&[]).unwrap();
6377 assert!(matches!(result, Value::Integer(1)));
6378
6379 assert!(prim_lcm(&[Value::real(4.5), Value::integer(6)]).is_err());
6381 }
6382
6383 #[test]
6384 fn test_floor() {
6385 let result = prim_floor(&[Value::real(3.7)]).unwrap();
6386 assert!(matches!(result, Value::Integer(3)));
6387
6388 let result = prim_floor(&[Value::real(-3.7)]).unwrap();
6389 assert!(matches!(result, Value::Integer(-4)));
6390 }
6391
6392 #[test]
6393 fn test_ceiling() {
6394 let result = prim_ceiling(&[Value::real(3.2)]).unwrap();
6395 assert!(matches!(result, Value::Integer(4)));
6396
6397 let result = prim_ceiling(&[Value::real(-3.2)]).unwrap();
6398 assert!(matches!(result, Value::Integer(-3)));
6399 }
6400
6401 #[test]
6402 fn test_truncate() {
6403 let result = prim_truncate(&[Value::real(3.7)]).unwrap();
6404 assert!(matches!(result, Value::Integer(3)));
6405
6406 let result = prim_truncate(&[Value::real(-3.7)]).unwrap();
6407 assert!(matches!(result, Value::Integer(-3)));
6408 }
6409
6410 #[test]
6411 fn test_round() {
6412 let result = prim_round(&[Value::real(3.5)]).unwrap();
6413 assert!(matches!(result, Value::Integer(4)));
6414
6415 let result = prim_round(&[Value::real(3.4)]).unwrap();
6416 assert!(matches!(result, Value::Integer(3)));
6417 }
6418
6419 #[test]
6424 fn test_string_length() {
6425 let s = Value::string("hello".to_string());
6426 let result = prim_string_length(&[s]).unwrap();
6427 assert!(matches!(result, Value::Integer(5)));
6428
6429 let empty = Value::string(String::new());
6430 let result = prim_string_length(&[empty]).unwrap();
6431 assert!(matches!(result, Value::Integer(0)));
6432 }
6433
6434 #[test]
6435 fn test_string_ref() {
6436 let s = Value::string("hello".to_string());
6437 let result = prim_string_ref(&[s.clone(), Value::integer(0)]).unwrap();
6438 assert!(matches!(result, Value::Char('h')));
6439
6440 let result = prim_string_ref(&[s, Value::integer(4)]).unwrap();
6441 assert!(matches!(result, Value::Char('o')));
6442 }
6443
6444 #[test]
6445 fn test_string_append() {
6446 let s1 = Value::string("hello".to_string());
6447 let s2 = Value::string(" ".to_string());
6448 let s3 = Value::string("world".to_string());
6449 let result = prim_string_append(&[s1, s2, s3]).unwrap();
6450
6451 if let Value::String(ref s) = result {
6452 assert_eq!(&**s, "hello world");
6453 } else {
6454 panic!("Expected string");
6455 }
6456 }
6457
6458 #[test]
6459 fn test_substring() {
6460 let s = Value::string("hello".to_string());
6461 let result = prim_substring(&[s, Value::integer(1), Value::integer(4)]).unwrap();
6462
6463 if let Value::String(ref s) = result {
6464 assert_eq!(&**s, "ell");
6465 } else {
6466 panic!("Expected string");
6467 }
6468 }
6469
6470 #[test]
6471 fn test_string_eq() {
6472 let s1 = Value::string("hello".to_string());
6473 let s2 = Value::string("hello".to_string());
6474 let s3 = Value::string("world".to_string());
6475
6476 let result = prim_string_eq(&[s1.clone(), s2]).unwrap();
6477 assert!(matches!(result, Value::Bool(true)));
6478
6479 let result = prim_string_eq(&[s1, s3]).unwrap();
6480 assert!(matches!(result, Value::Bool(false)));
6481 }
6482
6483 #[test]
6484 fn test_string_lt() {
6485 let s1 = Value::string("abc".to_string());
6486 let s2 = Value::string("def".to_string());
6487
6488 let result = prim_string_lt(&[s1.clone(), s2.clone()]).unwrap();
6489 assert!(matches!(result, Value::Bool(true)));
6490
6491 let result = prim_string_lt(&[s2, s1]).unwrap();
6492 assert!(matches!(result, Value::Bool(false)));
6493 }
6494
6495 #[test]
6496 fn test_string_ci_eq() {
6497 let result = prim_string_ci_eq(&[
6499 Value::string("Hello".to_string()),
6500 Value::string("hello".to_string()),
6501 ]).unwrap();
6502 assert!(matches!(result, Value::Bool(true)));
6503
6504 let result = prim_string_ci_eq(&[
6505 Value::string("WORLD".to_string()),
6506 Value::string("world".to_string()),
6507 ]).unwrap();
6508 assert!(matches!(result, Value::Bool(true)));
6509
6510 let result = prim_string_ci_eq(&[
6511 Value::string("hello".to_string()),
6512 Value::string("world".to_string()),
6513 ]).unwrap();
6514 assert!(matches!(result, Value::Bool(false)));
6515 }
6516
6517 #[test]
6518 fn test_string_ci_lt() {
6519 let result = prim_string_ci_lt(&[
6521 Value::string("ABC".to_string()),
6522 Value::string("def".to_string()),
6523 ]).unwrap();
6524 assert!(matches!(result, Value::Bool(true)));
6525
6526 let result = prim_string_ci_lt(&[
6527 Value::string("abc".to_string()),
6528 Value::string("DEF".to_string()),
6529 ]).unwrap();
6530 assert!(matches!(result, Value::Bool(true)));
6531
6532 let result = prim_string_ci_lt(&[
6533 Value::string("def".to_string()),
6534 Value::string("ABC".to_string()),
6535 ]).unwrap();
6536 assert!(matches!(result, Value::Bool(false)));
6537 }
6538
6539 #[test]
6540 fn test_string_ci_gt() {
6541 let result = prim_string_ci_gt(&[
6543 Value::string("DEF".to_string()),
6544 Value::string("abc".to_string()),
6545 ]).unwrap();
6546 assert!(matches!(result, Value::Bool(true)));
6547
6548 let result = prim_string_ci_gt(&[
6549 Value::string("def".to_string()),
6550 Value::string("ABC".to_string()),
6551 ]).unwrap();
6552 assert!(matches!(result, Value::Bool(true)));
6553
6554 let result = prim_string_ci_gt(&[
6555 Value::string("ABC".to_string()),
6556 Value::string("def".to_string()),
6557 ]).unwrap();
6558 assert!(matches!(result, Value::Bool(false)));
6559 }
6560
6561 #[test]
6562 fn test_string_ci_le() {
6563 let result = prim_string_ci_le(&[
6565 Value::string("ABC".to_string()),
6566 Value::string("def".to_string()),
6567 ]).unwrap();
6568 assert!(matches!(result, Value::Bool(true)));
6569
6570 let result = prim_string_ci_le(&[
6571 Value::string("Hello".to_string()),
6572 Value::string("hello".to_string()),
6573 ]).unwrap();
6574 assert!(matches!(result, Value::Bool(true)));
6575
6576 let result = prim_string_ci_le(&[
6577 Value::string("def".to_string()),
6578 Value::string("ABC".to_string()),
6579 ]).unwrap();
6580 assert!(matches!(result, Value::Bool(false)));
6581 }
6582
6583 #[test]
6584 fn test_string_ci_ge() {
6585 let result = prim_string_ci_ge(&[
6587 Value::string("DEF".to_string()),
6588 Value::string("abc".to_string()),
6589 ]).unwrap();
6590 assert!(matches!(result, Value::Bool(true)));
6591
6592 let result = prim_string_ci_ge(&[
6593 Value::string("Hello".to_string()),
6594 Value::string("hello".to_string()),
6595 ]).unwrap();
6596 assert!(matches!(result, Value::Bool(true)));
6597
6598 let result = prim_string_ci_ge(&[
6599 Value::string("ABC".to_string()),
6600 Value::string("def".to_string()),
6601 ]).unwrap();
6602 assert!(matches!(result, Value::Bool(false)));
6603 }
6604
6605 #[test]
6606 fn test_make_string() {
6607 let result = prim_make_string(&[Value::integer(5), Value::char('a')]).unwrap();
6608
6609 if let Value::String(ref s) = result {
6610 assert_eq!(&**s, "aaaaa");
6611 } else {
6612 panic!("Expected string");
6613 }
6614 }
6615
6616 #[test]
6617 fn test_string() {
6618 let result = prim_string(&[
6619 Value::char('h'),
6620 Value::char('i'),
6621 ]).unwrap();
6622
6623 if let Value::String(ref s) = result {
6624 assert_eq!(&**s, "hi");
6625 } else {
6626 panic!("Expected string");
6627 }
6628 }
6629
6630 #[test]
6631 fn test_string_to_list() {
6632 let s = Value::string("hi".to_string());
6633 let result = prim_string_to_list(&[s]).unwrap();
6634
6635 let len = prim_length(&[result.clone()]).unwrap();
6637 assert!(matches!(len, Value::Integer(2)));
6638
6639 let first = prim_car(&[result]).unwrap();
6640 assert!(matches!(first, Value::Char('h')));
6641 }
6642
6643 #[test]
6644 fn test_list_to_string() {
6645 let list = prim_list(&[
6646 Value::char('h'),
6647 Value::char('i'),
6648 ]).unwrap();
6649
6650 let result = prim_list_to_string(&[list]).unwrap();
6651
6652 if let Value::String(ref s) = result {
6653 assert_eq!(&**s, "hi");
6654 } else {
6655 panic!("Expected string");
6656 }
6657 }
6658
6659 #[test]
6660 fn test_symbol_to_string() {
6661 let sym = Value::symbol("foo");
6662 let result = prim_symbol_to_string(&[sym]).unwrap();
6663
6664 if let Value::String(ref s) = result {
6665 assert_eq!(&**s, "foo");
6666 } else {
6667 panic!("Expected string");
6668 }
6669 }
6670
6671 #[test]
6672 fn test_string_to_symbol() {
6673 let s = Value::string("foo".to_string());
6674 let result = prim_string_to_symbol(&[s]).unwrap();
6675
6676 assert!(matches!(result, Value::Symbol(_)));
6677 }
6678
6679 #[test]
6680 fn test_string_p() {
6681 assert!(matches!(prim_string_p(&[Value::string("hello".to_string())]).unwrap(), Value::Bool(true)));
6682 assert!(matches!(prim_string_p(&[Value::integer(42)]).unwrap(), Value::Bool(false)));
6683 }
6684
6685 #[test]
6686 fn test_symbol_p() {
6687 assert!(matches!(prim_symbol_p(&[Value::symbol("foo")]).unwrap(), Value::Bool(true)));
6688 assert!(matches!(prim_symbol_p(&[Value::string("foo".to_string())]).unwrap(), Value::Bool(false)));
6689 }
6690
6691 #[test]
6692 fn test_char_p() {
6693 assert!(matches!(prim_char_p(&[Value::char('a')]).unwrap(), Value::Bool(true)));
6694 assert!(matches!(prim_char_p(&[Value::integer(65)]).unwrap(), Value::Bool(false)));
6695 }
6696
6697 #[test]
6698 fn test_char_eq() {
6699 let result = prim_char_eq(&[Value::char('a'), Value::char('a')]).unwrap();
6700 assert!(matches!(result, Value::Bool(true)));
6701
6702 let result = prim_char_eq(&[Value::char('a'), Value::char('b')]).unwrap();
6703 assert!(matches!(result, Value::Bool(false)));
6704 }
6705
6706 #[test]
6707 fn test_char_lt() {
6708 let result = prim_char_lt(&[Value::char('a'), Value::char('b')]).unwrap();
6709 assert!(matches!(result, Value::Bool(true)));
6710
6711 let result = prim_char_lt(&[Value::char('b'), Value::char('a')]).unwrap();
6712 assert!(matches!(result, Value::Bool(false)));
6713 }
6714
6715 #[test]
6716 fn test_char_upcase() {
6717 let result = prim_char_upcase(&[Value::char('a')]).unwrap();
6718 assert!(matches!(result, Value::Char('A')));
6719 }
6720
6721 #[test]
6722 fn test_char_downcase() {
6723 let result = prim_char_downcase(&[Value::char('Z')]).unwrap();
6724 assert!(matches!(result, Value::Char('z')));
6725 }
6726
6727 #[test]
6728 fn test_char_le() {
6729 let result = prim_char_le(&[Value::char('a'), Value::char('b')]).unwrap();
6730 assert!(matches!(result, Value::Bool(true)));
6731
6732 let result = prim_char_le(&[Value::char('a'), Value::char('a')]).unwrap();
6733 assert!(matches!(result, Value::Bool(true)));
6734
6735 let result = prim_char_le(&[Value::char('b'), Value::char('a')]).unwrap();
6736 assert!(matches!(result, Value::Bool(false)));
6737 }
6738
6739 #[test]
6740 fn test_char_ge() {
6741 let result = prim_char_ge(&[Value::char('b'), Value::char('a')]).unwrap();
6742 assert!(matches!(result, Value::Bool(true)));
6743
6744 let result = prim_char_ge(&[Value::char('a'), Value::char('a')]).unwrap();
6745 assert!(matches!(result, Value::Bool(true)));
6746
6747 let result = prim_char_ge(&[Value::char('a'), Value::char('b')]).unwrap();
6748 assert!(matches!(result, Value::Bool(false)));
6749 }
6750
6751 #[test]
6752 fn test_char_to_integer() {
6753 let result = prim_char_to_integer(&[Value::char('A')]).unwrap();
6754 assert!(matches!(result, Value::Integer(65)));
6755
6756 let result = prim_char_to_integer(&[Value::char('a')]).unwrap();
6757 assert!(matches!(result, Value::Integer(97)));
6758
6759 let result = prim_char_to_integer(&[Value::char('0')]).unwrap();
6760 assert!(matches!(result, Value::Integer(48)));
6761
6762 assert!(prim_char_to_integer(&[Value::integer(65)]).is_err());
6764 }
6765
6766 #[test]
6767 fn test_integer_to_char() {
6768 let result = prim_integer_to_char(&[Value::integer(65)]).unwrap();
6769 assert!(matches!(result, Value::Char('A')));
6770
6771 let result = prim_integer_to_char(&[Value::integer(97)]).unwrap();
6772 assert!(matches!(result, Value::Char('a')));
6773
6774 let result = prim_integer_to_char(&[Value::integer(48)]).unwrap();
6775 assert!(matches!(result, Value::Char('0')));
6776
6777 assert!(prim_integer_to_char(&[Value::integer(-1)]).is_err());
6779 assert!(prim_integer_to_char(&[Value::integer(0x200000)]).is_err());
6780
6781 assert!(prim_integer_to_char(&[Value::char('A')]).is_err());
6783 }
6784
6785 #[test]
6786 fn test_char_alphabetic_p() {
6787 let result = prim_char_alphabetic_p(&[Value::char('a')]).unwrap();
6788 assert!(matches!(result, Value::Bool(true)));
6789
6790 let result = prim_char_alphabetic_p(&[Value::char('Z')]).unwrap();
6791 assert!(matches!(result, Value::Bool(true)));
6792
6793 let result = prim_char_alphabetic_p(&[Value::char('5')]).unwrap();
6794 assert!(matches!(result, Value::Bool(false)));
6795
6796 let result = prim_char_alphabetic_p(&[Value::char(' ')]).unwrap();
6797 assert!(matches!(result, Value::Bool(false)));
6798
6799 assert!(prim_char_alphabetic_p(&[Value::integer(97)]).is_err());
6801 }
6802
6803 #[test]
6804 fn test_char_numeric_p() {
6805 let result = prim_char_numeric_p(&[Value::char('5')]).unwrap();
6806 assert!(matches!(result, Value::Bool(true)));
6807
6808 let result = prim_char_numeric_p(&[Value::char('0')]).unwrap();
6809 assert!(matches!(result, Value::Bool(true)));
6810
6811 let result = prim_char_numeric_p(&[Value::char('a')]).unwrap();
6812 assert!(matches!(result, Value::Bool(false)));
6813
6814 let result = prim_char_numeric_p(&[Value::char(' ')]).unwrap();
6815 assert!(matches!(result, Value::Bool(false)));
6816
6817 assert!(prim_char_numeric_p(&[Value::integer(5)]).is_err());
6819 }
6820
6821 #[test]
6822 fn test_char_whitespace_p() {
6823 let result = prim_char_whitespace_p(&[Value::char(' ')]).unwrap();
6824 assert!(matches!(result, Value::Bool(true)));
6825
6826 let result = prim_char_whitespace_p(&[Value::char('\t')]).unwrap();
6827 assert!(matches!(result, Value::Bool(true)));
6828
6829 let result = prim_char_whitespace_p(&[Value::char('\n')]).unwrap();
6830 assert!(matches!(result, Value::Bool(true)));
6831
6832 let result = prim_char_whitespace_p(&[Value::char('a')]).unwrap();
6833 assert!(matches!(result, Value::Bool(false)));
6834
6835 let result = prim_char_whitespace_p(&[Value::char('5')]).unwrap();
6836 assert!(matches!(result, Value::Bool(false)));
6837
6838 assert!(prim_char_whitespace_p(&[Value::integer(32)]).is_err());
6840 }
6841
6842 #[test]
6843 fn test_char_ci_eq() {
6844 let result = prim_char_ci_eq(&[Value::char('a'), Value::char('A')]).unwrap();
6846 assert!(matches!(result, Value::Bool(true)));
6847
6848 let result = prim_char_ci_eq(&[Value::char('Z'), Value::char('z')]).unwrap();
6849 assert!(matches!(result, Value::Bool(true)));
6850
6851 let result = prim_char_ci_eq(&[Value::char('a'), Value::char('b')]).unwrap();
6852 assert!(matches!(result, Value::Bool(false)));
6853
6854 assert!(prim_char_ci_eq(&[Value::integer(97), Value::char('a')]).is_err());
6856 }
6857
6858 #[test]
6859 fn test_char_ci_lt() {
6860 let result = prim_char_ci_lt(&[Value::char('A'), Value::char('b')]).unwrap();
6862 assert!(matches!(result, Value::Bool(true)));
6863
6864 let result = prim_char_ci_lt(&[Value::char('a'), Value::char('B')]).unwrap();
6865 assert!(matches!(result, Value::Bool(true)));
6866
6867 let result = prim_char_ci_lt(&[Value::char('B'), Value::char('a')]).unwrap();
6868 assert!(matches!(result, Value::Bool(false)));
6869
6870 let result = prim_char_ci_lt(&[Value::char('A'), Value::char('a')]).unwrap();
6871 assert!(matches!(result, Value::Bool(false)));
6872 }
6873
6874 #[test]
6875 fn test_char_ci_gt() {
6876 let result = prim_char_ci_gt(&[Value::char('B'), Value::char('a')]).unwrap();
6878 assert!(matches!(result, Value::Bool(true)));
6879
6880 let result = prim_char_ci_gt(&[Value::char('b'), Value::char('A')]).unwrap();
6881 assert!(matches!(result, Value::Bool(true)));
6882
6883 let result = prim_char_ci_gt(&[Value::char('A'), Value::char('b')]).unwrap();
6884 assert!(matches!(result, Value::Bool(false)));
6885
6886 let result = prim_char_ci_gt(&[Value::char('A'), Value::char('a')]).unwrap();
6887 assert!(matches!(result, Value::Bool(false)));
6888 }
6889
6890 #[test]
6891 fn test_char_ci_le() {
6892 let result = prim_char_ci_le(&[Value::char('A'), Value::char('b')]).unwrap();
6894 assert!(matches!(result, Value::Bool(true)));
6895
6896 let result = prim_char_ci_le(&[Value::char('A'), Value::char('a')]).unwrap();
6897 assert!(matches!(result, Value::Bool(true)));
6898
6899 let result = prim_char_ci_le(&[Value::char('B'), Value::char('a')]).unwrap();
6900 assert!(matches!(result, Value::Bool(false)));
6901 }
6902
6903 #[test]
6904 fn test_char_ci_ge() {
6905 let result = prim_char_ci_ge(&[Value::char('B'), Value::char('a')]).unwrap();
6907 assert!(matches!(result, Value::Bool(true)));
6908
6909 let result = prim_char_ci_ge(&[Value::char('A'), Value::char('a')]).unwrap();
6910 assert!(matches!(result, Value::Bool(true)));
6911
6912 let result = prim_char_ci_ge(&[Value::char('A'), Value::char('b')]).unwrap();
6913 assert!(matches!(result, Value::Bool(false)));
6914 }
6915
6916 #[test]
6921 fn test_not() {
6922 let result = prim_not(&[Value::bool(true)]).unwrap();
6923 assert!(matches!(result, Value::Bool(false)));
6924
6925 let result = prim_not(&[Value::bool(false)]).unwrap();
6926 assert!(matches!(result, Value::Bool(true)));
6927
6928 let result = prim_not(&[Value::integer(0)]).unwrap();
6930 assert!(matches!(result, Value::Bool(false)));
6931 }
6932
6933 #[test]
6934 fn test_boolean_p() {
6935 assert!(matches!(prim_boolean_p(&[Value::bool(true)]).unwrap(), Value::Bool(true)));
6936 assert!(matches!(prim_boolean_p(&[Value::bool(false)]).unwrap(), Value::Bool(true)));
6937 assert!(matches!(prim_boolean_p(&[Value::integer(1)]).unwrap(), Value::Bool(false)));
6938 assert!(matches!(prim_boolean_p(&[Value::Nil]).unwrap(), Value::Bool(false)));
6939 }
6940
6941 #[test]
6942 fn test_equal_p() {
6943 let result = prim_equal_p(&[Value::integer(42), Value::integer(42)]).unwrap();
6945 assert!(matches!(result, Value::Bool(true)));
6946
6947 let result = prim_equal_p(&[Value::integer(42), Value::integer(43)]).unwrap();
6948 assert!(matches!(result, Value::Bool(false)));
6949
6950 let result = prim_equal_p(&[Value::string("hello".to_string()), Value::string("hello".to_string())]).unwrap();
6952 assert!(matches!(result, Value::Bool(true)));
6953
6954 let list1 = prim_list(&[Value::integer(1), Value::integer(2)]).unwrap();
6956 let list2 = prim_list(&[Value::integer(1), Value::integer(2)]).unwrap();
6957 let result = prim_equal_p(&[list1, list2]).unwrap();
6958 assert!(matches!(result, Value::Bool(true)));
6959 }
6960
6961 #[test]
6962 fn test_eqv_p() {
6963 let result = prim_eqv_p(&[Value::integer(42), Value::integer(42)]).unwrap();
6965 assert!(matches!(result, Value::Bool(true)));
6966
6967 let sym1 = Value::symbol("foo");
6969 let sym2 = Value::symbol("foo");
6970 let result = prim_eqv_p(&[sym1, sym2]).unwrap();
6971 assert!(matches!(result, Value::Bool(true)));
6972
6973 let result = prim_eqv_p(&[Value::integer(42), Value::string("42".to_string())]).unwrap();
6975 assert!(matches!(result, Value::Bool(false)));
6976 }
6977
6978 #[test]
6979 fn test_eq_p() {
6980 let result = prim_eq_p(&[Value::integer(42), Value::integer(42)]).unwrap();
6982 assert!(matches!(result, Value::Bool(true)));
6983
6984 let sym1 = Value::symbol("foo");
6986 let sym2 = Value::symbol("foo");
6987 let result = prim_eq_p(&[sym1, sym2]).unwrap();
6988 assert!(matches!(result, Value::Bool(true)));
6989
6990 let pair = Value::cons(Value::integer(1), Value::integer(2));
6992 let result = prim_eq_p(&[pair.clone(), pair]).unwrap();
6993 assert!(matches!(result, Value::Bool(true)));
6994 }
6995
6996 #[test]
6997 fn test_procedure_p() {
6998 let proc = Value::primitive("+", prim_add);
7000 assert!(matches!(prim_procedure_p(&[proc]).unwrap(), Value::Bool(true)));
7001
7002 assert!(matches!(prim_procedure_p(&[Value::integer(42)]).unwrap(), Value::Bool(false)));
7004 assert!(matches!(prim_procedure_p(&[Value::string("hello".to_string())]).unwrap(), Value::Bool(false)));
7005 }
7006
7007 #[test]
7012 fn test_error() {
7013 let result = prim_error(&[Value::string("test error".to_string())]);
7015 assert!(result.is_err());
7016 assert_eq!(result.unwrap_err(), "test error");
7017
7018 let result = prim_error(&[Value::symbol("error-symbol")]);
7020 assert!(result.is_err());
7021 assert!(result.unwrap_err().contains("error-symbol"));
7022
7023 let result = prim_error(&[
7025 Value::string("error:".to_string()),
7026 Value::integer(42),
7027 Value::string("foo".to_string()),
7028 ]);
7029 assert!(result.is_err());
7030 let msg = result.unwrap_err();
7031 assert!(msg.contains("error:"));
7032 assert!(msg.contains("42"));
7033 }
7034
7035 #[test]
7036 fn test_display() {
7037 let result = prim_display(&[Value::string("test".to_string())]).unwrap();
7039 assert!(matches!(result, Value::Unspecified));
7040
7041 let result = prim_display(&[Value::integer(42)]).unwrap();
7042 assert!(matches!(result, Value::Unspecified));
7043
7044 let result = prim_display(&[Value::Char('x')]).unwrap();
7045 assert!(matches!(result, Value::Unspecified));
7046 }
7047
7048 #[test]
7049 fn test_newline() {
7050 let result = prim_newline(&[]).unwrap();
7051 assert!(matches!(result, Value::Unspecified));
7052
7053 let result = prim_newline(&[Value::integer(1)]);
7055 assert!(result.is_err());
7056 }
7057
7058 #[test]
7059 fn test_write() {
7060 let result = prim_write(&[Value::string("test".to_string())]).unwrap();
7061 assert!(matches!(result, Value::Unspecified));
7062
7063 let result = prim_write(&[Value::integer(42)]).unwrap();
7064 assert!(matches!(result, Value::Unspecified));
7065 }
7066
7067 #[test]
7072 fn test_number_to_string() {
7073 let result = prim_number_to_string(&[Value::integer(42)]).unwrap();
7074 if let Value::String(ref s) = result {
7075 assert_eq!(&***s, "42");
7076 } else {
7077 panic!("Expected string");
7078 }
7079
7080 let result = prim_number_to_string(&[Value::real(3.14)]).unwrap();
7081 if let Value::String(ref s) = result {
7082 assert!(s.starts_with("3.14"));
7083 } else {
7084 panic!("Expected string");
7085 }
7086 }
7087
7088 #[test]
7089 fn test_string_to_number() {
7090 let result = prim_string_to_number(&[Value::string("42".to_string())]).unwrap();
7091 assert!(matches!(result, Value::Integer(42)));
7092
7093 let result = prim_string_to_number(&[Value::string("3.14".to_string())]).unwrap();
7094 assert!(matches!(result, Value::Real(_)));
7095
7096 let result = prim_string_to_number(&[Value::string("not-a-number".to_string())]).unwrap();
7098 assert!(matches!(result, Value::Bool(false)));
7099 }
7100
7101 #[test]
7106 fn test_keyword_p() {
7107 let kw = Value::keyword("test");
7108 assert!(matches!(prim_keyword_p(&[kw]).unwrap(), Value::Bool(true)));
7109
7110 assert!(matches!(prim_keyword_p(&[Value::symbol("test")]).unwrap(), Value::Bool(false)));
7111 assert!(matches!(prim_keyword_p(&[Value::string("test".to_string())]).unwrap(), Value::Bool(false)));
7112 }
7113
7114 #[test]
7115 fn test_keyword_to_string() {
7116 let kw = Value::keyword("test");
7117 let result = prim_keyword_to_string(&[kw]).unwrap();
7118 if let Value::String(ref s) = result {
7119 assert_eq!(&***s, "test");
7120 } else {
7121 panic!("Expected string");
7122 }
7123 }
7124
7125 #[test]
7126 fn test_string_to_keyword() {
7127 let result = prim_string_to_keyword(&[Value::string("test".to_string())]).unwrap();
7128 assert!(matches!(result, Value::Keyword(_)));
7129 }
7130
7131 #[test]
7136 fn test_memq() {
7137 let list = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
7138 let result = prim_memq(&[Value::integer(2), list.clone()]).unwrap();
7139 assert!(result.is_list());
7140
7141 let result = prim_memq(&[Value::integer(99), list]).unwrap();
7143 assert!(matches!(result, Value::Bool(false)));
7144 }
7145
7146 #[test]
7147 fn test_memv() {
7148 let list = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
7149 let result = prim_memv(&[Value::integer(2), list.clone()]).unwrap();
7150 assert!(result.is_list());
7151
7152 let result = prim_memv(&[Value::integer(99), list]).unwrap();
7154 assert!(matches!(result, Value::Bool(false)));
7155 }
7156
7157 #[test]
7158 fn test_member() {
7159 let list = prim_list(&[
7160 Value::string("a".to_string()),
7161 Value::string("b".to_string()),
7162 Value::string("c".to_string()),
7163 ])
7164 .unwrap();
7165 let result = prim_member(&[Value::string("b".to_string()), list.clone()]).unwrap();
7166 assert!(result.is_list());
7167
7168 let result = prim_member(&[Value::string("z".to_string()), list]).unwrap();
7170 assert!(matches!(result, Value::Bool(false)));
7171 }
7172
7173 #[test]
7174 fn test_assq() {
7175 let pair1 = Value::cons(Value::symbol("a"), Value::integer(1));
7177 let pair2 = Value::cons(Value::symbol("b"), Value::integer(2));
7178 let pair3 = Value::cons(Value::symbol("c"), Value::integer(3));
7179 let alist = prim_list(&[pair1, pair2, pair3]).unwrap();
7180
7181 let result = prim_assq(&[Value::symbol("b"), alist.clone()]).unwrap();
7182 assert!(result.is_pair());
7183
7184 let result = prim_assq(&[Value::symbol("z"), alist]).unwrap();
7186 assert!(matches!(result, Value::Bool(false)));
7187 }
7188
7189 #[test]
7190 fn test_assv() {
7191 let pair1 = Value::cons(Value::integer(1), Value::symbol("a"));
7193 let pair2 = Value::cons(Value::integer(2), Value::symbol("b"));
7194 let pair3 = Value::cons(Value::integer(3), Value::symbol("c"));
7195 let alist = prim_list(&[pair1, pair2, pair3]).unwrap();
7196
7197 let result = prim_assv(&[Value::integer(2), alist.clone()]).unwrap();
7198 assert!(result.is_pair());
7199
7200 let result = prim_assv(&[Value::integer(99), alist]).unwrap();
7202 assert!(matches!(result, Value::Bool(false)));
7203 }
7204
7205 #[test]
7206 fn test_assoc() {
7207 let pair1 = Value::cons(Value::string("a".to_string()), Value::integer(1));
7209 let pair2 = Value::cons(Value::string("b".to_string()), Value::integer(2));
7210 let pair3 = Value::cons(Value::string("c".to_string()), Value::integer(3));
7211 let alist = prim_list(&[pair1, pair2, pair3]).unwrap();
7212
7213 let result = prim_assoc(&[Value::string("b".to_string()), alist.clone()]).unwrap();
7214 assert!(result.is_pair());
7215
7216 let result = prim_assoc(&[Value::string("z".to_string()), alist]).unwrap();
7218 assert!(matches!(result, Value::Bool(false)));
7219 }
7220
7221 #[test]
7226 fn test_cadr() {
7227 let list = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
7229 let result = prim_cadr(&[list]).unwrap();
7230 assert!(matches!(result, Value::Integer(2)));
7231 }
7232
7233 #[test]
7234 fn test_caddr() {
7235 let list = prim_list(&[
7237 Value::integer(1),
7238 Value::integer(2),
7239 Value::integer(3),
7240 Value::integer(4),
7241 ])
7242 .unwrap();
7243 let result = prim_caddr(&[list]).unwrap();
7244 assert!(matches!(result, Value::Integer(3)));
7245 }
7246
7247 #[test]
7248 fn test_cadddr() {
7249 let list = prim_list(&[
7251 Value::integer(1),
7252 Value::integer(2),
7253 Value::integer(3),
7254 Value::integer(4),
7255 Value::integer(5),
7256 ])
7257 .unwrap();
7258 let result = prim_cadddr(&[list]).unwrap();
7259 assert!(matches!(result, Value::Integer(4)));
7260 }
7261
7262 #[test]
7263 fn test_caar() {
7264 let inner = prim_list(&[Value::integer(1), Value::integer(2)]).unwrap();
7266 let outer = prim_list(&[inner, Value::integer(3)]).unwrap();
7267 let result = prim_caar(&[outer]).unwrap();
7268 assert!(matches!(result, Value::Integer(1)));
7269 }
7270
7271 #[test]
7272 fn test_cddr() {
7273 let list = prim_list(&[
7275 Value::integer(1),
7276 Value::integer(2),
7277 Value::integer(3),
7278 Value::integer(4),
7279 ])
7280 .unwrap();
7281 let result = prim_cddr(&[list]).unwrap();
7282 assert!(result.is_list());
7283 let first = prim_car(&[result.clone()]).unwrap();
7285 assert!(matches!(first, Value::Integer(3)));
7286 }
7287
7288 #[test]
7289 fn test_cdar() {
7290 let inner = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
7292 let outer = prim_list(&[inner, Value::integer(4)]).unwrap();
7293 let result = prim_cdar(&[outer]).unwrap();
7294 assert!(result.is_list());
7295 let first = prim_car(&[result]).unwrap();
7296 assert!(matches!(first, Value::Integer(2)));
7297 }
7298
7299 #[test]
7300 fn test_caaar() {
7301 let innermost = prim_list(&[Value::integer(1), Value::integer(2)]).unwrap();
7303 let middle = prim_list(&[innermost, Value::integer(3)]).unwrap();
7304 let outer = prim_list(&[middle, Value::integer(4)]).unwrap();
7305 let result = prim_caaar(&[outer]).unwrap();
7306 assert!(matches!(result, Value::Integer(1)));
7307 }
7308
7309 #[test]
7310 fn test_cdaar() {
7311 let innermost = prim_list(&[Value::integer(1), Value::integer(2)]).unwrap();
7313 let middle = prim_list(&[innermost, Value::integer(3)]).unwrap();
7314 let outer = prim_list(&[middle, Value::integer(4)]).unwrap();
7315 let result = prim_cdaar(&[outer]).unwrap();
7316 assert!(result.is_list());
7317 let first = prim_car(&[result]).unwrap();
7318 assert!(matches!(first, Value::Integer(2)));
7319 }
7320
7321 #[test]
7322 fn test_cadar() {
7323 let inner = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
7325 let outer = prim_list(&[inner, Value::integer(4)]).unwrap();
7326 let result = prim_cadar(&[outer]).unwrap();
7327 assert!(matches!(result, Value::Integer(2)));
7328 }
7329
7330 #[test]
7331 fn test_cddar() {
7332 let inner = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3), Value::integer(4)]).unwrap();
7334 let outer = prim_list(&[inner, Value::integer(5)]).unwrap();
7335 let result = prim_cddar(&[outer]).unwrap();
7336 assert!(result.is_list());
7337 let first = prim_car(&[result]).unwrap();
7338 assert!(matches!(first, Value::Integer(3)));
7339 }
7340
7341 #[test]
7342 fn test_caadr() {
7343 let inner = prim_list(&[Value::integer(2), Value::integer(3)]).unwrap();
7345 let outer = prim_list(&[Value::integer(1), inner, Value::integer(4)]).unwrap();
7346 let result = prim_caadr(&[outer]).unwrap();
7347 assert!(matches!(result, Value::Integer(2)));
7348 }
7349
7350 #[test]
7351 fn test_cdadr() {
7352 let inner = prim_list(&[Value::integer(2), Value::integer(3), Value::integer(4)]).unwrap();
7354 let outer = prim_list(&[Value::integer(1), inner, Value::integer(5)]).unwrap();
7355 let result = prim_cdadr(&[outer]).unwrap();
7356 assert!(result.is_list());
7357 let first = prim_car(&[result]).unwrap();
7358 assert!(matches!(first, Value::Integer(3)));
7359 }
7360
7361 #[test]
7362 fn test_last() {
7363 let list = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3), Value::integer(4)]).unwrap();
7365 let result = prim_last(&[list]).unwrap();
7366 assert!(matches!(result, Value::Integer(4)));
7367
7368 let single = prim_list(&[Value::integer(1)]).unwrap();
7370 let result = prim_last(&[single]).unwrap();
7371 assert!(matches!(result, Value::Integer(1)));
7372
7373 assert!(prim_last(&[Value::Nil]).is_err());
7375 }
7376
7377 #[test]
7382 fn test_quantity_p() {
7383 assert!(matches!(prim_quantity_p(&[Value::integer(1)]).unwrap(), Value::Bool(false)));
7385 assert!(matches!(prim_quantity_p(&[Value::string("10pt".to_string())]).unwrap(), Value::Bool(false)));
7386 assert!(matches!(prim_quantity_p(&[Value::symbol("quantity")]).unwrap(), Value::Bool(false)));
7387 }
7388
7389 #[test]
7390 fn test_color_p() {
7391 assert!(matches!(prim_color_p(&[Value::string("red".to_string())]).unwrap(), Value::Bool(false)));
7393 assert!(matches!(prim_color_p(&[Value::integer(0)]).unwrap(), Value::Bool(false)));
7394 assert!(matches!(prim_color_p(&[Value::symbol("color")]).unwrap(), Value::Bool(false)));
7395 }
7396
7397 #[test]
7398 fn test_address_p() {
7399 assert!(matches!(prim_address_p(&[Value::string("addr".to_string())]).unwrap(), Value::Bool(false)));
7401 assert!(matches!(prim_address_p(&[Value::integer(0)]).unwrap(), Value::Bool(false)));
7402 assert!(matches!(prim_address_p(&[Value::symbol("address")]).unwrap(), Value::Bool(false)));
7403 }
7404
7405 #[test]
7410 fn test_format_number_decimal() {
7411 let result = prim_format_number(&[Value::integer(42), Value::string("1".to_string())]).unwrap();
7412 if let Value::String(ref s) = result {
7413 assert_eq!(&***s, "42");
7414 } else {
7415 panic!("Expected string");
7416 }
7417 }
7418
7419 #[test]
7420 fn test_format_number_roman_upper() {
7421 let result = prim_format_number(&[Value::integer(5), Value::string("I".to_string())]).unwrap();
7422 if let Value::String(ref s) = result {
7423 assert_eq!(&***s, "V");
7424 } else {
7425 panic!("Expected string");
7426 }
7427
7428 let result = prim_format_number(&[Value::integer(10), Value::string("I".to_string())]).unwrap();
7429 if let Value::String(ref s) = result {
7430 assert_eq!(&***s, "X");
7431 } else {
7432 panic!("Expected string");
7433 }
7434 }
7435
7436 #[test]
7437 fn test_format_number_roman_lower() {
7438 let result = prim_format_number(&[Value::integer(3), Value::string("i".to_string())]).unwrap();
7439 if let Value::String(ref s) = result {
7440 assert_eq!(&***s, "iii");
7441 } else {
7442 panic!("Expected string");
7443 }
7444 }
7445
7446 #[test]
7447 fn test_format_number_alpha_upper() {
7448 let result = prim_format_number(&[Value::integer(1), Value::string("A".to_string())]).unwrap();
7449 if let Value::String(ref s) = result {
7450 assert_eq!(&***s, "A");
7451 } else {
7452 panic!("Expected string");
7453 }
7454
7455 let result = prim_format_number(&[Value::integer(26), Value::string("A".to_string())]).unwrap();
7456 if let Value::String(ref s) = result {
7457 assert_eq!(&***s, "Z");
7458 } else {
7459 panic!("Expected string");
7460 }
7461 }
7462
7463 #[test]
7464 fn test_format_number_alpha_lower() {
7465 let result = prim_format_number(&[Value::integer(1), Value::string("a".to_string())]).unwrap();
7466 if let Value::String(ref s) = result {
7467 assert_eq!(&***s, "a");
7468 } else {
7469 panic!("Expected string");
7470 }
7471
7472 let result = prim_format_number(&[Value::integer(3), Value::string("a".to_string())]).unwrap();
7473 if let Value::String(ref s) = result {
7474 assert_eq!(&***s, "c");
7475 } else {
7476 panic!("Expected string");
7477 }
7478 }
7479
7480 #[test]
7481 fn test_format_number_list() {
7482 let nums = prim_list(&[Value::integer(1), Value::integer(2), Value::integer(3)]).unwrap();
7483 let result = prim_format_number_list(&[nums.clone()]).unwrap();
7484 if let Value::String(ref s) = result {
7485 assert_eq!(&***s, "1.2.3");
7486 } else {
7487 panic!("Expected string");
7488 }
7489
7490 let result = prim_format_number_list(&[nums, Value::string("-".to_string())]).unwrap();
7492 if let Value::String(ref s) = result {
7493 assert_eq!(&***s, "1-2-3");
7494 } else {
7495 panic!("Expected string");
7496 }
7497 }
7498
7499 #[test]
7504 fn test_node_list_p() {
7505 let nl = prim_empty_node_list(&[]).unwrap();
7507 assert!(matches!(prim_node_list_p(&[nl]).unwrap(), Value::Bool(true)));
7508
7509 assert!(matches!(prim_node_list_p(&[Value::integer(1)]).unwrap(), Value::Bool(false)));
7511 assert!(matches!(prim_node_list_p(&[Value::string("test".to_string())]).unwrap(), Value::Bool(false)));
7512 assert!(matches!(prim_node_list_p(&[Value::Nil]).unwrap(), Value::Bool(false)));
7513 }
7514
7515 #[test]
7516 fn test_empty_node_list() {
7517 let result = prim_empty_node_list(&[]).unwrap();
7518 assert!(matches!(result, Value::NodeList(_)));
7519 }
7520
7521 #[test]
7522 fn test_node_list_empty_p() {
7523 let nl = prim_empty_node_list(&[]).unwrap();
7525 let result = prim_node_list_empty_p(&[nl]).unwrap();
7526 assert!(matches!(result, Value::Bool(true)));
7527
7528 assert!(prim_node_list_empty_p(&[Value::integer(1)]).is_err());
7530 }
7531
7532 #[test]
7533 fn test_node_list_length() {
7534 let nl = prim_empty_node_list(&[]).unwrap();
7536 let result = prim_node_list_length(&[nl]).unwrap();
7537 assert!(matches!(result, Value::Integer(0)));
7538
7539 assert!(prim_node_list_length(&[Value::integer(1)]).is_err());
7541 }
7542
7543 #[test]
7544 fn test_node_list_first() {
7545 let nl = prim_empty_node_list(&[]).unwrap();
7547 let result = prim_node_list_first(&[nl]).unwrap();
7548 assert!(matches!(result, Value::Bool(false)));
7549
7550 assert!(prim_node_list_first(&[Value::integer(1)]).is_err());
7552 }
7553
7554 #[test]
7555 fn test_node_list_rest() {
7556 let nl = prim_empty_node_list(&[]).unwrap();
7558 let result = prim_node_list_rest(&[nl]).unwrap();
7559 assert!(matches!(result, Value::NodeList(_)));
7560
7561 assert!(prim_node_list_rest(&[Value::integer(1)]).is_err());
7563 }
7564
7565 #[test]
7566 fn test_node_list_ref() {
7567 let nl = prim_empty_node_list(&[]).unwrap();
7569 let result = prim_node_list_ref(&[nl, Value::integer(0)]).unwrap();
7570 assert!(matches!(result, Value::Bool(false)));
7571
7572 assert!(prim_node_list_ref(&[Value::integer(1), Value::integer(0)]).is_err());
7574
7575 let nl = prim_empty_node_list(&[]).unwrap();
7577 assert!(prim_node_list_ref(&[nl, Value::string("x".to_string())]).is_err());
7578 }
7579
7580 #[test]
7581 fn test_node_list_reverse() {
7582 let nl = prim_empty_node_list(&[]).unwrap();
7584 let result = prim_node_list_reverse(&[nl]).unwrap();
7585 assert!(matches!(result, Value::NodeList(_)));
7586
7587 assert!(prim_node_list_reverse(&[Value::integer(1)]).is_err());
7589 }
7590
7591 #[test]
7596 fn test_expt() {
7597 let result = prim_expt(&[Value::integer(2), Value::integer(3)]).unwrap();
7599 assert!(matches!(result, Value::Integer(8)));
7600
7601 let result = prim_expt(&[Value::real(2.0), Value::integer(3)]).unwrap();
7603 assert!(matches!(result, Value::Real(r) if (r - 8.0).abs() < 0.001));
7604
7605 let result = prim_expt(&[Value::integer(4), Value::real(0.5)]).unwrap();
7607 assert!(matches!(result, Value::Real(r) if (r - 2.0).abs() < 0.001));
7608
7609 assert!(prim_expt(&[Value::string("x".to_string()), Value::integer(2)]).is_err());
7611 }
7612
7613 #[test]
7614 fn test_sqrt() {
7615 let result = prim_sqrt(&[Value::integer(16)]).unwrap();
7617 assert!(matches!(result, Value::Real(r) if (r - 4.0).abs() < 0.001));
7618
7619 let result = prim_sqrt(&[Value::real(2.0)]).unwrap();
7621 assert!(matches!(result, Value::Real(r) if (r - 1.414).abs() < 0.01));
7622
7623 assert!(prim_sqrt(&[Value::integer(-1)]).is_err());
7625
7626 assert!(prim_sqrt(&[Value::string("x".to_string())]).is_err());
7628 }
7629
7630 #[test]
7631 fn test_sin() {
7632 let result = prim_sin(&[Value::integer(0)]).unwrap();
7634 assert!(matches!(result, Value::Real(r) if r.abs() < 0.001));
7635
7636 let result = prim_sin(&[Value::real(std::f64::consts::PI / 2.0)]).unwrap();
7638 assert!(matches!(result, Value::Real(r) if (r - 1.0).abs() < 0.001));
7639
7640 assert!(prim_sin(&[Value::string("x".to_string())]).is_err());
7642 }
7643
7644 #[test]
7645 fn test_cos() {
7646 let result = prim_cos(&[Value::integer(0)]).unwrap();
7648 assert!(matches!(result, Value::Real(r) if (r - 1.0).abs() < 0.001));
7649
7650 let result = prim_cos(&[Value::real(std::f64::consts::PI)]).unwrap();
7652 assert!(matches!(result, Value::Real(r) if (r + 1.0).abs() < 0.001));
7653
7654 assert!(prim_cos(&[Value::string("x".to_string())]).is_err());
7656 }
7657
7658 #[test]
7659 fn test_tan() {
7660 let result = prim_tan(&[Value::integer(0)]).unwrap();
7662 assert!(matches!(result, Value::Real(r) if r.abs() < 0.001));
7663
7664 let result = prim_tan(&[Value::real(std::f64::consts::PI / 4.0)]).unwrap();
7666 assert!(matches!(result, Value::Real(r) if (r - 1.0).abs() < 0.001));
7667
7668 assert!(prim_tan(&[Value::string("x".to_string())]).is_err());
7670 }
7671
7672 #[test]
7673 fn test_atan() {
7674 let result = prim_atan(&[Value::integer(0)]).unwrap();
7676 assert!(matches!(result, Value::Real(r) if r.abs() < 0.001));
7677
7678 let result = prim_atan(&[Value::integer(1)]).unwrap();
7680 assert!(matches!(result, Value::Real(r) if (r - std::f64::consts::PI / 4.0).abs() < 0.001));
7681
7682 assert!(prim_atan(&[Value::string("x".to_string())]).is_err());
7684 }
7685
7686 #[test]
7687 fn test_log() {
7688 let result = prim_log(&[Value::real(std::f64::consts::E)]).unwrap();
7690 assert!(matches!(result, Value::Real(r) if (r - 1.0).abs() < 0.001));
7691
7692 let result = prim_log(&[Value::integer(1)]).unwrap();
7694 assert!(matches!(result, Value::Real(r) if r.abs() < 0.001));
7695
7696 assert!(prim_log(&[Value::integer(-1)]).is_err());
7698
7699 assert!(prim_log(&[Value::string("x".to_string())]).is_err());
7701 }
7702
7703 #[test]
7704 fn test_exp() {
7705 let result = prim_exp(&[Value::integer(0)]).unwrap();
7707 assert!(matches!(result, Value::Real(r) if (r - 1.0).abs() < 0.001));
7708
7709 let result = prim_exp(&[Value::integer(1)]).unwrap();
7711 assert!(matches!(result, Value::Real(r) if (r - std::f64::consts::E).abs() < 0.001));
7712
7713 assert!(prim_exp(&[Value::string("x".to_string())]).is_err());
7715 }
7716
7717 #[test]
7722 fn test_sosofo_p() {
7723 assert!(matches!(prim_sosofo_p(&[Value::Sosofo]).unwrap(), Value::Bool(true)));
7725
7726 assert!(matches!(prim_sosofo_p(&[Value::integer(1)]).unwrap(), Value::Bool(false)));
7728 assert!(matches!(prim_sosofo_p(&[Value::string("test".to_string())]).unwrap(), Value::Bool(false)));
7729 let nl = prim_empty_node_list(&[]).unwrap();
7730 assert!(matches!(prim_sosofo_p(&[nl]).unwrap(), Value::Bool(false)));
7731 }
7732
7733 #[test]
7734 fn test_empty_sosofo() {
7735 let result = prim_empty_sosofo(&[]).unwrap();
7736 assert!(matches!(result, Value::Sosofo));
7737 }
7738
7739 #[test]
7740 fn test_literal() {
7741 let result = prim_literal(&[Value::string("hello".to_string())]).unwrap();
7742 assert!(matches!(result, Value::Sosofo));
7743
7744 assert!(prim_literal(&[Value::integer(1)]).is_err());
7746 }
7747
7748 #[test]
7749 fn test_sosofo_append() {
7750 let s1 = prim_empty_sosofo(&[]).unwrap();
7752 let s2 = prim_empty_sosofo(&[]).unwrap();
7753 let result = prim_sosofo_append(&[s1, s2]).unwrap();
7754 assert!(matches!(result, Value::Sosofo));
7755
7756 assert!(prim_sosofo_append(&[Value::Sosofo, Value::integer(1)]).is_err());
7758 }
7759
7760 #[test]
7765 fn test_string_equiv_p() {
7766 let result = prim_string_equiv_p(&[
7768 Value::string("Hello".to_string()),
7769 Value::string("hello".to_string()),
7770 ])
7771 .unwrap();
7772 assert!(matches!(result, Value::Bool(true)));
7773
7774 let result = prim_string_equiv_p(&[
7775 Value::string("HELLO".to_string()),
7776 Value::string("hello".to_string()),
7777 ])
7778 .unwrap();
7779 assert!(matches!(result, Value::Bool(true)));
7780
7781 let result = prim_string_equiv_p(&[
7782 Value::string("hello".to_string()),
7783 Value::string("world".to_string()),
7784 ])
7785 .unwrap();
7786 assert!(matches!(result, Value::Bool(false)));
7787
7788 assert!(prim_string_equiv_p(&[Value::integer(1), Value::string("test".to_string())]).is_err());
7790 }
7791
7792 #[test]
7797 fn test_time() {
7798 let result = prim_time(&[]).unwrap();
7800 assert!(matches!(result, Value::Unspecified));
7801 }
7802
7803 #[test]
7804 fn test_time_to_string() {
7805 let result = prim_time_to_string(&[Value::Unspecified, Value::string("".to_string())]).unwrap();
7807 if let Value::String(ref s) = result {
7808 assert_eq!(&***s, "");
7809 } else {
7810 panic!("Expected string");
7811 }
7812 }
7813
7814 #[test]
7819 fn test_language_p() {
7820 assert!(matches!(prim_language_p(&[Value::Unspecified]).unwrap(), Value::Bool(false)));
7822 assert!(matches!(prim_language_p(&[Value::string("en".to_string())]).unwrap(), Value::Bool(false)));
7823 }
7824
7825 #[test]
7826 fn test_current_language() {
7827 let result = prim_current_language(&[]).unwrap();
7829 assert!(matches!(result, Value::Unspecified));
7830 }
7831}