1use crate::seqstring::global_string;
7use crate::stack::{Stack, pop, 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 assert!(!stack.is_null(), "f.add: stack is empty");
34 let (stack, b) = unsafe { pop(stack) };
35 assert!(!stack.is_null(), "f.add: need two floats");
36 let (stack, a) = unsafe { pop(stack) };
37
38 match (a, b) {
39 (Value::Float(x), Value::Float(y)) => unsafe { push(stack, Value::Float(x + y)) },
40 _ => panic!("f.add: expected two Floats on stack"),
41 }
42}
43
44#[unsafe(no_mangle)]
49pub unsafe extern "C" fn patch_seq_f_subtract(stack: Stack) -> Stack {
50 assert!(!stack.is_null(), "f.subtract: stack is empty");
51 let (stack, b) = unsafe { pop(stack) };
52 assert!(!stack.is_null(), "f.subtract: need two floats");
53 let (stack, a) = unsafe { pop(stack) };
54
55 match (a, b) {
56 (Value::Float(x), Value::Float(y)) => unsafe { push(stack, Value::Float(x - y)) },
57 _ => panic!("f.subtract: expected two Floats on stack"),
58 }
59}
60
61#[unsafe(no_mangle)]
66pub unsafe extern "C" fn patch_seq_f_multiply(stack: Stack) -> Stack {
67 assert!(!stack.is_null(), "f.multiply: stack is empty");
68 let (stack, b) = unsafe { pop(stack) };
69 assert!(!stack.is_null(), "f.multiply: need two floats");
70 let (stack, a) = unsafe { pop(stack) };
71
72 match (a, b) {
73 (Value::Float(x), Value::Float(y)) => unsafe { push(stack, Value::Float(x * y)) },
74 _ => panic!("f.multiply: expected two Floats on stack"),
75 }
76}
77
78#[unsafe(no_mangle)]
85pub unsafe extern "C" fn patch_seq_f_divide(stack: Stack) -> Stack {
86 assert!(!stack.is_null(), "f.divide: stack is empty");
87 let (stack, b) = unsafe { pop(stack) };
88 assert!(!stack.is_null(), "f.divide: need two floats");
89 let (stack, a) = unsafe { pop(stack) };
90
91 match (a, b) {
92 (Value::Float(x), Value::Float(y)) => unsafe { push(stack, Value::Float(x / y)) },
93 _ => panic!("f.divide: expected two Floats on stack"),
94 }
95}
96
97#[unsafe(no_mangle)]
110pub unsafe extern "C" fn patch_seq_f_eq(stack: Stack) -> Stack {
111 assert!(!stack.is_null(), "f.=: stack is empty");
112 let (stack, b) = unsafe { pop(stack) };
113 assert!(!stack.is_null(), "f.=: need two floats");
114 let (stack, a) = unsafe { pop(stack) };
115
116 match (a, b) {
117 (Value::Float(x), Value::Float(y)) => {
118 let result = if x == y { 1 } else { 0 };
119 unsafe { push(stack, Value::Int(result)) }
120 }
121 _ => panic!("f.=: expected two Floats on stack"),
122 }
123}
124
125#[unsafe(no_mangle)]
130pub unsafe extern "C" fn patch_seq_f_lt(stack: Stack) -> Stack {
131 assert!(!stack.is_null(), "f.<: stack is empty");
132 let (stack, b) = unsafe { pop(stack) };
133 assert!(!stack.is_null(), "f.<: need two floats");
134 let (stack, a) = unsafe { pop(stack) };
135
136 match (a, b) {
137 (Value::Float(x), Value::Float(y)) => {
138 let result = if x < y { 1 } else { 0 };
139 unsafe { push(stack, Value::Int(result)) }
140 }
141 _ => panic!("f.<: expected two Floats on stack"),
142 }
143}
144
145#[unsafe(no_mangle)]
150pub unsafe extern "C" fn patch_seq_f_gt(stack: Stack) -> Stack {
151 assert!(!stack.is_null(), "f.>: stack is empty");
152 let (stack, b) = unsafe { pop(stack) };
153 assert!(!stack.is_null(), "f.>: need two floats");
154 let (stack, a) = unsafe { pop(stack) };
155
156 match (a, b) {
157 (Value::Float(x), Value::Float(y)) => {
158 let result = if x > y { 1 } else { 0 };
159 unsafe { push(stack, Value::Int(result)) }
160 }
161 _ => panic!("f.>: expected two Floats on stack"),
162 }
163}
164
165#[unsafe(no_mangle)]
170pub unsafe extern "C" fn patch_seq_f_lte(stack: Stack) -> Stack {
171 assert!(!stack.is_null(), "f.<=: stack is empty");
172 let (stack, b) = unsafe { pop(stack) };
173 assert!(!stack.is_null(), "f.<=: need two floats");
174 let (stack, a) = unsafe { pop(stack) };
175
176 match (a, b) {
177 (Value::Float(x), Value::Float(y)) => {
178 let result = if x <= y { 1 } else { 0 };
179 unsafe { push(stack, Value::Int(result)) }
180 }
181 _ => panic!("f.<=: expected two Floats on stack"),
182 }
183}
184
185#[unsafe(no_mangle)]
190pub unsafe extern "C" fn patch_seq_f_gte(stack: Stack) -> Stack {
191 assert!(!stack.is_null(), "f.>=: stack is empty");
192 let (stack, b) = unsafe { pop(stack) };
193 assert!(!stack.is_null(), "f.>=: need two floats");
194 let (stack, a) = unsafe { pop(stack) };
195
196 match (a, b) {
197 (Value::Float(x), Value::Float(y)) => {
198 let result = if x >= y { 1 } else { 0 };
199 unsafe { push(stack, Value::Int(result)) }
200 }
201 _ => panic!("f.>=: expected two Floats on stack"),
202 }
203}
204
205#[unsafe(no_mangle)]
210pub unsafe extern "C" fn patch_seq_f_neq(stack: Stack) -> Stack {
211 assert!(!stack.is_null(), "f.<>: stack is empty");
212 let (stack, b) = unsafe { pop(stack) };
213 assert!(!stack.is_null(), "f.<>: need two floats");
214 let (stack, a) = unsafe { pop(stack) };
215
216 match (a, b) {
217 (Value::Float(x), Value::Float(y)) => {
218 let result = if x != y { 1 } else { 0 };
219 unsafe { push(stack, Value::Int(result)) }
220 }
221 _ => panic!("f.<>: expected two Floats on stack"),
222 }
223}
224
225#[unsafe(no_mangle)]
234pub unsafe extern "C" fn patch_seq_int_to_float(stack: Stack) -> Stack {
235 assert!(!stack.is_null(), "int->float: stack is empty");
236 let (stack, val) = unsafe { pop(stack) };
237
238 match val {
239 Value::Int(i) => unsafe { push(stack, Value::Float(i as f64)) },
240 _ => panic!("int->float: expected Int on stack"),
241 }
242}
243
244#[unsafe(no_mangle)]
254pub unsafe extern "C" fn patch_seq_float_to_int(stack: Stack) -> Stack {
255 assert!(!stack.is_null(), "float->int: stack is empty");
256 let (stack, val) = unsafe { pop(stack) };
257
258 match val {
259 Value::Float(f) => {
260 let i = if f.is_nan() {
262 0
263 } else if f >= i64::MAX as f64 {
264 i64::MAX
265 } else if f <= i64::MIN as f64 {
266 i64::MIN
267 } else {
268 f as i64
269 };
270 unsafe { push(stack, Value::Int(i)) }
271 }
272 _ => panic!("float->int: expected Float on stack"),
273 }
274}
275
276#[unsafe(no_mangle)]
281pub unsafe extern "C" fn patch_seq_float_to_string(stack: Stack) -> Stack {
282 assert!(!stack.is_null(), "float->string: stack is empty");
283 let (stack, val) = unsafe { pop(stack) };
284
285 match val {
286 Value::Float(f) => {
287 let s = f.to_string();
288 unsafe { push(stack, Value::String(global_string(s))) }
289 }
290 _ => panic!("float->string: expected Float on stack"),
291 }
292}
293
294#[unsafe(no_mangle)]
300pub unsafe extern "C" fn patch_seq_string_to_float(stack: Stack) -> Stack {
301 assert!(!stack.is_null(), "string->float: stack is empty");
302 let (stack, val) = unsafe { pop(stack) };
303
304 match val {
305 Value::String(s) => match s.as_str().parse::<f64>() {
306 Ok(f) => {
307 let stack = unsafe { push(stack, Value::Float(f)) };
308 unsafe { push(stack, Value::Int(1)) }
309 }
310 Err(_) => {
311 let stack = unsafe { push(stack, Value::Float(0.0)) };
312 unsafe { push(stack, Value::Int(0)) }
313 }
314 },
315 _ => panic!("string->float: expected String on stack"),
316 }
317}
318
319pub use patch_seq_f_add as f_add;
324pub use patch_seq_f_divide as f_divide;
325pub use patch_seq_f_eq as f_eq;
326pub use patch_seq_f_gt as f_gt;
327pub use patch_seq_f_gte as f_gte;
328pub use patch_seq_f_lt as f_lt;
329pub use patch_seq_f_lte as f_lte;
330pub use patch_seq_f_multiply as f_multiply;
331pub use patch_seq_f_neq as f_neq;
332pub use patch_seq_f_subtract as f_subtract;
333pub use patch_seq_float_to_int as float_to_int;
334pub use patch_seq_float_to_string as float_to_string;
335pub use patch_seq_int_to_float as int_to_float;
336pub use patch_seq_push_float as push_float;
337pub use patch_seq_string_to_float as string_to_float;
338
339#[cfg(test)]
344mod tests {
345 use super::*;
346
347 #[test]
348 fn test_push_float() {
349 unsafe {
350 let stack = std::ptr::null_mut();
351 let stack = push_float(stack, 3.5);
352
353 let (stack, result) = pop(stack);
354 assert_eq!(result, Value::Float(3.5));
355 assert!(stack.is_null());
356 }
357 }
358
359 #[test]
360 fn test_f_add() {
361 unsafe {
362 let stack = std::ptr::null_mut();
363 let stack = push(stack, Value::Float(1.5));
364 let stack = push(stack, Value::Float(2.5));
365
366 let stack = f_add(stack);
367
368 let (stack, result) = pop(stack);
369 assert_eq!(result, Value::Float(4.0));
370 assert!(stack.is_null());
371 }
372 }
373
374 #[test]
375 fn test_f_subtract() {
376 unsafe {
377 let stack = std::ptr::null_mut();
378 let stack = push(stack, Value::Float(5.0));
379 let stack = push(stack, Value::Float(2.0));
380
381 let stack = f_subtract(stack);
382
383 let (stack, result) = pop(stack);
384 assert_eq!(result, Value::Float(3.0));
385 assert!(stack.is_null());
386 }
387 }
388
389 #[test]
390 fn test_f_multiply() {
391 unsafe {
392 let stack = std::ptr::null_mut();
393 let stack = push(stack, Value::Float(3.0));
394 let stack = push(stack, Value::Float(4.0));
395
396 let stack = f_multiply(stack);
397
398 let (stack, result) = pop(stack);
399 assert_eq!(result, Value::Float(12.0));
400 assert!(stack.is_null());
401 }
402 }
403
404 #[test]
405 fn test_f_divide() {
406 unsafe {
407 let stack = std::ptr::null_mut();
408 let stack = push(stack, Value::Float(10.0));
409 let stack = push(stack, Value::Float(4.0));
410
411 let stack = f_divide(stack);
412
413 let (stack, result) = pop(stack);
414 assert_eq!(result, Value::Float(2.5));
415 assert!(stack.is_null());
416 }
417 }
418
419 #[test]
420 fn test_f_divide_by_zero() {
421 unsafe {
422 let stack = std::ptr::null_mut();
423 let stack = push(stack, Value::Float(1.0));
424 let stack = push(stack, Value::Float(0.0));
425
426 let stack = f_divide(stack);
427
428 let (stack, result) = pop(stack);
429 match result {
430 Value::Float(f) => assert!(f.is_infinite()),
431 _ => panic!("Expected Float"),
432 }
433 assert!(stack.is_null());
434 }
435 }
436
437 #[test]
438 fn test_f_eq_true() {
439 unsafe {
440 let stack = std::ptr::null_mut();
441 let stack = push(stack, Value::Float(3.5));
442 let stack = push(stack, Value::Float(3.5));
443
444 let stack = f_eq(stack);
445
446 let (stack, result) = pop(stack);
447 assert_eq!(result, Value::Int(1));
448 assert!(stack.is_null());
449 }
450 }
451
452 #[test]
453 fn test_f_eq_false() {
454 unsafe {
455 let stack = std::ptr::null_mut();
456 let stack = push(stack, Value::Float(3.5));
457 let stack = push(stack, Value::Float(2.5));
458
459 let stack = f_eq(stack);
460
461 let (stack, result) = pop(stack);
462 assert_eq!(result, Value::Int(0));
463 assert!(stack.is_null());
464 }
465 }
466
467 #[test]
468 fn test_f_lt() {
469 unsafe {
470 let stack = std::ptr::null_mut();
471 let stack = push(stack, Value::Float(1.5));
472 let stack = push(stack, Value::Float(2.5));
473
474 let stack = f_lt(stack);
475
476 let (stack, result) = pop(stack);
477 assert_eq!(result, Value::Int(1)); assert!(stack.is_null());
479 }
480 }
481
482 #[test]
483 fn test_f_gt() {
484 unsafe {
485 let stack = std::ptr::null_mut();
486 let stack = push(stack, Value::Float(2.5));
487 let stack = push(stack, Value::Float(1.5));
488
489 let stack = f_gt(stack);
490
491 let (stack, result) = pop(stack);
492 assert_eq!(result, Value::Int(1)); assert!(stack.is_null());
494 }
495 }
496
497 #[test]
498 fn test_f_lte() {
499 unsafe {
500 let stack = std::ptr::null_mut();
501 let stack = push(stack, Value::Float(2.5));
502 let stack = push(stack, Value::Float(2.5));
503
504 let stack = f_lte(stack);
505
506 let (stack, result) = pop(stack);
507 assert_eq!(result, Value::Int(1)); assert!(stack.is_null());
509 }
510 }
511
512 #[test]
513 fn test_f_gte() {
514 unsafe {
515 let stack = std::ptr::null_mut();
516 let stack = push(stack, Value::Float(2.5));
517 let stack = push(stack, Value::Float(2.5));
518
519 let stack = f_gte(stack);
520
521 let (stack, result) = pop(stack);
522 assert_eq!(result, Value::Int(1)); assert!(stack.is_null());
524 }
525 }
526
527 #[test]
528 fn test_f_neq() {
529 unsafe {
530 let stack = std::ptr::null_mut();
531 let stack = push(stack, Value::Float(1.0));
532 let stack = push(stack, Value::Float(2.0));
533
534 let stack = f_neq(stack);
535
536 let (stack, result) = pop(stack);
537 assert_eq!(result, Value::Int(1)); assert!(stack.is_null());
539 }
540 }
541
542 #[test]
543 fn test_int_to_float() {
544 unsafe {
545 let stack = std::ptr::null_mut();
546 let stack = push(stack, Value::Int(42));
547
548 let stack = int_to_float(stack);
549
550 let (stack, result) = pop(stack);
551 assert_eq!(result, Value::Float(42.0));
552 assert!(stack.is_null());
553 }
554 }
555
556 #[test]
557 fn test_float_to_int() {
558 unsafe {
559 let stack = std::ptr::null_mut();
560 let stack = push(stack, Value::Float(3.7));
561
562 let stack = float_to_int(stack);
563
564 let (stack, result) = pop(stack);
565 assert_eq!(result, Value::Int(3)); assert!(stack.is_null());
567 }
568 }
569
570 #[test]
571 fn test_float_to_int_negative() {
572 unsafe {
573 let stack = std::ptr::null_mut();
574 let stack = push(stack, Value::Float(-3.7));
575
576 let stack = float_to_int(stack);
577
578 let (stack, result) = pop(stack);
579 assert_eq!(result, Value::Int(-3)); assert!(stack.is_null());
581 }
582 }
583
584 #[test]
585 fn test_float_to_int_overflow_positive() {
586 unsafe {
587 let stack = std::ptr::null_mut();
588 let stack = push(stack, Value::Float(1e20)); let stack = float_to_int(stack);
591
592 let (stack, result) = pop(stack);
593 assert_eq!(result, Value::Int(i64::MAX)); assert!(stack.is_null());
595 }
596 }
597
598 #[test]
599 fn test_float_to_int_overflow_negative() {
600 unsafe {
601 let stack = std::ptr::null_mut();
602 let stack = push(stack, Value::Float(-1e20)); let stack = float_to_int(stack);
605
606 let (stack, result) = pop(stack);
607 assert_eq!(result, Value::Int(i64::MIN)); assert!(stack.is_null());
609 }
610 }
611
612 #[test]
613 fn test_float_to_int_nan() {
614 unsafe {
615 let stack = std::ptr::null_mut();
616 let stack = push(stack, Value::Float(f64::NAN));
617
618 let stack = float_to_int(stack);
619
620 let (stack, result) = pop(stack);
621 assert_eq!(result, Value::Int(0)); assert!(stack.is_null());
623 }
624 }
625
626 #[test]
627 fn test_float_to_int_infinity() {
628 unsafe {
629 let stack = std::ptr::null_mut();
630 let stack = push(stack, Value::Float(f64::INFINITY));
631
632 let stack = float_to_int(stack);
633
634 let (stack, result) = pop(stack);
635 assert_eq!(result, Value::Int(i64::MAX)); assert!(stack.is_null());
637 }
638 }
639
640 #[test]
641 fn test_float_to_string() {
642 unsafe {
643 let stack = std::ptr::null_mut();
644 let stack = push(stack, Value::Float(3.5));
645
646 let stack = float_to_string(stack);
647
648 let (stack, result) = pop(stack);
649 match result {
650 Value::String(s) => assert_eq!(s.as_str(), "3.5"),
651 _ => panic!("Expected String"),
652 }
653 assert!(stack.is_null());
654 }
655 }
656
657 #[test]
658 fn test_float_to_string_whole_number() {
659 unsafe {
660 let stack = std::ptr::null_mut();
661 let stack = push(stack, Value::Float(42.0));
662
663 let stack = float_to_string(stack);
664
665 let (stack, result) = pop(stack);
666 match result {
667 Value::String(s) => assert_eq!(s.as_str(), "42"),
668 _ => panic!("Expected String"),
669 }
670 assert!(stack.is_null());
671 }
672 }
673
674 #[test]
675 fn test_nan_propagation() {
676 unsafe {
677 let stack = std::ptr::null_mut();
678 let stack = push(stack, Value::Float(f64::NAN));
679 let stack = push(stack, Value::Float(1.0));
680
681 let stack = f_add(stack);
682
683 let (stack, result) = pop(stack);
684 match result {
685 Value::Float(f) => assert!(f.is_nan()),
686 _ => panic!("Expected Float"),
687 }
688 assert!(stack.is_null());
689 }
690 }
691
692 #[test]
693 fn test_infinity() {
694 unsafe {
695 let stack = std::ptr::null_mut();
696 let stack = push(stack, Value::Float(f64::INFINITY));
697 let stack = push(stack, Value::Float(1.0));
698
699 let stack = f_add(stack);
700
701 let (stack, result) = pop(stack);
702 match result {
703 Value::Float(f) => assert!(f.is_infinite()),
704 _ => panic!("Expected Float"),
705 }
706 assert!(stack.is_null());
707 }
708 }
709}