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 const INT63_MAX: i64 = (1i64 << 62) - 1;
221 const INT63_MIN: i64 = -(1i64 << 62);
222 let i = if f.is_nan() {
223 0
224 } else if f >= INT63_MAX as f64 {
225 INT63_MAX
226 } else if f <= INT63_MIN as f64 {
227 INT63_MIN
228 } else {
229 f as i64
230 };
231 unsafe { push(stack, Value::Int(i)) }
232 }
233 _ => panic!("float->int: expected Float on stack"),
234 }
235}
236
237#[unsafe(no_mangle)]
242pub unsafe extern "C" fn patch_seq_float_to_string(stack: Stack) -> Stack {
243 assert!(!stack.is_null(), "float->string: stack is empty");
244 let (stack, val) = unsafe { pop(stack) };
245
246 match val {
247 Value::Float(f) => {
248 let s = f.to_string();
249 unsafe { push(stack, Value::String(global_string(s))) }
250 }
251 _ => panic!("float->string: expected Float on stack"),
252 }
253}
254
255#[unsafe(no_mangle)]
261pub unsafe extern "C" fn patch_seq_string_to_float(stack: Stack) -> Stack {
262 assert!(!stack.is_null(), "string->float: stack is empty");
263 let (stack, val) = unsafe { pop(stack) };
264
265 match val {
266 Value::String(s) => match s.as_str().parse::<f64>() {
267 Ok(f) => {
268 let stack = unsafe { push(stack, Value::Float(f)) };
269 unsafe { push(stack, Value::Bool(true)) }
270 }
271 Err(_) => {
272 let stack = unsafe { push(stack, Value::Float(0.0)) };
273 unsafe { push(stack, Value::Bool(false)) }
274 }
275 },
276 _ => panic!("string->float: expected String on stack"),
277 }
278}
279
280pub use patch_seq_f_add as f_add;
285pub use patch_seq_f_divide as f_divide;
286pub use patch_seq_f_eq as f_eq;
287pub use patch_seq_f_gt as f_gt;
288pub use patch_seq_f_gte as f_gte;
289pub use patch_seq_f_lt as f_lt;
290pub use patch_seq_f_lte as f_lte;
291pub use patch_seq_f_multiply as f_multiply;
292pub use patch_seq_f_neq as f_neq;
293pub use patch_seq_f_subtract as f_subtract;
294pub use patch_seq_float_to_int as float_to_int;
295pub use patch_seq_float_to_string as float_to_string;
296pub use patch_seq_int_to_float as int_to_float;
297pub use patch_seq_push_float as push_float;
298pub use patch_seq_string_to_float as string_to_float;
299
300#[cfg(test)]
305mod tests {
306 use super::*;
307
308 #[test]
309 fn test_push_float() {
310 unsafe {
311 let stack = crate::stack::alloc_test_stack();
312 let stack = push_float(stack, 3.5);
313
314 let (_stack, result) = pop(stack);
315 assert_eq!(result, Value::Float(3.5));
316 }
317 }
318
319 #[test]
320 fn test_f_add() {
321 unsafe {
322 let stack = crate::stack::alloc_test_stack();
323 let stack = push(stack, Value::Float(1.5));
324 let stack = push(stack, Value::Float(2.5));
325
326 let stack = f_add(stack);
327
328 let (_stack, result) = pop(stack);
329 assert_eq!(result, Value::Float(4.0));
330 }
331 }
332
333 #[test]
334 fn test_f_subtract() {
335 unsafe {
336 let stack = crate::stack::alloc_test_stack();
337 let stack = push(stack, Value::Float(5.0));
338 let stack = push(stack, Value::Float(2.0));
339
340 let stack = f_subtract(stack);
341
342 let (_stack, result) = pop(stack);
343 assert_eq!(result, Value::Float(3.0));
344 }
345 }
346
347 #[test]
348 fn test_f_multiply() {
349 unsafe {
350 let stack = crate::stack::alloc_test_stack();
351 let stack = push(stack, Value::Float(3.0));
352 let stack = push(stack, Value::Float(4.0));
353
354 let stack = f_multiply(stack);
355
356 let (_stack, result) = pop(stack);
357 assert_eq!(result, Value::Float(12.0));
358 }
359 }
360
361 #[test]
362 fn test_f_divide() {
363 unsafe {
364 let stack = crate::stack::alloc_test_stack();
365 let stack = push(stack, Value::Float(10.0));
366 let stack = push(stack, Value::Float(4.0));
367
368 let stack = f_divide(stack);
369
370 let (_stack, result) = pop(stack);
371 assert_eq!(result, Value::Float(2.5));
372 }
373 }
374
375 #[test]
376 fn test_f_divide_by_zero() {
377 unsafe {
378 let stack = crate::stack::alloc_test_stack();
379 let stack = push(stack, Value::Float(1.0));
380 let stack = push(stack, Value::Float(0.0));
381
382 let stack = f_divide(stack);
383
384 let (_stack, result) = pop(stack);
385 match result {
386 Value::Float(f) => assert!(f.is_infinite()),
387 _ => panic!("Expected Float"),
388 }
389 }
390 }
391
392 #[test]
393 fn test_f_eq_true() {
394 unsafe {
395 let stack = crate::stack::alloc_test_stack();
396 let stack = push(stack, Value::Float(3.5));
397 let stack = push(stack, Value::Float(3.5));
398
399 let stack = f_eq(stack);
400
401 let (_stack, result) = pop(stack);
402 assert_eq!(result, Value::Int(1));
403 }
404 }
405
406 #[test]
407 fn test_f_eq_false() {
408 unsafe {
409 let stack = crate::stack::alloc_test_stack();
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 }
418 }
419
420 #[test]
421 fn test_f_lt() {
422 unsafe {
423 let stack = crate::stack::alloc_test_stack();
424 let stack = push(stack, Value::Float(1.5));
425 let stack = push(stack, Value::Float(2.5));
426
427 let stack = f_lt(stack);
428
429 let (_stack, result) = pop(stack);
430 assert_eq!(result, Value::Int(1)); }
432 }
433
434 #[test]
435 fn test_f_gt() {
436 unsafe {
437 let stack = crate::stack::alloc_test_stack();
438 let stack = push(stack, Value::Float(2.5));
439 let stack = push(stack, Value::Float(1.5));
440
441 let stack = f_gt(stack);
442
443 let (_stack, result) = pop(stack);
444 assert_eq!(result, Value::Int(1)); }
446 }
447
448 #[test]
449 fn test_f_lte() {
450 unsafe {
451 let stack = crate::stack::alloc_test_stack();
452 let stack = push(stack, Value::Float(2.5));
453 let stack = push(stack, Value::Float(2.5));
454
455 let stack = f_lte(stack);
456
457 let (_stack, result) = pop(stack);
458 assert_eq!(result, Value::Int(1)); }
460 }
461
462 #[test]
463 fn test_f_gte() {
464 unsafe {
465 let stack = crate::stack::alloc_test_stack();
466 let stack = push(stack, Value::Float(2.5));
467 let stack = push(stack, Value::Float(2.5));
468
469 let stack = f_gte(stack);
470
471 let (_stack, result) = pop(stack);
472 assert_eq!(result, Value::Int(1)); }
474 }
475
476 #[test]
477 fn test_f_neq() {
478 unsafe {
479 let stack = crate::stack::alloc_test_stack();
480 let stack = push(stack, Value::Float(1.0));
481 let stack = push(stack, Value::Float(2.0));
482
483 let stack = f_neq(stack);
484
485 let (_stack, result) = pop(stack);
486 assert_eq!(result, Value::Int(1)); }
488 }
489
490 #[test]
491 fn test_int_to_float() {
492 unsafe {
493 let stack = crate::stack::alloc_test_stack();
494 let stack = push(stack, Value::Int(42));
495
496 let stack = int_to_float(stack);
497
498 let (_stack, result) = pop(stack);
499 assert_eq!(result, Value::Float(42.0));
500 }
501 }
502
503 #[test]
504 fn test_float_to_int() {
505 unsafe {
506 let stack = crate::stack::alloc_test_stack();
507 let stack = push(stack, Value::Float(3.7));
508
509 let stack = float_to_int(stack);
510
511 let (_stack, result) = pop(stack);
512 assert_eq!(result, Value::Int(3)); }
514 }
515
516 #[test]
517 fn test_float_to_int_negative() {
518 unsafe {
519 let stack = crate::stack::alloc_test_stack();
520 let stack = push(stack, Value::Float(-3.7));
521
522 let stack = float_to_int(stack);
523
524 let (_stack, result) = pop(stack);
525 assert_eq!(result, Value::Int(-3)); }
527 }
528
529 #[test]
530 fn test_float_to_int_nan() {
531 unsafe {
532 let stack = crate::stack::alloc_test_stack();
533 let stack = push(stack, Value::Float(f64::NAN));
534
535 let stack = float_to_int(stack);
536
537 let (_stack, result) = pop(stack);
538 assert_eq!(result, Value::Int(0)); }
540 }
541
542 #[test]
543 fn test_float_to_int_clamps_to_63bit_max() {
544 unsafe {
545 let stack = crate::stack::alloc_test_stack();
546 let stack = push(stack, Value::Float(1e20)); let stack = float_to_int(stack);
549
550 let (_stack, result) = pop(stack);
551 let int63_max = (1i64 << 62) - 1;
552 assert_eq!(result, Value::Int(int63_max));
553 }
554 }
555
556 #[test]
557 fn test_float_to_int_clamps_to_63bit_min() {
558 unsafe {
559 let stack = crate::stack::alloc_test_stack();
560 let stack = push(stack, Value::Float(-1e20)); let stack = float_to_int(stack);
563
564 let (_stack, result) = pop(stack);
565 let int63_min = -(1i64 << 62);
566 assert_eq!(result, Value::Int(int63_min));
567 }
568 }
569
570 #[test]
571 fn test_float_to_int_infinity_clamps() {
572 unsafe {
573 let stack = crate::stack::alloc_test_stack();
574 let stack = push(stack, Value::Float(f64::INFINITY));
575
576 let stack = float_to_int(stack);
577
578 let (_stack, result) = pop(stack);
579 let int63_max = (1i64 << 62) - 1;
580 assert_eq!(result, Value::Int(int63_max));
581 }
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}