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 {
98 push(rest, Value::Int(if x == y { 1 } else { 0 }))
99 },
100 _ => panic!("f.=: expected two Floats on stack"),
101 }
102}
103
104#[unsafe(no_mangle)]
109pub unsafe extern "C" fn patch_seq_f_lt(stack: Stack) -> Stack {
110 let (rest, a, b) = unsafe { pop_two(stack, "f.<") };
111 match (a, b) {
112 (Value::Float(x), Value::Float(y)) => unsafe {
113 push(rest, Value::Int(if x < y { 1 } else { 0 }))
114 },
115 _ => panic!("f.<: expected two Floats on stack"),
116 }
117}
118
119#[unsafe(no_mangle)]
124pub unsafe extern "C" fn patch_seq_f_gt(stack: Stack) -> Stack {
125 let (rest, a, b) = unsafe { pop_two(stack, "f.>") };
126 match (a, b) {
127 (Value::Float(x), Value::Float(y)) => unsafe {
128 push(rest, Value::Int(if x > y { 1 } else { 0 }))
129 },
130 _ => panic!("f.>: expected two Floats on stack"),
131 }
132}
133
134#[unsafe(no_mangle)]
139pub unsafe extern "C" fn patch_seq_f_lte(stack: Stack) -> Stack {
140 let (rest, a, b) = unsafe { pop_two(stack, "f.<=") };
141 match (a, b) {
142 (Value::Float(x), Value::Float(y)) => unsafe {
143 push(rest, Value::Int(if x <= y { 1 } else { 0 }))
144 },
145 _ => panic!("f.<=: expected two Floats on stack"),
146 }
147}
148
149#[unsafe(no_mangle)]
154pub unsafe extern "C" fn patch_seq_f_gte(stack: Stack) -> Stack {
155 let (rest, a, b) = unsafe { pop_two(stack, "f.>=") };
156 match (a, b) {
157 (Value::Float(x), Value::Float(y)) => unsafe {
158 push(rest, Value::Int(if x >= y { 1 } else { 0 }))
159 },
160 _ => panic!("f.>=: expected two Floats on stack"),
161 }
162}
163
164#[unsafe(no_mangle)]
169pub unsafe extern "C" fn patch_seq_f_neq(stack: Stack) -> Stack {
170 let (rest, a, b) = unsafe { pop_two(stack, "f.<>") };
171 match (a, b) {
172 (Value::Float(x), Value::Float(y)) => unsafe {
173 push(rest, Value::Int(if x != y { 1 } else { 0 }))
174 },
175 _ => panic!("f.<>: expected two Floats on stack"),
176 }
177}
178
179#[unsafe(no_mangle)]
188pub unsafe extern "C" fn patch_seq_int_to_float(stack: Stack) -> Stack {
189 assert!(!stack.is_null(), "int->float: stack is empty");
190 let (stack, val) = unsafe { pop(stack) };
191
192 match val {
193 Value::Int(i) => unsafe { push(stack, Value::Float(i as f64)) },
194 _ => panic!("int->float: expected Int on stack"),
195 }
196}
197
198#[unsafe(no_mangle)]
208pub unsafe extern "C" fn patch_seq_float_to_int(stack: Stack) -> Stack {
209 assert!(!stack.is_null(), "float->int: stack is empty");
210 let (stack, val) = unsafe { pop(stack) };
211
212 match val {
213 Value::Float(f) => {
214 let i = if f.is_nan() {
216 0
217 } else if f >= i64::MAX as f64 {
218 i64::MAX
219 } else if f <= i64::MIN as f64 {
220 i64::MIN
221 } else {
222 f as i64
223 };
224 unsafe { push(stack, Value::Int(i)) }
225 }
226 _ => panic!("float->int: expected Float on stack"),
227 }
228}
229
230#[unsafe(no_mangle)]
235pub unsafe extern "C" fn patch_seq_float_to_string(stack: Stack) -> Stack {
236 assert!(!stack.is_null(), "float->string: stack is empty");
237 let (stack, val) = unsafe { pop(stack) };
238
239 match val {
240 Value::Float(f) => {
241 let s = f.to_string();
242 unsafe { push(stack, Value::String(global_string(s))) }
243 }
244 _ => panic!("float->string: expected Float on stack"),
245 }
246}
247
248#[unsafe(no_mangle)]
254pub unsafe extern "C" fn patch_seq_string_to_float(stack: Stack) -> Stack {
255 assert!(!stack.is_null(), "string->float: stack is empty");
256 let (stack, val) = unsafe { pop(stack) };
257
258 match val {
259 Value::String(s) => match s.as_str().parse::<f64>() {
260 Ok(f) => {
261 let stack = unsafe { push(stack, Value::Float(f)) };
262 unsafe { push(stack, Value::Int(1)) }
263 }
264 Err(_) => {
265 let stack = unsafe { push(stack, Value::Float(0.0)) };
266 unsafe { push(stack, Value::Int(0)) }
267 }
268 },
269 _ => panic!("string->float: expected String on stack"),
270 }
271}
272
273pub use patch_seq_f_add as f_add;
278pub use patch_seq_f_divide as f_divide;
279pub use patch_seq_f_eq as f_eq;
280pub use patch_seq_f_gt as f_gt;
281pub use patch_seq_f_gte as f_gte;
282pub use patch_seq_f_lt as f_lt;
283pub use patch_seq_f_lte as f_lte;
284pub use patch_seq_f_multiply as f_multiply;
285pub use patch_seq_f_neq as f_neq;
286pub use patch_seq_f_subtract as f_subtract;
287pub use patch_seq_float_to_int as float_to_int;
288pub use patch_seq_float_to_string as float_to_string;
289pub use patch_seq_int_to_float as int_to_float;
290pub use patch_seq_push_float as push_float;
291pub use patch_seq_string_to_float as string_to_float;
292
293#[cfg(test)]
298mod tests {
299 use super::*;
300
301 #[test]
302 fn test_push_float() {
303 unsafe {
304 let stack = crate::stack::alloc_test_stack();
305 let stack = push_float(stack, 3.5);
306
307 let (_stack, result) = pop(stack);
308 assert_eq!(result, Value::Float(3.5));
309 }
310 }
311
312 #[test]
313 fn test_f_add() {
314 unsafe {
315 let stack = crate::stack::alloc_test_stack();
316 let stack = push(stack, Value::Float(1.5));
317 let stack = push(stack, Value::Float(2.5));
318
319 let stack = f_add(stack);
320
321 let (_stack, result) = pop(stack);
322 assert_eq!(result, Value::Float(4.0));
323 }
324 }
325
326 #[test]
327 fn test_f_subtract() {
328 unsafe {
329 let stack = crate::stack::alloc_test_stack();
330 let stack = push(stack, Value::Float(5.0));
331 let stack = push(stack, Value::Float(2.0));
332
333 let stack = f_subtract(stack);
334
335 let (_stack, result) = pop(stack);
336 assert_eq!(result, Value::Float(3.0));
337 }
338 }
339
340 #[test]
341 fn test_f_multiply() {
342 unsafe {
343 let stack = crate::stack::alloc_test_stack();
344 let stack = push(stack, Value::Float(3.0));
345 let stack = push(stack, Value::Float(4.0));
346
347 let stack = f_multiply(stack);
348
349 let (_stack, result) = pop(stack);
350 assert_eq!(result, Value::Float(12.0));
351 }
352 }
353
354 #[test]
355 fn test_f_divide() {
356 unsafe {
357 let stack = crate::stack::alloc_test_stack();
358 let stack = push(stack, Value::Float(10.0));
359 let stack = push(stack, Value::Float(4.0));
360
361 let stack = f_divide(stack);
362
363 let (_stack, result) = pop(stack);
364 assert_eq!(result, Value::Float(2.5));
365 }
366 }
367
368 #[test]
369 fn test_f_divide_by_zero() {
370 unsafe {
371 let stack = crate::stack::alloc_test_stack();
372 let stack = push(stack, Value::Float(1.0));
373 let stack = push(stack, Value::Float(0.0));
374
375 let stack = f_divide(stack);
376
377 let (_stack, result) = pop(stack);
378 match result {
379 Value::Float(f) => assert!(f.is_infinite()),
380 _ => panic!("Expected Float"),
381 }
382 }
383 }
384
385 #[test]
386 fn test_f_eq_true() {
387 unsafe {
388 let stack = crate::stack::alloc_test_stack();
389 let stack = push(stack, Value::Float(3.5));
390 let stack = push(stack, Value::Float(3.5));
391
392 let stack = f_eq(stack);
393
394 let (_stack, result) = pop(stack);
395 assert_eq!(result, Value::Int(1));
396 }
397 }
398
399 #[test]
400 fn test_f_eq_false() {
401 unsafe {
402 let stack = crate::stack::alloc_test_stack();
403 let stack = push(stack, Value::Float(3.5));
404 let stack = push(stack, Value::Float(2.5));
405
406 let stack = f_eq(stack);
407
408 let (_stack, result) = pop(stack);
409 assert_eq!(result, Value::Int(0));
410 }
411 }
412
413 #[test]
414 fn test_f_lt() {
415 unsafe {
416 let stack = crate::stack::alloc_test_stack();
417 let stack = push(stack, Value::Float(1.5));
418 let stack = push(stack, Value::Float(2.5));
419
420 let stack = f_lt(stack);
421
422 let (_stack, result) = pop(stack);
423 assert_eq!(result, Value::Int(1)); }
425 }
426
427 #[test]
428 fn test_f_gt() {
429 unsafe {
430 let stack = crate::stack::alloc_test_stack();
431 let stack = push(stack, Value::Float(2.5));
432 let stack = push(stack, Value::Float(1.5));
433
434 let stack = f_gt(stack);
435
436 let (_stack, result) = pop(stack);
437 assert_eq!(result, Value::Int(1)); }
439 }
440
441 #[test]
442 fn test_f_lte() {
443 unsafe {
444 let stack = crate::stack::alloc_test_stack();
445 let stack = push(stack, Value::Float(2.5));
446 let stack = push(stack, Value::Float(2.5));
447
448 let stack = f_lte(stack);
449
450 let (_stack, result) = pop(stack);
451 assert_eq!(result, Value::Int(1)); }
453 }
454
455 #[test]
456 fn test_f_gte() {
457 unsafe {
458 let stack = crate::stack::alloc_test_stack();
459 let stack = push(stack, Value::Float(2.5));
460 let stack = push(stack, Value::Float(2.5));
461
462 let stack = f_gte(stack);
463
464 let (_stack, result) = pop(stack);
465 assert_eq!(result, Value::Int(1)); }
467 }
468
469 #[test]
470 fn test_f_neq() {
471 unsafe {
472 let stack = crate::stack::alloc_test_stack();
473 let stack = push(stack, Value::Float(1.0));
474 let stack = push(stack, Value::Float(2.0));
475
476 let stack = f_neq(stack);
477
478 let (_stack, result) = pop(stack);
479 assert_eq!(result, Value::Int(1)); }
481 }
482
483 #[test]
484 fn test_int_to_float() {
485 unsafe {
486 let stack = crate::stack::alloc_test_stack();
487 let stack = push(stack, Value::Int(42));
488
489 let stack = int_to_float(stack);
490
491 let (_stack, result) = pop(stack);
492 assert_eq!(result, Value::Float(42.0));
493 }
494 }
495
496 #[test]
497 fn test_float_to_int() {
498 unsafe {
499 let stack = crate::stack::alloc_test_stack();
500 let stack = push(stack, Value::Float(3.7));
501
502 let stack = float_to_int(stack);
503
504 let (_stack, result) = pop(stack);
505 assert_eq!(result, Value::Int(3)); }
507 }
508
509 #[test]
510 fn test_float_to_int_negative() {
511 unsafe {
512 let stack = crate::stack::alloc_test_stack();
513 let stack = push(stack, Value::Float(-3.7));
514
515 let stack = float_to_int(stack);
516
517 let (_stack, result) = pop(stack);
518 assert_eq!(result, Value::Int(-3)); }
520 }
521
522 #[test]
523 fn test_float_to_int_overflow_positive() {
524 unsafe {
525 let stack = crate::stack::alloc_test_stack();
526 let stack = push(stack, Value::Float(1e20)); let stack = float_to_int(stack);
529
530 let (_stack, result) = pop(stack);
531 assert_eq!(result, Value::Int(i64::MAX)); }
533 }
534
535 #[test]
536 fn test_float_to_int_overflow_negative() {
537 unsafe {
538 let stack = crate::stack::alloc_test_stack();
539 let stack = push(stack, Value::Float(-1e20)); let stack = float_to_int(stack);
542
543 let (_stack, result) = pop(stack);
544 assert_eq!(result, Value::Int(i64::MIN)); }
546 }
547
548 #[test]
549 fn test_float_to_int_nan() {
550 unsafe {
551 let stack = crate::stack::alloc_test_stack();
552 let stack = push(stack, Value::Float(f64::NAN));
553
554 let stack = float_to_int(stack);
555
556 let (_stack, result) = pop(stack);
557 assert_eq!(result, Value::Int(0)); }
559 }
560
561 #[test]
562 fn test_float_to_int_infinity() {
563 unsafe {
564 let stack = crate::stack::alloc_test_stack();
565 let stack = push(stack, Value::Float(f64::INFINITY));
566
567 let stack = float_to_int(stack);
568
569 let (_stack, result) = pop(stack);
570 assert_eq!(result, Value::Int(i64::MAX)); }
572 }
573
574 #[test]
575 fn test_float_to_string() {
576 unsafe {
577 let stack = crate::stack::alloc_test_stack();
578 let stack = push(stack, Value::Float(3.5));
579
580 let stack = float_to_string(stack);
581
582 let (_stack, result) = pop(stack);
583 match result {
584 Value::String(s) => assert_eq!(s.as_str(), "3.5"),
585 _ => panic!("Expected String"),
586 }
587 }
588 }
589
590 #[test]
591 fn test_float_to_string_whole_number() {
592 unsafe {
593 let stack = crate::stack::alloc_test_stack();
594 let stack = push(stack, Value::Float(42.0));
595
596 let stack = float_to_string(stack);
597
598 let (_stack, result) = pop(stack);
599 match result {
600 Value::String(s) => assert_eq!(s.as_str(), "42"),
601 _ => panic!("Expected String"),
602 }
603 }
604 }
605
606 #[test]
607 fn test_nan_propagation() {
608 unsafe {
609 let stack = crate::stack::alloc_test_stack();
610 let stack = push(stack, Value::Float(f64::NAN));
611 let stack = push(stack, Value::Float(1.0));
612
613 let stack = f_add(stack);
614
615 let (_stack, result) = pop(stack);
616 match result {
617 Value::Float(f) => assert!(f.is_nan()),
618 _ => panic!("Expected Float"),
619 }
620 }
621 }
622
623 #[test]
624 fn test_infinity() {
625 unsafe {
626 let stack = crate::stack::alloc_test_stack();
627 let stack = push(stack, Value::Float(f64::INFINITY));
628 let stack = push(stack, Value::Float(1.0));
629
630 let stack = f_add(stack);
631
632 let (_stack, result) = pop(stack);
633 match result {
634 Value::Float(f) => assert!(f.is_infinite()),
635 _ => panic!("Expected Float"),
636 }
637 }
638 }
639}