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 #[test]
680 fn test_63bit_overflow_wrapping() {
681 unsafe {
686 let int63_max = (1i64 << 62) - 1; let stack = crate::stack::alloc_test_stack();
690 let stack = push(stack, Value::Int(int63_max));
691 let stack = push(stack, Value::Int(1));
692 let stack = add(stack);
693 let (_stack, result) = pop(stack);
694 assert!(matches!(result, Value::Int(_)));
696 }
697 }
698
699 #[test]
700 fn test_negative_division() {
701 unsafe {
702 let stack = crate::stack::alloc_test_stack();
704 let stack = push_int(stack, -10);
705 let stack = push_int(stack, 3);
706 let stack = divide(stack);
707 let (stack, success) = pop(stack);
708 assert_eq!(success, Value::Bool(true));
709 let (_stack, result) = pop(stack);
710 assert_eq!(result, Value::Int(-3)); let stack = push_int(stack, 10);
714 let stack = push_int(stack, -3);
715 let stack = divide(stack);
716 let (stack, success) = pop(stack);
717 assert_eq!(success, Value::Bool(true));
718 let (_stack, result) = pop(stack);
719 assert_eq!(result, Value::Int(-3));
720
721 let stack = push_int(stack, -10);
723 let stack = push_int(stack, -3);
724 let stack = divide(stack);
725 let (stack, success) = pop(stack);
726 assert_eq!(success, Value::Bool(true));
727 let (_stack, result) = pop(stack);
728 assert_eq!(result, Value::Int(3));
729 }
730 }
731
732 #[test]
733 fn test_and_true_true() {
734 unsafe {
735 let stack = crate::stack::alloc_test_stack();
736 let stack = push_int(stack, 1);
737 let stack = push_int(stack, 1);
738 let stack = and(stack);
739 let (_stack, result) = pop(stack);
740 assert_eq!(result, Value::Int(1));
741 }
742 }
743
744 #[test]
745 fn test_and_true_false() {
746 unsafe {
747 let stack = crate::stack::alloc_test_stack();
748 let stack = push_int(stack, 1);
749 let stack = push_int(stack, 0);
750 let stack = and(stack);
751 let (_stack, result) = pop(stack);
752 assert_eq!(result, Value::Int(0));
753 }
754 }
755
756 #[test]
757 fn test_and_false_false() {
758 unsafe {
759 let stack = crate::stack::alloc_test_stack();
760 let stack = push_int(stack, 0);
761 let stack = push_int(stack, 0);
762 let stack = and(stack);
763 let (_stack, result) = pop(stack);
764 assert_eq!(result, Value::Int(0));
765 }
766 }
767
768 #[test]
769 fn test_or_true_true() {
770 unsafe {
771 let stack = crate::stack::alloc_test_stack();
772 let stack = push_int(stack, 1);
773 let stack = push_int(stack, 1);
774 let stack = or(stack);
775 let (_stack, result) = pop(stack);
776 assert_eq!(result, Value::Int(1));
777 }
778 }
779
780 #[test]
781 fn test_or_true_false() {
782 unsafe {
783 let stack = crate::stack::alloc_test_stack();
784 let stack = push_int(stack, 1);
785 let stack = push_int(stack, 0);
786 let stack = or(stack);
787 let (_stack, result) = pop(stack);
788 assert_eq!(result, Value::Int(1));
789 }
790 }
791
792 #[test]
793 fn test_or_false_false() {
794 unsafe {
795 let stack = crate::stack::alloc_test_stack();
796 let stack = push_int(stack, 0);
797 let stack = push_int(stack, 0);
798 let stack = or(stack);
799 let (_stack, result) = pop(stack);
800 assert_eq!(result, Value::Int(0));
801 }
802 }
803
804 #[test]
805 fn test_not_true() {
806 unsafe {
807 let stack = crate::stack::alloc_test_stack();
808 let stack = push_int(stack, 1);
809 let stack = not(stack);
810 let (_stack, result) = pop(stack);
811 assert_eq!(result, Value::Int(0));
812 }
813 }
814
815 #[test]
816 fn test_not_false() {
817 unsafe {
818 let stack = crate::stack::alloc_test_stack();
819 let stack = push_int(stack, 0);
820 let stack = not(stack);
821 let (_stack, result) = pop(stack);
822 assert_eq!(result, Value::Int(1));
823 }
824 }
825
826 #[test]
827 fn test_and_nonzero_values() {
828 unsafe {
830 let stack = crate::stack::alloc_test_stack();
831 let stack = push_int(stack, 42);
832 let stack = push_int(stack, -5);
833 let stack = and(stack);
834 let (_stack, result) = pop(stack);
835 assert_eq!(result, Value::Int(1));
836 }
837 }
838
839 #[test]
840 fn test_divide_by_zero_returns_false() {
841 unsafe {
842 let stack = crate::stack::alloc_test_stack();
843 let stack = push_int(stack, 42);
844 let stack = push_int(stack, 0);
845 let stack = divide(stack);
846
847 let (stack, success) = pop(stack);
849 assert_eq!(success, Value::Bool(false));
850
851 let (_stack, result) = pop(stack);
853 assert_eq!(result, Value::Int(0));
854 }
855 }
856}