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)]
315pub unsafe extern "C" fn patch_seq_peek_int_value(stack: Stack) -> i64 {
316 assert!(!stack.is_null(), "peek_int_value: stack is empty");
317
318 let node = unsafe { &*stack };
319 match &node.value {
320 Value::Int(n) => *n,
321 _ => panic!(
322 "peek_int_value: expected Int on stack, got {:?}",
323 node.value
324 ),
325 }
326}
327
328#[unsafe(no_mangle)]
338pub unsafe extern "C" fn patch_seq_pop_stack(stack: Stack) -> Stack {
339 assert!(!stack.is_null(), "pop_stack: stack is empty");
340 let (rest, _value) = unsafe { pop(stack) };
341 rest
342}
343
344pub use patch_seq_add as add;
346pub use patch_seq_and as and;
347pub use patch_seq_divide as divide;
348pub use patch_seq_eq as eq;
349pub use patch_seq_gt as gt;
350pub use patch_seq_gte as gte;
351pub use patch_seq_lt as lt;
352pub use patch_seq_lte as lte;
353pub use patch_seq_multiply as multiply;
354pub use patch_seq_neq as neq;
355pub use patch_seq_not as not;
356pub use patch_seq_or as or;
357pub use patch_seq_push_bool as push_bool;
358pub use patch_seq_push_int as push_int;
359pub use patch_seq_subtract as subtract;
360
361#[cfg(test)]
362mod tests {
363 use super::*;
364
365 #[test]
366 fn test_add() {
367 unsafe {
368 let stack = std::ptr::null_mut();
369 let stack = push_int(stack, 5);
370 let stack = push_int(stack, 3);
371 let stack = add(stack);
372
373 let (stack, result) = pop(stack);
374 assert_eq!(result, Value::Int(8));
375 assert!(stack.is_null());
376 }
377 }
378
379 #[test]
380 fn test_subtract() {
381 unsafe {
382 let stack = std::ptr::null_mut();
383 let stack = push_int(stack, 10);
384 let stack = push_int(stack, 3);
385 let stack = subtract(stack);
386
387 let (stack, result) = pop(stack);
388 assert_eq!(result, Value::Int(7));
389 assert!(stack.is_null());
390 }
391 }
392
393 #[test]
394 fn test_multiply() {
395 unsafe {
396 let stack = std::ptr::null_mut();
397 let stack = push_int(stack, 4);
398 let stack = push_int(stack, 5);
399 let stack = multiply(stack);
400
401 let (stack, result) = pop(stack);
402 assert_eq!(result, Value::Int(20));
403 assert!(stack.is_null());
404 }
405 }
406
407 #[test]
408 fn test_divide() {
409 unsafe {
410 let stack = std::ptr::null_mut();
411 let stack = push_int(stack, 20);
412 let stack = push_int(stack, 4);
413 let stack = divide(stack);
414
415 let (stack, result) = pop(stack);
416 assert_eq!(result, Value::Int(5));
417 assert!(stack.is_null());
418 }
419 }
420
421 #[test]
422 fn test_comparisons() {
423 unsafe {
424 let stack = std::ptr::null_mut();
426 let stack = push_int(stack, 5);
427 let stack = push_int(stack, 5);
428 let stack = eq(stack);
429 let (stack, result) = pop(stack);
430 assert_eq!(result, Value::Int(1)); assert!(stack.is_null());
432
433 let stack = push_int(stack, 3);
435 let stack = push_int(stack, 5);
436 let stack = lt(stack);
437 let (stack, result) = pop(stack);
438 assert_eq!(result, Value::Int(1)); assert!(stack.is_null());
440
441 let stack = push_int(stack, 7);
443 let stack = push_int(stack, 5);
444 let stack = gt(stack);
445 let (stack, result) = pop(stack);
446 assert_eq!(result, Value::Int(1)); assert!(stack.is_null());
448 }
449 }
450
451 #[test]
452 fn test_overflow_wrapping() {
453 unsafe {
455 let stack = std::ptr::null_mut();
457 let stack = push_int(stack, i64::MAX);
458 let stack = push_int(stack, 1);
459 let stack = add(stack);
460 let (stack, result) = pop(stack);
461 assert_eq!(result, Value::Int(i64::MIN)); assert!(stack.is_null());
463
464 let stack = push_int(stack, i64::MAX);
466 let stack = push_int(stack, 2);
467 let stack = multiply(stack);
468 let (stack, result) = pop(stack);
469 assert!(matches!(result, Value::Int(_)));
471 assert!(stack.is_null());
472
473 let stack = push_int(stack, i64::MIN);
475 let stack = push_int(stack, 1);
476 let stack = subtract(stack);
477 let (stack, result) = pop(stack);
478 assert_eq!(result, Value::Int(i64::MAX)); assert!(stack.is_null());
480 }
481 }
482
483 #[test]
484 fn test_negative_division() {
485 unsafe {
486 let stack = std::ptr::null_mut();
488 let stack = push_int(stack, -10);
489 let stack = push_int(stack, 3);
490 let stack = divide(stack);
491 let (stack, result) = pop(stack);
492 assert_eq!(result, Value::Int(-3)); assert!(stack.is_null());
494
495 let stack = push_int(stack, 10);
497 let stack = push_int(stack, -3);
498 let stack = divide(stack);
499 let (stack, result) = pop(stack);
500 assert_eq!(result, Value::Int(-3));
501 assert!(stack.is_null());
502
503 let stack = push_int(stack, -10);
505 let stack = push_int(stack, -3);
506 let stack = divide(stack);
507 let (stack, result) = pop(stack);
508 assert_eq!(result, Value::Int(3));
509 assert!(stack.is_null());
510 }
511 }
512
513 #[test]
514 fn test_division_overflow_edge_case() {
515 unsafe {
518 let stack = std::ptr::null_mut();
519 let stack = push_int(stack, i64::MIN);
520 let stack = push_int(stack, -1);
521 let stack = divide(stack);
522 let (stack, result) = pop(stack);
523 assert_eq!(result, Value::Int(i64::MIN));
525 assert!(stack.is_null());
526 }
527 }
528
529 #[test]
530 fn test_and_true_true() {
531 unsafe {
532 let stack = std::ptr::null_mut();
533 let stack = push_int(stack, 1);
534 let stack = push_int(stack, 1);
535 let stack = and(stack);
536 let (stack, result) = pop(stack);
537 assert_eq!(result, Value::Int(1));
538 assert!(stack.is_null());
539 }
540 }
541
542 #[test]
543 fn test_and_true_false() {
544 unsafe {
545 let stack = std::ptr::null_mut();
546 let stack = push_int(stack, 1);
547 let stack = push_int(stack, 0);
548 let stack = and(stack);
549 let (stack, result) = pop(stack);
550 assert_eq!(result, Value::Int(0));
551 assert!(stack.is_null());
552 }
553 }
554
555 #[test]
556 fn test_and_false_false() {
557 unsafe {
558 let stack = std::ptr::null_mut();
559 let stack = push_int(stack, 0);
560 let stack = push_int(stack, 0);
561 let stack = and(stack);
562 let (stack, result) = pop(stack);
563 assert_eq!(result, Value::Int(0));
564 assert!(stack.is_null());
565 }
566 }
567
568 #[test]
569 fn test_or_true_true() {
570 unsafe {
571 let stack = std::ptr::null_mut();
572 let stack = push_int(stack, 1);
573 let stack = push_int(stack, 1);
574 let stack = or(stack);
575 let (stack, result) = pop(stack);
576 assert_eq!(result, Value::Int(1));
577 assert!(stack.is_null());
578 }
579 }
580
581 #[test]
582 fn test_or_true_false() {
583 unsafe {
584 let stack = std::ptr::null_mut();
585 let stack = push_int(stack, 1);
586 let stack = push_int(stack, 0);
587 let stack = or(stack);
588 let (stack, result) = pop(stack);
589 assert_eq!(result, Value::Int(1));
590 assert!(stack.is_null());
591 }
592 }
593
594 #[test]
595 fn test_or_false_false() {
596 unsafe {
597 let stack = std::ptr::null_mut();
598 let stack = push_int(stack, 0);
599 let stack = push_int(stack, 0);
600 let stack = or(stack);
601 let (stack, result) = pop(stack);
602 assert_eq!(result, Value::Int(0));
603 assert!(stack.is_null());
604 }
605 }
606
607 #[test]
608 fn test_not_true() {
609 unsafe {
610 let stack = std::ptr::null_mut();
611 let stack = push_int(stack, 1);
612 let stack = not(stack);
613 let (stack, result) = pop(stack);
614 assert_eq!(result, Value::Int(0));
615 assert!(stack.is_null());
616 }
617 }
618
619 #[test]
620 fn test_not_false() {
621 unsafe {
622 let stack = std::ptr::null_mut();
623 let stack = push_int(stack, 0);
624 let stack = not(stack);
625 let (stack, result) = pop(stack);
626 assert_eq!(result, Value::Int(1));
627 assert!(stack.is_null());
628 }
629 }
630
631 #[test]
632 fn test_and_nonzero_values() {
633 unsafe {
635 let stack = std::ptr::null_mut();
636 let stack = push_int(stack, 42);
637 let stack = push_int(stack, -5);
638 let stack = and(stack);
639 let (stack, result) = pop(stack);
640 assert_eq!(result, Value::Int(1));
641 assert!(stack.is_null());
642 }
643 }
644
645 }