1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
use arret_runtime::binding::*; use arret_runtime::boxed; use arret_runtime::boxed::refs::Gc; use arret_runtime::task::Task; fn compare_nums<IC, FC>( initial: Gc<boxed::Num>, rest: Gc<boxed::List<boxed::Num>>, int_comparator: IC, float_comparator: FC, ) -> bool where IC: Fn(&i64, &i64) -> bool, FC: Fn(&f64, &f64) -> bool, { let mut left = initial; for right in rest.iter() { use boxed::NumSubtype; let result = match (left.as_subtype(), right.as_subtype()) { (NumSubtype::Int(left_ref), NumSubtype::Int(right_ref)) => { int_comparator(&left_ref.value(), &right_ref.value()) } (NumSubtype::Float(left_ref), NumSubtype::Int(right_ref)) => { float_comparator(&left_ref.value(), &(right_ref.value() as f64)) } (NumSubtype::Int(left_ref), NumSubtype::Float(right_ref)) => { float_comparator(&(left_ref.value() as f64), &right_ref.value()) } (NumSubtype::Float(left_ref), NumSubtype::Float(right_ref)) => { float_comparator(&left_ref.value(), &right_ref.value()) } }; if !result { return false; } left = right; } true } #[arret_rfi_derive::rust_fun("(Num -> Float)")] pub fn stdlib_float(input: Gc<boxed::Num>) -> f64 { match input.as_subtype() { boxed::NumSubtype::Int(int_ref) => int_ref.value() as f64, boxed::NumSubtype::Float(float_ref) => float_ref.value(), } } #[arret_rfi_derive::rust_fun("(Num -> Int)")] pub fn stdlib_int(task: &mut Task, input: Gc<boxed::Num>) -> i64 { match input.as_subtype() { boxed::NumSubtype::Int(int_ref) => int_ref.value(), boxed::NumSubtype::Float(float_ref) => { let float_val = float_ref.value(); if float_val.is_nan() { task.panic(format!( "Float value `{}` is not a number; cannot convert to Int", float_val )); } else if float_val.is_infinite() { task.panic(format!( "Float value `{}` is infinite; cannot convert to Int", float_val )); } float_val as i64 } } } #[arret_rfi_derive::rust_fun("(Num & Num -> Bool)")] pub fn stdlib_num_lt(initial: Gc<boxed::Num>, rest: Gc<boxed::List<boxed::Num>>) -> bool { compare_nums(initial, rest, i64::lt, f64::lt) } #[arret_rfi_derive::rust_fun("(Num & Num -> Bool)")] pub fn stdlib_num_le(initial: Gc<boxed::Num>, rest: Gc<boxed::List<boxed::Num>>) -> bool { compare_nums(initial, rest, i64::le, f64::le) } #[arret_rfi_derive::rust_fun("(Num & Num -> Bool)")] pub fn stdlib_num_eq(initial: Gc<boxed::Num>, rest: Gc<boxed::List<boxed::Num>>) -> bool { compare_nums(initial, rest, i64::eq, f64::eq) } #[arret_rfi_derive::rust_fun("(Num & Num -> Bool)")] pub fn stdlib_num_gt(initial: Gc<boxed::Num>, rest: Gc<boxed::List<boxed::Num>>) -> bool { compare_nums(initial, rest, i64::gt, f64::gt) } #[arret_rfi_derive::rust_fun("(Num & Num -> Bool)")] pub fn stdlib_num_ge(initial: Gc<boxed::Num>, rest: Gc<boxed::List<boxed::Num>>) -> bool { compare_nums(initial, rest, i64::ge, f64::ge) }