Implement Num.toNNNChecked

Closes #2411
This commit is contained in:
ayazhafiz 2022-02-19 16:20:07 -05:00
parent d90915a8cd
commit 13067f2908
11 changed files with 531 additions and 213 deletions

View file

@ -12,7 +12,7 @@ pub const BUILTINS_WASM32_OBJ_PATH: &str = env!(
"Env var BUILTINS_WASM32_O not found. Is there a problem with the build script?"
);
#[derive(Debug, Default)]
#[derive(Debug, Default, Copy, Clone)]
pub struct IntrinsicName {
pub options: [&'static str; 14],
}
@ -159,6 +159,21 @@ impl IntWidth {
_ => None,
}
}
pub const fn type_name(&self) -> &'static str {
match self {
Self::I8 => "i8",
Self::I16 => "i16",
Self::I32 => "i32",
Self::I64 => "i64",
Self::I128 => "i128",
Self::U8 => "u8",
Self::U16 => "u16",
Self::U32 => "u32",
Self::U64 => "u64",
Self::U128 => "u128",
}
}
}
impl Index<DecWidth> for IntrinsicName {
@ -214,11 +229,12 @@ macro_rules! float_intrinsic {
}
#[macro_export]
macro_rules! int_intrinsic {
macro_rules! llvm_int_intrinsic {
($signed_name:literal, $unsigned_name:literal) => {{
let mut output = IntrinsicName::default();
// The indeces align with the `Index` impl for `IntrinsicName`.
// LLVM uses the same types for both signed and unsigned integers.
output.options[4] = concat!($unsigned_name, ".i8");
output.options[5] = concat!($unsigned_name, ".i16");
output.options[6] = concat!($unsigned_name, ".i32");
@ -239,6 +255,28 @@ macro_rules! int_intrinsic {
};
}
#[macro_export]
macro_rules! int_intrinsic {
($name:expr) => {{
let mut output = IntrinsicName::default();
// The indeces align with the `Index` impl for `IntrinsicName`.
output.options[4] = concat!($name, ".u8");
output.options[5] = concat!($name, ".u16");
output.options[6] = concat!($name, ".u32");
output.options[7] = concat!($name, ".u64");
output.options[8] = concat!($name, ".u128");
output.options[9] = concat!($name, ".i8");
output.options[10] = concat!($name, ".i16");
output.options[11] = concat!($name, ".i32");
output.options[12] = concat!($name, ".i64");
output.options[13] = concat!($name, ".i128");
output
}};
}
pub const NUM_ASIN: IntrinsicName = float_intrinsic!("roc_builtins.num.asin");
pub const NUM_ACOS: IntrinsicName = float_intrinsic!("roc_builtins.num.acos");
pub const NUM_ATAN: IntrinsicName = float_intrinsic!("roc_builtins.num.atan");
@ -339,3 +377,50 @@ pub const UTILS_DECREF_CHECK_NULL: &str = "roc_builtins.utils.decref_check_null"
pub const UTILS_EXPECT_FAILED: &str = "roc_builtins.expect.expect_failed";
pub const UTILS_GET_EXPECT_FAILURES: &str = "roc_builtins.expect.get_expect_failures";
pub const UTILS_DEINIT_FAILURES: &str = "roc_builtins.expect.deinit_failures";
#[derive(Debug, Default)]
pub struct IntToIntrinsicName {
pub options: [IntrinsicName; 10],
}
impl IntToIntrinsicName {
pub const fn default() -> Self {
Self {
options: [IntrinsicName::default(); 10],
}
}
}
impl Index<IntWidth> for IntToIntrinsicName {
type Output = IntrinsicName;
fn index(&self, index: IntWidth) -> &Self::Output {
&self.options[index as usize]
}
}
#[macro_export]
macro_rules! int_to_int_intrinsic {
($name_prefix:literal, $name_suffix:literal) => {{
let mut output = IntToIntrinsicName::default();
output.options[0] = int_intrinsic!(concat!($name_prefix, "u8", $name_suffix));
output.options[1] = int_intrinsic!(concat!($name_prefix, "u16", $name_suffix));
output.options[2] = int_intrinsic!(concat!($name_prefix, "u32", $name_suffix));
output.options[3] = int_intrinsic!(concat!($name_prefix, "u64", $name_suffix));
output.options[4] = int_intrinsic!(concat!($name_prefix, "u128", $name_suffix));
output.options[5] = int_intrinsic!(concat!($name_prefix, "i8", $name_suffix));
output.options[6] = int_intrinsic!(concat!($name_prefix, "i16", $name_suffix));
output.options[7] = int_intrinsic!(concat!($name_prefix, "i32", $name_suffix));
output.options[8] = int_intrinsic!(concat!($name_prefix, "i64", $name_suffix));
output.options[9] = int_intrinsic!(concat!($name_prefix, "i128", $name_suffix));
output
}};
}
pub const NUM_INT_TO_INT_CHECKING_MAX: IntToIntrinsicName =
int_to_int_intrinsic!("roc_builtins.num.int_to_", "_checking_max");
pub const NUM_INT_TO_INT_CHECKING_MAX_AND_MIN: IntToIntrinsicName =
int_to_int_intrinsic!("roc_builtins.num.int_to_", "_checking_max_and_min");