Skip to main content

seq_runtime/arithmetic/
arith.rs

1//! Integer arithmetic: push literals + `add`, `subtract`, `multiply`,
2//! `divide`, `modulo`. All use wrapping semantics.
3
4use crate::stack::{Stack, pop_two, push};
5use crate::value::Value;
6
7/// Push an integer literal onto the stack (for compiler-generated code)
8///
9/// Stack effect: ( -- n )
10///
11/// # Safety
12/// Always safe to call
13#[unsafe(no_mangle)]
14pub unsafe extern "C" fn patch_seq_push_int(stack: Stack, value: i64) -> Stack {
15    unsafe { push(stack, Value::Int(value)) }
16}
17
18/// Push a boolean literal onto the stack (for compiler-generated code)
19///
20/// Stack effect: ( -- bool )
21///
22/// # Safety
23/// Always safe to call
24#[unsafe(no_mangle)]
25pub unsafe extern "C" fn patch_seq_push_bool(stack: Stack, value: bool) -> Stack {
26    unsafe { push(stack, Value::Bool(value)) }
27}
28
29/// Add two integers
30///
31/// Stack effect: ( a b -- a+b )
32///
33/// # Safety
34/// Stack must have two Int values on top
35#[unsafe(no_mangle)]
36pub unsafe extern "C" fn patch_seq_add(stack: Stack) -> Stack {
37    let (rest, a, b) = unsafe { pop_two(stack, "add") };
38    match (a, b) {
39        (Value::Int(a_val), Value::Int(b_val)) => unsafe {
40            push(rest, Value::Int(a_val.wrapping_add(b_val)))
41        },
42        _ => panic!("add: expected two integers on stack"),
43    }
44}
45
46/// Subtract two integers (a - b)
47///
48/// Stack effect: ( a b -- a-b )
49///
50/// # Safety
51/// Stack must have two Int values on top
52#[unsafe(no_mangle)]
53pub unsafe extern "C" fn patch_seq_subtract(stack: Stack) -> Stack {
54    let (rest, a, b) = unsafe { pop_two(stack, "subtract") };
55    match (a, b) {
56        (Value::Int(a_val), Value::Int(b_val)) => unsafe {
57            push(rest, Value::Int(a_val.wrapping_sub(b_val)))
58        },
59        _ => panic!("subtract: expected two integers on stack"),
60    }
61}
62
63/// Multiply two integers
64///
65/// Stack effect: ( a b -- a*b )
66///
67/// # Safety
68/// Stack must have two Int values on top
69#[unsafe(no_mangle)]
70pub unsafe extern "C" fn patch_seq_multiply(stack: Stack) -> Stack {
71    let (rest, a, b) = unsafe { pop_two(stack, "multiply") };
72    match (a, b) {
73        (Value::Int(a_val), Value::Int(b_val)) => unsafe {
74            push(rest, Value::Int(a_val.wrapping_mul(b_val)))
75        },
76        _ => panic!("multiply: expected two integers on stack"),
77    }
78}
79
80/// Divide two integers (a / b)
81///
82/// Stack effect: ( a b -- result success )
83///
84/// Returns the quotient and a Bool success flag.
85/// On division by zero, returns (0, false).
86/// On success, returns (a/b, true).
87///
88/// # Safety
89/// Stack must have at least two values on top
90#[unsafe(no_mangle)]
91pub unsafe extern "C" fn patch_seq_divide(stack: Stack) -> Stack {
92    let (rest, a, b) = unsafe { pop_two(stack, "divide") };
93    match (a, b) {
94        (Value::Int(_a_val), Value::Int(0)) => {
95            // Division by zero - return 0 and false
96            let stack = unsafe { push(rest, Value::Int(0)) };
97            unsafe { push(stack, Value::Bool(false)) }
98        }
99        (Value::Int(a_val), Value::Int(b_val)) => {
100            // Use wrapping_div to handle i64::MIN / -1 overflow edge case
101            let stack = unsafe { push(rest, Value::Int(a_val.wrapping_div(b_val))) };
102            unsafe { push(stack, Value::Bool(true)) }
103        }
104        _ => {
105            // Type error - should not happen with type-checked code
106            panic!("divide: expected two integers on stack");
107        }
108    }
109}
110
111/// Modulo (remainder) of two integers (a % b)
112///
113/// Stack effect: ( a b -- result success )
114///
115/// Returns the remainder and a Bool success flag.
116/// On division by zero, returns (0, false).
117/// On success, returns (a%b, true).
118///
119/// # Safety
120/// Stack must have at least two values on top
121#[unsafe(no_mangle)]
122pub unsafe extern "C" fn patch_seq_modulo(stack: Stack) -> Stack {
123    let (rest, a, b) = unsafe { pop_two(stack, "modulo") };
124    match (a, b) {
125        (Value::Int(_a_val), Value::Int(0)) => {
126            // Division by zero - return 0 and false
127            let stack = unsafe { push(rest, Value::Int(0)) };
128            unsafe { push(stack, Value::Bool(false)) }
129        }
130        (Value::Int(a_val), Value::Int(b_val)) => {
131            // Use wrapping_rem to handle i64::MIN % -1 overflow edge case
132            let stack = unsafe { push(rest, Value::Int(a_val.wrapping_rem(b_val))) };
133            unsafe { push(stack, Value::Bool(true)) }
134        }
135        _ => {
136            // Type error - should not happen with type-checked code
137            panic!("modulo: expected two integers on stack");
138        }
139    }
140}