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)]
98pub unsafe extern "C" fn patch_seq_f_eq(stack: Stack) -> Stack {
99 let (rest, a, b) = unsafe { pop_two(stack, "f.=") };
100 match (a, b) {
101 (Value::Float(x), Value::Float(y)) => unsafe {
102 push(rest, Value::Int(if x == y { 1 } else { 0 }))
103 },
104 _ => panic!("f.=: expected two Floats on stack"),
105 }
106}
107
108#[unsafe(no_mangle)]
113pub unsafe extern "C" fn patch_seq_f_lt(stack: Stack) -> Stack {
114 let (rest, a, b) = unsafe { pop_two(stack, "f.<") };
115 match (a, b) {
116 (Value::Float(x), Value::Float(y)) => unsafe {
117 push(rest, Value::Int(if x < y { 1 } else { 0 }))
118 },
119 _ => panic!("f.<: expected two Floats on stack"),
120 }
121}
122
123#[unsafe(no_mangle)]
128pub unsafe extern "C" fn patch_seq_f_gt(stack: Stack) -> Stack {
129 let (rest, a, b) = unsafe { pop_two(stack, "f.>") };
130 match (a, b) {
131 (Value::Float(x), Value::Float(y)) => unsafe {
132 push(rest, Value::Int(if x > y { 1 } else { 0 }))
133 },
134 _ => panic!("f.>: expected two Floats on stack"),
135 }
136}
137
138#[unsafe(no_mangle)]
143pub unsafe extern "C" fn patch_seq_f_lte(stack: Stack) -> Stack {
144 let (rest, a, b) = unsafe { pop_two(stack, "f.<=") };
145 match (a, b) {
146 (Value::Float(x), Value::Float(y)) => unsafe {
147 push(rest, Value::Int(if x <= y { 1 } else { 0 }))
148 },
149 _ => panic!("f.<=: expected two Floats on stack"),
150 }
151}
152
153#[unsafe(no_mangle)]
158pub unsafe extern "C" fn patch_seq_f_gte(stack: Stack) -> Stack {
159 let (rest, a, b) = unsafe { pop_two(stack, "f.>=") };
160 match (a, b) {
161 (Value::Float(x), Value::Float(y)) => unsafe {
162 push(rest, Value::Int(if x >= y { 1 } else { 0 }))
163 },
164 _ => panic!("f.>=: expected two Floats on stack"),
165 }
166}
167
168#[unsafe(no_mangle)]
173pub unsafe extern "C" fn patch_seq_f_neq(stack: Stack) -> Stack {
174 let (rest, a, b) = unsafe { pop_two(stack, "f.<>") };
175 match (a, b) {
176 (Value::Float(x), Value::Float(y)) => unsafe {
177 push(rest, Value::Int(if x != y { 1 } else { 0 }))
178 },
179 _ => panic!("f.<>: expected two Floats on stack"),
180 }
181}
182
183#[unsafe(no_mangle)]
192pub unsafe extern "C" fn patch_seq_int_to_float(stack: Stack) -> Stack {
193 assert!(!stack.is_null(), "int->float: stack is empty");
194 let (stack, val) = unsafe { pop(stack) };
195
196 match val {
197 Value::Int(i) => unsafe { push(stack, Value::Float(i as f64)) },
198 _ => panic!("int->float: expected Int on stack"),
199 }
200}
201
202#[unsafe(no_mangle)]
212pub unsafe extern "C" fn patch_seq_float_to_int(stack: Stack) -> Stack {
213 assert!(!stack.is_null(), "float->int: stack is empty");
214 let (stack, val) = unsafe { pop(stack) };
215
216 match val {
217 Value::Float(f) => {
218 let i = if f.is_nan() {
220 0
221 } else if f >= i64::MAX as f64 {
222 i64::MAX
223 } else if f <= i64::MIN as f64 {
224 i64::MIN
225 } else {
226 f as i64
227 };
228 unsafe { push(stack, Value::Int(i)) }
229 }
230 _ => panic!("float->int: expected Float on stack"),
231 }
232}
233
234#[unsafe(no_mangle)]
239pub unsafe extern "C" fn patch_seq_float_to_string(stack: Stack) -> Stack {
240 assert!(!stack.is_null(), "float->string: stack is empty");
241 let (stack, val) = unsafe { pop(stack) };
242
243 match val {
244 Value::Float(f) => {
245 let s = f.to_string();
246 unsafe { push(stack, Value::String(global_string(s))) }
247 }
248 _ => panic!("float->string: expected Float on stack"),
249 }
250}
251
252#[unsafe(no_mangle)]
258pub unsafe extern "C" fn patch_seq_string_to_float(stack: Stack) -> Stack {
259 assert!(!stack.is_null(), "string->float: stack is empty");
260 let (stack, val) = unsafe { pop(stack) };
261
262 match val {
263 Value::String(s) => match s.as_str().parse::<f64>() {
264 Ok(f) => {
265 let stack = unsafe { push(stack, Value::Float(f)) };
266 unsafe { push(stack, Value::Bool(true)) }
267 }
268 Err(_) => {
269 let stack = unsafe { push(stack, Value::Float(0.0)) };
270 unsafe { push(stack, Value::Bool(false)) }
271 }
272 },
273 _ => panic!("string->float: expected String on stack"),
274 }
275}
276
277pub use patch_seq_f_add as f_add;
282pub use patch_seq_f_divide as f_divide;
283pub use patch_seq_f_eq as f_eq;
284pub use patch_seq_f_gt as f_gt;
285pub use patch_seq_f_gte as f_gte;
286pub use patch_seq_f_lt as f_lt;
287pub use patch_seq_f_lte as f_lte;
288pub use patch_seq_f_multiply as f_multiply;
289pub use patch_seq_f_neq as f_neq;
290pub use patch_seq_f_subtract as f_subtract;
291pub use patch_seq_float_to_int as float_to_int;
292pub use patch_seq_float_to_string as float_to_string;
293pub use patch_seq_int_to_float as int_to_float;
294pub use patch_seq_push_float as push_float;
295pub use patch_seq_string_to_float as string_to_float;
296
297#[cfg(test)]
302mod tests {
303 use super::*;
304
305 #[test]
306 fn test_push_float() {
307 unsafe {
308 let stack = crate::stack::alloc_test_stack();
309 let stack = push_float(stack, 3.5);
310
311 let (_stack, result) = pop(stack);
312 assert_eq!(result, Value::Float(3.5));
313 }
314 }
315
316 #[test]
317 fn test_f_add() {
318 unsafe {
319 let stack = crate::stack::alloc_test_stack();
320 let stack = push(stack, Value::Float(1.5));
321 let stack = push(stack, Value::Float(2.5));
322
323 let stack = f_add(stack);
324
325 let (_stack, result) = pop(stack);
326 assert_eq!(result, Value::Float(4.0));
327 }
328 }
329
330 #[test]
331 fn test_f_subtract() {
332 unsafe {
333 let stack = crate::stack::alloc_test_stack();
334 let stack = push(stack, Value::Float(5.0));
335 let stack = push(stack, Value::Float(2.0));
336
337 let stack = f_subtract(stack);
338
339 let (_stack, result) = pop(stack);
340 assert_eq!(result, Value::Float(3.0));
341 }
342 }
343
344 #[test]
345 fn test_f_multiply() {
346 unsafe {
347 let stack = crate::stack::alloc_test_stack();
348 let stack = push(stack, Value::Float(3.0));
349 let stack = push(stack, Value::Float(4.0));
350
351 let stack = f_multiply(stack);
352
353 let (_stack, result) = pop(stack);
354 assert_eq!(result, Value::Float(12.0));
355 }
356 }
357
358 #[test]
359 fn test_f_divide() {
360 unsafe {
361 let stack = crate::stack::alloc_test_stack();
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 }
370 }
371
372 #[test]
373 fn test_f_divide_by_zero() {
374 unsafe {
375 let stack = crate::stack::alloc_test_stack();
376 let stack = push(stack, Value::Float(1.0));
377 let stack = push(stack, Value::Float(0.0));
378
379 let stack = f_divide(stack);
380
381 let (_stack, result) = pop(stack);
382 match result {
383 Value::Float(f) => assert!(f.is_infinite()),
384 _ => panic!("Expected Float"),
385 }
386 }
387 }
388
389 #[test]
390 fn test_f_eq_true() {
391 unsafe {
392 let stack = crate::stack::alloc_test_stack();
393 let stack = push(stack, Value::Float(3.5));
394 let stack = push(stack, Value::Float(3.5));
395
396 let stack = f_eq(stack);
397
398 let (_stack, result) = pop(stack);
399 assert_eq!(result, Value::Int(1));
400 }
401 }
402
403 #[test]
404 fn test_f_eq_false() {
405 unsafe {
406 let stack = crate::stack::alloc_test_stack();
407 let stack = push(stack, Value::Float(3.5));
408 let stack = push(stack, Value::Float(2.5));
409
410 let stack = f_eq(stack);
411
412 let (_stack, result) = pop(stack);
413 assert_eq!(result, Value::Int(0));
414 }
415 }
416
417 #[test]
418 fn test_f_lt() {
419 unsafe {
420 let stack = crate::stack::alloc_test_stack();
421 let stack = push(stack, Value::Float(1.5));
422 let stack = push(stack, Value::Float(2.5));
423
424 let stack = f_lt(stack);
425
426 let (_stack, result) = pop(stack);
427 assert_eq!(result, Value::Int(1)); }
429 }
430
431 #[test]
432 fn test_f_gt() {
433 unsafe {
434 let stack = crate::stack::alloc_test_stack();
435 let stack = push(stack, Value::Float(2.5));
436 let stack = push(stack, Value::Float(1.5));
437
438 let stack = f_gt(stack);
439
440 let (_stack, result) = pop(stack);
441 assert_eq!(result, Value::Int(1)); }
443 }
444
445 #[test]
446 fn test_f_lte() {
447 unsafe {
448 let stack = crate::stack::alloc_test_stack();
449 let stack = push(stack, Value::Float(2.5));
450 let stack = push(stack, Value::Float(2.5));
451
452 let stack = f_lte(stack);
453
454 let (_stack, result) = pop(stack);
455 assert_eq!(result, Value::Int(1)); }
457 }
458
459 #[test]
460 fn test_f_gte() {
461 unsafe {
462 let stack = crate::stack::alloc_test_stack();
463 let stack = push(stack, Value::Float(2.5));
464 let stack = push(stack, Value::Float(2.5));
465
466 let stack = f_gte(stack);
467
468 let (_stack, result) = pop(stack);
469 assert_eq!(result, Value::Int(1)); }
471 }
472
473 #[test]
474 fn test_f_neq() {
475 unsafe {
476 let stack = crate::stack::alloc_test_stack();
477 let stack = push(stack, Value::Float(1.0));
478 let stack = push(stack, Value::Float(2.0));
479
480 let stack = f_neq(stack);
481
482 let (_stack, result) = pop(stack);
483 assert_eq!(result, Value::Int(1)); }
485 }
486
487 #[test]
488 fn test_int_to_float() {
489 unsafe {
490 let stack = crate::stack::alloc_test_stack();
491 let stack = push(stack, Value::Int(42));
492
493 let stack = int_to_float(stack);
494
495 let (_stack, result) = pop(stack);
496 assert_eq!(result, Value::Float(42.0));
497 }
498 }
499
500 #[test]
501 fn test_float_to_int() {
502 unsafe {
503 let stack = crate::stack::alloc_test_stack();
504 let stack = push(stack, Value::Float(3.7));
505
506 let stack = float_to_int(stack);
507
508 let (_stack, result) = pop(stack);
509 assert_eq!(result, Value::Int(3)); }
511 }
512
513 #[test]
514 fn test_float_to_int_negative() {
515 unsafe {
516 let stack = crate::stack::alloc_test_stack();
517 let stack = push(stack, Value::Float(-3.7));
518
519 let stack = float_to_int(stack);
520
521 let (_stack, result) = pop(stack);
522 assert_eq!(result, Value::Int(-3)); }
524 }
525
526 #[cfg(not(feature = "tagged-ptr"))]
528 #[test]
529 fn test_float_to_int_overflow_positive() {
530 unsafe {
531 let stack = crate::stack::alloc_test_stack();
532 let stack = push(stack, Value::Float(1e20)); let stack = float_to_int(stack);
535
536 let (_stack, result) = pop(stack);
537 assert_eq!(result, Value::Int(i64::MAX)); }
539 }
540
541 #[cfg(not(feature = "tagged-ptr"))]
543 #[test]
544 fn test_float_to_int_overflow_negative() {
545 unsafe {
546 let stack = crate::stack::alloc_test_stack();
547 let stack = push(stack, Value::Float(-1e20)); let stack = float_to_int(stack);
550
551 let (_stack, result) = pop(stack);
552 assert_eq!(result, Value::Int(i64::MIN)); }
554 }
555
556 #[test]
557 fn test_float_to_int_nan() {
558 unsafe {
559 let stack = crate::stack::alloc_test_stack();
560 let stack = push(stack, Value::Float(f64::NAN));
561
562 let stack = float_to_int(stack);
563
564 let (_stack, result) = pop(stack);
565 assert_eq!(result, Value::Int(0)); }
567 }
568
569 #[cfg(not(feature = "tagged-ptr"))]
571 #[test]
572 fn test_float_to_int_infinity() {
573 unsafe {
574 let stack = crate::stack::alloc_test_stack();
575 let stack = push(stack, Value::Float(f64::INFINITY));
576
577 let stack = float_to_int(stack);
578
579 let (_stack, result) = pop(stack);
580 assert_eq!(result, Value::Int(i64::MAX)); }
582 }
583
584 #[test]
585 fn test_float_to_string() {
586 unsafe {
587 let stack = crate::stack::alloc_test_stack();
588 let stack = push(stack, Value::Float(3.5));
589
590 let stack = float_to_string(stack);
591
592 let (_stack, result) = pop(stack);
593 match result {
594 Value::String(s) => assert_eq!(s.as_str(), "3.5"),
595 _ => panic!("Expected String"),
596 }
597 }
598 }
599
600 #[test]
601 fn test_float_to_string_whole_number() {
602 unsafe {
603 let stack = crate::stack::alloc_test_stack();
604 let stack = push(stack, Value::Float(42.0));
605
606 let stack = float_to_string(stack);
607
608 let (_stack, result) = pop(stack);
609 match result {
610 Value::String(s) => assert_eq!(s.as_str(), "42"),
611 _ => panic!("Expected String"),
612 }
613 }
614 }
615
616 #[test]
617 fn test_nan_propagation() {
618 unsafe {
619 let stack = crate::stack::alloc_test_stack();
620 let stack = push(stack, Value::Float(f64::NAN));
621 let stack = push(stack, Value::Float(1.0));
622
623 let stack = f_add(stack);
624
625 let (_stack, result) = pop(stack);
626 match result {
627 Value::Float(f) => assert!(f.is_nan()),
628 _ => panic!("Expected Float"),
629 }
630 }
631 }
632
633 #[test]
634 fn test_infinity() {
635 unsafe {
636 let stack = crate::stack::alloc_test_stack();
637 let stack = push(stack, Value::Float(f64::INFINITY));
638 let stack = push(stack, Value::Float(1.0));
639
640 let stack = f_add(stack);
641
642 let (_stack, result) = pop(stack);
643 match result {
644 Value::Float(f) => assert!(f.is_infinite()),
645 _ => panic!("Expected Float"),
646 }
647 }
648 }
649}