1use crate::stack::{Stack, pop, 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 assert!(!stack.is_null(), "add: stack is empty");
58 let (rest, b) = unsafe { pop(stack) };
59 assert!(!rest.is_null(), "add: stack has only one value");
60 let (rest, a) = unsafe { pop(rest) };
61
62 match (a, b) {
63 (Value::Int(a_val), Value::Int(b_val)) => {
64 let result = a_val.wrapping_add(b_val); unsafe { push(rest, Value::Int(result)) }
66 }
67 _ => panic!("add: expected two integers on stack"),
68 }
69}
70
71#[unsafe(no_mangle)]
78pub unsafe extern "C" fn patch_seq_subtract(stack: Stack) -> Stack {
79 assert!(!stack.is_null(), "subtract: stack is empty");
80 let (rest, b) = unsafe { pop(stack) };
81 assert!(!rest.is_null(), "subtract: stack has only one value");
82 let (rest, a) = unsafe { pop(rest) };
83
84 match (a, b) {
85 (Value::Int(a_val), Value::Int(b_val)) => {
86 let result = a_val.wrapping_sub(b_val);
87 unsafe { push(rest, Value::Int(result)) }
88 }
89 _ => panic!("subtract: expected two integers on stack"),
90 }
91}
92
93#[unsafe(no_mangle)]
100pub unsafe extern "C" fn patch_seq_multiply(stack: Stack) -> Stack {
101 assert!(!stack.is_null(), "multiply: stack is empty");
102 let (rest, b) = unsafe { pop(stack) };
103 assert!(!rest.is_null(), "multiply: stack has only one value");
104 let (rest, a) = unsafe { pop(rest) };
105
106 match (a, b) {
107 (Value::Int(a_val), Value::Int(b_val)) => {
108 let result = a_val.wrapping_mul(b_val);
109 unsafe { push(rest, Value::Int(result)) }
110 }
111 _ => panic!("multiply: expected two integers on stack"),
112 }
113}
114
115#[unsafe(no_mangle)]
122pub unsafe extern "C" fn patch_seq_divide(stack: Stack) -> Stack {
123 assert!(!stack.is_null(), "divide: stack is empty");
124 let (rest, b) = unsafe { pop(stack) };
125 assert!(!rest.is_null(), "divide: stack has only one value");
126 let (rest, a) = unsafe { pop(rest) };
127
128 match (a, b) {
129 (Value::Int(a_val), Value::Int(b_val)) => {
130 assert!(
131 b_val != 0,
132 "divide: division by zero (attempted {} / {})",
133 a_val,
134 b_val
135 );
136 let result = a_val.wrapping_div(b_val);
139 unsafe { push(rest, Value::Int(result)) }
140 }
141 _ => panic!("divide: expected two integers on stack"),
142 }
143}
144
145#[unsafe(no_mangle)]
153pub unsafe extern "C" fn patch_seq_eq(stack: Stack) -> Stack {
154 assert!(!stack.is_null(), "eq: stack is empty");
155 let (rest, b) = unsafe { pop(stack) };
156 assert!(!rest.is_null(), "eq: stack has only one value");
157 let (rest, a) = unsafe { pop(rest) };
158
159 match (a, b) {
160 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
161 push(rest, Value::Int(if a_val == b_val { 1 } else { 0 }))
162 },
163 _ => panic!("eq: expected two integers on stack"),
164 }
165}
166
167#[unsafe(no_mangle)]
175pub unsafe extern "C" fn patch_seq_lt(stack: Stack) -> Stack {
176 assert!(!stack.is_null(), "lt: stack is empty");
177 let (rest, b) = unsafe { pop(stack) };
178 assert!(!rest.is_null(), "lt: stack has only one value");
179 let (rest, a) = unsafe { pop(rest) };
180
181 match (a, b) {
182 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
183 push(rest, Value::Int(if a_val < b_val { 1 } else { 0 }))
184 },
185 _ => panic!("lt: expected two integers on stack"),
186 }
187}
188
189#[unsafe(no_mangle)]
197pub unsafe extern "C" fn patch_seq_gt(stack: Stack) -> Stack {
198 assert!(!stack.is_null(), "gt: stack is empty");
199 let (rest, b) = unsafe { pop(stack) };
200 assert!(!rest.is_null(), "gt: stack has only one value");
201 let (rest, a) = unsafe { pop(rest) };
202
203 match (a, b) {
204 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
205 push(rest, Value::Int(if a_val > b_val { 1 } else { 0 }))
206 },
207 _ => panic!("gt: expected two integers on stack"),
208 }
209}
210
211#[unsafe(no_mangle)]
219pub unsafe extern "C" fn patch_seq_lte(stack: Stack) -> Stack {
220 assert!(!stack.is_null(), "lte: stack is empty");
221 let (rest, b) = unsafe { pop(stack) };
222 assert!(!rest.is_null(), "lte: stack has only one value");
223 let (rest, a) = unsafe { pop(rest) };
224
225 match (a, b) {
226 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
227 push(rest, Value::Int(if a_val <= b_val { 1 } else { 0 }))
228 },
229 _ => panic!("lte: expected two integers on stack"),
230 }
231}
232
233#[unsafe(no_mangle)]
241pub unsafe extern "C" fn patch_seq_gte(stack: Stack) -> Stack {
242 assert!(!stack.is_null(), "gte: stack is empty");
243 let (rest, b) = unsafe { pop(stack) };
244 assert!(!rest.is_null(), "gte: stack has only one value");
245 let (rest, a) = unsafe { pop(rest) };
246
247 match (a, b) {
248 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
249 push(rest, Value::Int(if a_val >= b_val { 1 } else { 0 }))
250 },
251 _ => panic!("gte: expected two integers on stack"),
252 }
253}
254
255#[unsafe(no_mangle)]
263pub unsafe extern "C" fn patch_seq_neq(stack: Stack) -> Stack {
264 assert!(!stack.is_null(), "neq: stack is empty");
265 let (rest, b) = unsafe { pop(stack) };
266 assert!(!rest.is_null(), "neq: stack has only one value");
267 let (rest, a) = unsafe { pop(rest) };
268
269 match (a, b) {
270 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
271 push(rest, Value::Int(if a_val != b_val { 1 } else { 0 }))
272 },
273 _ => panic!("neq: expected two integers on stack"),
274 }
275}
276
277#[unsafe(no_mangle)]
286pub unsafe extern "C" fn patch_seq_and(stack: Stack) -> Stack {
287 assert!(!stack.is_null(), "and: stack is empty");
288 let (rest, b) = unsafe { pop(stack) };
289 assert!(!rest.is_null(), "and: stack has only one value");
290 let (rest, a) = unsafe { pop(rest) };
291
292 match (a, b) {
293 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
294 push(
295 rest,
296 Value::Int(if a_val != 0 && b_val != 0 { 1 } else { 0 }),
297 )
298 },
299 _ => panic!("and: expected two integers on stack"),
300 }
301}
302
303#[unsafe(no_mangle)]
312pub unsafe extern "C" fn patch_seq_or(stack: Stack) -> Stack {
313 assert!(!stack.is_null(), "or: stack is empty");
314 let (rest, b) = unsafe { pop(stack) };
315 assert!(!rest.is_null(), "or: stack has only one value");
316 let (rest, a) = unsafe { pop(rest) };
317
318 match (a, b) {
319 (Value::Int(a_val), Value::Int(b_val)) => unsafe {
320 push(
321 rest,
322 Value::Int(if a_val != 0 || b_val != 0 { 1 } else { 0 }),
323 )
324 },
325 _ => panic!("or: expected two integers on stack"),
326 }
327}
328
329#[unsafe(no_mangle)]
338pub unsafe extern "C" fn patch_seq_not(stack: Stack) -> Stack {
339 assert!(!stack.is_null(), "not: stack is empty");
340 let (rest, a) = unsafe { pop(stack) };
341
342 match a {
343 Value::Int(a_val) => unsafe { push(rest, Value::Int(if a_val == 0 { 1 } else { 0 })) },
344 _ => panic!("not: expected integer on stack"),
345 }
346}
347
348#[unsafe(no_mangle)]
368pub unsafe extern "C" fn patch_seq_peek_int_value(stack: Stack) -> i64 {
369 assert!(!stack.is_null(), "peek_int_value: stack is empty");
370
371 let node = unsafe { &*stack };
372 match &node.value {
373 Value::Int(n) => *n,
374 _ => panic!(
375 "peek_int_value: expected Int on stack, got {:?}",
376 node.value
377 ),
378 }
379}
380
381#[unsafe(no_mangle)]
391pub unsafe extern "C" fn patch_seq_pop_stack(stack: Stack) -> Stack {
392 assert!(!stack.is_null(), "pop_stack: stack is empty");
393 let (rest, _value) = unsafe { pop(stack) };
394 rest
395}
396
397pub use patch_seq_add as add;
399pub use patch_seq_and as and;
400pub use patch_seq_divide as divide;
401pub use patch_seq_eq as eq;
402pub use patch_seq_gt as gt;
403pub use patch_seq_gte as gte;
404pub use patch_seq_lt as lt;
405pub use patch_seq_lte as lte;
406pub use patch_seq_multiply as multiply;
407pub use patch_seq_neq as neq;
408pub use patch_seq_not as not;
409pub use patch_seq_or as or;
410pub use patch_seq_push_bool as push_bool;
411pub use patch_seq_push_int as push_int;
412pub use patch_seq_subtract as subtract;
413
414#[cfg(test)]
415mod tests {
416 use super::*;
417
418 #[test]
419 fn test_add() {
420 unsafe {
421 let stack = std::ptr::null_mut();
422 let stack = push_int(stack, 5);
423 let stack = push_int(stack, 3);
424 let stack = add(stack);
425
426 let (stack, result) = pop(stack);
427 assert_eq!(result, Value::Int(8));
428 assert!(stack.is_null());
429 }
430 }
431
432 #[test]
433 fn test_subtract() {
434 unsafe {
435 let stack = std::ptr::null_mut();
436 let stack = push_int(stack, 10);
437 let stack = push_int(stack, 3);
438 let stack = subtract(stack);
439
440 let (stack, result) = pop(stack);
441 assert_eq!(result, Value::Int(7));
442 assert!(stack.is_null());
443 }
444 }
445
446 #[test]
447 fn test_multiply() {
448 unsafe {
449 let stack = std::ptr::null_mut();
450 let stack = push_int(stack, 4);
451 let stack = push_int(stack, 5);
452 let stack = multiply(stack);
453
454 let (stack, result) = pop(stack);
455 assert_eq!(result, Value::Int(20));
456 assert!(stack.is_null());
457 }
458 }
459
460 #[test]
461 fn test_divide() {
462 unsafe {
463 let stack = std::ptr::null_mut();
464 let stack = push_int(stack, 20);
465 let stack = push_int(stack, 4);
466 let stack = divide(stack);
467
468 let (stack, result) = pop(stack);
469 assert_eq!(result, Value::Int(5));
470 assert!(stack.is_null());
471 }
472 }
473
474 #[test]
475 fn test_comparisons() {
476 unsafe {
477 let stack = std::ptr::null_mut();
479 let stack = push_int(stack, 5);
480 let stack = push_int(stack, 5);
481 let stack = eq(stack);
482 let (stack, result) = pop(stack);
483 assert_eq!(result, Value::Int(1)); assert!(stack.is_null());
485
486 let stack = push_int(stack, 3);
488 let stack = push_int(stack, 5);
489 let stack = lt(stack);
490 let (stack, result) = pop(stack);
491 assert_eq!(result, Value::Int(1)); assert!(stack.is_null());
493
494 let stack = push_int(stack, 7);
496 let stack = push_int(stack, 5);
497 let stack = gt(stack);
498 let (stack, result) = pop(stack);
499 assert_eq!(result, Value::Int(1)); assert!(stack.is_null());
501 }
502 }
503
504 #[test]
505 fn test_overflow_wrapping() {
506 unsafe {
508 let stack = std::ptr::null_mut();
510 let stack = push_int(stack, i64::MAX);
511 let stack = push_int(stack, 1);
512 let stack = add(stack);
513 let (stack, result) = pop(stack);
514 assert_eq!(result, Value::Int(i64::MIN)); assert!(stack.is_null());
516
517 let stack = push_int(stack, i64::MAX);
519 let stack = push_int(stack, 2);
520 let stack = multiply(stack);
521 let (stack, result) = pop(stack);
522 assert!(matches!(result, Value::Int(_)));
524 assert!(stack.is_null());
525
526 let stack = push_int(stack, i64::MIN);
528 let stack = push_int(stack, 1);
529 let stack = subtract(stack);
530 let (stack, result) = pop(stack);
531 assert_eq!(result, Value::Int(i64::MAX)); assert!(stack.is_null());
533 }
534 }
535
536 #[test]
537 fn test_negative_division() {
538 unsafe {
539 let stack = std::ptr::null_mut();
541 let stack = push_int(stack, -10);
542 let stack = push_int(stack, 3);
543 let stack = divide(stack);
544 let (stack, result) = pop(stack);
545 assert_eq!(result, Value::Int(-3)); assert!(stack.is_null());
547
548 let stack = push_int(stack, 10);
550 let stack = push_int(stack, -3);
551 let stack = divide(stack);
552 let (stack, result) = pop(stack);
553 assert_eq!(result, Value::Int(-3));
554 assert!(stack.is_null());
555
556 let stack = push_int(stack, -10);
558 let stack = push_int(stack, -3);
559 let stack = divide(stack);
560 let (stack, result) = pop(stack);
561 assert_eq!(result, Value::Int(3));
562 assert!(stack.is_null());
563 }
564 }
565
566 #[test]
567 fn test_division_overflow_edge_case() {
568 unsafe {
571 let stack = std::ptr::null_mut();
572 let stack = push_int(stack, i64::MIN);
573 let stack = push_int(stack, -1);
574 let stack = divide(stack);
575 let (stack, result) = pop(stack);
576 assert_eq!(result, Value::Int(i64::MIN));
578 assert!(stack.is_null());
579 }
580 }
581
582 #[test]
583 fn test_and_true_true() {
584 unsafe {
585 let stack = std::ptr::null_mut();
586 let stack = push_int(stack, 1);
587 let stack = push_int(stack, 1);
588 let stack = and(stack);
589 let (stack, result) = pop(stack);
590 assert_eq!(result, Value::Int(1));
591 assert!(stack.is_null());
592 }
593 }
594
595 #[test]
596 fn test_and_true_false() {
597 unsafe {
598 let stack = std::ptr::null_mut();
599 let stack = push_int(stack, 1);
600 let stack = push_int(stack, 0);
601 let stack = and(stack);
602 let (stack, result) = pop(stack);
603 assert_eq!(result, Value::Int(0));
604 assert!(stack.is_null());
605 }
606 }
607
608 #[test]
609 fn test_and_false_false() {
610 unsafe {
611 let stack = std::ptr::null_mut();
612 let stack = push_int(stack, 0);
613 let stack = push_int(stack, 0);
614 let stack = and(stack);
615 let (stack, result) = pop(stack);
616 assert_eq!(result, Value::Int(0));
617 assert!(stack.is_null());
618 }
619 }
620
621 #[test]
622 fn test_or_true_true() {
623 unsafe {
624 let stack = std::ptr::null_mut();
625 let stack = push_int(stack, 1);
626 let stack = push_int(stack, 1);
627 let stack = or(stack);
628 let (stack, result) = pop(stack);
629 assert_eq!(result, Value::Int(1));
630 assert!(stack.is_null());
631 }
632 }
633
634 #[test]
635 fn test_or_true_false() {
636 unsafe {
637 let stack = std::ptr::null_mut();
638 let stack = push_int(stack, 1);
639 let stack = push_int(stack, 0);
640 let stack = or(stack);
641 let (stack, result) = pop(stack);
642 assert_eq!(result, Value::Int(1));
643 assert!(stack.is_null());
644 }
645 }
646
647 #[test]
648 fn test_or_false_false() {
649 unsafe {
650 let stack = std::ptr::null_mut();
651 let stack = push_int(stack, 0);
652 let stack = push_int(stack, 0);
653 let stack = or(stack);
654 let (stack, result) = pop(stack);
655 assert_eq!(result, Value::Int(0));
656 assert!(stack.is_null());
657 }
658 }
659
660 #[test]
661 fn test_not_true() {
662 unsafe {
663 let stack = std::ptr::null_mut();
664 let stack = push_int(stack, 1);
665 let stack = not(stack);
666 let (stack, result) = pop(stack);
667 assert_eq!(result, Value::Int(0));
668 assert!(stack.is_null());
669 }
670 }
671
672 #[test]
673 fn test_not_false() {
674 unsafe {
675 let stack = std::ptr::null_mut();
676 let stack = push_int(stack, 0);
677 let stack = not(stack);
678 let (stack, result) = pop(stack);
679 assert_eq!(result, Value::Int(1));
680 assert!(stack.is_null());
681 }
682 }
683
684 #[test]
685 fn test_and_nonzero_values() {
686 unsafe {
688 let stack = std::ptr::null_mut();
689 let stack = push_int(stack, 42);
690 let stack = push_int(stack, -5);
691 let stack = and(stack);
692 let (stack, result) = pop(stack);
693 assert_eq!(result, Value::Int(1));
694 assert!(stack.is_null());
695 }
696 }
697
698 }