1use crate::stack::{Stack, 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)]
107pub unsafe extern "C" fn patch_seq_divide(stack: Stack) -> Stack {
108 let (rest, a, b) = unsafe { pop_two(stack, "divide") };
109 match (a, b) {
110 (Value::Int(a_val), Value::Int(b_val)) => {
111 assert!(
112 b_val != 0,
113 "divide: division by zero (attempted {} / {})",
114 a_val,
115 b_val
116 );
117 unsafe { push(rest, Value::Int(a_val.wrapping_div(b_val))) }
119 }
120 _ => panic!("divide: expected two integers on stack"),
121 }
122}
123
124#[unsafe(no_mangle)]
132pub unsafe extern "C" fn patch_seq_eq(stack: Stack) -> Stack {
133 let (rest, a, b) = unsafe { pop_two(stack, "=") };
134 match (a, b) {
135 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
136 push(rest, Value::Int(if a_val == b_val { 1 } else { 0 }))
137 },
138 _ => panic!("=: expected two integers on stack"),
139 }
140}
141
142#[unsafe(no_mangle)]
150pub unsafe extern "C" fn patch_seq_lt(stack: Stack) -> Stack {
151 let (rest, a, b) = unsafe { pop_two(stack, "<") };
152 match (a, b) {
153 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
154 push(rest, Value::Int(if a_val < b_val { 1 } else { 0 }))
155 },
156 _ => panic!("<: expected two integers on stack"),
157 }
158}
159
160#[unsafe(no_mangle)]
168pub unsafe extern "C" fn patch_seq_gt(stack: Stack) -> Stack {
169 let (rest, a, b) = unsafe { pop_two(stack, ">") };
170 match (a, b) {
171 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
172 push(rest, Value::Int(if a_val > b_val { 1 } else { 0 }))
173 },
174 _ => panic!(">: expected two integers on stack"),
175 }
176}
177
178#[unsafe(no_mangle)]
186pub unsafe extern "C" fn patch_seq_lte(stack: Stack) -> Stack {
187 let (rest, a, b) = unsafe { pop_two(stack, "<=") };
188 match (a, b) {
189 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
190 push(rest, Value::Int(if a_val <= b_val { 1 } else { 0 }))
191 },
192 _ => panic!("<=: expected two integers on stack"),
193 }
194}
195
196#[unsafe(no_mangle)]
204pub unsafe extern "C" fn patch_seq_gte(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 {
208 push(rest, Value::Int(if a_val >= b_val { 1 } else { 0 }))
209 },
210 _ => panic!(">=: expected two integers on stack"),
211 }
212}
213
214#[unsafe(no_mangle)]
222pub unsafe extern "C" fn patch_seq_neq(stack: Stack) -> Stack {
223 let (rest, a, b) = unsafe { pop_two(stack, "<>") };
224 match (a, b) {
225 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
226 push(rest, Value::Int(if a_val != b_val { 1 } else { 0 }))
227 },
228 _ => panic!("<>: expected two integers on stack"),
229 }
230}
231
232#[unsafe(no_mangle)]
241pub unsafe extern "C" fn patch_seq_and(stack: Stack) -> Stack {
242 let (rest, a, b) = unsafe { pop_two(stack, "and") };
243 match (a, b) {
244 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
245 push(
246 rest,
247 Value::Int(if a_val != 0 && b_val != 0 { 1 } else { 0 }),
248 )
249 },
250 _ => panic!("and: expected two integers on stack"),
251 }
252}
253
254#[unsafe(no_mangle)]
263pub unsafe extern "C" fn patch_seq_or(stack: Stack) -> Stack {
264 let (rest, a, b) = unsafe { pop_two(stack, "or") };
265 match (a, b) {
266 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
267 push(
268 rest,
269 Value::Int(if a_val != 0 || b_val != 0 { 1 } else { 0 }),
270 )
271 },
272 _ => panic!("or: expected two integers on stack"),
273 }
274}
275
276#[unsafe(no_mangle)]
285pub unsafe extern "C" fn patch_seq_not(stack: Stack) -> Stack {
286 assert!(!stack.is_null(), "not: stack is empty");
287 let (rest, a) = unsafe { pop(stack) };
288
289 match a {
290 Value::Int(a_val) => unsafe { push(rest, Value::Int(if a_val == 0 { 1 } else { 0 })) },
291 _ => panic!("not: expected integer on stack"),
292 }
293}
294
295#[unsafe(no_mangle)]
306pub unsafe extern "C" fn patch_seq_band(stack: Stack) -> Stack {
307 let (rest, a, b) = unsafe { pop_two(stack, "band") };
308 match (a, b) {
309 (Value::Int(a_val), Value::Int(b_val)) => unsafe { push(rest, Value::Int(a_val & b_val)) },
310 _ => panic!("band: expected two integers on stack"),
311 }
312}
313
314#[unsafe(no_mangle)]
321pub unsafe extern "C" fn patch_seq_bor(stack: Stack) -> Stack {
322 let (rest, a, b) = unsafe { pop_two(stack, "bor") };
323 match (a, b) {
324 (Value::Int(a_val), Value::Int(b_val)) => unsafe { push(rest, Value::Int(a_val | b_val)) },
325 _ => panic!("bor: expected two integers on stack"),
326 }
327}
328
329#[unsafe(no_mangle)]
336pub unsafe extern "C" fn patch_seq_bxor(stack: Stack) -> Stack {
337 let (rest, a, b) = unsafe { pop_two(stack, "bxor") };
338 match (a, b) {
339 (Value::Int(a_val), Value::Int(b_val)) => unsafe { push(rest, Value::Int(a_val ^ b_val)) },
340 _ => panic!("bxor: expected two integers on stack"),
341 }
342}
343
344#[unsafe(no_mangle)]
351pub unsafe extern "C" fn patch_seq_bnot(stack: Stack) -> Stack {
352 assert!(!stack.is_null(), "bnot: stack is empty");
353 let (rest, a) = unsafe { pop(stack) };
354 match a {
355 Value::Int(a_val) => unsafe { push(rest, Value::Int(!a_val)) },
356 _ => panic!("bnot: expected integer on stack"),
357 }
358}
359
360#[unsafe(no_mangle)]
368pub unsafe extern "C" fn patch_seq_shl(stack: Stack) -> Stack {
369 let (rest, value, count) = unsafe { pop_two(stack, "shl") };
370 match (value, count) {
371 (Value::Int(v), Value::Int(c)) => {
372 let result = if c < 0 {
375 0
376 } else {
377 v.checked_shl(c as u32).unwrap_or(0)
378 };
379 unsafe { push(rest, Value::Int(result)) }
380 }
381 _ => panic!("shl: expected two integers on stack"),
382 }
383}
384
385#[unsafe(no_mangle)]
394pub unsafe extern "C" fn patch_seq_shr(stack: Stack) -> Stack {
395 let (rest, value, count) = unsafe { pop_two(stack, "shr") };
396 match (value, count) {
397 (Value::Int(v), Value::Int(c)) => {
398 let result = if c < 0 {
401 0
402 } else {
403 (v as u64).checked_shr(c as u32).unwrap_or(0) as i64
404 };
405 unsafe { push(rest, Value::Int(result)) }
406 }
407 _ => panic!("shr: expected two integers on stack"),
408 }
409}
410
411#[unsafe(no_mangle)]
418pub unsafe extern "C" fn patch_seq_popcount(stack: Stack) -> Stack {
419 assert!(!stack.is_null(), "popcount: stack is empty");
420 let (rest, a) = unsafe { pop(stack) };
421 match a {
422 Value::Int(v) => unsafe { push(rest, Value::Int(v.count_ones() as i64)) },
423 _ => panic!("popcount: expected integer on stack"),
424 }
425}
426
427#[unsafe(no_mangle)]
434pub unsafe extern "C" fn patch_seq_clz(stack: Stack) -> Stack {
435 assert!(!stack.is_null(), "clz: stack is empty");
436 let (rest, a) = unsafe { pop(stack) };
437 match a {
438 Value::Int(v) => unsafe { push(rest, Value::Int(v.leading_zeros() as i64)) },
439 _ => panic!("clz: expected integer on stack"),
440 }
441}
442
443#[unsafe(no_mangle)]
450pub unsafe extern "C" fn patch_seq_ctz(stack: Stack) -> Stack {
451 assert!(!stack.is_null(), "ctz: stack is empty");
452 let (rest, a) = unsafe { pop(stack) };
453 match a {
454 Value::Int(v) => unsafe { push(rest, Value::Int(v.trailing_zeros() as i64)) },
455 _ => panic!("ctz: expected integer on stack"),
456 }
457}
458
459#[unsafe(no_mangle)]
466pub unsafe extern "C" fn patch_seq_int_bits(stack: Stack) -> Stack {
467 unsafe { push(stack, Value::Int(64)) }
468}
469
470#[unsafe(no_mangle)]
490pub unsafe extern "C" fn patch_seq_peek_int_value(stack: Stack) -> i64 {
491 assert!(!stack.is_null(), "peek_int_value: stack is empty");
492
493 let node = unsafe { &*stack };
494 match &node.value {
495 Value::Int(n) => *n,
496 _ => panic!(
497 "peek_int_value: expected Int on stack, got {:?}",
498 node.value
499 ),
500 }
501}
502
503#[unsafe(no_mangle)]
513pub unsafe extern "C" fn patch_seq_pop_stack(stack: Stack) -> Stack {
514 assert!(!stack.is_null(), "pop_stack: stack is empty");
515 let (rest, _value) = unsafe { pop(stack) };
516 rest
517}
518
519pub use patch_seq_add as add;
521pub use patch_seq_and as and;
522pub use patch_seq_band as band;
523pub use patch_seq_bnot as bnot;
524pub use patch_seq_bor as bor;
525pub use patch_seq_bxor as bxor;
526pub use patch_seq_clz as clz;
527pub use patch_seq_ctz as ctz;
528pub use patch_seq_divide as divide;
529pub use patch_seq_eq as eq;
530pub use patch_seq_gt as gt;
531pub use patch_seq_gte as gte;
532pub use patch_seq_int_bits as int_bits;
533pub use patch_seq_lt as lt;
534pub use patch_seq_lte as lte;
535pub use patch_seq_multiply as multiply;
536pub use patch_seq_neq as neq;
537pub use patch_seq_not as not;
538pub use patch_seq_or as or;
539pub use patch_seq_popcount as popcount;
540pub use patch_seq_push_bool as push_bool;
541pub use patch_seq_push_int as push_int;
542pub use patch_seq_shl as shl;
543pub use patch_seq_shr as shr;
544pub use patch_seq_subtract as subtract;
545
546#[cfg(test)]
547mod tests {
548 use super::*;
549
550 #[test]
551 fn test_add() {
552 unsafe {
553 let stack = std::ptr::null_mut();
554 let stack = push_int(stack, 5);
555 let stack = push_int(stack, 3);
556 let stack = add(stack);
557
558 let (stack, result) = pop(stack);
559 assert_eq!(result, Value::Int(8));
560 assert!(stack.is_null());
561 }
562 }
563
564 #[test]
565 fn test_subtract() {
566 unsafe {
567 let stack = std::ptr::null_mut();
568 let stack = push_int(stack, 10);
569 let stack = push_int(stack, 3);
570 let stack = subtract(stack);
571
572 let (stack, result) = pop(stack);
573 assert_eq!(result, Value::Int(7));
574 assert!(stack.is_null());
575 }
576 }
577
578 #[test]
579 fn test_multiply() {
580 unsafe {
581 let stack = std::ptr::null_mut();
582 let stack = push_int(stack, 4);
583 let stack = push_int(stack, 5);
584 let stack = multiply(stack);
585
586 let (stack, result) = pop(stack);
587 assert_eq!(result, Value::Int(20));
588 assert!(stack.is_null());
589 }
590 }
591
592 #[test]
593 fn test_divide() {
594 unsafe {
595 let stack = std::ptr::null_mut();
596 let stack = push_int(stack, 20);
597 let stack = push_int(stack, 4);
598 let stack = divide(stack);
599
600 let (stack, result) = pop(stack);
601 assert_eq!(result, Value::Int(5));
602 assert!(stack.is_null());
603 }
604 }
605
606 #[test]
607 fn test_comparisons() {
608 unsafe {
609 let stack = std::ptr::null_mut();
611 let stack = push_int(stack, 5);
612 let stack = push_int(stack, 5);
613 let stack = eq(stack);
614 let (stack, result) = pop(stack);
615 assert_eq!(result, Value::Int(1)); assert!(stack.is_null());
617
618 let stack = push_int(stack, 3);
620 let stack = push_int(stack, 5);
621 let stack = lt(stack);
622 let (stack, result) = pop(stack);
623 assert_eq!(result, Value::Int(1)); assert!(stack.is_null());
625
626 let stack = push_int(stack, 7);
628 let stack = push_int(stack, 5);
629 let stack = gt(stack);
630 let (stack, result) = pop(stack);
631 assert_eq!(result, Value::Int(1)); assert!(stack.is_null());
633 }
634 }
635
636 #[test]
637 fn test_overflow_wrapping() {
638 unsafe {
640 let stack = std::ptr::null_mut();
642 let stack = push_int(stack, i64::MAX);
643 let stack = push_int(stack, 1);
644 let stack = add(stack);
645 let (stack, result) = pop(stack);
646 assert_eq!(result, Value::Int(i64::MIN)); assert!(stack.is_null());
648
649 let stack = push_int(stack, i64::MAX);
651 let stack = push_int(stack, 2);
652 let stack = multiply(stack);
653 let (stack, result) = pop(stack);
654 assert!(matches!(result, Value::Int(_)));
656 assert!(stack.is_null());
657
658 let stack = push_int(stack, i64::MIN);
660 let stack = push_int(stack, 1);
661 let stack = subtract(stack);
662 let (stack, result) = pop(stack);
663 assert_eq!(result, Value::Int(i64::MAX)); assert!(stack.is_null());
665 }
666 }
667
668 #[test]
669 fn test_negative_division() {
670 unsafe {
671 let stack = std::ptr::null_mut();
673 let stack = push_int(stack, -10);
674 let stack = push_int(stack, 3);
675 let stack = divide(stack);
676 let (stack, result) = pop(stack);
677 assert_eq!(result, Value::Int(-3)); assert!(stack.is_null());
679
680 let stack = push_int(stack, 10);
682 let stack = push_int(stack, -3);
683 let stack = divide(stack);
684 let (stack, result) = pop(stack);
685 assert_eq!(result, Value::Int(-3));
686 assert!(stack.is_null());
687
688 let stack = push_int(stack, -10);
690 let stack = push_int(stack, -3);
691 let stack = divide(stack);
692 let (stack, result) = pop(stack);
693 assert_eq!(result, Value::Int(3));
694 assert!(stack.is_null());
695 }
696 }
697
698 #[test]
699 fn test_division_overflow_edge_case() {
700 unsafe {
703 let stack = std::ptr::null_mut();
704 let stack = push_int(stack, i64::MIN);
705 let stack = push_int(stack, -1);
706 let stack = divide(stack);
707 let (stack, result) = pop(stack);
708 assert_eq!(result, Value::Int(i64::MIN));
710 assert!(stack.is_null());
711 }
712 }
713
714 #[test]
715 fn test_and_true_true() {
716 unsafe {
717 let stack = std::ptr::null_mut();
718 let stack = push_int(stack, 1);
719 let stack = push_int(stack, 1);
720 let stack = and(stack);
721 let (stack, result) = pop(stack);
722 assert_eq!(result, Value::Int(1));
723 assert!(stack.is_null());
724 }
725 }
726
727 #[test]
728 fn test_and_true_false() {
729 unsafe {
730 let stack = std::ptr::null_mut();
731 let stack = push_int(stack, 1);
732 let stack = push_int(stack, 0);
733 let stack = and(stack);
734 let (stack, result) = pop(stack);
735 assert_eq!(result, Value::Int(0));
736 assert!(stack.is_null());
737 }
738 }
739
740 #[test]
741 fn test_and_false_false() {
742 unsafe {
743 let stack = std::ptr::null_mut();
744 let stack = push_int(stack, 0);
745 let stack = push_int(stack, 0);
746 let stack = and(stack);
747 let (stack, result) = pop(stack);
748 assert_eq!(result, Value::Int(0));
749 assert!(stack.is_null());
750 }
751 }
752
753 #[test]
754 fn test_or_true_true() {
755 unsafe {
756 let stack = std::ptr::null_mut();
757 let stack = push_int(stack, 1);
758 let stack = push_int(stack, 1);
759 let stack = or(stack);
760 let (stack, result) = pop(stack);
761 assert_eq!(result, Value::Int(1));
762 assert!(stack.is_null());
763 }
764 }
765
766 #[test]
767 fn test_or_true_false() {
768 unsafe {
769 let stack = std::ptr::null_mut();
770 let stack = push_int(stack, 1);
771 let stack = push_int(stack, 0);
772 let stack = or(stack);
773 let (stack, result) = pop(stack);
774 assert_eq!(result, Value::Int(1));
775 assert!(stack.is_null());
776 }
777 }
778
779 #[test]
780 fn test_or_false_false() {
781 unsafe {
782 let stack = std::ptr::null_mut();
783 let stack = push_int(stack, 0);
784 let stack = push_int(stack, 0);
785 let stack = or(stack);
786 let (stack, result) = pop(stack);
787 assert_eq!(result, Value::Int(0));
788 assert!(stack.is_null());
789 }
790 }
791
792 #[test]
793 fn test_not_true() {
794 unsafe {
795 let stack = std::ptr::null_mut();
796 let stack = push_int(stack, 1);
797 let stack = not(stack);
798 let (stack, result) = pop(stack);
799 assert_eq!(result, Value::Int(0));
800 assert!(stack.is_null());
801 }
802 }
803
804 #[test]
805 fn test_not_false() {
806 unsafe {
807 let stack = std::ptr::null_mut();
808 let stack = push_int(stack, 0);
809 let stack = not(stack);
810 let (stack, result) = pop(stack);
811 assert_eq!(result, Value::Int(1));
812 assert!(stack.is_null());
813 }
814 }
815
816 #[test]
817 fn test_and_nonzero_values() {
818 unsafe {
820 let stack = std::ptr::null_mut();
821 let stack = push_int(stack, 42);
822 let stack = push_int(stack, -5);
823 let stack = and(stack);
824 let (stack, result) = pop(stack);
825 assert_eq!(result, Value::Int(1));
826 assert!(stack.is_null());
827 }
828 }
829
830 }