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 = std::ptr::null_mut();
305 let stack = push_float(stack, 3.5);
306
307 let (stack, result) = pop(stack);
308 assert_eq!(result, Value::Float(3.5));
309 assert!(stack.is_null());
310 }
311 }
312
313 #[test]
314 fn test_f_add() {
315 unsafe {
316 let stack = std::ptr::null_mut();
317 let stack = push(stack, Value::Float(1.5));
318 let stack = push(stack, Value::Float(2.5));
319
320 let stack = f_add(stack);
321
322 let (stack, result) = pop(stack);
323 assert_eq!(result, Value::Float(4.0));
324 assert!(stack.is_null());
325 }
326 }
327
328 #[test]
329 fn test_f_subtract() {
330 unsafe {
331 let stack = std::ptr::null_mut();
332 let stack = push(stack, Value::Float(5.0));
333 let stack = push(stack, Value::Float(2.0));
334
335 let stack = f_subtract(stack);
336
337 let (stack, result) = pop(stack);
338 assert_eq!(result, Value::Float(3.0));
339 assert!(stack.is_null());
340 }
341 }
342
343 #[test]
344 fn test_f_multiply() {
345 unsafe {
346 let stack = std::ptr::null_mut();
347 let stack = push(stack, Value::Float(3.0));
348 let stack = push(stack, Value::Float(4.0));
349
350 let stack = f_multiply(stack);
351
352 let (stack, result) = pop(stack);
353 assert_eq!(result, Value::Float(12.0));
354 assert!(stack.is_null());
355 }
356 }
357
358 #[test]
359 fn test_f_divide() {
360 unsafe {
361 let stack = std::ptr::null_mut();
362 let stack = push(stack, Value::Float(10.0));
363 let stack = push(stack, Value::Float(4.0));
364
365 let stack = f_divide(stack);
366
367 let (stack, result) = pop(stack);
368 assert_eq!(result, Value::Float(2.5));
369 assert!(stack.is_null());
370 }
371 }
372
373 #[test]
374 fn test_f_divide_by_zero() {
375 unsafe {
376 let stack = std::ptr::null_mut();
377 let stack = push(stack, Value::Float(1.0));
378 let stack = push(stack, Value::Float(0.0));
379
380 let stack = f_divide(stack);
381
382 let (stack, result) = pop(stack);
383 match result {
384 Value::Float(f) => assert!(f.is_infinite()),
385 _ => panic!("Expected Float"),
386 }
387 assert!(stack.is_null());
388 }
389 }
390
391 #[test]
392 fn test_f_eq_true() {
393 unsafe {
394 let stack = std::ptr::null_mut();
395 let stack = push(stack, Value::Float(3.5));
396 let stack = push(stack, Value::Float(3.5));
397
398 let stack = f_eq(stack);
399
400 let (stack, result) = pop(stack);
401 assert_eq!(result, Value::Int(1));
402 assert!(stack.is_null());
403 }
404 }
405
406 #[test]
407 fn test_f_eq_false() {
408 unsafe {
409 let stack = std::ptr::null_mut();
410 let stack = push(stack, Value::Float(3.5));
411 let stack = push(stack, Value::Float(2.5));
412
413 let stack = f_eq(stack);
414
415 let (stack, result) = pop(stack);
416 assert_eq!(result, Value::Int(0));
417 assert!(stack.is_null());
418 }
419 }
420
421 #[test]
422 fn test_f_lt() {
423 unsafe {
424 let stack = std::ptr::null_mut();
425 let stack = push(stack, Value::Float(1.5));
426 let stack = push(stack, Value::Float(2.5));
427
428 let stack = f_lt(stack);
429
430 let (stack, result) = pop(stack);
431 assert_eq!(result, Value::Int(1)); assert!(stack.is_null());
433 }
434 }
435
436 #[test]
437 fn test_f_gt() {
438 unsafe {
439 let stack = std::ptr::null_mut();
440 let stack = push(stack, Value::Float(2.5));
441 let stack = push(stack, Value::Float(1.5));
442
443 let stack = f_gt(stack);
444
445 let (stack, result) = pop(stack);
446 assert_eq!(result, Value::Int(1)); assert!(stack.is_null());
448 }
449 }
450
451 #[test]
452 fn test_f_lte() {
453 unsafe {
454 let stack = std::ptr::null_mut();
455 let stack = push(stack, Value::Float(2.5));
456 let stack = push(stack, Value::Float(2.5));
457
458 let stack = f_lte(stack);
459
460 let (stack, result) = pop(stack);
461 assert_eq!(result, Value::Int(1)); assert!(stack.is_null());
463 }
464 }
465
466 #[test]
467 fn test_f_gte() {
468 unsafe {
469 let stack = std::ptr::null_mut();
470 let stack = push(stack, Value::Float(2.5));
471 let stack = push(stack, Value::Float(2.5));
472
473 let stack = f_gte(stack);
474
475 let (stack, result) = pop(stack);
476 assert_eq!(result, Value::Int(1)); assert!(stack.is_null());
478 }
479 }
480
481 #[test]
482 fn test_f_neq() {
483 unsafe {
484 let stack = std::ptr::null_mut();
485 let stack = push(stack, Value::Float(1.0));
486 let stack = push(stack, Value::Float(2.0));
487
488 let stack = f_neq(stack);
489
490 let (stack, result) = pop(stack);
491 assert_eq!(result, Value::Int(1)); assert!(stack.is_null());
493 }
494 }
495
496 #[test]
497 fn test_int_to_float() {
498 unsafe {
499 let stack = std::ptr::null_mut();
500 let stack = push(stack, Value::Int(42));
501
502 let stack = int_to_float(stack);
503
504 let (stack, result) = pop(stack);
505 assert_eq!(result, Value::Float(42.0));
506 assert!(stack.is_null());
507 }
508 }
509
510 #[test]
511 fn test_float_to_int() {
512 unsafe {
513 let stack = std::ptr::null_mut();
514 let stack = push(stack, Value::Float(3.7));
515
516 let stack = float_to_int(stack);
517
518 let (stack, result) = pop(stack);
519 assert_eq!(result, Value::Int(3)); assert!(stack.is_null());
521 }
522 }
523
524 #[test]
525 fn test_float_to_int_negative() {
526 unsafe {
527 let stack = std::ptr::null_mut();
528 let stack = push(stack, Value::Float(-3.7));
529
530 let stack = float_to_int(stack);
531
532 let (stack, result) = pop(stack);
533 assert_eq!(result, Value::Int(-3)); assert!(stack.is_null());
535 }
536 }
537
538 #[test]
539 fn test_float_to_int_overflow_positive() {
540 unsafe {
541 let stack = std::ptr::null_mut();
542 let stack = push(stack, Value::Float(1e20)); let stack = float_to_int(stack);
545
546 let (stack, result) = pop(stack);
547 assert_eq!(result, Value::Int(i64::MAX)); assert!(stack.is_null());
549 }
550 }
551
552 #[test]
553 fn test_float_to_int_overflow_negative() {
554 unsafe {
555 let stack = std::ptr::null_mut();
556 let stack = push(stack, Value::Float(-1e20)); let stack = float_to_int(stack);
559
560 let (stack, result) = pop(stack);
561 assert_eq!(result, Value::Int(i64::MIN)); assert!(stack.is_null());
563 }
564 }
565
566 #[test]
567 fn test_float_to_int_nan() {
568 unsafe {
569 let stack = std::ptr::null_mut();
570 let stack = push(stack, Value::Float(f64::NAN));
571
572 let stack = float_to_int(stack);
573
574 let (stack, result) = pop(stack);
575 assert_eq!(result, Value::Int(0)); assert!(stack.is_null());
577 }
578 }
579
580 #[test]
581 fn test_float_to_int_infinity() {
582 unsafe {
583 let stack = std::ptr::null_mut();
584 let stack = push(stack, Value::Float(f64::INFINITY));
585
586 let stack = float_to_int(stack);
587
588 let (stack, result) = pop(stack);
589 assert_eq!(result, Value::Int(i64::MAX)); assert!(stack.is_null());
591 }
592 }
593
594 #[test]
595 fn test_float_to_string() {
596 unsafe {
597 let stack = std::ptr::null_mut();
598 let stack = push(stack, Value::Float(3.5));
599
600 let stack = float_to_string(stack);
601
602 let (stack, result) = pop(stack);
603 match result {
604 Value::String(s) => assert_eq!(s.as_str(), "3.5"),
605 _ => panic!("Expected String"),
606 }
607 assert!(stack.is_null());
608 }
609 }
610
611 #[test]
612 fn test_float_to_string_whole_number() {
613 unsafe {
614 let stack = std::ptr::null_mut();
615 let stack = push(stack, Value::Float(42.0));
616
617 let stack = float_to_string(stack);
618
619 let (stack, result) = pop(stack);
620 match result {
621 Value::String(s) => assert_eq!(s.as_str(), "42"),
622 _ => panic!("Expected String"),
623 }
624 assert!(stack.is_null());
625 }
626 }
627
628 #[test]
629 fn test_nan_propagation() {
630 unsafe {
631 let stack = std::ptr::null_mut();
632 let stack = push(stack, Value::Float(f64::NAN));
633 let stack = push(stack, Value::Float(1.0));
634
635 let stack = f_add(stack);
636
637 let (stack, result) = pop(stack);
638 match result {
639 Value::Float(f) => assert!(f.is_nan()),
640 _ => panic!("Expected Float"),
641 }
642 assert!(stack.is_null());
643 }
644 }
645
646 #[test]
647 fn test_infinity() {
648 unsafe {
649 let stack = std::ptr::null_mut();
650 let stack = push(stack, Value::Float(f64::INFINITY));
651 let stack = push(stack, Value::Float(1.0));
652
653 let stack = f_add(stack);
654
655 let (stack, result) = pop(stack);
656 match result {
657 Value::Float(f) => assert!(f.is_infinite()),
658 _ => panic!("Expected Float"),
659 }
660 assert!(stack.is_null());
661 }
662 }
663}