1use crate::pool;
2use crate::value::Value;
3
4pub struct StackNode {
10 pub value: Value,
12
13 pub next: *mut StackNode,
16}
17
18pub type Stack = *mut StackNode;
22
23pub unsafe fn push(stack: Stack, value: Value) -> Stack {
34 pool::pool_allocate(value, stack)
35}
36
37pub unsafe fn pop(stack: Stack) -> (Stack, Value) {
48 assert!(!stack.is_null(), "pop: stack is empty");
49
50 unsafe {
51 let rest = (*stack).next;
52 let value = std::mem::replace(&mut (*stack).value, Value::Int(0));
56
57 pool::pool_free(stack);
59
60 (rest, value)
61 }
62}
63
64pub unsafe fn pop_two(stack: Stack, op_name: &str) -> (Stack, Value, Value) {
76 assert!(!stack.is_null(), "{}: stack is empty", op_name);
77 let (rest, b) = unsafe { pop(stack) };
78 assert!(!rest.is_null(), "{}: need two values", op_name);
79 let (rest, a) = unsafe { pop(rest) };
80 (rest, a, b)
81}
82
83pub fn is_empty(stack: Stack) -> bool {
85 stack.is_null()
86}
87
88pub unsafe fn peek<'a>(stack: Stack) -> &'a Value {
94 assert!(!stack.is_null(), "peek: stack is empty");
95 unsafe { &(*stack).value }
96}
97
98#[unsafe(no_mangle)]
103pub unsafe extern "C" fn patch_seq_dup(stack: Stack) -> Stack {
104 assert!(!stack.is_null(), "dup: stack is empty");
105 let value = unsafe { (*stack).value.clone() };
110 unsafe { push(stack, value) }
111}
112
113pub unsafe fn drop(stack: Stack) -> Stack {
118 assert!(!stack.is_null(), "drop: stack is empty");
119 let (rest, _) = unsafe { pop(stack) };
120 rest
121}
122
123#[unsafe(no_mangle)]
130pub unsafe extern "C" fn patch_seq_drop_op(stack: Stack) -> Stack {
131 unsafe { drop(stack) }
132}
133
134#[allow(improper_ctypes_definitions)]
142#[unsafe(no_mangle)]
143pub unsafe extern "C" fn patch_seq_push_value(stack: Stack, value: Value) -> Stack {
144 unsafe { push(stack, value) }
145}
146
147#[unsafe(no_mangle)]
152pub unsafe extern "C" fn patch_seq_swap(stack: Stack) -> Stack {
153 assert!(!stack.is_null(), "swap: stack is empty");
154 let (rest, b) = unsafe { pop(stack) };
155 assert!(!rest.is_null(), "swap: stack has only one value");
156 let (rest, a) = unsafe { pop(rest) };
157 let stack = unsafe { push(rest, b) };
158 unsafe { push(stack, a) }
159}
160
161#[unsafe(no_mangle)]
166pub unsafe extern "C" fn patch_seq_over(stack: Stack) -> Stack {
167 assert!(!stack.is_null(), "over: stack is empty");
168 let (rest, b) = unsafe { pop(stack) };
169 assert!(!rest.is_null(), "over: stack has only one value");
170 let a = unsafe { (*rest).value.clone() };
171 let stack = unsafe { push(rest, b) };
172 unsafe { push(stack, a) }
173}
174
175#[unsafe(no_mangle)]
180pub unsafe extern "C" fn patch_seq_rot(stack: Stack) -> Stack {
181 assert!(!stack.is_null(), "rot: stack is empty");
182 let (rest, c) = unsafe { pop(stack) };
183 assert!(!rest.is_null(), "rot: stack has only one value");
184 let (rest, b) = unsafe { pop(rest) };
185 assert!(!rest.is_null(), "rot: stack has only two values");
186 let (rest, a) = unsafe { pop(rest) };
187 let stack = unsafe { push(rest, b) };
188 let stack = unsafe { push(stack, c) };
189 unsafe { push(stack, a) }
190}
191
192#[unsafe(no_mangle)]
197pub unsafe extern "C" fn patch_seq_nip(stack: Stack) -> Stack {
198 assert!(!stack.is_null(), "nip: stack is empty");
199 let (rest, b) = unsafe { pop(stack) };
200 assert!(!rest.is_null(), "nip: stack has only one value");
201 let (rest, _a) = unsafe { pop(rest) };
202 unsafe { push(rest, b) }
203}
204
205#[unsafe(no_mangle)]
210pub unsafe extern "C" fn patch_seq_tuck(stack: Stack) -> Stack {
211 assert!(!stack.is_null(), "tuck: stack is empty");
212 let (rest, b) = unsafe { pop(stack) };
213 assert!(!rest.is_null(), "tuck: stack has only one value");
214 let (rest, a) = unsafe { pop(rest) };
215 let stack = unsafe { push(rest, b.clone()) };
216 let stack = unsafe { push(stack, a) };
217 unsafe { push(stack, b) }
218}
219
220pub unsafe fn pick(stack: Stack, n: usize) -> Stack {
231 assert!(!stack.is_null(), "pick: stack is empty");
232
233 let mut current = stack;
235 for i in 0..n {
236 assert!(
237 !current.is_null(),
238 "pick: stack has only {} values, need at least {}",
239 i + 1,
240 n + 1
241 );
242 current = unsafe { (*current).next };
243 }
244
245 assert!(
246 !current.is_null(),
247 "pick: stack has only {} values, need at least {}",
248 n,
249 n + 1
250 );
251
252 let value = unsafe { (*current).value.clone() };
254
255 unsafe { push(stack, value) }
257}
258
259#[unsafe(no_mangle)]
291pub unsafe extern "C" fn patch_seq_pick_op(stack: Stack) -> Stack {
292 use crate::value::Value;
293
294 assert!(!stack.is_null(), "pick: stack is empty");
295
296 let depth_value = unsafe { &(*stack).value };
298 let n = match depth_value {
299 Value::Int(i) => {
300 if *i < 0 {
301 panic!("pick: depth must be non-negative, got {}", i);
302 }
303 *i as usize
304 }
305 _ => panic!(
306 "pick: expected Int depth on top of stack, got {:?}",
307 depth_value
308 ),
309 };
310
311 let mut count = 0;
313 let mut current = unsafe { (*stack).next };
314 while !current.is_null() {
315 count += 1;
316 current = unsafe { (*current).next };
317 }
318
319 if count < n + 1 {
324 panic!(
325 "pick: cannot access depth {} - stack has only {} value{} (need at least {})",
326 n,
327 count,
328 if count == 1 { "" } else { "s" },
329 n + 1
330 );
331 }
332
333 let (stack, _) = unsafe { pop(stack) };
335 unsafe { pick(stack, n) }
336}
337
338#[unsafe(no_mangle)]
352pub unsafe extern "C" fn patch_seq_roll(stack: Stack) -> Stack {
353 use crate::value::Value;
354
355 assert!(!stack.is_null(), "roll: stack is empty");
356
357 let depth_value = unsafe { &(*stack).value };
359 let n = match depth_value {
360 Value::Int(i) => {
361 if *i < 0 {
362 panic!("roll: depth must be non-negative, got {}", i);
363 }
364 *i as usize
365 }
366 _ => panic!(
367 "roll: expected Int depth on top of stack, got {:?}",
368 depth_value
369 ),
370 };
371
372 let (stack, _) = unsafe { pop(stack) };
374
375 if n == 0 {
377 return stack;
379 }
380 if n == 1 {
381 return unsafe { patch_seq_swap(stack) };
383 }
384 if n == 2 {
385 return unsafe { patch_seq_rot(stack) };
387 }
388
389 let mut count = 0;
394 let mut current = stack;
395 while !current.is_null() && count <= n {
396 count += 1;
397 current = unsafe { (*current).next };
398 }
399
400 if count < n + 1 {
401 panic!(
402 "roll: cannot rotate {} items - stack has only {} value{}",
403 n + 1,
404 count,
405 if count == 1 { "" } else { "s" }
406 );
407 }
408
409 let mut items = Vec::with_capacity(n + 1);
411 let mut current_stack = stack;
412 for _ in 0..=n {
413 let (rest, val) = unsafe { pop(current_stack) };
414 items.push(val);
415 current_stack = rest;
416 }
417
418 let top_item = items.swap_remove(n);
426
427 for val in items.into_iter().rev() {
430 current_stack = unsafe { push(current_stack, val) };
431 }
432 current_stack = unsafe { push(current_stack, top_item) };
434
435 current_stack
436}
437
438pub unsafe fn clone_stack(stack: Stack) -> Stack {
450 if stack.is_null() {
451 return std::ptr::null_mut();
452 }
453
454 let mut values = Vec::new();
456 let mut current = stack;
457 while !current.is_null() {
458 values.push(unsafe { (*current).value.clone() });
459 current = unsafe { (*current).next };
460 }
461
462 let mut new_stack: Stack = std::ptr::null_mut();
465 for value in values.into_iter().rev() {
466 let node = Box::new(StackNode {
467 value,
468 next: new_stack,
469 });
470 new_stack = Box::into_raw(node);
471 }
472
473 new_stack
474}
475
476pub use patch_seq_drop_op as drop_op;
478pub use patch_seq_dup as dup;
479pub use patch_seq_nip as nip;
480pub use patch_seq_over as over;
481pub use patch_seq_pick_op as pick_op;
482pub use patch_seq_push_value as push_value;
483pub use patch_seq_roll as roll;
484pub use patch_seq_rot as rot;
485pub use patch_seq_swap as swap;
486pub use patch_seq_tuck as tuck;
487
488#[cfg(test)]
489mod tests {
490 use super::*;
491
492 fn make_stack(values: &[i64]) -> Stack {
494 unsafe {
495 let mut stack = std::ptr::null_mut();
496 for &val in values {
497 stack = push(stack, Value::Int(val));
498 }
499 stack
500 }
501 }
502
503 fn drain_stack(mut stack: Stack) -> Vec<Value> {
505 unsafe {
506 let mut values = Vec::new();
507 while !is_empty(stack) {
508 let (rest, val) = pop(stack);
509 stack = rest;
510 values.push(val);
511 }
512 values
513 }
514 }
515
516 fn assert_stack_ints(stack: Stack, expected: &[i64]) {
518 let values = drain_stack(stack);
519 let ints: Vec<i64> = values
520 .into_iter()
521 .map(|v| match v {
522 Value::Int(n) => n,
523 _ => panic!("Expected Int, got {:?}", v),
524 })
525 .collect();
526 assert_eq!(ints, expected);
527 }
528
529 #[test]
530 fn test_push_pop() {
531 unsafe {
532 let stack = std::ptr::null_mut();
533 assert!(is_empty(stack));
534
535 let stack = push(stack, Value::Int(42));
536 assert!(!is_empty(stack));
537
538 let (stack, value) = pop(stack);
539 assert_eq!(value, Value::Int(42));
540 assert!(is_empty(stack));
541 }
542 }
543
544 #[test]
545 fn test_multiple_values() {
546 unsafe {
547 let mut stack = std::ptr::null_mut();
548
549 stack = push(stack, Value::Int(1));
550 stack = push(stack, Value::Int(2));
551 stack = push(stack, Value::Int(3));
552
553 let (stack, val) = pop(stack);
554 assert_eq!(val, Value::Int(3));
555
556 let (stack, val) = pop(stack);
557 assert_eq!(val, Value::Int(2));
558
559 let (stack, val) = pop(stack);
560 assert_eq!(val, Value::Int(1));
561
562 assert!(is_empty(stack));
563 }
564 }
565
566 #[test]
567 fn test_peek() {
568 unsafe {
569 let stack = push(std::ptr::null_mut(), Value::Int(42));
570 let peeked = peek(stack);
571 assert_eq!(*peeked, Value::Int(42));
572
573 let (stack, value) = pop(stack);
575 assert_eq!(value, Value::Int(42));
576 assert!(is_empty(stack));
577 }
578 }
579
580 #[test]
581 fn test_dup() {
582 unsafe {
583 let stack = push(std::ptr::null_mut(), Value::Int(42));
584 let stack = dup(stack);
585
586 let (stack, val1) = pop(stack);
588 assert_eq!(val1, Value::Int(42));
589
590 let (stack, val2) = pop(stack);
591 assert_eq!(val2, Value::Int(42));
592
593 assert!(is_empty(stack));
594 }
595 }
596
597 #[test]
598 fn test_drop() {
599 unsafe {
600 let mut stack = std::ptr::null_mut();
601 stack = push(stack, Value::Int(1));
602 stack = push(stack, Value::Int(2));
603 stack = push(stack, Value::Int(3));
604
605 stack = drop(stack);
607
608 let (stack, val) = pop(stack);
610 assert_eq!(val, Value::Int(2));
611
612 let (stack, val) = pop(stack);
613 assert_eq!(val, Value::Int(1));
614
615 assert!(is_empty(stack));
616 }
617 }
618
619 #[test]
620 fn test_swap() {
621 unsafe {
622 let mut stack = std::ptr::null_mut();
623 stack = push(stack, Value::Int(1));
624 stack = push(stack, Value::Int(2));
625
626 stack = swap(stack);
628
629 let (stack, val) = pop(stack);
630 assert_eq!(val, Value::Int(1));
631
632 let (stack, val) = pop(stack);
633 assert_eq!(val, Value::Int(2));
634
635 assert!(is_empty(stack));
636 }
637 }
638
639 #[test]
640 fn test_composition() {
641 unsafe {
650 let mut stack = make_stack(&[1, 2, 3]);
651
652 stack = swap(stack);
653 stack = drop(stack);
654 stack = dup(stack);
655
656 assert_stack_ints(stack, &[3, 3, 1]);
657 }
658 }
659
660 #[test]
661 fn test_over() {
662 unsafe {
664 let mut stack = std::ptr::null_mut();
665 stack = push(stack, Value::Int(1));
666 stack = push(stack, Value::Int(2));
667
668 stack = over(stack); let (stack, val) = pop(stack);
671 assert_eq!(val, Value::Int(1));
672
673 let (stack, val) = pop(stack);
674 assert_eq!(val, Value::Int(2));
675
676 let (stack, val) = pop(stack);
677 assert_eq!(val, Value::Int(1));
678
679 assert!(is_empty(stack));
680 }
681 }
682
683 #[test]
684 fn test_rot() {
685 unsafe {
687 let mut stack = std::ptr::null_mut();
688 stack = push(stack, Value::Int(1));
689 stack = push(stack, Value::Int(2));
690 stack = push(stack, Value::Int(3));
691
692 stack = rot(stack); let (stack, val) = pop(stack);
695 assert_eq!(val, Value::Int(1));
696
697 let (stack, val) = pop(stack);
698 assert_eq!(val, Value::Int(3));
699
700 let (stack, val) = pop(stack);
701 assert_eq!(val, Value::Int(2));
702
703 assert!(is_empty(stack));
704 }
705 }
706
707 #[test]
708 fn test_nip() {
709 unsafe {
711 let mut stack = std::ptr::null_mut();
712 stack = push(stack, Value::Int(1));
713 stack = push(stack, Value::Int(2));
714
715 stack = nip(stack); let (stack, val) = pop(stack);
718 assert_eq!(val, Value::Int(2));
719
720 assert!(is_empty(stack));
721 }
722 }
723
724 #[test]
725 fn test_tuck() {
726 unsafe {
728 let mut stack = std::ptr::null_mut();
729 stack = push(stack, Value::Int(1));
730 stack = push(stack, Value::Int(2));
731
732 stack = tuck(stack); let (stack, val) = pop(stack);
735 assert_eq!(val, Value::Int(2));
736
737 let (stack, val) = pop(stack);
738 assert_eq!(val, Value::Int(1));
739
740 let (stack, val) = pop(stack);
741 assert_eq!(val, Value::Int(2));
742
743 assert!(is_empty(stack));
744 }
745 }
746
747 #[test]
748 fn test_critical_shuffle_pattern() {
749 unsafe {
763 let mut stack = make_stack(&[1, 2, 3, 4, 5]);
764
765 stack = rot(stack);
769 stack = swap(stack);
775 stack = rot(stack);
781 stack = rot(stack);
787 stack = swap(stack);
793 assert_stack_ints(stack, &[4, 3, 5, 2, 1]);
801 }
802 }
803
804 #[test]
805 fn test_pick_0_is_dup() {
806 unsafe {
808 let mut stack = std::ptr::null_mut();
809 stack = push(stack, Value::Int(42));
810
811 stack = pick(stack, 0);
812
813 let (stack, val) = pop(stack);
814 assert_eq!(val, Value::Int(42));
815
816 let (stack, val) = pop(stack);
817 assert_eq!(val, Value::Int(42));
818
819 assert!(is_empty(stack));
820 }
821 }
822
823 #[test]
824 fn test_pick_1_is_over() {
825 unsafe {
827 let mut stack = std::ptr::null_mut();
828 stack = push(stack, Value::Int(1));
829 stack = push(stack, Value::Int(2));
830
831 stack = pick(stack, 1);
832
833 let (stack, val) = pop(stack);
834 assert_eq!(val, Value::Int(1));
835
836 let (stack, val) = pop(stack);
837 assert_eq!(val, Value::Int(2));
838
839 let (stack, val) = pop(stack);
840 assert_eq!(val, Value::Int(1));
841
842 assert!(is_empty(stack));
843 }
844 }
845
846 #[test]
847 fn test_pick_deep() {
848 unsafe {
850 let mut stack = std::ptr::null_mut();
851 stack = push(stack, Value::Int(1));
852 stack = push(stack, Value::Int(2));
853 stack = push(stack, Value::Int(3));
854 stack = push(stack, Value::Int(4));
855 stack = push(stack, Value::Int(5));
856
857 stack = pick(stack, 3); let (stack, val) = pop(stack);
863 assert_eq!(val, Value::Int(2));
864
865 let (stack, val) = pop(stack);
866 assert_eq!(val, Value::Int(5));
867
868 let (stack, val) = pop(stack);
869 assert_eq!(val, Value::Int(4));
870
871 let (stack, val) = pop(stack);
872 assert_eq!(val, Value::Int(3));
873
874 let (stack, val) = pop(stack);
875 assert_eq!(val, Value::Int(2));
876
877 let (stack, val) = pop(stack);
878 assert_eq!(val, Value::Int(1));
879
880 assert!(is_empty(stack));
881 }
882 }
883
884 #[test]
885 fn test_multifield_variant_survives_shuffle() {
886 use crate::value::VariantData;
890
891 unsafe {
892 let nil = Value::Variant(Box::new(VariantData::new(0, vec![])));
895 let cons = Value::Variant(Box::new(VariantData::new(
896 1,
897 vec![Value::Int(42), nil.clone()],
898 )));
899
900 let mut stack = std::ptr::null_mut();
902 stack = push(stack, Value::Int(100)); stack = push(stack, Value::Int(200)); stack = push(stack, cons.clone()); stack = push(stack, Value::Int(300)); stack = push(stack, Value::Int(400)); stack = rot(stack); stack = swap(stack); stack = rot(stack); stack = rot(stack); stack = swap(stack); let mut found_variant = None;
917 while !is_empty(stack) {
918 let (rest, val) = pop(stack);
919 stack = rest;
920 if matches!(val, Value::Variant(_)) {
921 found_variant = Some(val);
922 }
923 }
924
925 assert!(found_variant.is_some(), "Variant was lost during shuffle!");
927
928 if let Some(Value::Variant(variant_data)) = found_variant {
929 assert_eq!(variant_data.tag, 1, "Variant tag corrupted!");
930 assert_eq!(
931 variant_data.fields.len(),
932 2,
933 "Variant field count corrupted!"
934 );
935 assert_eq!(
936 variant_data.fields[0],
937 Value::Int(42),
938 "First field corrupted!"
939 );
940
941 if let Value::Variant(nil_data) = &variant_data.fields[1] {
943 assert_eq!(nil_data.tag, 0, "Nested variant tag corrupted!");
944 assert_eq!(nil_data.fields.len(), 0, "Nested variant should be empty!");
945 } else {
946 panic!("Second field should be a Variant!");
947 }
948 }
949 }
950 }
951
952 #[test]
953 fn test_arbitrary_depth_operations() {
954 unsafe {
957 let mut stack = std::ptr::null_mut();
958
959 for i in 0..100 {
961 stack = push(stack, Value::Int(i));
962 }
963
964 stack = dup(stack); stack = swap(stack); stack = over(stack); stack = rot(stack); stack = drop(stack); stack = pick(stack, 50); let mut count = 0;
976 while !is_empty(stack) {
977 let (rest, _val) = pop(stack);
978 stack = rest;
979 count += 1;
980 }
981
982 assert_eq!(count, 102);
984 }
985 }
986
987 #[test]
988 fn test_operation_composition_completeness() {
989 unsafe {
992 let mut stack = std::ptr::null_mut();
993
994 for i in 1..=10 {
996 stack = push(stack, Value::Int(i));
997 }
998
999 stack = dup(stack); stack = over(stack); stack = rot(stack); stack = swap(stack); stack = nip(stack); stack = tuck(stack); stack = pick(stack, 5); stack = drop(stack); let mut depth = 0;
1013 let mut current = stack;
1014 while !current.is_null() {
1015 depth += 1;
1016 current = (*current).next;
1017 }
1018
1019 assert!(depth > 0, "Stack should not be empty after operations");
1020 }
1021 }
1022
1023 #[test]
1024 fn test_pick_at_arbitrary_depths() {
1025 unsafe {
1028 let mut stack = std::ptr::null_mut();
1029
1030 for i in 0..50 {
1032 stack = push(stack, Value::Int(i * 10));
1033 }
1034
1035 stack = pick(stack, 0); let (mut stack, val) = pop(stack);
1041 assert_eq!(val, Value::Int(490));
1042
1043 stack = pick(stack, 10); let (mut stack, val) = pop(stack);
1045 assert_eq!(val, Value::Int(390)); stack = pick(stack, 40); let (stack, val) = pop(stack);
1049 assert_eq!(val, Value::Int(90)); let mut count = 0;
1053 let mut current = stack;
1054 while !current.is_null() {
1055 count += 1;
1056 current = (*current).next;
1057 }
1058
1059 assert_eq!(count, 50, "Stack depth should be unchanged");
1060 }
1061 }
1062
1063 #[test]
1064 fn test_pick_op_equivalence_to_dup() {
1065 unsafe {
1067 let mut stack = std::ptr::null_mut();
1068 stack = push(stack, Value::Int(42));
1069 stack = push(stack, Value::Int(0)); stack = pick_op(stack);
1072
1073 let (stack, val1) = pop(stack);
1075 assert_eq!(val1, Value::Int(42));
1076 let (stack, val2) = pop(stack);
1077 assert_eq!(val2, Value::Int(42));
1078 assert!(stack.is_null());
1079 }
1080 }
1081
1082 #[test]
1083 fn test_pick_op_equivalence_to_over() {
1084 unsafe {
1086 let mut stack = std::ptr::null_mut();
1087 stack = push(stack, Value::Int(10));
1088 stack = push(stack, Value::Int(20));
1089 stack = push(stack, Value::Int(1)); stack = pick_op(stack);
1092
1093 let (stack, val1) = pop(stack);
1095 assert_eq!(val1, Value::Int(10));
1096 let (stack, val2) = pop(stack);
1097 assert_eq!(val2, Value::Int(20));
1098 let (stack, val3) = pop(stack);
1099 assert_eq!(val3, Value::Int(10));
1100 assert!(stack.is_null());
1101 }
1102 }
1103
1104 #[test]
1105 fn test_pick_op_deep_access() {
1106 unsafe {
1108 let mut stack = std::ptr::null_mut();
1109 for i in 0..10 {
1110 stack = push(stack, Value::Int(i));
1111 }
1112 stack = push(stack, Value::Int(5)); stack = pick_op(stack);
1115
1116 let (stack, val) = pop(stack);
1118 assert_eq!(val, Value::Int(4));
1119
1120 let mut count = 0;
1122 let mut current = stack;
1123 while !current.is_null() {
1124 count += 1;
1125 current = (*current).next;
1126 }
1127 assert_eq!(count, 10);
1128 }
1129 }
1130
1131 #[test]
1137 fn test_roll_0_is_noop() {
1138 unsafe {
1140 let mut stack = std::ptr::null_mut();
1141 stack = push(stack, Value::Int(42));
1142 stack = push(stack, Value::Int(0)); stack = roll(stack);
1145
1146 let (stack, val) = pop(stack);
1147 assert_eq!(val, Value::Int(42));
1148 assert!(stack.is_null());
1149 }
1150 }
1151
1152 #[test]
1153 fn test_roll_1_is_swap() {
1154 unsafe {
1156 let mut stack = std::ptr::null_mut();
1157 stack = push(stack, Value::Int(1));
1158 stack = push(stack, Value::Int(2));
1159 stack = push(stack, Value::Int(1)); stack = roll(stack);
1162
1163 let (stack, val1) = pop(stack);
1165 assert_eq!(val1, Value::Int(1));
1166 let (stack, val2) = pop(stack);
1167 assert_eq!(val2, Value::Int(2));
1168 assert!(stack.is_null());
1169 }
1170 }
1171
1172 #[test]
1173 fn test_roll_2_is_rot() {
1174 unsafe {
1176 let mut stack = std::ptr::null_mut();
1177 stack = push(stack, Value::Int(1));
1178 stack = push(stack, Value::Int(2));
1179 stack = push(stack, Value::Int(3));
1180 stack = push(stack, Value::Int(2)); stack = roll(stack);
1183
1184 let (stack, val1) = pop(stack);
1186 assert_eq!(val1, Value::Int(1));
1187 let (stack, val2) = pop(stack);
1188 assert_eq!(val2, Value::Int(3));
1189 let (stack, val3) = pop(stack);
1190 assert_eq!(val3, Value::Int(2));
1191 assert!(stack.is_null());
1192 }
1193 }
1194
1195 #[test]
1196 fn test_roll_3_rotates_4_items() {
1197 unsafe {
1199 let mut stack = std::ptr::null_mut();
1200 stack = push(stack, Value::Int(1)); stack = push(stack, Value::Int(2));
1202 stack = push(stack, Value::Int(3));
1203 stack = push(stack, Value::Int(4)); stack = push(stack, Value::Int(3)); stack = roll(stack);
1207
1208 let (stack, val1) = pop(stack);
1210 assert_eq!(val1, Value::Int(1)); let (stack, val2) = pop(stack);
1212 assert_eq!(val2, Value::Int(4));
1213 let (stack, val3) = pop(stack);
1214 assert_eq!(val3, Value::Int(3));
1215 let (stack, val4) = pop(stack);
1216 assert_eq!(val4, Value::Int(2));
1217 assert!(stack.is_null());
1218 }
1219 }
1220
1221 #[test]
1222 fn test_roll_deep() {
1223 unsafe {
1225 let mut stack = std::ptr::null_mut();
1226 for i in 0..10 {
1227 stack = push(stack, Value::Int(i));
1228 }
1229 stack = push(stack, Value::Int(5)); stack = roll(stack);
1233
1234 let (stack, val) = pop(stack);
1237 assert_eq!(val, Value::Int(4)); let (stack, val) = pop(stack);
1241 assert_eq!(val, Value::Int(9));
1242 let (stack, val) = pop(stack);
1243 assert_eq!(val, Value::Int(8));
1244 let (stack, val) = pop(stack);
1245 assert_eq!(val, Value::Int(7));
1246 let (stack, val) = pop(stack);
1247 assert_eq!(val, Value::Int(6));
1248 let (stack, val) = pop(stack);
1249 assert_eq!(val, Value::Int(5));
1250 let (stack, val) = pop(stack);
1252 assert_eq!(val, Value::Int(3));
1253 let (stack, val) = pop(stack);
1254 assert_eq!(val, Value::Int(2));
1255 let (stack, val) = pop(stack);
1256 assert_eq!(val, Value::Int(1));
1257 let (stack, val) = pop(stack);
1258 assert_eq!(val, Value::Int(0));
1259 assert!(stack.is_null());
1260 }
1261 }
1262
1263 #[test]
1264 fn test_roll_with_extra_stack() {
1265 unsafe {
1267 let mut stack = std::ptr::null_mut();
1268 stack = push(stack, Value::Int(100)); stack = push(stack, Value::Int(1));
1270 stack = push(stack, Value::Int(2));
1271 stack = push(stack, Value::Int(3));
1272 stack = push(stack, Value::Int(4));
1273 stack = push(stack, Value::Int(3)); stack = roll(stack);
1276
1277 let (stack, val1) = pop(stack);
1279 assert_eq!(val1, Value::Int(1));
1280 let (stack, val2) = pop(stack);
1281 assert_eq!(val2, Value::Int(4));
1282 let (stack, val3) = pop(stack);
1283 assert_eq!(val3, Value::Int(3));
1284 let (stack, val4) = pop(stack);
1285 assert_eq!(val4, Value::Int(2));
1286 let (stack, val5) = pop(stack);
1287 assert_eq!(val5, Value::Int(100)); assert!(stack.is_null());
1289 }
1290 }
1291
1292 #[test]
1293 fn test_operations_preserve_stack_integrity() {
1294 unsafe {
1297 let mut stack = std::ptr::null_mut();
1298
1299 for i in 0..20 {
1300 stack = push(stack, Value::Int(i));
1301 }
1302
1303 stack = swap(stack);
1305 stack = rot(stack);
1306 stack = swap(stack);
1307 stack = rot(stack);
1308 stack = over(stack);
1309 stack = tuck(stack);
1310
1311 let mut visited = std::collections::HashSet::new();
1315 let mut current = stack;
1316 let mut count = 0;
1317
1318 while !current.is_null() {
1319 assert!(
1321 visited.insert(current as usize),
1322 "Detected cycle in stack - next pointer corruption!"
1323 );
1324
1325 count += 1;
1326 current = (*current).next;
1327
1328 assert!(
1330 count < 1000,
1331 "Stack walk exceeded reasonable depth - likely corrupted"
1332 );
1333 }
1334
1335 assert!(count > 0, "Stack should have elements");
1336 }
1337 }
1338
1339 #[test]
1340 fn test_nested_variants_with_deep_stacks() {
1341 use crate::value::VariantData;
1344
1345 unsafe {
1346 let nil = Value::Variant(Box::new(VariantData::new(0, vec![])));
1348 let cons3 = Value::Variant(Box::new(VariantData::new(1, vec![Value::Int(3), nil])));
1349 let cons2 = Value::Variant(Box::new(VariantData::new(1, vec![Value::Int(2), cons3])));
1350 let cons1 = Value::Variant(Box::new(VariantData::new(1, vec![Value::Int(1), cons2])));
1351
1352 let mut stack = std::ptr::null_mut();
1354 for i in 0..30 {
1355 stack = push(stack, Value::Int(i));
1356 }
1357 stack = push(stack, cons1.clone());
1358 for i in 30..60 {
1359 stack = push(stack, Value::Int(i));
1360 }
1361
1362 for _ in 0..10 {
1364 stack = rot(stack);
1365 stack = swap(stack);
1366 stack = over(stack);
1367 stack = drop(stack);
1368 }
1369
1370 let mut found_variant = None;
1372 while !is_empty(stack) {
1373 let (rest, val) = pop(stack);
1374 stack = rest;
1375 if let Value::Variant(ref vdata) = val
1376 && vdata.tag == 1
1377 && vdata.fields.len() == 2
1378 && let Value::Int(1) = vdata.fields[0]
1379 {
1380 found_variant = Some(val);
1381 break;
1382 }
1383 }
1384
1385 assert!(
1386 found_variant.is_some(),
1387 "Nested variant lost during deep stack operations"
1388 );
1389 }
1390 }
1391}