From c497641e63bd32813f57a7682b598082f47e91ba Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Wed, 19 Apr 2023 11:27:12 -0500 Subject: [PATCH] Support underscores in Dec numbers Closes #5303 --- crates/compiler/uitest/tests/weaken/i5306.txt | 0 crates/roc_std/src/lib.rs | 36 +++++++++++++++---- crates/roc_std/tests/test_roc_std.rs | 3 ++ 3 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 crates/compiler/uitest/tests/weaken/i5306.txt diff --git a/crates/compiler/uitest/tests/weaken/i5306.txt b/crates/compiler/uitest/tests/weaken/i5306.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/crates/roc_std/src/lib.rs b/crates/roc_std/src/lib.rs index 2b5fbd4aa4..ecc9ffa344 100644 --- a/crates/roc_std/src/lib.rs +++ b/crates/roc_std/src/lib.rs @@ -298,12 +298,36 @@ impl RocDec { }; // Calculate the high digits - the ones before the decimal point. - match before_point.parse::() { - Ok(answer) => match answer.checked_mul(Self::ONE_POINT_ZERO) { - Some(hi) => hi.checked_add(lo).map(|num| Self(num.to_ne_bytes())), - None => None, - }, - Err(_) => None, + let (is_pos, digits) = match before_point.chars().next() { + Some('+') => (true, &before_point[1..]), + Some('-') => (false, &before_point[1..]), + _ => (true, before_point), + }; + + let mut hi: i128 = 0; + macro_rules! adjust_hi { + ($op:ident) => {{ + for digit in digits.chars() { + if digit == '_' { + continue; + } + + let digit = digit.to_digit(10)?; + hi = hi.checked_mul(10)?; + hi = hi.$op(digit as _)?; + } + }}; + } + + if is_pos { + adjust_hi!(checked_add); + } else { + adjust_hi!(checked_sub); + } + + match hi.checked_mul(Self::ONE_POINT_ZERO) { + Some(hi) => hi.checked_add(lo).map(|num| Self(num.to_ne_bytes())), + None => None, } } diff --git a/crates/roc_std/tests/test_roc_std.rs b/crates/roc_std/tests/test_roc_std.rs index 63aec446a9..eb83e0f340 100644 --- a/crates/roc_std/tests/test_roc_std.rs +++ b/crates/roc_std/tests/test_roc_std.rs @@ -295,6 +295,9 @@ mod test_roc_std { let example = RocDec::from_str("1234.5678").unwrap(); assert_eq!(format!("{}", example), "1234.5678"); + + let example = RocDec::from_str("1_000.5678").unwrap(); + assert_eq!(format!("{}", example), "1000.5678"); } #[test]