seq_runtime/arithmetic/
arith.rs1use crate::stack::{Stack, pop_two, push};
5use crate::value::Value;
6
7#[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#[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#[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#[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#[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#[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 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 let stack = unsafe { push(rest, Value::Int(a_val.wrapping_div(b_val))) };
102 unsafe { push(stack, Value::Bool(true)) }
103 }
104 _ => {
105 panic!("divide: expected two integers on stack");
107 }
108 }
109}
110
111#[unsafe(no_mangle)]
125pub unsafe extern "C" fn patch_seq_pow(stack: Stack) -> Stack {
126 let (rest, a, b) = unsafe { pop_two(stack, "pow") };
127 match (a, b) {
128 (Value::Int(base), Value::Int(exp)) => {
129 let result = if (0..=i64::from(u32::MAX)).contains(&exp) {
130 base.checked_pow(exp as u32)
131 } else {
132 None
133 };
134 match result {
135 Some(v) => {
136 let stack = unsafe { push(rest, Value::Int(v)) };
137 unsafe { push(stack, Value::Bool(true)) }
138 }
139 None => {
140 let stack = unsafe { push(rest, Value::Int(0)) };
141 unsafe { push(stack, Value::Bool(false)) }
142 }
143 }
144 }
145 _ => panic!("pow: expected two integers on stack"),
146 }
147}
148
149#[unsafe(no_mangle)]
160pub unsafe extern "C" fn patch_seq_modulo(stack: Stack) -> Stack {
161 let (rest, a, b) = unsafe { pop_two(stack, "modulo") };
162 match (a, b) {
163 (Value::Int(_a_val), Value::Int(0)) => {
164 let stack = unsafe { push(rest, Value::Int(0)) };
166 unsafe { push(stack, Value::Bool(false)) }
167 }
168 (Value::Int(a_val), Value::Int(b_val)) => {
169 let stack = unsafe { push(rest, Value::Int(a_val.wrapping_rem(b_val))) };
171 unsafe { push(stack, Value::Bool(true)) }
172 }
173 _ => {
174 panic!("modulo: expected two integers on stack");
176 }
177 }
178}