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 #[test]
528 fn test_float_to_int_overflow_positive() {
529 unsafe {
530 let stack = crate::stack::alloc_test_stack();
531 let stack = push(stack, Value::Float(1e20)); let stack = float_to_int(stack);
534
535 let (_stack, result) = pop(stack);
536 assert_eq!(result, Value::Int(i64::MAX)); }
538 }
539
540 #[test]
542 fn test_float_to_int_overflow_negative() {
543 unsafe {
544 let stack = crate::stack::alloc_test_stack();
545 let stack = push(stack, Value::Float(-1e20)); let stack = float_to_int(stack);
548
549 let (_stack, result) = pop(stack);
550 assert_eq!(result, Value::Int(i64::MIN)); }
552 }
553
554 #[test]
555 fn test_float_to_int_nan() {
556 unsafe {
557 let stack = crate::stack::alloc_test_stack();
558 let stack = push(stack, Value::Float(f64::NAN));
559
560 let stack = float_to_int(stack);
561
562 let (_stack, result) = pop(stack);
563 assert_eq!(result, Value::Int(0)); }
565 }
566
567 #[test]
569 fn test_float_to_int_infinity() {
570 unsafe {
571 let stack = crate::stack::alloc_test_stack();
572 let stack = push(stack, Value::Float(f64::INFINITY));
573
574 let stack = float_to_int(stack);
575
576 let (_stack, result) = pop(stack);
577 assert_eq!(result, Value::Int(i64::MAX)); }
579 }
580
581 #[test]
582 fn test_float_to_string() {
583 unsafe {
584 let stack = crate::stack::alloc_test_stack();
585 let stack = push(stack, Value::Float(3.5));
586
587 let stack = float_to_string(stack);
588
589 let (_stack, result) = pop(stack);
590 match result {
591 Value::String(s) => assert_eq!(s.as_str(), "3.5"),
592 _ => panic!("Expected String"),
593 }
594 }
595 }
596
597 #[test]
598 fn test_float_to_string_whole_number() {
599 unsafe {
600 let stack = crate::stack::alloc_test_stack();
601 let stack = push(stack, Value::Float(42.0));
602
603 let stack = float_to_string(stack);
604
605 let (_stack, result) = pop(stack);
606 match result {
607 Value::String(s) => assert_eq!(s.as_str(), "42"),
608 _ => panic!("Expected String"),
609 }
610 }
611 }
612
613 #[test]
614 fn test_nan_propagation() {
615 unsafe {
616 let stack = crate::stack::alloc_test_stack();
617 let stack = push(stack, Value::Float(f64::NAN));
618 let stack = push(stack, Value::Float(1.0));
619
620 let stack = f_add(stack);
621
622 let (_stack, result) = pop(stack);
623 match result {
624 Value::Float(f) => assert!(f.is_nan()),
625 _ => panic!("Expected Float"),
626 }
627 }
628 }
629
630 #[test]
631 fn test_infinity() {
632 unsafe {
633 let stack = crate::stack::alloc_test_stack();
634 let stack = push(stack, Value::Float(f64::INFINITY));
635 let stack = push(stack, Value::Float(1.0));
636
637 let stack = f_add(stack);
638
639 let (_stack, result) = pop(stack);
640 match result {
641 Value::Float(f) => assert!(f.is_infinite()),
642 _ => panic!("Expected Float"),
643 }
644 }
645 }
646}