1use crate::seqstring::global_string;
7use crate::stack::{Stack, pop, pop_two, push};
8use crate::value::Value;
9
10#[unsafe(no_mangle)]
19pub unsafe extern "C" fn patch_seq_push_float(stack: Stack, value: f64) -> Stack {
20 unsafe { push(stack, Value::Float(value)) }
21}
22
23#[unsafe(no_mangle)]
32pub unsafe extern "C" fn patch_seq_f_add(stack: Stack) -> Stack {
33 let (rest, a, b) = unsafe { pop_two(stack, "f.add") };
34 match (a, b) {
35 (Value::Float(x), Value::Float(y)) => unsafe { push(rest, Value::Float(x + y)) },
36 _ => panic!("f.add: expected two Floats on stack"),
37 }
38}
39
40#[unsafe(no_mangle)]
45pub unsafe extern "C" fn patch_seq_f_subtract(stack: Stack) -> Stack {
46 let (rest, a, b) = unsafe { pop_two(stack, "f.subtract") };
47 match (a, b) {
48 (Value::Float(x), Value::Float(y)) => unsafe { push(rest, Value::Float(x - y)) },
49 _ => panic!("f.subtract: expected two Floats on stack"),
50 }
51}
52
53#[unsafe(no_mangle)]
58pub unsafe extern "C" fn patch_seq_f_multiply(stack: Stack) -> Stack {
59 let (rest, a, b) = unsafe { pop_two(stack, "f.multiply") };
60 match (a, b) {
61 (Value::Float(x), Value::Float(y)) => unsafe { push(rest, Value::Float(x * y)) },
62 _ => panic!("f.multiply: expected two Floats on stack"),
63 }
64}
65
66#[unsafe(no_mangle)]
73pub unsafe extern "C" fn patch_seq_f_divide(stack: Stack) -> Stack {
74 let (rest, a, b) = unsafe { pop_two(stack, "f.divide") };
75 match (a, b) {
76 (Value::Float(x), Value::Float(y)) => unsafe { push(rest, Value::Float(x / y)) },
77 _ => panic!("f.divide: expected two Floats on stack"),
78 }
79}
80
81#[unsafe(no_mangle)]
94pub unsafe extern "C" fn patch_seq_f_eq(stack: Stack) -> Stack {
95 let (rest, a, b) = unsafe { pop_two(stack, "f.=") };
96 match (a, b) {
97 (Value::Float(x), Value::Float(y)) => unsafe { push(rest, Value::Bool(x == y)) },
98 _ => panic!("f.=: expected two Floats on stack"),
99 }
100}
101
102#[unsafe(no_mangle)]
107pub unsafe extern "C" fn patch_seq_f_lt(stack: Stack) -> Stack {
108 let (rest, a, b) = unsafe { pop_two(stack, "f.<") };
109 match (a, b) {
110 (Value::Float(x), Value::Float(y)) => unsafe { push(rest, Value::Bool(x < y)) },
111 _ => panic!("f.<: expected two Floats on stack"),
112 }
113}
114
115#[unsafe(no_mangle)]
120pub unsafe extern "C" fn patch_seq_f_gt(stack: Stack) -> Stack {
121 let (rest, a, b) = unsafe { pop_two(stack, "f.>") };
122 match (a, b) {
123 (Value::Float(x), Value::Float(y)) => unsafe { push(rest, Value::Bool(x > y)) },
124 _ => panic!("f.>: expected two Floats on stack"),
125 }
126}
127
128#[unsafe(no_mangle)]
133pub unsafe extern "C" fn patch_seq_f_lte(stack: Stack) -> Stack {
134 let (rest, a, b) = unsafe { pop_two(stack, "f.<=") };
135 match (a, b) {
136 (Value::Float(x), Value::Float(y)) => unsafe { push(rest, Value::Bool(x <= y)) },
137 _ => panic!("f.<=: expected two Floats on stack"),
138 }
139}
140
141#[unsafe(no_mangle)]
146pub unsafe extern "C" fn patch_seq_f_gte(stack: Stack) -> Stack {
147 let (rest, a, b) = unsafe { pop_two(stack, "f.>=") };
148 match (a, b) {
149 (Value::Float(x), Value::Float(y)) => unsafe { push(rest, Value::Bool(x >= y)) },
150 _ => panic!("f.>=: expected two Floats on stack"),
151 }
152}
153
154#[unsafe(no_mangle)]
159pub unsafe extern "C" fn patch_seq_f_neq(stack: Stack) -> Stack {
160 let (rest, a, b) = unsafe { pop_two(stack, "f.<>") };
161 match (a, b) {
162 (Value::Float(x), Value::Float(y)) => unsafe { push(rest, Value::Bool(x != y)) },
163 _ => panic!("f.<>: expected two Floats on stack"),
164 }
165}
166
167#[unsafe(no_mangle)]
176pub unsafe extern "C" fn patch_seq_int_to_float(stack: Stack) -> Stack {
177 assert!(!stack.is_null(), "int->float: stack is empty");
178 let (stack, val) = unsafe { pop(stack) };
179
180 match val {
181 Value::Int(i) => unsafe { push(stack, Value::Float(i as f64)) },
182 _ => panic!("int->float: expected Int on stack"),
183 }
184}
185
186#[unsafe(no_mangle)]
196pub unsafe extern "C" fn patch_seq_float_to_int(stack: Stack) -> Stack {
197 assert!(!stack.is_null(), "float->int: stack is empty");
198 let (stack, val) = unsafe { pop(stack) };
199
200 match val {
201 Value::Float(f) => {
202 const INT63_MAX: i64 = (1i64 << 62) - 1;
205 const INT63_MIN: i64 = -(1i64 << 62);
206 let i = if f.is_nan() {
207 0
208 } else if f >= INT63_MAX as f64 {
209 INT63_MAX
210 } else if f <= INT63_MIN as f64 {
211 INT63_MIN
212 } else {
213 f as i64
214 };
215 unsafe { push(stack, Value::Int(i)) }
216 }
217 _ => panic!("float->int: expected Float on stack"),
218 }
219}
220
221#[unsafe(no_mangle)]
226pub unsafe extern "C" fn patch_seq_float_to_string(stack: Stack) -> Stack {
227 assert!(!stack.is_null(), "float->string: stack is empty");
228 let (stack, val) = unsafe { pop(stack) };
229
230 match val {
231 Value::Float(f) => {
232 let s = f.to_string();
233 unsafe { push(stack, Value::String(global_string(s))) }
234 }
235 _ => panic!("float->string: expected Float on stack"),
236 }
237}
238
239#[unsafe(no_mangle)]
245pub unsafe extern "C" fn patch_seq_string_to_float(stack: Stack) -> Stack {
246 assert!(!stack.is_null(), "string->float: stack is empty");
247 let (stack, val) = unsafe { pop(stack) };
248
249 match val {
250 Value::String(s) => match s.as_str().parse::<f64>() {
251 Ok(f) => {
252 let stack = unsafe { push(stack, Value::Float(f)) };
253 unsafe { push(stack, Value::Bool(true)) }
254 }
255 Err(_) => {
256 let stack = unsafe { push(stack, Value::Float(0.0)) };
257 unsafe { push(stack, Value::Bool(false)) }
258 }
259 },
260 _ => panic!("string->float: expected String on stack"),
261 }
262}
263
264pub use patch_seq_f_add as f_add;
269pub use patch_seq_f_divide as f_divide;
270pub use patch_seq_f_eq as f_eq;
271pub use patch_seq_f_gt as f_gt;
272pub use patch_seq_f_gte as f_gte;
273pub use patch_seq_f_lt as f_lt;
274pub use patch_seq_f_lte as f_lte;
275pub use patch_seq_f_multiply as f_multiply;
276pub use patch_seq_f_neq as f_neq;
277pub use patch_seq_f_subtract as f_subtract;
278pub use patch_seq_float_to_int as float_to_int;
279pub use patch_seq_float_to_string as float_to_string;
280pub use patch_seq_int_to_float as int_to_float;
281pub use patch_seq_push_float as push_float;
282pub use patch_seq_string_to_float as string_to_float;
283
284#[cfg(test)]
289mod tests;