1use crate::stack::{Stack, peek, pop, pop_two, push};
25use crate::value::Value;
26
27#[unsafe(no_mangle)]
34pub unsafe extern "C" fn patch_seq_push_int(stack: Stack, value: i64) -> Stack {
35 unsafe { push(stack, Value::Int(value)) }
36}
37
38#[unsafe(no_mangle)]
45pub unsafe extern "C" fn patch_seq_push_bool(stack: Stack, value: bool) -> Stack {
46 unsafe { push(stack, Value::Bool(value)) }
47}
48
49#[unsafe(no_mangle)]
56pub unsafe extern "C" fn patch_seq_add(stack: Stack) -> Stack {
57 let (rest, a, b) = unsafe { pop_two(stack, "add") };
58 match (a, b) {
59 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
60 push(rest, Value::Int(a_val.wrapping_add(b_val)))
61 },
62 _ => panic!("add: expected two integers on stack"),
63 }
64}
65
66#[unsafe(no_mangle)]
73pub unsafe extern "C" fn patch_seq_subtract(stack: Stack) -> Stack {
74 let (rest, a, b) = unsafe { pop_two(stack, "subtract") };
75 match (a, b) {
76 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
77 push(rest, Value::Int(a_val.wrapping_sub(b_val)))
78 },
79 _ => panic!("subtract: expected two integers on stack"),
80 }
81}
82
83#[unsafe(no_mangle)]
90pub unsafe extern "C" fn patch_seq_multiply(stack: Stack) -> Stack {
91 let (rest, a, b) = unsafe { pop_two(stack, "multiply") };
92 match (a, b) {
93 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
94 push(rest, Value::Int(a_val.wrapping_mul(b_val)))
95 },
96 _ => panic!("multiply: expected two integers on stack"),
97 }
98}
99
100#[unsafe(no_mangle)]
111pub unsafe extern "C" fn patch_seq_divide(stack: Stack) -> Stack {
112 let (rest, a, b) = unsafe { pop_two(stack, "divide") };
113 match (a, b) {
114 (Value::Int(_a_val), Value::Int(0)) => {
115 let stack = unsafe { push(rest, Value::Int(0)) };
117 unsafe { push(stack, Value::Bool(false)) }
118 }
119 (Value::Int(a_val), Value::Int(b_val)) => {
120 let stack = unsafe { push(rest, Value::Int(a_val.wrapping_div(b_val))) };
122 unsafe { push(stack, Value::Bool(true)) }
123 }
124 _ => {
125 panic!("divide: expected two integers on stack");
127 }
128 }
129}
130
131#[unsafe(no_mangle)]
142pub unsafe extern "C" fn patch_seq_modulo(stack: Stack) -> Stack {
143 let (rest, a, b) = unsafe { pop_two(stack, "modulo") };
144 match (a, b) {
145 (Value::Int(_a_val), Value::Int(0)) => {
146 let stack = unsafe { push(rest, Value::Int(0)) };
148 unsafe { push(stack, Value::Bool(false)) }
149 }
150 (Value::Int(a_val), Value::Int(b_val)) => {
151 let stack = unsafe { push(rest, Value::Int(a_val.wrapping_rem(b_val))) };
153 unsafe { push(stack, Value::Bool(true)) }
154 }
155 _ => {
156 panic!("modulo: expected two integers on stack");
158 }
159 }
160}
161
162#[unsafe(no_mangle)]
170pub unsafe extern "C" fn patch_seq_eq(stack: Stack) -> Stack {
171 let (rest, a, b) = unsafe { pop_two(stack, "=") };
172 match (a, b) {
173 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
174 push(rest, Value::Bool(a_val == b_val))
175 },
176 _ => panic!("=: expected two integers on stack"),
177 }
178}
179
180#[unsafe(no_mangle)]
188pub unsafe extern "C" fn patch_seq_lt(stack: Stack) -> Stack {
189 let (rest, a, b) = unsafe { pop_two(stack, "<") };
190 match (a, b) {
191 (Value::Int(a_val), Value::Int(b_val)) => unsafe { push(rest, Value::Bool(a_val < b_val)) },
192 _ => panic!("<: expected two integers on stack"),
193 }
194}
195
196#[unsafe(no_mangle)]
204pub unsafe extern "C" fn patch_seq_gt(stack: Stack) -> Stack {
205 let (rest, a, b) = unsafe { pop_two(stack, ">") };
206 match (a, b) {
207 (Value::Int(a_val), Value::Int(b_val)) => unsafe { push(rest, Value::Bool(a_val > b_val)) },
208 _ => panic!(">: expected two integers on stack"),
209 }
210}
211
212#[unsafe(no_mangle)]
220pub unsafe extern "C" fn patch_seq_lte(stack: Stack) -> Stack {
221 let (rest, a, b) = unsafe { pop_two(stack, "<=") };
222 match (a, b) {
223 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
224 push(rest, Value::Bool(a_val <= b_val))
225 },
226 _ => panic!("<=: expected two integers on stack"),
227 }
228}
229
230#[unsafe(no_mangle)]
238pub unsafe extern "C" fn patch_seq_gte(stack: Stack) -> Stack {
239 let (rest, a, b) = unsafe { pop_two(stack, ">=") };
240 match (a, b) {
241 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
242 push(rest, Value::Bool(a_val >= b_val))
243 },
244 _ => panic!(">=: expected two integers on stack"),
245 }
246}
247
248#[unsafe(no_mangle)]
256pub unsafe extern "C" fn patch_seq_neq(stack: Stack) -> Stack {
257 let (rest, a, b) = unsafe { pop_two(stack, "<>") };
258 match (a, b) {
259 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
260 push(rest, Value::Bool(a_val != b_val))
261 },
262 _ => panic!("<>: expected two integers on stack"),
263 }
264}
265
266#[unsafe(no_mangle)]
275pub unsafe extern "C" fn patch_seq_and(stack: Stack) -> Stack {
276 let (rest, a, b) = unsafe { pop_two(stack, "and") };
277 match (a, b) {
278 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
279 push(
280 rest,
281 Value::Int(if a_val != 0 && b_val != 0 { 1 } else { 0 }),
282 )
283 },
284 _ => panic!("and: expected two integers on stack"),
285 }
286}
287
288#[unsafe(no_mangle)]
297pub unsafe extern "C" fn patch_seq_or(stack: Stack) -> Stack {
298 let (rest, a, b) = unsafe { pop_two(stack, "or") };
299 match (a, b) {
300 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
301 push(
302 rest,
303 Value::Int(if a_val != 0 || b_val != 0 { 1 } else { 0 }),
304 )
305 },
306 _ => panic!("or: expected two integers on stack"),
307 }
308}
309
310#[unsafe(no_mangle)]
319pub unsafe extern "C" fn patch_seq_not(stack: Stack) -> Stack {
320 assert!(!stack.is_null(), "not: stack is empty");
321 let (rest, a) = unsafe { pop(stack) };
322
323 match a {
324 Value::Int(a_val) => unsafe { push(rest, Value::Int(if a_val == 0 { 1 } else { 0 })) },
325 _ => panic!("not: expected integer on stack"),
326 }
327}
328
329#[unsafe(no_mangle)]
340pub unsafe extern "C" fn patch_seq_band(stack: Stack) -> Stack {
341 let (rest, a, b) = unsafe { pop_two(stack, "band") };
342 match (a, b) {
343 (Value::Int(a_val), Value::Int(b_val)) => unsafe { push(rest, Value::Int(a_val & b_val)) },
344 _ => panic!("band: expected two integers on stack"),
345 }
346}
347
348#[unsafe(no_mangle)]
355pub unsafe extern "C" fn patch_seq_bor(stack: Stack) -> Stack {
356 let (rest, a, b) = unsafe { pop_two(stack, "bor") };
357 match (a, b) {
358 (Value::Int(a_val), Value::Int(b_val)) => unsafe { push(rest, Value::Int(a_val | b_val)) },
359 _ => panic!("bor: expected two integers on stack"),
360 }
361}
362
363#[unsafe(no_mangle)]
370pub unsafe extern "C" fn patch_seq_bxor(stack: Stack) -> Stack {
371 let (rest, a, b) = unsafe { pop_two(stack, "bxor") };
372 match (a, b) {
373 (Value::Int(a_val), Value::Int(b_val)) => unsafe { push(rest, Value::Int(a_val ^ b_val)) },
374 _ => panic!("bxor: expected two integers on stack"),
375 }
376}
377
378#[unsafe(no_mangle)]
385pub unsafe extern "C" fn patch_seq_bnot(stack: Stack) -> Stack {
386 assert!(!stack.is_null(), "bnot: stack is empty");
387 let (rest, a) = unsafe { pop(stack) };
388 match a {
389 Value::Int(a_val) => unsafe { push(rest, Value::Int(!a_val)) },
390 _ => panic!("bnot: expected integer on stack"),
391 }
392}
393
394#[unsafe(no_mangle)]
402pub unsafe extern "C" fn patch_seq_shl(stack: Stack) -> Stack {
403 let (rest, value, count) = unsafe { pop_two(stack, "shl") };
404 match (value, count) {
405 (Value::Int(v), Value::Int(c)) => {
406 let result = if c < 0 {
409 0
410 } else {
411 v.checked_shl(c as u32).unwrap_or(0)
412 };
413 unsafe { push(rest, Value::Int(result)) }
414 }
415 _ => panic!("shl: expected two integers on stack"),
416 }
417}
418
419#[unsafe(no_mangle)]
428pub unsafe extern "C" fn patch_seq_shr(stack: Stack) -> Stack {
429 let (rest, value, count) = unsafe { pop_two(stack, "shr") };
430 match (value, count) {
431 (Value::Int(v), Value::Int(c)) => {
432 let result = if c < 0 {
435 0
436 } else {
437 (v as u64).checked_shr(c as u32).unwrap_or(0) as i64
438 };
439 unsafe { push(rest, Value::Int(result)) }
440 }
441 _ => panic!("shr: expected two integers on stack"),
442 }
443}
444
445#[unsafe(no_mangle)]
452pub unsafe extern "C" fn patch_seq_popcount(stack: Stack) -> Stack {
453 assert!(!stack.is_null(), "popcount: stack is empty");
454 let (rest, a) = unsafe { pop(stack) };
455 match a {
456 Value::Int(v) => unsafe { push(rest, Value::Int(v.count_ones() as i64)) },
457 _ => panic!("popcount: expected integer on stack"),
458 }
459}
460
461#[unsafe(no_mangle)]
468pub unsafe extern "C" fn patch_seq_clz(stack: Stack) -> Stack {
469 assert!(!stack.is_null(), "clz: stack is empty");
470 let (rest, a) = unsafe { pop(stack) };
471 match a {
472 Value::Int(v) => unsafe { push(rest, Value::Int(v.leading_zeros() as i64)) },
473 _ => panic!("clz: expected integer on stack"),
474 }
475}
476
477#[unsafe(no_mangle)]
484pub unsafe extern "C" fn patch_seq_ctz(stack: Stack) -> Stack {
485 assert!(!stack.is_null(), "ctz: stack is empty");
486 let (rest, a) = unsafe { pop(stack) };
487 match a {
488 Value::Int(v) => unsafe { push(rest, Value::Int(v.trailing_zeros() as i64)) },
489 _ => panic!("ctz: expected integer on stack"),
490 }
491}
492
493#[unsafe(no_mangle)]
500pub unsafe extern "C" fn patch_seq_int_bits(stack: Stack) -> Stack {
501 unsafe { push(stack, Value::Int(64)) }
502}
503
504#[unsafe(no_mangle)]
524pub unsafe extern "C" fn patch_seq_peek_int_value(stack: Stack) -> i64 {
525 assert!(!stack.is_null(), "peek_int_value: stack is empty");
526
527 let val = unsafe { peek(stack) };
529 match val {
530 Value::Int(i) => i,
531 other => panic!("peek_int_value: expected Int on stack, got {:?}", other),
532 }
533}
534
535#[unsafe(no_mangle)]
540pub unsafe extern "C" fn patch_seq_peek_bool_value(stack: Stack) -> bool {
541 assert!(!stack.is_null(), "peek_bool_value: stack is empty");
542
543 let val = unsafe { peek(stack) };
544 match val {
545 Value::Bool(b) => b,
546 other => panic!("peek_bool_value: expected Bool on stack, got {:?}", other),
547 }
548}
549
550#[unsafe(no_mangle)]
560pub unsafe extern "C" fn patch_seq_pop_stack(stack: Stack) -> Stack {
561 assert!(!stack.is_null(), "pop_stack: stack is empty");
562 let (rest, _value) = unsafe { pop(stack) };
563 rest
564}
565
566pub use patch_seq_add as add;
568pub use patch_seq_and as and;
569pub use patch_seq_band as band;
570pub use patch_seq_bnot as bnot;
571pub use patch_seq_bor as bor;
572pub use patch_seq_bxor as bxor;
573pub use patch_seq_clz as clz;
574pub use patch_seq_ctz as ctz;
575pub use patch_seq_divide as divide;
576pub use patch_seq_eq as eq;
577pub use patch_seq_gt as gt;
578pub use patch_seq_gte as gte;
579pub use patch_seq_int_bits as int_bits;
580pub use patch_seq_lt as lt;
581pub use patch_seq_lte as lte;
582pub use patch_seq_multiply as multiply;
583pub use patch_seq_neq as neq;
584pub use patch_seq_not as not;
585pub use patch_seq_or as or;
586pub use patch_seq_popcount as popcount;
587pub use patch_seq_push_bool as push_bool;
588pub use patch_seq_push_int as push_int;
589pub use patch_seq_shl as shl;
590pub use patch_seq_shr as shr;
591pub use patch_seq_subtract as subtract;
592
593#[cfg(test)]
594mod tests {
595 use super::*;
596
597 #[test]
598 fn test_add() {
599 unsafe {
600 let stack = crate::stack::alloc_test_stack();
601 let stack = push_int(stack, 5);
602 let stack = push_int(stack, 3);
603 let stack = add(stack);
604
605 let (_stack, result) = pop(stack);
606 assert_eq!(result, Value::Int(8));
607 }
608 }
609
610 #[test]
611 fn test_subtract() {
612 unsafe {
613 let stack = crate::stack::alloc_test_stack();
614 let stack = push_int(stack, 10);
615 let stack = push_int(stack, 3);
616 let stack = subtract(stack);
617
618 let (_stack, result) = pop(stack);
619 assert_eq!(result, Value::Int(7));
620 }
621 }
622
623 #[test]
624 fn test_multiply() {
625 unsafe {
626 let stack = crate::stack::alloc_test_stack();
627 let stack = push_int(stack, 4);
628 let stack = push_int(stack, 5);
629 let stack = multiply(stack);
630
631 let (_stack, result) = pop(stack);
632 assert_eq!(result, Value::Int(20));
633 }
634 }
635
636 #[test]
637 fn test_divide() {
638 unsafe {
639 let stack = crate::stack::alloc_test_stack();
640 let stack = push_int(stack, 20);
641 let stack = push_int(stack, 4);
642 let stack = divide(stack);
643
644 let (stack, success) = pop(stack);
646 assert_eq!(success, Value::Bool(true));
647 let (_stack, result) = pop(stack);
648 assert_eq!(result, Value::Int(5));
649 }
650 }
651
652 #[test]
653 fn test_comparisons() {
654 unsafe {
655 let stack = crate::stack::alloc_test_stack();
657 let stack = push_int(stack, 5);
658 let stack = push_int(stack, 5);
659 let stack = eq(stack);
660 let (_stack, result) = pop(stack);
661 assert_eq!(result, Value::Bool(true));
662
663 let stack = push_int(stack, 3);
665 let stack = push_int(stack, 5);
666 let stack = lt(stack);
667 let (_stack, result) = pop(stack);
668 assert_eq!(result, Value::Bool(true));
669
670 let stack = push_int(stack, 7);
672 let stack = push_int(stack, 5);
673 let stack = gt(stack);
674 let (_stack, result) = pop(stack);
675 assert_eq!(result, Value::Bool(true));
676 }
677 }
678
679 #[cfg(not(feature = "tagged-ptr"))]
681 #[test]
682 fn test_overflow_wrapping() {
683 unsafe {
685 let stack = crate::stack::alloc_test_stack();
687 let stack = push_int(stack, i64::MAX);
688 let stack = push_int(stack, 1);
689 let stack = add(stack);
690 let (_stack, result) = pop(stack);
691 assert_eq!(result, Value::Int(i64::MIN)); let stack = push_int(stack, i64::MAX);
695 let stack = push_int(stack, 2);
696 let stack = multiply(stack);
697 let (_stack, result) = pop(stack);
698 assert!(matches!(result, Value::Int(_)));
700
701 let stack = push_int(stack, i64::MIN);
703 let stack = push_int(stack, 1);
704 let stack = subtract(stack);
705 let (_stack, result) = pop(stack);
706 assert_eq!(result, Value::Int(i64::MAX)); }
708 }
709
710 #[test]
711 fn test_negative_division() {
712 unsafe {
713 let stack = crate::stack::alloc_test_stack();
715 let stack = push_int(stack, -10);
716 let stack = push_int(stack, 3);
717 let stack = divide(stack);
718 let (stack, success) = pop(stack);
719 assert_eq!(success, Value::Bool(true));
720 let (_stack, result) = pop(stack);
721 assert_eq!(result, Value::Int(-3)); let stack = push_int(stack, 10);
725 let stack = push_int(stack, -3);
726 let stack = divide(stack);
727 let (stack, success) = pop(stack);
728 assert_eq!(success, Value::Bool(true));
729 let (_stack, result) = pop(stack);
730 assert_eq!(result, Value::Int(-3));
731
732 let stack = push_int(stack, -10);
734 let stack = push_int(stack, -3);
735 let stack = divide(stack);
736 let (stack, success) = pop(stack);
737 assert_eq!(success, Value::Bool(true));
738 let (_stack, result) = pop(stack);
739 assert_eq!(result, Value::Int(3));
740 }
741 }
742
743 #[cfg(not(feature = "tagged-ptr"))]
745 #[test]
746 fn test_division_overflow_edge_case() {
747 unsafe {
750 let stack = crate::stack::alloc_test_stack();
751 let stack = push_int(stack, i64::MIN);
752 let stack = push_int(stack, -1);
753 let stack = divide(stack);
754 let (stack, success) = pop(stack);
755 assert_eq!(success, Value::Bool(true));
756 let (_stack, result) = pop(stack);
757 assert_eq!(result, Value::Int(i64::MIN));
759 }
760 }
761
762 #[test]
763 fn test_and_true_true() {
764 unsafe {
765 let stack = crate::stack::alloc_test_stack();
766 let stack = push_int(stack, 1);
767 let stack = push_int(stack, 1);
768 let stack = and(stack);
769 let (_stack, result) = pop(stack);
770 assert_eq!(result, Value::Int(1));
771 }
772 }
773
774 #[test]
775 fn test_and_true_false() {
776 unsafe {
777 let stack = crate::stack::alloc_test_stack();
778 let stack = push_int(stack, 1);
779 let stack = push_int(stack, 0);
780 let stack = and(stack);
781 let (_stack, result) = pop(stack);
782 assert_eq!(result, Value::Int(0));
783 }
784 }
785
786 #[test]
787 fn test_and_false_false() {
788 unsafe {
789 let stack = crate::stack::alloc_test_stack();
790 let stack = push_int(stack, 0);
791 let stack = push_int(stack, 0);
792 let stack = and(stack);
793 let (_stack, result) = pop(stack);
794 assert_eq!(result, Value::Int(0));
795 }
796 }
797
798 #[test]
799 fn test_or_true_true() {
800 unsafe {
801 let stack = crate::stack::alloc_test_stack();
802 let stack = push_int(stack, 1);
803 let stack = push_int(stack, 1);
804 let stack = or(stack);
805 let (_stack, result) = pop(stack);
806 assert_eq!(result, Value::Int(1));
807 }
808 }
809
810 #[test]
811 fn test_or_true_false() {
812 unsafe {
813 let stack = crate::stack::alloc_test_stack();
814 let stack = push_int(stack, 1);
815 let stack = push_int(stack, 0);
816 let stack = or(stack);
817 let (_stack, result) = pop(stack);
818 assert_eq!(result, Value::Int(1));
819 }
820 }
821
822 #[test]
823 fn test_or_false_false() {
824 unsafe {
825 let stack = crate::stack::alloc_test_stack();
826 let stack = push_int(stack, 0);
827 let stack = push_int(stack, 0);
828 let stack = or(stack);
829 let (_stack, result) = pop(stack);
830 assert_eq!(result, Value::Int(0));
831 }
832 }
833
834 #[test]
835 fn test_not_true() {
836 unsafe {
837 let stack = crate::stack::alloc_test_stack();
838 let stack = push_int(stack, 1);
839 let stack = not(stack);
840 let (_stack, result) = pop(stack);
841 assert_eq!(result, Value::Int(0));
842 }
843 }
844
845 #[test]
846 fn test_not_false() {
847 unsafe {
848 let stack = crate::stack::alloc_test_stack();
849 let stack = push_int(stack, 0);
850 let stack = not(stack);
851 let (_stack, result) = pop(stack);
852 assert_eq!(result, Value::Int(1));
853 }
854 }
855
856 #[test]
857 fn test_and_nonzero_values() {
858 unsafe {
860 let stack = crate::stack::alloc_test_stack();
861 let stack = push_int(stack, 42);
862 let stack = push_int(stack, -5);
863 let stack = and(stack);
864 let (_stack, result) = pop(stack);
865 assert_eq!(result, Value::Int(1));
866 }
867 }
868
869 #[test]
870 fn test_divide_by_zero_returns_false() {
871 unsafe {
872 let stack = crate::stack::alloc_test_stack();
873 let stack = push_int(stack, 42);
874 let stack = push_int(stack, 0);
875 let stack = divide(stack);
876
877 let (stack, success) = pop(stack);
879 assert_eq!(success, Value::Bool(false));
880
881 let (_stack, result) = pop(stack);
883 assert_eq!(result, Value::Int(0));
884 }
885 }
886}