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 { push(rest, Value::Bool(x == y)) },
98 _ => panic!("f.=: expected two Floats on stack"),
99 }
100}
101
102#[unsafe(no_mangle)]
107pub unsafe extern "C" fn patch_seq_f_lt(stack: Stack) -> Stack {
108 let (rest, a, b) = unsafe { pop_two(stack, "f.<") };
109 match (a, b) {
110 (Value::Float(x), Value::Float(y)) => unsafe { push(rest, Value::Bool(x < y)) },
111 _ => panic!("f.<: expected two Floats on stack"),
112 }
113}
114
115#[unsafe(no_mangle)]
120pub unsafe extern "C" fn patch_seq_f_gt(stack: Stack) -> Stack {
121 let (rest, a, b) = unsafe { pop_two(stack, "f.>") };
122 match (a, b) {
123 (Value::Float(x), Value::Float(y)) => unsafe { push(rest, Value::Bool(x > y)) },
124 _ => panic!("f.>: expected two Floats on stack"),
125 }
126}
127
128#[unsafe(no_mangle)]
133pub unsafe extern "C" fn patch_seq_f_lte(stack: Stack) -> Stack {
134 let (rest, a, b) = unsafe { pop_two(stack, "f.<=") };
135 match (a, b) {
136 (Value::Float(x), Value::Float(y)) => unsafe { push(rest, Value::Bool(x <= y)) },
137 _ => panic!("f.<=: expected two Floats on stack"),
138 }
139}
140
141#[unsafe(no_mangle)]
146pub unsafe extern "C" fn patch_seq_f_gte(stack: Stack) -> Stack {
147 let (rest, a, b) = unsafe { pop_two(stack, "f.>=") };
148 match (a, b) {
149 (Value::Float(x), Value::Float(y)) => unsafe { push(rest, Value::Bool(x >= y)) },
150 _ => panic!("f.>=: expected two Floats on stack"),
151 }
152}
153
154#[unsafe(no_mangle)]
159pub unsafe extern "C" fn patch_seq_f_neq(stack: Stack) -> Stack {
160 let (rest, a, b) = unsafe { pop_two(stack, "f.<>") };
161 match (a, b) {
162 (Value::Float(x), Value::Float(y)) => unsafe { push(rest, Value::Bool(x != y)) },
163 _ => panic!("f.<>: expected two Floats on stack"),
164 }
165}
166
167#[unsafe(no_mangle)]
176pub unsafe extern "C" fn patch_seq_int_to_float(stack: Stack) -> Stack {
177 assert!(!stack.is_null(), "int->float: stack is empty");
178 let (stack, val) = unsafe { pop(stack) };
179
180 match val {
181 Value::Int(i) => unsafe { push(stack, Value::Float(i as f64)) },
182 _ => panic!("int->float: expected Int on stack"),
183 }
184}
185
186#[unsafe(no_mangle)]
196pub unsafe extern "C" fn patch_seq_float_to_int(stack: Stack) -> Stack {
197 assert!(!stack.is_null(), "float->int: stack is empty");
198 let (stack, val) = unsafe { pop(stack) };
199
200 match val {
201 Value::Float(f) => {
202 const INT63_MAX: i64 = (1i64 << 62) - 1;
205 const INT63_MIN: i64 = -(1i64 << 62);
206 let i = if f.is_nan() {
207 0
208 } else if f >= INT63_MAX as f64 {
209 INT63_MAX
210 } else if f <= INT63_MIN as f64 {
211 INT63_MIN
212 } else {
213 f as i64
214 };
215 unsafe { push(stack, Value::Int(i)) }
216 }
217 _ => panic!("float->int: expected Float on stack"),
218 }
219}
220
221#[unsafe(no_mangle)]
226pub unsafe extern "C" fn patch_seq_float_to_string(stack: Stack) -> Stack {
227 assert!(!stack.is_null(), "float->string: stack is empty");
228 let (stack, val) = unsafe { pop(stack) };
229
230 match val {
231 Value::Float(f) => {
232 let s = f.to_string();
233 unsafe { push(stack, Value::String(global_string(s))) }
234 }
235 _ => panic!("float->string: expected Float on stack"),
236 }
237}
238
239#[unsafe(no_mangle)]
245pub unsafe extern "C" fn patch_seq_string_to_float(stack: Stack) -> Stack {
246 assert!(!stack.is_null(), "string->float: stack is empty");
247 let (stack, val) = unsafe { pop(stack) };
248
249 match val {
250 Value::String(s) => match s.as_str().parse::<f64>() {
251 Ok(f) => {
252 let stack = unsafe { push(stack, Value::Float(f)) };
253 unsafe { push(stack, Value::Bool(true)) }
254 }
255 Err(_) => {
256 let stack = unsafe { push(stack, Value::Float(0.0)) };
257 unsafe { push(stack, Value::Bool(false)) }
258 }
259 },
260 _ => panic!("string->float: expected String on stack"),
261 }
262}
263
264pub use patch_seq_f_add as f_add;
269pub use patch_seq_f_divide as f_divide;
270pub use patch_seq_f_eq as f_eq;
271pub use patch_seq_f_gt as f_gt;
272pub use patch_seq_f_gte as f_gte;
273pub use patch_seq_f_lt as f_lt;
274pub use patch_seq_f_lte as f_lte;
275pub use patch_seq_f_multiply as f_multiply;
276pub use patch_seq_f_neq as f_neq;
277pub use patch_seq_f_subtract as f_subtract;
278pub use patch_seq_float_to_int as float_to_int;
279pub use patch_seq_float_to_string as float_to_string;
280pub use patch_seq_int_to_float as int_to_float;
281pub use patch_seq_push_float as push_float;
282pub use patch_seq_string_to_float as string_to_float;
283
284#[cfg(test)]
289mod tests {
290 use super::*;
291
292 #[test]
293 fn test_push_float() {
294 unsafe {
295 let stack = crate::stack::alloc_test_stack();
296 let stack = push_float(stack, 3.5);
297
298 let (_stack, result) = pop(stack);
299 assert_eq!(result, Value::Float(3.5));
300 }
301 }
302
303 #[test]
304 fn test_f_add() {
305 unsafe {
306 let stack = crate::stack::alloc_test_stack();
307 let stack = push(stack, Value::Float(1.5));
308 let stack = push(stack, Value::Float(2.5));
309
310 let stack = f_add(stack);
311
312 let (_stack, result) = pop(stack);
313 assert_eq!(result, Value::Float(4.0));
314 }
315 }
316
317 #[test]
318 fn test_f_subtract() {
319 unsafe {
320 let stack = crate::stack::alloc_test_stack();
321 let stack = push(stack, Value::Float(5.0));
322 let stack = push(stack, Value::Float(2.0));
323
324 let stack = f_subtract(stack);
325
326 let (_stack, result) = pop(stack);
327 assert_eq!(result, Value::Float(3.0));
328 }
329 }
330
331 #[test]
332 fn test_f_multiply() {
333 unsafe {
334 let stack = crate::stack::alloc_test_stack();
335 let stack = push(stack, Value::Float(3.0));
336 let stack = push(stack, Value::Float(4.0));
337
338 let stack = f_multiply(stack);
339
340 let (_stack, result) = pop(stack);
341 assert_eq!(result, Value::Float(12.0));
342 }
343 }
344
345 #[test]
346 fn test_f_divide() {
347 unsafe {
348 let stack = crate::stack::alloc_test_stack();
349 let stack = push(stack, Value::Float(10.0));
350 let stack = push(stack, Value::Float(4.0));
351
352 let stack = f_divide(stack);
353
354 let (_stack, result) = pop(stack);
355 assert_eq!(result, Value::Float(2.5));
356 }
357 }
358
359 #[test]
360 fn test_f_divide_by_zero() {
361 unsafe {
362 let stack = crate::stack::alloc_test_stack();
363 let stack = push(stack, Value::Float(1.0));
364 let stack = push(stack, Value::Float(0.0));
365
366 let stack = f_divide(stack);
367
368 let (_stack, result) = pop(stack);
369 match result {
370 Value::Float(f) => assert!(f.is_infinite()),
371 _ => panic!("Expected Float"),
372 }
373 }
374 }
375
376 #[test]
377 fn test_f_eq_true() {
378 unsafe {
379 let stack = crate::stack::alloc_test_stack();
380 let stack = push(stack, Value::Float(3.5));
381 let stack = push(stack, Value::Float(3.5));
382
383 let stack = f_eq(stack);
384
385 let (_stack, result) = pop(stack);
386 assert_eq!(result, Value::Bool(true));
387 }
388 }
389
390 #[test]
391 fn test_f_eq_false() {
392 unsafe {
393 let stack = crate::stack::alloc_test_stack();
394 let stack = push(stack, Value::Float(3.5));
395 let stack = push(stack, Value::Float(2.5));
396
397 let stack = f_eq(stack);
398
399 let (_stack, result) = pop(stack);
400 assert_eq!(result, Value::Bool(false));
401 }
402 }
403
404 #[test]
405 fn test_f_lt() {
406 unsafe {
407 let stack = crate::stack::alloc_test_stack();
408 let stack = push(stack, Value::Float(1.5));
409 let stack = push(stack, Value::Float(2.5));
410
411 let stack = f_lt(stack);
412
413 let (_stack, result) = pop(stack);
414 assert_eq!(result, Value::Bool(true)); }
416 }
417
418 #[test]
419 fn test_f_gt() {
420 unsafe {
421 let stack = crate::stack::alloc_test_stack();
422 let stack = push(stack, Value::Float(2.5));
423 let stack = push(stack, Value::Float(1.5));
424
425 let stack = f_gt(stack);
426
427 let (_stack, result) = pop(stack);
428 assert_eq!(result, Value::Bool(true)); }
430 }
431
432 #[test]
433 fn test_f_lte() {
434 unsafe {
435 let stack = crate::stack::alloc_test_stack();
436 let stack = push(stack, Value::Float(2.5));
437 let stack = push(stack, Value::Float(2.5));
438
439 let stack = f_lte(stack);
440
441 let (_stack, result) = pop(stack);
442 assert_eq!(result, Value::Bool(true)); }
444 }
445
446 #[test]
447 fn test_f_gte() {
448 unsafe {
449 let stack = crate::stack::alloc_test_stack();
450 let stack = push(stack, Value::Float(2.5));
451 let stack = push(stack, Value::Float(2.5));
452
453 let stack = f_gte(stack);
454
455 let (_stack, result) = pop(stack);
456 assert_eq!(result, Value::Bool(true)); }
458 }
459
460 #[test]
461 fn test_f_neq() {
462 unsafe {
463 let stack = crate::stack::alloc_test_stack();
464 let stack = push(stack, Value::Float(1.0));
465 let stack = push(stack, Value::Float(2.0));
466
467 let stack = f_neq(stack);
468
469 let (_stack, result) = pop(stack);
470 assert_eq!(result, Value::Bool(true)); }
472 }
473
474 #[test]
475 fn test_int_to_float() {
476 unsafe {
477 let stack = crate::stack::alloc_test_stack();
478 let stack = push(stack, Value::Int(42));
479
480 let stack = int_to_float(stack);
481
482 let (_stack, result) = pop(stack);
483 assert_eq!(result, Value::Float(42.0));
484 }
485 }
486
487 #[test]
488 fn test_float_to_int() {
489 unsafe {
490 let stack = crate::stack::alloc_test_stack();
491 let stack = push(stack, Value::Float(3.7));
492
493 let stack = float_to_int(stack);
494
495 let (_stack, result) = pop(stack);
496 assert_eq!(result, Value::Int(3)); }
498 }
499
500 #[test]
501 fn test_float_to_int_negative() {
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_nan() {
515 unsafe {
516 let stack = crate::stack::alloc_test_stack();
517 let stack = push(stack, Value::Float(f64::NAN));
518
519 let stack = float_to_int(stack);
520
521 let (_stack, result) = pop(stack);
522 assert_eq!(result, Value::Int(0)); }
524 }
525
526 #[test]
527 fn test_float_to_int_clamps_to_63bit_max() {
528 unsafe {
529 let stack = crate::stack::alloc_test_stack();
530 let stack = push(stack, Value::Float(1e20)); let stack = float_to_int(stack);
533
534 let (_stack, result) = pop(stack);
535 let int63_max = (1i64 << 62) - 1;
536 assert_eq!(result, Value::Int(int63_max));
537 }
538 }
539
540 #[test]
541 fn test_float_to_int_clamps_to_63bit_min() {
542 unsafe {
543 let stack = crate::stack::alloc_test_stack();
544 let stack = push(stack, Value::Float(-1e20)); let stack = float_to_int(stack);
547
548 let (_stack, result) = pop(stack);
549 let int63_min = -(1i64 << 62);
550 assert_eq!(result, Value::Int(int63_min));
551 }
552 }
553
554 #[test]
555 fn test_float_to_int_infinity_clamps() {
556 unsafe {
557 let stack = crate::stack::alloc_test_stack();
558 let stack = push(stack, Value::Float(f64::INFINITY));
559
560 let stack = float_to_int(stack);
561
562 let (_stack, result) = pop(stack);
563 let int63_max = (1i64 << 62) - 1;
564 assert_eq!(result, Value::Int(int63_max));
565 }
566 }
567
568 #[test]
569 fn test_float_to_string() {
570 unsafe {
571 let stack = crate::stack::alloc_test_stack();
572 let stack = push(stack, Value::Float(3.5));
573
574 let stack = float_to_string(stack);
575
576 let (_stack, result) = pop(stack);
577 match result {
578 Value::String(s) => assert_eq!(s.as_str(), "3.5"),
579 _ => panic!("Expected String"),
580 }
581 }
582 }
583
584 #[test]
585 fn test_float_to_string_whole_number() {
586 unsafe {
587 let stack = crate::stack::alloc_test_stack();
588 let stack = push(stack, Value::Float(42.0));
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(), "42"),
595 _ => panic!("Expected String"),
596 }
597 }
598 }
599
600 #[test]
601 fn test_nan_propagation() {
602 unsafe {
603 let stack = crate::stack::alloc_test_stack();
604 let stack = push(stack, Value::Float(f64::NAN));
605 let stack = push(stack, Value::Float(1.0));
606
607 let stack = f_add(stack);
608
609 let (_stack, result) = pop(stack);
610 match result {
611 Value::Float(f) => assert!(f.is_nan()),
612 _ => panic!("Expected Float"),
613 }
614 }
615 }
616
617 #[test]
618 fn test_infinity() {
619 unsafe {
620 let stack = crate::stack::alloc_test_stack();
621 let stack = push(stack, Value::Float(f64::INFINITY));
622 let stack = push(stack, Value::Float(1.0));
623
624 let stack = f_add(stack);
625
626 let (_stack, result) = pop(stack);
627 match result {
628 Value::Float(f) => assert!(f.is_infinite()),
629 _ => panic!("Expected Float"),
630 }
631 }
632 }
633}