From ff2c3d794587e5ae55d0ac6fa13f11acac47c895 Mon Sep 17 00:00:00 2001 From: Joshua Hoeflich Date: Sat, 14 Aug 2021 17:59:53 -0500 Subject: [PATCH 01/19] Dummy implementation that doesn't do what we want --- compiler/builtins/bitcode/src/main.zig | 1 + compiler/builtins/bitcode/src/num.zig | 6 ++++++ compiler/builtins/src/bitcode.rs | 2 ++ compiler/builtins/src/std.rs | 8 +++++++ compiler/can/src/builtins.rs | 22 +++++++++++++++++++ compiler/gen_llvm/src/llvm/build.rs | 30 ++++++++++++++++++++++++++ compiler/module/src/low_level.rs | 3 ++- compiler/module/src/symbol.rs | 2 +- compiler/mono/src/borrow.rs | 2 ++ compiler/test_gen/src/gen_num.rs | 5 +++++ 10 files changed, 79 insertions(+), 2 deletions(-) diff --git a/compiler/builtins/bitcode/src/main.zig b/compiler/builtins/bitcode/src/main.zig index e4843166ab..0a8c712117 100644 --- a/compiler/builtins/bitcode/src/main.zig +++ b/compiler/builtins/bitcode/src/main.zig @@ -79,6 +79,7 @@ comptime { exportNumFn(num.powInt, "pow_int"); exportNumFn(num.acos, "acos"); exportNumFn(num.asin, "asin"); + exportNumFn(num.bytesToU16C, "bytes_to_u16"); } // Str Module diff --git a/compiler/builtins/bitcode/src/num.zig b/compiler/builtins/bitcode/src/num.zig index b42aee20ca..9820766589 100644 --- a/compiler/builtins/bitcode/src/num.zig +++ b/compiler/builtins/bitcode/src/num.zig @@ -21,3 +21,9 @@ pub fn acos(num: f64) callconv(.C) f64 { pub fn asin(num: f64) callconv(.C) f64 { return @call(.{ .modifier = always_inline }, math.asin, .{num}); } + +/// TODO: Obviously, this should not be an alias for arcsin(x); +/// fix me! +pub fn bytesToU16C(num: f64) callconv(.C) f64 { + return @call(.{ .modifier = always_inline }, math.asin, .{num}); +} diff --git a/compiler/builtins/src/bitcode.rs b/compiler/builtins/src/bitcode.rs index 14f7c82198..224d08e526 100644 --- a/compiler/builtins/src/bitcode.rs +++ b/compiler/builtins/src/bitcode.rs @@ -8,6 +8,8 @@ pub const NUM_ACOS: &str = "roc_builtins.num.acos"; pub const NUM_ATAN: &str = "roc_builtins.num.atan"; pub const NUM_IS_FINITE: &str = "roc_builtins.num.is_finite"; pub const NUM_POW_INT: &str = "roc_builtins.num.pow_int"; +pub const NUM_BYTES_TO_U16: &str = "roc_builtins.num.bytes_to_u16"; + pub const STR_INIT: &str = "roc_builtins.str.init"; pub const STR_COUNT_SEGMENTS: &str = "roc_builtins.str.count_segments"; diff --git a/compiler/builtins/src/std.rs b/compiler/builtins/src/std.rs index 0dcc377c40..ea0b749ae8 100644 --- a/compiler/builtins/src/std.rs +++ b/compiler/builtins/src/std.rs @@ -501,6 +501,14 @@ pub fn types() -> MutMap { Box::new(float_type(flex(TVAR1))), ); + // TODO: This is obviously wrong! Fix me! + // bytesToU16 : Float a -> Float a + add_top_level_function_type!( + Symbol::NUM_BYTES_TO_U16, + vec![float_type(flex(TVAR1))], + Box::new(float_type(flex(TVAR1))), + ); + // Bool module // and : Bool, Bool -> Bool diff --git a/compiler/can/src/builtins.rs b/compiler/can/src/builtins.rs index 349cac6f80..9310501875 100644 --- a/compiler/can/src/builtins.rs +++ b/compiler/can/src/builtins.rs @@ -161,6 +161,7 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option NUM_ATAN => num_atan, NUM_ACOS => num_acos, NUM_ASIN => num_asin, + NUM_BYTES_TO_U16 => num_bytes_to_u16, NUM_MAX_INT => num_max_int, NUM_MIN_INT => num_min_int, NUM_BITWISE_AND => num_bitwise_and, @@ -1088,6 +1089,27 @@ fn num_asin(symbol: Symbol, var_store: &mut VarStore) -> Def { ) } +/// TODO: This is obviously wrong! Fix me! +/// Num.bytesToU16 : Float -> Float +fn num_bytes_to_u16(symbol: Symbol, var_store: &mut VarStore) -> Def { + let arg_float_var = var_store.fresh(); + let ret_float_var = var_store.fresh(); + + let body = RunLowLevel { + op: LowLevel::NumAsin, + args: vec![(arg_float_var, Var(Symbol::ARG_1))], + ret_var: ret_float_var, + }; + + defn( + symbol, + vec![(arg_float_var, Symbol::ARG_1)], + var_store, + body, + ret_float_var, + ) +} + /// Num.bitwiseAnd : Int a, Int a -> Int a fn num_bitwise_and(symbol: Symbol, var_store: &mut VarStore) -> Def { num_binop(symbol, var_store, LowLevel::NumBitwiseAnd) diff --git a/compiler/gen_llvm/src/llvm/build.rs b/compiler/gen_llvm/src/llvm/build.rs index 400f42f63a..66dfe8dd31 100644 --- a/compiler/gen_llvm/src/llvm/build.rs +++ b/compiler/gen_llvm/src/llvm/build.rs @@ -4738,6 +4738,36 @@ fn run_low_level<'a, 'ctx, 'env>( } } } + // TODO: Obviously, this is completely wrong! Fix me! + NumBytesToU16 => { + debug_assert_eq!(args.len(), 1); + + let (arg, arg_layout) = load_symbol_and_layout(scope, &args[0]); + + match arg_layout { + Layout::Builtin(arg_builtin) => { + use roc_mono::layout::Builtin::*; + + match arg_builtin { + Usize | Int128 | Int64 | Int32 | Int16 | Int8 => { + build_int_unary_op(env, arg.into_int_value(), arg_builtin, op) + } + Float128 | Float64 | Float32 | Float16 => { + build_float_unary_op(env, arg.into_float_value(), op) + } + _ => { + unreachable!("Compiler bug: tried to run numeric operation {:?} on invalid builtin layout: ({:?})", op, arg_layout); + } + } + } + _ => { + unreachable!( + "Compiler bug: tried to run numeric operation {:?} on invalid layout: {:?}", + op, arg_layout + ); + } + } + } NumCompare => { use inkwell::FloatPredicate; diff --git a/compiler/module/src/low_level.rs b/compiler/module/src/low_level.rs index d360192d8c..868f4ed635 100644 --- a/compiler/module/src/low_level.rs +++ b/compiler/module/src/low_level.rs @@ -87,6 +87,7 @@ pub enum LowLevel { NumAtan, NumAcos, NumAsin, + NumBytesToU16, NumBitwiseAnd, NumBitwiseXor, NumBitwiseOr, @@ -122,7 +123,7 @@ impl LowLevel { | NumRemUnchecked | NumIsMultipleOf | NumAbs | NumNeg | NumSin | NumCos | NumSqrtUnchecked | NumLogUnchecked | NumRound | NumToFloat | NumPow | NumCeiling | NumPowInt | NumFloor | NumIsFinite | NumAtan | NumAcos | NumAsin | NumBitwiseAnd - | NumBitwiseXor | NumBitwiseOr | NumShiftLeftBy | NumShiftRightBy + | NumBitwiseXor | NumBitwiseOr | NumShiftLeftBy | NumShiftRightBy | NumBytesToU16 | NumShiftRightZfBy | NumIntCast | Eq | NotEq | And | Or | Not | Hash | ExpectTrue => { false } diff --git a/compiler/module/src/symbol.rs b/compiler/module/src/symbol.rs index 3b32c1fd8e..caddb4a0b4 100644 --- a/compiler/module/src/symbol.rs +++ b/compiler/module/src/symbol.rs @@ -891,7 +891,7 @@ define_builtins! { 100 NUM_AT_DECIMAL: "@Decimal" 101 NUM_DECIMAL: "Decimal" imported 102 NUM_DEC: "Dec" imported // the Num.Dectype alias - + 103 NUM_BYTES_TO_U16: "bytesToU16" } 2 BOOL: "Bool" => { 0 BOOL_BOOL: "Bool" imported // the Bool.Bool type alias diff --git a/compiler/mono/src/borrow.rs b/compiler/mono/src/borrow.rs index b5b2584801..9a7b952d3c 100644 --- a/compiler/mono/src/borrow.rs +++ b/compiler/mono/src/borrow.rs @@ -1012,6 +1012,8 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] { NumAbs | NumNeg | NumSin | NumCos | NumSqrtUnchecked | NumLogUnchecked | NumRound | NumCeiling | NumFloor | NumToFloat | Not | NumIsFinite | NumAtan | NumAcos | NumAsin | NumIntCast => arena.alloc_slice_copy(&[irrelevant]), + // TODO: Fix me! I am wrong! + NumBytesToU16 => arena.alloc_slice_copy(&[irrelevant]), StrStartsWith | StrEndsWith => arena.alloc_slice_copy(&[owned, borrowed]), StrStartsWithCodePt => arena.alloc_slice_copy(&[borrowed, irrelevant]), StrFromUtf8 => arena.alloc_slice_copy(&[owned]), diff --git a/compiler/test_gen/src/gen_num.rs b/compiler/test_gen/src/gen_num.rs index fb1621eb8c..fb7baf3d1e 100644 --- a/compiler/test_gen/src/gen_num.rs +++ b/compiler/test_gen/src/gen_num.rs @@ -1620,4 +1620,9 @@ mod gen_num { // overflow assert_evals_to!("Num.isMultipleOf -9223372036854775808 -1", true, bool); } + + #[test] + fn num_bytes_to_u16_ascii() { + assert_evals_to!("Num.bytesToU16 0", 0.0, f64); + } } From ce8f947522823d51f257244872cb0a57146c952b Mon Sep 17 00:00:00 2001 From: Joshua Hoeflich Date: Sat, 14 Aug 2021 18:08:36 -0500 Subject: [PATCH 02/19] Split sig into two separate functions --- compiler/builtins/bitcode/src/num.zig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/builtins/bitcode/src/num.zig b/compiler/builtins/bitcode/src/num.zig index 9820766589..cdb936d66b 100644 --- a/compiler/builtins/bitcode/src/num.zig +++ b/compiler/builtins/bitcode/src/num.zig @@ -25,5 +25,9 @@ pub fn asin(num: f64) callconv(.C) f64 { /// TODO: Obviously, this should not be an alias for arcsin(x); /// fix me! pub fn bytesToU16C(num: f64) callconv(.C) f64 { - return @call(.{ .modifier = always_inline }, math.asin, .{num}); + return @call(.{ .modifier = always_inline }, bytesToU16, .{num}); +} + +fn bytesToU16(num: f64) f64 { + return math.asin(num); } From 744fefc3a18029d82ff6c9d39c3af0b10934f237 Mon Sep 17 00:00:00 2001 From: Joshua Hoeflich Date: Sat, 14 Aug 2021 18:20:11 -0500 Subject: [PATCH 03/19] Fixed: Actually calling llvm we generate --- compiler/builtins/bitcode/src/num.zig | 4 ++-- compiler/can/src/builtins.rs | 2 +- compiler/gen_llvm/src/llvm/build.rs | 1 + compiler/test_gen/src/gen_num.rs | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/builtins/bitcode/src/num.zig b/compiler/builtins/bitcode/src/num.zig index cdb936d66b..a7d3fc5269 100644 --- a/compiler/builtins/bitcode/src/num.zig +++ b/compiler/builtins/bitcode/src/num.zig @@ -25,9 +25,9 @@ pub fn asin(num: f64) callconv(.C) f64 { /// TODO: Obviously, this should not be an alias for arcsin(x); /// fix me! pub fn bytesToU16C(num: f64) callconv(.C) f64 { - return @call(.{ .modifier = always_inline }, bytesToU16, .{num}); + return num + 1; } fn bytesToU16(num: f64) f64 { - return math.asin(num); + return num + 1; } diff --git a/compiler/can/src/builtins.rs b/compiler/can/src/builtins.rs index 9310501875..da496a36b2 100644 --- a/compiler/can/src/builtins.rs +++ b/compiler/can/src/builtins.rs @@ -1096,7 +1096,7 @@ fn num_bytes_to_u16(symbol: Symbol, var_store: &mut VarStore) -> Def { let ret_float_var = var_store.fresh(); let body = RunLowLevel { - op: LowLevel::NumAsin, + op: LowLevel::NumBytesToU16, args: vec![(arg_float_var, Var(Symbol::ARG_1))], ret_var: ret_float_var, }; diff --git a/compiler/gen_llvm/src/llvm/build.rs b/compiler/gen_llvm/src/llvm/build.rs index 66dfe8dd31..7f57e43414 100644 --- a/compiler/gen_llvm/src/llvm/build.rs +++ b/compiler/gen_llvm/src/llvm/build.rs @@ -6061,6 +6061,7 @@ fn build_float_unary_op<'a, 'ctx, 'env>( NumAtan => call_bitcode_fn(env, &[arg.into()], bitcode::NUM_ATAN), NumAcos => call_bitcode_fn(env, &[arg.into()], bitcode::NUM_ACOS), NumAsin => call_bitcode_fn(env, &[arg.into()], bitcode::NUM_ASIN), + NumBytesToU16 => call_bitcode_fn(env, &[arg.into()], bitcode::NUM_BYTES_TO_U16), _ => { unreachable!("Unrecognized int unary operation: {:?}", op); } diff --git a/compiler/test_gen/src/gen_num.rs b/compiler/test_gen/src/gen_num.rs index fb7baf3d1e..6d7fd10eb4 100644 --- a/compiler/test_gen/src/gen_num.rs +++ b/compiler/test_gen/src/gen_num.rs @@ -1623,6 +1623,6 @@ mod gen_num { #[test] fn num_bytes_to_u16_ascii() { - assert_evals_to!("Num.bytesToU16 0", 0.0, f64); + assert_evals_to!("Num.bytesToU16 1", 2.0, f64); } } From 59f07377fe945421ee1d30102a685e0353e6b7c2 Mon Sep 17 00:00:00 2001 From: Joshua Hoeflich Date: Sat, 14 Aug 2021 18:23:49 -0500 Subject: [PATCH 04/19] More testing; clean up --- compiler/gen_llvm/src/llvm/build.rs | 29 ++--------------------------- compiler/test_gen/src/gen_num.rs | 5 +++++ 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/compiler/gen_llvm/src/llvm/build.rs b/compiler/gen_llvm/src/llvm/build.rs index 7f57e43414..ebb8cd2a2e 100644 --- a/compiler/gen_llvm/src/llvm/build.rs +++ b/compiler/gen_llvm/src/llvm/build.rs @@ -4741,32 +4741,8 @@ fn run_low_level<'a, 'ctx, 'env>( // TODO: Obviously, this is completely wrong! Fix me! NumBytesToU16 => { debug_assert_eq!(args.len(), 1); - - let (arg, arg_layout) = load_symbol_and_layout(scope, &args[0]); - - match arg_layout { - Layout::Builtin(arg_builtin) => { - use roc_mono::layout::Builtin::*; - - match arg_builtin { - Usize | Int128 | Int64 | Int32 | Int16 | Int8 => { - build_int_unary_op(env, arg.into_int_value(), arg_builtin, op) - } - Float128 | Float64 | Float32 | Float16 => { - build_float_unary_op(env, arg.into_float_value(), op) - } - _ => { - unreachable!("Compiler bug: tried to run numeric operation {:?} on invalid builtin layout: ({:?})", op, arg_layout); - } - } - } - _ => { - unreachable!( - "Compiler bug: tried to run numeric operation {:?} on invalid layout: {:?}", - op, arg_layout - ); - } - } + let arg = load_symbol(scope, &args[0]); + call_bitcode_fn(env, &[arg.into()], bitcode::NUM_BYTES_TO_U16) } NumCompare => { use inkwell::FloatPredicate; @@ -6061,7 +6037,6 @@ fn build_float_unary_op<'a, 'ctx, 'env>( NumAtan => call_bitcode_fn(env, &[arg.into()], bitcode::NUM_ATAN), NumAcos => call_bitcode_fn(env, &[arg.into()], bitcode::NUM_ACOS), NumAsin => call_bitcode_fn(env, &[arg.into()], bitcode::NUM_ASIN), - NumBytesToU16 => call_bitcode_fn(env, &[arg.into()], bitcode::NUM_BYTES_TO_U16), _ => { unreachable!("Unrecognized int unary operation: {:?}", op); } diff --git a/compiler/test_gen/src/gen_num.rs b/compiler/test_gen/src/gen_num.rs index 6d7fd10eb4..047c9f4e9b 100644 --- a/compiler/test_gen/src/gen_num.rs +++ b/compiler/test_gen/src/gen_num.rs @@ -1625,4 +1625,9 @@ mod gen_num { fn num_bytes_to_u16_ascii() { assert_evals_to!("Num.bytesToU16 1", 2.0, f64); } + + #[test] + fn num_bytes_to_u16_ascii_2() { + assert_evals_to!("Num.bytesToU16 0", 1.0, f64); + } } From d976f2fc935bbca37b225eaf7402d86a231e80fa Mon Sep 17 00:00:00 2001 From: Joshua Hoeflich Date: Sat, 14 Aug 2021 18:26:46 -0500 Subject: [PATCH 05/19] Inlining zig side --- compiler/builtins/bitcode/src/num.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/builtins/bitcode/src/num.zig b/compiler/builtins/bitcode/src/num.zig index a7d3fc5269..bc20195d1d 100644 --- a/compiler/builtins/bitcode/src/num.zig +++ b/compiler/builtins/bitcode/src/num.zig @@ -25,7 +25,7 @@ pub fn asin(num: f64) callconv(.C) f64 { /// TODO: Obviously, this should not be an alias for arcsin(x); /// fix me! pub fn bytesToU16C(num: f64) callconv(.C) f64 { - return num + 1; + return @call(.{ .modifier = always_inline }, bytesToU16, .{num}); } fn bytesToU16(num: f64) f64 { From c8f6762debfce9b6ffcebe3d7e8facd38912e64f Mon Sep 17 00:00:00 2001 From: Joshua Hoeflich Date: Sat, 14 Aug 2021 18:30:43 -0500 Subject: [PATCH 06/19] Switch from floats to usize --- compiler/builtins/bitcode/src/num.zig | 6 +++--- compiler/builtins/src/std.rs | 4 ++-- compiler/can/src/builtins.rs | 2 +- compiler/test_gen/src/gen_num.rs | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/builtins/bitcode/src/num.zig b/compiler/builtins/bitcode/src/num.zig index bc20195d1d..dd8e00f036 100644 --- a/compiler/builtins/bitcode/src/num.zig +++ b/compiler/builtins/bitcode/src/num.zig @@ -22,12 +22,12 @@ pub fn asin(num: f64) callconv(.C) f64 { return @call(.{ .modifier = always_inline }, math.asin, .{num}); } -/// TODO: Obviously, this should not be an alias for arcsin(x); +/// TODO: Obviously, this should not be an alias for x + 1. /// fix me! -pub fn bytesToU16C(num: f64) callconv(.C) f64 { +pub fn bytesToU16C(num: usize) callconv(.C) usize { return @call(.{ .modifier = always_inline }, bytesToU16, .{num}); } -fn bytesToU16(num: f64) f64 { +fn bytesToU16(num: usize) usize { return num + 1; } diff --git a/compiler/builtins/src/std.rs b/compiler/builtins/src/std.rs index ea0b749ae8..9a4611e0f6 100644 --- a/compiler/builtins/src/std.rs +++ b/compiler/builtins/src/std.rs @@ -505,8 +505,8 @@ pub fn types() -> MutMap { // bytesToU16 : Float a -> Float a add_top_level_function_type!( Symbol::NUM_BYTES_TO_U16, - vec![float_type(flex(TVAR1))], - Box::new(float_type(flex(TVAR1))), + vec![nat_type()], + Box::new(nat_type()), ); // Bool module diff --git a/compiler/can/src/builtins.rs b/compiler/can/src/builtins.rs index da496a36b2..0217440687 100644 --- a/compiler/can/src/builtins.rs +++ b/compiler/can/src/builtins.rs @@ -1090,7 +1090,7 @@ fn num_asin(symbol: Symbol, var_store: &mut VarStore) -> Def { } /// TODO: This is obviously wrong! Fix me! -/// Num.bytesToU16 : Float -> Float +/// Num.bytesToU16 : Nat -> Nat fn num_bytes_to_u16(symbol: Symbol, var_store: &mut VarStore) -> Def { let arg_float_var = var_store.fresh(); let ret_float_var = var_store.fresh(); diff --git a/compiler/test_gen/src/gen_num.rs b/compiler/test_gen/src/gen_num.rs index 047c9f4e9b..e0acc3f1fa 100644 --- a/compiler/test_gen/src/gen_num.rs +++ b/compiler/test_gen/src/gen_num.rs @@ -1623,11 +1623,11 @@ mod gen_num { #[test] fn num_bytes_to_u16_ascii() { - assert_evals_to!("Num.bytesToU16 1", 2.0, f64); + assert_evals_to!("Num.bytesToU16 1", 2, usize); } #[test] fn num_bytes_to_u16_ascii_2() { - assert_evals_to!("Num.bytesToU16 0", 1.0, f64); + assert_evals_to!("Num.bytesToU16 0", 1, usize); } } From 5115a004ed78cca0b54a911e0dc9a780c6bd32d6 Mon Sep 17 00:00:00 2001 From: Joshua Hoeflich Date: Sat, 14 Aug 2021 18:50:49 -0500 Subject: [PATCH 07/19] Type shenanigans work --- compiler/builtins/bitcode/src/num.zig | 7 ++++--- compiler/builtins/src/std.rs | 6 +++--- compiler/test_gen/src/gen_num.rs | 4 ++-- compiler/types/src/builtin_aliases.rs | 10 ++++++++++ 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/compiler/builtins/bitcode/src/num.zig b/compiler/builtins/bitcode/src/num.zig index dd8e00f036..649a1c87ba 100644 --- a/compiler/builtins/bitcode/src/num.zig +++ b/compiler/builtins/bitcode/src/num.zig @@ -24,10 +24,11 @@ pub fn asin(num: f64) callconv(.C) f64 { /// TODO: Obviously, this should not be an alias for x + 1. /// fix me! -pub fn bytesToU16C(num: usize) callconv(.C) usize { +pub fn bytesToU16C(num: usize) callconv(.C) u16 { return @call(.{ .modifier = always_inline }, bytesToU16, .{num}); } -fn bytesToU16(num: usize) usize { - return num + 1; +fn bytesToU16(num: usize) u16 { + const exampleAnswer: u16 = 40; + return 40; } diff --git a/compiler/builtins/src/std.rs b/compiler/builtins/src/std.rs index 9a4611e0f6..49b6cac6c9 100644 --- a/compiler/builtins/src/std.rs +++ b/compiler/builtins/src/std.rs @@ -5,7 +5,7 @@ use roc_region::all::Region; use roc_types::builtin_aliases::{ bool_type, dict_type, float_type, i128_type, int_type, list_type, nat_type, num_type, ordering_type, result_type, set_type, str_type, str_utf8_byte_problem_type, u32_type, u64_type, - u8_type, + u8_type, u16_type }; use roc_types::solved_types::SolvedType; use roc_types::subs::VarId; @@ -502,11 +502,11 @@ pub fn types() -> MutMap { ); // TODO: This is obviously wrong! Fix me! - // bytesToU16 : Float a -> Float a + // bytesToU16 : Nat -> U16 add_top_level_function_type!( Symbol::NUM_BYTES_TO_U16, vec![nat_type()], - Box::new(nat_type()), + Box::new(u16_type()), ); // Bool module diff --git a/compiler/test_gen/src/gen_num.rs b/compiler/test_gen/src/gen_num.rs index e0acc3f1fa..623f0dda1c 100644 --- a/compiler/test_gen/src/gen_num.rs +++ b/compiler/test_gen/src/gen_num.rs @@ -1623,11 +1623,11 @@ mod gen_num { #[test] fn num_bytes_to_u16_ascii() { - assert_evals_to!("Num.bytesToU16 1", 2, usize); + assert_evals_to!("Num.bytesToU16 1", 40, u16); } #[test] fn num_bytes_to_u16_ascii_2() { - assert_evals_to!("Num.bytesToU16 0", 1, usize); + assert_evals_to!("Num.bytesToU16 0", 40, u16); } } diff --git a/compiler/types/src/builtin_aliases.rs b/compiler/types/src/builtin_aliases.rs index 6e2caa4e72..dc49280bc7 100644 --- a/compiler/types/src/builtin_aliases.rs +++ b/compiler/types/src/builtin_aliases.rs @@ -521,6 +521,16 @@ pub fn u8_type() -> SolvedType { ) } +#[inline(always)] +pub fn u16_type() -> SolvedType { + SolvedType::Alias( + Symbol::NUM_U16, + vec![], + vec![], + Box::new(int_alias_content(unsigned16_type())), + ) +} + #[inline(always)] pub fn binary64_type() -> SolvedType { SolvedType::Alias( From 8022e3e5f486c24134c640573d892a7885e70d54 Mon Sep 17 00:00:00 2001 From: Joshua Hoeflich Date: Sat, 14 Aug 2021 18:52:48 -0500 Subject: [PATCH 08/19] Rename var --- compiler/builtins/bitcode/src/num.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/builtins/bitcode/src/num.zig b/compiler/builtins/bitcode/src/num.zig index 649a1c87ba..b4657eaae1 100644 --- a/compiler/builtins/bitcode/src/num.zig +++ b/compiler/builtins/bitcode/src/num.zig @@ -24,11 +24,11 @@ pub fn asin(num: f64) callconv(.C) f64 { /// TODO: Obviously, this should not be an alias for x + 1. /// fix me! -pub fn bytesToU16C(num: usize) callconv(.C) u16 { - return @call(.{ .modifier = always_inline }, bytesToU16, .{num}); +pub fn bytesToU16C(position: usize) callconv(.C) u16 { + return @call(.{ .modifier = always_inline }, bytesToU16, .{position}); } -fn bytesToU16(num: usize) u16 { +fn bytesToU16(position: usize) u16 { const exampleAnswer: u16 = 40; return 40; } From 9dad304e9521d695662e2f2d5ef023a0e59c6a21 Mon Sep 17 00:00:00 2001 From: Joshua Hoeflich Date: Sat, 14 Aug 2021 19:11:27 -0500 Subject: [PATCH 09/19] Passing arguments successfully to bytesToU16 --- compiler/builtins/bitcode/src/num.zig | 7 ++++--- compiler/builtins/src/std.rs | 5 ++--- compiler/can/src/builtins.rs | 19 +++++++++++-------- compiler/gen_llvm/src/llvm/build.rs | 20 ++++++++++++++++---- compiler/mono/src/borrow.rs | 2 +- compiler/test_gen/src/gen_num.rs | 4 ++-- 6 files changed, 36 insertions(+), 21 deletions(-) diff --git a/compiler/builtins/bitcode/src/num.zig b/compiler/builtins/bitcode/src/num.zig index b4657eaae1..a542938ed3 100644 --- a/compiler/builtins/bitcode/src/num.zig +++ b/compiler/builtins/bitcode/src/num.zig @@ -1,6 +1,7 @@ const std = @import("std"); const always_inline = std.builtin.CallOptions.Modifier.always_inline; const math = std.math; +const RocList = @import("list.zig").RocList; pub fn atan(num: f64) callconv(.C) f64 { return @call(.{ .modifier = always_inline }, math.atan, .{num}); @@ -24,11 +25,11 @@ pub fn asin(num: f64) callconv(.C) f64 { /// TODO: Obviously, this should not be an alias for x + 1. /// fix me! -pub fn bytesToU16C(position: usize) callconv(.C) u16 { - return @call(.{ .modifier = always_inline }, bytesToU16, .{position}); +pub fn bytesToU16C(arg: RocList, position: usize) callconv(.C) u16 { + return @call(.{ .modifier = always_inline }, bytesToU16, .{arg, position}); } -fn bytesToU16(position: usize) u16 { +fn bytesToU16(arg: RocList, position: usize) u16 { const exampleAnswer: u16 = 40; return 40; } diff --git a/compiler/builtins/src/std.rs b/compiler/builtins/src/std.rs index 49b6cac6c9..5506ffa60c 100644 --- a/compiler/builtins/src/std.rs +++ b/compiler/builtins/src/std.rs @@ -501,11 +501,10 @@ pub fn types() -> MutMap { Box::new(float_type(flex(TVAR1))), ); - // TODO: This is obviously wrong! Fix me! - // bytesToU16 : Nat -> U16 + // bytesToU16 : List U8, Nat -> U16 add_top_level_function_type!( Symbol::NUM_BYTES_TO_U16, - vec![nat_type()], + vec![list_type(u8_type()), nat_type()], Box::new(u16_type()), ); diff --git a/compiler/can/src/builtins.rs b/compiler/can/src/builtins.rs index 0217440687..5f0eae30fd 100644 --- a/compiler/can/src/builtins.rs +++ b/compiler/can/src/builtins.rs @@ -1089,24 +1089,27 @@ fn num_asin(symbol: Symbol, var_store: &mut VarStore) -> Def { ) } -/// TODO: This is obviously wrong! Fix me! -/// Num.bytesToU16 : Nat -> Nat +/// Num.bytesToU16 : List U8, Nat -> Nat fn num_bytes_to_u16(symbol: Symbol, var_store: &mut VarStore) -> Def { - let arg_float_var = var_store.fresh(); - let ret_float_var = var_store.fresh(); + let list_var = var_store.fresh(); + let nat_var = var_store.fresh(); + let ret_var = var_store.fresh(); let body = RunLowLevel { op: LowLevel::NumBytesToU16, - args: vec![(arg_float_var, Var(Symbol::ARG_1))], - ret_var: ret_float_var, + args: vec![ + (list_var, Var(Symbol::ARG_1)), + (nat_var, Var(Symbol::ARG_2)), + ], + ret_var, }; defn( symbol, - vec![(arg_float_var, Symbol::ARG_1)], + vec![(list_var, Symbol::ARG_1), (nat_var, Symbol::ARG_2)], var_store, body, - ret_float_var, + ret_var, ) } diff --git a/compiler/gen_llvm/src/llvm/build.rs b/compiler/gen_llvm/src/llvm/build.rs index ebb8cd2a2e..e7edf60197 100644 --- a/compiler/gen_llvm/src/llvm/build.rs +++ b/compiler/gen_llvm/src/llvm/build.rs @@ -4738,11 +4738,23 @@ fn run_low_level<'a, 'ctx, 'env>( } } } - // TODO: Obviously, this is completely wrong! Fix me! NumBytesToU16 => { - debug_assert_eq!(args.len(), 1); - let arg = load_symbol(scope, &args[0]); - call_bitcode_fn(env, &[arg.into()], bitcode::NUM_BYTES_TO_U16) + debug_assert_eq!(args.len(), 2); + let list = load_symbol(scope, &args[0]).into_struct_value(); + let position = load_symbol(scope, &args[1]); + call_bitcode_fn( + env, + &[ + complex_bitcast( + env.builder, + list.into(), + env.context.i128_type().into(), + "to_i128", + ), + position.into(), + ], + bitcode::NUM_BYTES_TO_U16, + ) } NumCompare => { use inkwell::FloatPredicate; diff --git a/compiler/mono/src/borrow.rs b/compiler/mono/src/borrow.rs index 9a7b952d3c..a3349f3255 100644 --- a/compiler/mono/src/borrow.rs +++ b/compiler/mono/src/borrow.rs @@ -1013,7 +1013,7 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] { | NumCeiling | NumFloor | NumToFloat | Not | NumIsFinite | NumAtan | NumAcos | NumAsin | NumIntCast => arena.alloc_slice_copy(&[irrelevant]), // TODO: Fix me! I am wrong! - NumBytesToU16 => arena.alloc_slice_copy(&[irrelevant]), + NumBytesToU16 => arena.alloc_slice_copy(&[borrowed, irrelevant]), StrStartsWith | StrEndsWith => arena.alloc_slice_copy(&[owned, borrowed]), StrStartsWithCodePt => arena.alloc_slice_copy(&[borrowed, irrelevant]), StrFromUtf8 => arena.alloc_slice_copy(&[owned]), diff --git a/compiler/test_gen/src/gen_num.rs b/compiler/test_gen/src/gen_num.rs index 623f0dda1c..b294c25472 100644 --- a/compiler/test_gen/src/gen_num.rs +++ b/compiler/test_gen/src/gen_num.rs @@ -1623,11 +1623,11 @@ mod gen_num { #[test] fn num_bytes_to_u16_ascii() { - assert_evals_to!("Num.bytesToU16 1", 40, u16); + assert_evals_to!("Num.bytesToU16 [] 1", 40, u16); } #[test] fn num_bytes_to_u16_ascii_2() { - assert_evals_to!("Num.bytesToU16 0", 40, u16); + assert_evals_to!("Num.bytesToU16 [] 0", 40, u16); } } From 22e781259d9e1d4e8cf1d7e6cb59cc45e547f769 Mon Sep 17 00:00:00 2001 From: Joshua Hoeflich Date: Sat, 14 Aug 2021 19:28:13 -0500 Subject: [PATCH 10/19] TODO: Actually implement the functions --- compiler/builtins/bitcode/src/main.zig | 1 + compiler/builtins/bitcode/src/num.zig | 15 ++++++++++++-- compiler/builtins/src/bitcode.rs | 2 +- compiler/builtins/src/std.rs | 7 +++++++ compiler/can/src/builtins.rs | 27 +++++++++++++++++++++++++- compiler/gen_llvm/src/llvm/build.rs | 18 +++++++++++++++++ compiler/module/src/low_level.rs | 6 +++--- compiler/module/src/symbol.rs | 1 + compiler/mono/src/borrow.rs | 2 +- compiler/test_gen/src/gen_num.rs | 15 ++++++++++++-- 10 files changed, 84 insertions(+), 10 deletions(-) diff --git a/compiler/builtins/bitcode/src/main.zig b/compiler/builtins/bitcode/src/main.zig index 0a8c712117..eb7dd39bb5 100644 --- a/compiler/builtins/bitcode/src/main.zig +++ b/compiler/builtins/bitcode/src/main.zig @@ -80,6 +80,7 @@ comptime { exportNumFn(num.acos, "acos"); exportNumFn(num.asin, "asin"); exportNumFn(num.bytesToU16C, "bytes_to_u16"); + exportNumFn(num.bytesToU32C, "bytes_to_u32"); } // Str Module diff --git a/compiler/builtins/bitcode/src/num.zig b/compiler/builtins/bitcode/src/num.zig index a542938ed3..71df53bd2c 100644 --- a/compiler/builtins/bitcode/src/num.zig +++ b/compiler/builtins/bitcode/src/num.zig @@ -23,8 +23,8 @@ pub fn asin(num: f64) callconv(.C) f64 { return @call(.{ .modifier = always_inline }, math.asin, .{num}); } -/// TODO: Obviously, this should not be an alias for x + 1. -/// fix me! +/// TODO: Obviously, this function should do something more interesting +/// than return the number 40. Fix me! pub fn bytesToU16C(arg: RocList, position: usize) callconv(.C) u16 { return @call(.{ .modifier = always_inline }, bytesToU16, .{arg, position}); } @@ -33,3 +33,14 @@ fn bytesToU16(arg: RocList, position: usize) u16 { const exampleAnswer: u16 = 40; return 40; } + +/// TODO: Obviously, this function should do something more interesting +/// than return the number 40. Fix me! +pub fn bytesToU32C(arg: RocList, position: usize) callconv(.C) u32 { + return @call(.{ .modifier = always_inline }, bytesToU32, .{arg, position}); +} + +fn bytesToU32(arg: RocList, position: usize) u32 { + const exampleAnswer: u32 = 41; + return 41; +} diff --git a/compiler/builtins/src/bitcode.rs b/compiler/builtins/src/bitcode.rs index 224d08e526..9d08bbbf45 100644 --- a/compiler/builtins/src/bitcode.rs +++ b/compiler/builtins/src/bitcode.rs @@ -9,7 +9,7 @@ pub const NUM_ATAN: &str = "roc_builtins.num.atan"; pub const NUM_IS_FINITE: &str = "roc_builtins.num.is_finite"; pub const NUM_POW_INT: &str = "roc_builtins.num.pow_int"; pub const NUM_BYTES_TO_U16: &str = "roc_builtins.num.bytes_to_u16"; - +pub const NUM_BYTES_TO_U32: &str = "roc_builtins.num.bytes_to_u32"; pub const STR_INIT: &str = "roc_builtins.str.init"; pub const STR_COUNT_SEGMENTS: &str = "roc_builtins.str.count_segments"; diff --git a/compiler/builtins/src/std.rs b/compiler/builtins/src/std.rs index 5506ffa60c..13f380e6ab 100644 --- a/compiler/builtins/src/std.rs +++ b/compiler/builtins/src/std.rs @@ -508,6 +508,13 @@ pub fn types() -> MutMap { Box::new(u16_type()), ); + // bytesToU32 : List U8, Nat -> U32 + add_top_level_function_type!( + Symbol::NUM_BYTES_TO_U32, + vec![list_type(u8_type()), nat_type()], + Box::new(u32_type()), + ); + // Bool module // and : Bool, Bool -> Bool diff --git a/compiler/can/src/builtins.rs b/compiler/can/src/builtins.rs index 5f0eae30fd..f34e317858 100644 --- a/compiler/can/src/builtins.rs +++ b/compiler/can/src/builtins.rs @@ -162,6 +162,7 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option NUM_ACOS => num_acos, NUM_ASIN => num_asin, NUM_BYTES_TO_U16 => num_bytes_to_u16, + NUM_BYTES_TO_U32 => num_bytes_to_u32, NUM_MAX_INT => num_max_int, NUM_MIN_INT => num_min_int, NUM_BITWISE_AND => num_bitwise_and, @@ -1089,7 +1090,7 @@ fn num_asin(symbol: Symbol, var_store: &mut VarStore) -> Def { ) } -/// Num.bytesToU16 : List U8, Nat -> Nat +/// Num.bytesToU16 : List U8, Nat -> U16 fn num_bytes_to_u16(symbol: Symbol, var_store: &mut VarStore) -> Def { let list_var = var_store.fresh(); let nat_var = var_store.fresh(); @@ -1113,6 +1114,30 @@ fn num_bytes_to_u16(symbol: Symbol, var_store: &mut VarStore) -> Def { ) } +/// Num.bytesToU32 : List U8, Nat -> U32 +fn num_bytes_to_u32(symbol: Symbol, var_store: &mut VarStore) -> Def { + let list_var = var_store.fresh(); + let nat_var = var_store.fresh(); + let ret_var = var_store.fresh(); + + let body = RunLowLevel { + op: LowLevel::NumBytesToU32, + args: vec![ + (list_var, Var(Symbol::ARG_1)), + (nat_var, Var(Symbol::ARG_2)), + ], + ret_var, + }; + + defn( + symbol, + vec![(list_var, Symbol::ARG_1), (nat_var, Symbol::ARG_2)], + var_store, + body, + ret_var, + ) +} + /// Num.bitwiseAnd : Int a, Int a -> Int a fn num_bitwise_and(symbol: Symbol, var_store: &mut VarStore) -> Def { num_binop(symbol, var_store, LowLevel::NumBitwiseAnd) diff --git a/compiler/gen_llvm/src/llvm/build.rs b/compiler/gen_llvm/src/llvm/build.rs index e7edf60197..a89908f588 100644 --- a/compiler/gen_llvm/src/llvm/build.rs +++ b/compiler/gen_llvm/src/llvm/build.rs @@ -4756,6 +4756,24 @@ fn run_low_level<'a, 'ctx, 'env>( bitcode::NUM_BYTES_TO_U16, ) } + NumBytesToU32 => { + debug_assert_eq!(args.len(), 2); + let list = load_symbol(scope, &args[0]).into_struct_value(); + let position = load_symbol(scope, &args[1]); + call_bitcode_fn( + env, + &[ + complex_bitcast( + env.builder, + list.into(), + env.context.i128_type().into(), + "to_i128", + ), + position.into(), + ], + bitcode::NUM_BYTES_TO_U32, + ) + } NumCompare => { use inkwell::FloatPredicate; diff --git a/compiler/module/src/low_level.rs b/compiler/module/src/low_level.rs index 868f4ed635..583e6017c1 100644 --- a/compiler/module/src/low_level.rs +++ b/compiler/module/src/low_level.rs @@ -88,6 +88,7 @@ pub enum LowLevel { NumAcos, NumAsin, NumBytesToU16, + NumBytesToU32, NumBitwiseAnd, NumBitwiseXor, NumBitwiseOr, @@ -124,9 +125,8 @@ impl LowLevel { | NumSqrtUnchecked | NumLogUnchecked | NumRound | NumToFloat | NumPow | NumCeiling | NumPowInt | NumFloor | NumIsFinite | NumAtan | NumAcos | NumAsin | NumBitwiseAnd | NumBitwiseXor | NumBitwiseOr | NumShiftLeftBy | NumShiftRightBy | NumBytesToU16 - | NumShiftRightZfBy | NumIntCast | Eq | NotEq | And | Or | Not | Hash | ExpectTrue => { - false - } + | NumBytesToU32 | NumShiftRightZfBy | NumIntCast | Eq | NotEq | And | Or | Not + | Hash | ExpectTrue => false, ListMap | ListMap2 | ListMap3 | ListMapWithIndex | ListKeepIf | ListWalk | ListWalkUntil | ListWalkBackwards | ListKeepOks | ListKeepErrs | ListSortWith diff --git a/compiler/module/src/symbol.rs b/compiler/module/src/symbol.rs index caddb4a0b4..eb0200337d 100644 --- a/compiler/module/src/symbol.rs +++ b/compiler/module/src/symbol.rs @@ -892,6 +892,7 @@ define_builtins! { 101 NUM_DECIMAL: "Decimal" imported 102 NUM_DEC: "Dec" imported // the Num.Dectype alias 103 NUM_BYTES_TO_U16: "bytesToU16" + 104 NUM_BYTES_TO_U32: "bytesToU32" } 2 BOOL: "Bool" => { 0 BOOL_BOOL: "Bool" imported // the Bool.Bool type alias diff --git a/compiler/mono/src/borrow.rs b/compiler/mono/src/borrow.rs index a3349f3255..521ebcd371 100644 --- a/compiler/mono/src/borrow.rs +++ b/compiler/mono/src/borrow.rs @@ -1012,8 +1012,8 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] { NumAbs | NumNeg | NumSin | NumCos | NumSqrtUnchecked | NumLogUnchecked | NumRound | NumCeiling | NumFloor | NumToFloat | Not | NumIsFinite | NumAtan | NumAcos | NumAsin | NumIntCast => arena.alloc_slice_copy(&[irrelevant]), - // TODO: Fix me! I am wrong! NumBytesToU16 => arena.alloc_slice_copy(&[borrowed, irrelevant]), + NumBytesToU32 => arena.alloc_slice_copy(&[borrowed, irrelevant]), StrStartsWith | StrEndsWith => arena.alloc_slice_copy(&[owned, borrowed]), StrStartsWithCodePt => arena.alloc_slice_copy(&[borrowed, irrelevant]), StrFromUtf8 => arena.alloc_slice_copy(&[owned]), diff --git a/compiler/test_gen/src/gen_num.rs b/compiler/test_gen/src/gen_num.rs index b294c25472..2e1ec08de6 100644 --- a/compiler/test_gen/src/gen_num.rs +++ b/compiler/test_gen/src/gen_num.rs @@ -1621,13 +1621,24 @@ mod gen_num { assert_evals_to!("Num.isMultipleOf -9223372036854775808 -1", true, bool); } + // TODO: Once we know what the function should do, let's give these real names! #[test] - fn num_bytes_to_u16_ascii() { + fn potato_1() { assert_evals_to!("Num.bytesToU16 [] 1", 40, u16); } #[test] - fn num_bytes_to_u16_ascii_2() { + fn potato_2() { assert_evals_to!("Num.bytesToU16 [] 0", 40, u16); } + + #[test] + fn potato_3() { + assert_evals_to!("Num.bytesToU32 [] 1", 41, u32); + } + + #[test] + fn potato_4() { + assert_evals_to!("Num.bytesToU32 [] 0", 41, u32); + } } From 92da003fba988da953808c0699c5b97a60fcc913 Mon Sep 17 00:00:00 2001 From: Joshua Hoeflich Date: Wed, 18 Aug 2021 11:02:20 -0500 Subject: [PATCH 11/19] Adds castToNat --- compiler/builtins/bitcode/src/main.zig | 1 + compiler/builtins/bitcode/src/num.zig | 4 ++++ compiler/builtins/src/bitcode.rs | 1 + compiler/builtins/src/std.rs | 7 +++++++ compiler/gen_llvm/src/llvm/build.rs | 5 +++++ compiler/module/src/low_level.rs | 5 +++-- compiler/module/src/symbol.rs | 1 + compiler/mono/src/borrow.rs | 1 + 8 files changed, 23 insertions(+), 2 deletions(-) diff --git a/compiler/builtins/bitcode/src/main.zig b/compiler/builtins/bitcode/src/main.zig index 21fd75b19b..26135c21ad 100644 --- a/compiler/builtins/bitcode/src/main.zig +++ b/compiler/builtins/bitcode/src/main.zig @@ -81,6 +81,7 @@ comptime { exportNumFn(num.asin, "asin"); exportNumFn(num.bytesToU16C, "bytes_to_u16"); exportNumFn(num.bytesToU32C, "bytes_to_u32"); + exportNumFn(num.castToNat, "cast_to_nat"); exportNumFn(num.round, "round"); } diff --git a/compiler/builtins/bitcode/src/num.zig b/compiler/builtins/bitcode/src/num.zig index 15a8644762..7256171b46 100644 --- a/compiler/builtins/bitcode/src/num.zig +++ b/compiler/builtins/bitcode/src/num.zig @@ -45,6 +45,10 @@ fn bytesToU32(arg: RocList, position: usize) u32 { return 41; } +pub fn castToNat(num: i64) callconv(.C) usize { + return @intCast(usize, num); +} + pub fn round(num: f64) callconv(.C) i64 { return @floatToInt(i32, (@round(num))); } diff --git a/compiler/builtins/src/bitcode.rs b/compiler/builtins/src/bitcode.rs index 8da5367bec..18d695ae1b 100644 --- a/compiler/builtins/src/bitcode.rs +++ b/compiler/builtins/src/bitcode.rs @@ -10,6 +10,7 @@ pub const NUM_IS_FINITE: &str = "roc_builtins.num.is_finite"; pub const NUM_POW_INT: &str = "roc_builtins.num.pow_int"; pub const NUM_BYTES_TO_U16: &str = "roc_builtins.num.bytes_to_u16"; pub const NUM_BYTES_TO_U32: &str = "roc_builtins.num.bytes_to_u32"; +pub const NUM_CAST_TO_NAT: &str = "roc_builtins.num.cast_to_nat"; pub const NUM_ROUND: &str = "roc_builtins.num.round"; pub const STR_INIT: &str = "roc_builtins.str.init"; diff --git a/compiler/builtins/src/std.rs b/compiler/builtins/src/std.rs index 13f380e6ab..5dd954fe56 100644 --- a/compiler/builtins/src/std.rs +++ b/compiler/builtins/src/std.rs @@ -501,6 +501,13 @@ pub fn types() -> MutMap { Box::new(float_type(flex(TVAR1))), ); + // castToNat : Num a -> Nat + add_top_level_function_type!( + Symbol::NUM_CAST_TO_NAT, + vec![int_type(flex(TVAR1))], + Box::new(nat_type()), + ); + // bytesToU16 : List U8, Nat -> U16 add_top_level_function_type!( Symbol::NUM_BYTES_TO_U16, diff --git a/compiler/gen_llvm/src/llvm/build.rs b/compiler/gen_llvm/src/llvm/build.rs index a89908f588..bfa5f23ebb 100644 --- a/compiler/gen_llvm/src/llvm/build.rs +++ b/compiler/gen_llvm/src/llvm/build.rs @@ -4738,6 +4738,11 @@ fn run_low_level<'a, 'ctx, 'env>( } } } + NumCastToNat => { + debug_assert_eq!(args.len(), 1); + let num = load_symbol(scope, &args[0]).into_int_value(); + call_bitcode_fn(env, &[num.into()], bitcode::NUM_CAST_TO_NAT) + } NumBytesToU16 => { debug_assert_eq!(args.len(), 2); let list = load_symbol(scope, &args[0]).into_struct_value(); diff --git a/compiler/module/src/low_level.rs b/compiler/module/src/low_level.rs index 583e6017c1..2941fdd941 100644 --- a/compiler/module/src/low_level.rs +++ b/compiler/module/src/low_level.rs @@ -89,6 +89,7 @@ pub enum LowLevel { NumAsin, NumBytesToU16, NumBytesToU32, + NumCastToNat, NumBitwiseAnd, NumBitwiseXor, NumBitwiseOr, @@ -125,8 +126,8 @@ impl LowLevel { | NumSqrtUnchecked | NumLogUnchecked | NumRound | NumToFloat | NumPow | NumCeiling | NumPowInt | NumFloor | NumIsFinite | NumAtan | NumAcos | NumAsin | NumBitwiseAnd | NumBitwiseXor | NumBitwiseOr | NumShiftLeftBy | NumShiftRightBy | NumBytesToU16 - | NumBytesToU32 | NumShiftRightZfBy | NumIntCast | Eq | NotEq | And | Or | Not - | Hash | ExpectTrue => false, + | NumBytesToU32 | NumCastToNat | NumShiftRightZfBy | NumIntCast | Eq | NotEq | And + | Or | Not | Hash | ExpectTrue => false, ListMap | ListMap2 | ListMap3 | ListMapWithIndex | ListKeepIf | ListWalk | ListWalkUntil | ListWalkBackwards | ListKeepOks | ListKeepErrs | ListSortWith diff --git a/compiler/module/src/symbol.rs b/compiler/module/src/symbol.rs index eb0200337d..dfbc95f3a7 100644 --- a/compiler/module/src/symbol.rs +++ b/compiler/module/src/symbol.rs @@ -893,6 +893,7 @@ define_builtins! { 102 NUM_DEC: "Dec" imported // the Num.Dectype alias 103 NUM_BYTES_TO_U16: "bytesToU16" 104 NUM_BYTES_TO_U32: "bytesToU32" + 105 NUM_CAST_TO_NAT: "#castToNat" } 2 BOOL: "Bool" => { 0 BOOL_BOOL: "Bool" imported // the Bool.Bool type alias diff --git a/compiler/mono/src/borrow.rs b/compiler/mono/src/borrow.rs index 521ebcd371..ed2c06e82f 100644 --- a/compiler/mono/src/borrow.rs +++ b/compiler/mono/src/borrow.rs @@ -1014,6 +1014,7 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] { | NumIntCast => arena.alloc_slice_copy(&[irrelevant]), NumBytesToU16 => arena.alloc_slice_copy(&[borrowed, irrelevant]), NumBytesToU32 => arena.alloc_slice_copy(&[borrowed, irrelevant]), + NumCastToNat => arena.alloc_slice_copy(&[irrelevant]), StrStartsWith | StrEndsWith => arena.alloc_slice_copy(&[owned, borrowed]), StrStartsWithCodePt => arena.alloc_slice_copy(&[borrowed, irrelevant]), StrFromUtf8 => arena.alloc_slice_copy(&[owned]), From b4f575736b9f67d442bf930c9bc2507879e02e56 Mon Sep 17 00:00:00 2001 From: Joshua Hoeflich Date: Wed, 18 Aug 2021 11:31:48 -0500 Subject: [PATCH 12/19] castToNat working --- compiler/builtins/src/std.rs | 20 ++++-- compiler/can/src/builtins.rs | 107 ++++++++++++++++++++++++++++--- compiler/test_gen/src/gen_num.rs | 44 ++++++++++++- 3 files changed, 151 insertions(+), 20 deletions(-) diff --git a/compiler/builtins/src/std.rs b/compiler/builtins/src/std.rs index 5dd954fe56..aeb77a803b 100644 --- a/compiler/builtins/src/std.rs +++ b/compiler/builtins/src/std.rs @@ -4,8 +4,8 @@ use roc_module::symbol::Symbol; use roc_region::all::Region; use roc_types::builtin_aliases::{ bool_type, dict_type, float_type, i128_type, int_type, list_type, nat_type, num_type, - ordering_type, result_type, set_type, str_type, str_utf8_byte_problem_type, u32_type, u64_type, - u8_type, u16_type + ordering_type, result_type, set_type, str_type, str_utf8_byte_problem_type, u16_type, u32_type, + u64_type, u8_type, }; use roc_types::solved_types::SolvedType; use roc_types::subs::VarId; @@ -509,11 +509,17 @@ pub fn types() -> MutMap { ); // bytesToU16 : List U8, Nat -> U16 - add_top_level_function_type!( - Symbol::NUM_BYTES_TO_U16, - vec![list_type(u8_type()), nat_type()], - Box::new(u16_type()), - ); + { + let position_out_of_bounds = SolvedType::TagUnion( + vec![(TagName::Global("OutOfBounds".into()), vec![])], + Box::new(SolvedType::Wildcard), + ); + add_top_level_function_type!( + Symbol::NUM_BYTES_TO_U16, + vec![list_type(u8_type()), nat_type()], + Box::new(result_type(u16_type(), position_out_of_bounds)), + ); + } // bytesToU32 : List U8, Nat -> U32 add_top_level_function_type!( diff --git a/compiler/can/src/builtins.rs b/compiler/can/src/builtins.rs index f34e317858..a645fb917e 100644 --- a/compiler/can/src/builtins.rs +++ b/compiler/can/src/builtins.rs @@ -1092,26 +1092,113 @@ fn num_asin(symbol: Symbol, var_store: &mut VarStore) -> Def { /// Num.bytesToU16 : List U8, Nat -> U16 fn num_bytes_to_u16(symbol: Symbol, var_store: &mut VarStore) -> Def { + let len_var = var_store.fresh(); let list_var = var_store.fresh(); - let nat_var = var_store.fresh(); - let ret_var = var_store.fresh(); + let elem_var = var_store.fresh(); - let body = RunLowLevel { - op: LowLevel::NumBytesToU16, - args: vec![ - (list_var, Var(Symbol::ARG_1)), - (nat_var, Var(Symbol::ARG_2)), - ], - ret_var, + let ret_var = var_store.fresh(); + let bool_var = var_store.fresh(); + let add_var = var_store.fresh(); + let cast_var = var_store.fresh(); + + // Perform a bounds check. If it passes, run LowLevel::NumBytesToU16 + let body = If { + cond_var: bool_var, + branch_var: var_store.fresh(), + branches: vec![( + // if-condition + no_region( + // index + 1 < List.len list + RunLowLevel { + op: LowLevel::NumLt, + args: vec![ + ( + len_var, + RunLowLevel { + op: LowLevel::NumAdd, + args: vec![ + (add_var, Var(Symbol::ARG_2)), + ( + add_var, + RunLowLevel { + ret_var: cast_var, + args: vec![(cast_var, Num(var_store.fresh(), 1))], + op: LowLevel::NumCastToNat, + }, + ), + ], + ret_var: add_var, + }, + ), + ( + len_var, + RunLowLevel { + op: LowLevel::ListLen, + args: vec![(list_var, Var(Symbol::ARG_1))], + ret_var: len_var, + }, + ), + ], + ret_var: bool_var, + }, + ), + // then-branch + no_region( + // Ok + tag( + "Ok", + vec![RunLowLevel { + op: LowLevel::NumBytesToU16, + args: vec![ + (list_var, Var(Symbol::ARG_1)), + (len_var, Var(Symbol::ARG_2)), + ], + ret_var: elem_var, + }], + var_store, + ), + ), + )], + final_else: Box::new( + // else-branch + no_region( + // Err + tag( + "Err", + vec![tag("OutOfBounds", Vec::new(), var_store)], + var_store, + ), + ), + ), }; defn( symbol, - vec![(list_var, Symbol::ARG_1), (nat_var, Symbol::ARG_2)], + vec![(list_var, Symbol::ARG_1), (len_var, Symbol::ARG_2)], var_store, body, ret_var, ) + // let list_var = var_store.fresh(); + // let nat_var = var_store.fresh(); + // let ret_var = var_store.fresh(); + + // let body = RunLowLevel { + // op: LowLevel::NumBytesToU16, + // args: vec![ + // (list_var, Var(Symbol::ARG_1)), + // (nat_var, Var(Symbol::ARG_2)), + // ], + // ret_var, + // }; + + // defn( + // symbol, + // vec![(list_var, Symbol::ARG_1), (nat_var, Symbol::ARG_2)], + // var_store, + // body, + // ret_var, + // ) } /// Num.bytesToU32 : List U8, Nat -> U32 diff --git a/compiler/test_gen/src/gen_num.rs b/compiler/test_gen/src/gen_num.rs index 4f9162fcc7..c2e78941c1 100644 --- a/compiler/test_gen/src/gen_num.rs +++ b/compiler/test_gen/src/gen_num.rs @@ -1628,21 +1628,59 @@ mod gen_num { // TODO: Once we know what the function should do, let's give these real names! #[test] fn potato_1() { - assert_evals_to!("Num.bytesToU16 [] 1", 40, u16); + assert_evals_to!( + indoc!( + r#" + bytes = Str.toUtf8 "hello" + when Num.bytesToU16 bytes 0 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 40, + usize + ); } #[test] fn potato_2() { - assert_evals_to!("Num.bytesToU16 [] 0", 40, u16); + assert_evals_to!( + indoc!( + r#" + bytes = Str.toUtf8 "hello" + when Num.bytesToU16 bytes 234 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 1, + usize + ); } #[test] fn potato_3() { - assert_evals_to!("Num.bytesToU32 [] 1", 41, u32); + assert_evals_to!( + indoc!( + r#" + bytes = Str.toUtf8 "hello" + when Num.bytesToU16 bytes 4 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 1, + usize + ); } #[test] fn potato_4() { + assert_evals_to!("Num.bytesToU32 [] 1", 41, u32); + } + + #[test] + fn potato_5() { assert_evals_to!("Num.bytesToU32 [] 0", 41, u32); } } From a4197d073cd187ccc965b646e48b59331d6e2f75 Mon Sep 17 00:00:00 2001 From: Joshua Hoeflich Date: Wed, 18 Aug 2021 15:46:53 -0500 Subject: [PATCH 13/19] bytesToU16 and bytesToU32 have proper types --- compiler/builtins/src/std.rs | 20 ++- compiler/can/src/builtins.rs | 224 +++++++++++++------------------ compiler/test_gen/src/gen_num.rs | 37 ++++- 3 files changed, 138 insertions(+), 143 deletions(-) diff --git a/compiler/builtins/src/std.rs b/compiler/builtins/src/std.rs index aeb77a803b..0b32ca80b3 100644 --- a/compiler/builtins/src/std.rs +++ b/compiler/builtins/src/std.rs @@ -508,7 +508,7 @@ pub fn types() -> MutMap { Box::new(nat_type()), ); - // bytesToU16 : List U8, Nat -> U16 + // bytesToU16 : List U8, Nat -> Result U16 [ OutOfBounds ] { let position_out_of_bounds = SolvedType::TagUnion( vec![(TagName::Global("OutOfBounds".into()), vec![])], @@ -521,12 +521,18 @@ pub fn types() -> MutMap { ); } - // bytesToU32 : List U8, Nat -> U32 - add_top_level_function_type!( - Symbol::NUM_BYTES_TO_U32, - vec![list_type(u8_type()), nat_type()], - Box::new(u32_type()), - ); + // bytesToU32 : List U8, Nat -> Result U32 [ OutOfBounds ] + { + let position_out_of_bounds = SolvedType::TagUnion( + vec![(TagName::Global("OutOfBounds".into()), vec![])], + Box::new(SolvedType::Wildcard), + ); + add_top_level_function_type!( + Symbol::NUM_BYTES_TO_U32, + vec![list_type(u8_type()), nat_type()], + Box::new(result_type(u32_type(), position_out_of_bounds)), + ); + } // Bool module diff --git a/compiler/can/src/builtins.rs b/compiler/can/src/builtins.rs index a645fb917e..c71a0cb2e7 100644 --- a/compiler/can/src/builtins.rs +++ b/compiler/can/src/builtins.rs @@ -1090,139 +1090,14 @@ fn num_asin(symbol: Symbol, var_store: &mut VarStore) -> Def { ) } -/// Num.bytesToU16 : List U8, Nat -> U16 +/// Num.bytesToU16 : List U8, Nat -> Result U16 [ OutOfBounds ] fn num_bytes_to_u16(symbol: Symbol, var_store: &mut VarStore) -> Def { - let len_var = var_store.fresh(); - let list_var = var_store.fresh(); - let elem_var = var_store.fresh(); - - let ret_var = var_store.fresh(); - let bool_var = var_store.fresh(); - let add_var = var_store.fresh(); - let cast_var = var_store.fresh(); - - // Perform a bounds check. If it passes, run LowLevel::NumBytesToU16 - let body = If { - cond_var: bool_var, - branch_var: var_store.fresh(), - branches: vec![( - // if-condition - no_region( - // index + 1 < List.len list - RunLowLevel { - op: LowLevel::NumLt, - args: vec![ - ( - len_var, - RunLowLevel { - op: LowLevel::NumAdd, - args: vec![ - (add_var, Var(Symbol::ARG_2)), - ( - add_var, - RunLowLevel { - ret_var: cast_var, - args: vec![(cast_var, Num(var_store.fresh(), 1))], - op: LowLevel::NumCastToNat, - }, - ), - ], - ret_var: add_var, - }, - ), - ( - len_var, - RunLowLevel { - op: LowLevel::ListLen, - args: vec![(list_var, Var(Symbol::ARG_1))], - ret_var: len_var, - }, - ), - ], - ret_var: bool_var, - }, - ), - // then-branch - no_region( - // Ok - tag( - "Ok", - vec![RunLowLevel { - op: LowLevel::NumBytesToU16, - args: vec![ - (list_var, Var(Symbol::ARG_1)), - (len_var, Var(Symbol::ARG_2)), - ], - ret_var: elem_var, - }], - var_store, - ), - ), - )], - final_else: Box::new( - // else-branch - no_region( - // Err - tag( - "Err", - vec![tag("OutOfBounds", Vec::new(), var_store)], - var_store, - ), - ), - ), - }; - - defn( - symbol, - vec![(list_var, Symbol::ARG_1), (len_var, Symbol::ARG_2)], - var_store, - body, - ret_var, - ) - // let list_var = var_store.fresh(); - // let nat_var = var_store.fresh(); - // let ret_var = var_store.fresh(); - - // let body = RunLowLevel { - // op: LowLevel::NumBytesToU16, - // args: vec![ - // (list_var, Var(Symbol::ARG_1)), - // (nat_var, Var(Symbol::ARG_2)), - // ], - // ret_var, - // }; - - // defn( - // symbol, - // vec![(list_var, Symbol::ARG_1), (nat_var, Symbol::ARG_2)], - // var_store, - // body, - // ret_var, - // ) + num_bytes_to(symbol, var_store, 1, LowLevel::NumBytesToU16) } -/// Num.bytesToU32 : List U8, Nat -> U32 +/// Num.bytesToU32 : List U8, Nat -> Result U32 [ OutOfBounds ] fn num_bytes_to_u32(symbol: Symbol, var_store: &mut VarStore) -> Def { - let list_var = var_store.fresh(); - let nat_var = var_store.fresh(); - let ret_var = var_store.fresh(); - - let body = RunLowLevel { - op: LowLevel::NumBytesToU32, - args: vec![ - (list_var, Var(Symbol::ARG_1)), - (nat_var, Var(Symbol::ARG_2)), - ], - ret_var, - }; - - defn( - symbol, - vec![(list_var, Symbol::ARG_1), (nat_var, Symbol::ARG_2)], - var_store, - body, - ret_var, - ) + num_bytes_to(symbol, var_store, 3, LowLevel::NumBytesToU32) } /// Num.bitwiseAnd : Int a, Int a -> Int a @@ -3496,6 +3371,97 @@ fn defn( } } +#[inline(always)] +fn num_bytes_to(symbol: Symbol, var_store: &mut VarStore, offset: i64, low_level: LowLevel) -> Def { + let len_var = var_store.fresh(); + let list_var = var_store.fresh(); + let elem_var = var_store.fresh(); + + let ret_var = var_store.fresh(); + let bool_var = var_store.fresh(); + let add_var = var_store.fresh(); + let cast_var = var_store.fresh(); + + // Perform a bounds check. If it passes, run LowLevel::NumBytesToU16 + let body = If { + cond_var: bool_var, + branch_var: var_store.fresh(), + branches: vec![( + // if-condition + no_region( + // index + 1 < List.len list + RunLowLevel { + op: LowLevel::NumLt, + args: vec![ + ( + len_var, + RunLowLevel { + op: LowLevel::NumAdd, + args: vec![ + (add_var, Var(Symbol::ARG_2)), + ( + add_var, + RunLowLevel { + ret_var: cast_var, + args: vec![(cast_var, Num(var_store.fresh(), offset))], + op: LowLevel::NumCastToNat, + }, + ), + ], + ret_var: add_var, + }, + ), + ( + len_var, + RunLowLevel { + op: LowLevel::ListLen, + args: vec![(list_var, Var(Symbol::ARG_1))], + ret_var: len_var, + }, + ), + ], + ret_var: bool_var, + }, + ), + // then-branch + no_region( + // Ok + tag( + "Ok", + vec![RunLowLevel { + op: low_level, + args: vec![ + (list_var, Var(Symbol::ARG_1)), + (len_var, Var(Symbol::ARG_2)), + ], + ret_var: elem_var, + }], + var_store, + ), + ), + )], + final_else: Box::new( + // else-branch + no_region( + // Err + tag( + "Err", + vec![tag("OutOfBounds", Vec::new(), var_store)], + var_store, + ), + ), + ), + }; + + defn( + symbol, + vec![(list_var, Symbol::ARG_1), (len_var, Symbol::ARG_2)], + var_store, + body, + ret_var, + ) +} + #[inline(always)] fn defn_help( fn_name: Symbol, diff --git a/compiler/test_gen/src/gen_num.rs b/compiler/test_gen/src/gen_num.rs index c2e78941c1..4d3b67cb29 100644 --- a/compiler/test_gen/src/gen_num.rs +++ b/compiler/test_gen/src/gen_num.rs @@ -1638,7 +1638,7 @@ mod gen_num { "# ), 40, - usize + u16 ); } @@ -1654,7 +1654,7 @@ mod gen_num { "# ), 1, - usize + u16 ); } @@ -1664,23 +1664,46 @@ mod gen_num { indoc!( r#" bytes = Str.toUtf8 "hello" - when Num.bytesToU16 bytes 4 is + when Num.bytesToU32 bytes 0 is Ok v -> v Err OutOfBounds -> 1 "# ), - 1, - usize + 41, + u32 ); } #[test] fn potato_4() { - assert_evals_to!("Num.bytesToU32 [] 1", 41, u32); + assert_evals_to!( + indoc!( + r#" + bytes = Str.toUtf8 "hello" + when Num.bytesToU32 bytes 234 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 1, + u32 + ); } + #[test] fn potato_5() { - assert_evals_to!("Num.bytesToU32 [] 0", 41, u32); + assert_evals_to!( + indoc!( + r#" + bytes = Str.toUtf8 "hello" + when Num.bytesToU32 bytes 2 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 1, + u32 + ); } } From 2672c8ed102b2893d70080a5b0a00f812f40c3a4 Mon Sep 17 00:00:00 2001 From: Joshua Hoeflich Date: Wed, 18 Aug 2021 17:39:59 -0500 Subject: [PATCH 14/19] NumBytesToU16 and NumBytesToU32 tested --- compiler/builtins/bitcode/src/num.zig | 16 ++-- compiler/can/src/builtins.rs | 2 +- compiler/test_gen/src/gen_num.rs | 124 ++++++++++++++++++++------ 3 files changed, 106 insertions(+), 36 deletions(-) diff --git a/compiler/builtins/bitcode/src/num.zig b/compiler/builtins/bitcode/src/num.zig index 7256171b46..5afb88aa41 100644 --- a/compiler/builtins/bitcode/src/num.zig +++ b/compiler/builtins/bitcode/src/num.zig @@ -23,26 +23,22 @@ pub fn asin(num: f64) callconv(.C) f64 { return @call(.{ .modifier = always_inline }, math.asin, .{num}); } -/// TODO: Obviously, this function should do something more interesting -/// than return the number 40. Fix me! pub fn bytesToU16C(arg: RocList, position: usize) callconv(.C) u16 { - return @call(.{ .modifier = always_inline }, bytesToU16, .{arg, position}); + return @call(.{ .modifier = always_inline }, bytesToU16, .{ arg, position }); } fn bytesToU16(arg: RocList, position: usize) u16 { - const exampleAnswer: u16 = 40; - return 40; + const bytes = @ptrCast([*]const u8, arg.bytes); + return @bitCast(u16, [_]u8{ bytes[position], bytes[position + 1] }); } -/// TODO: Obviously, this function should do something more interesting -/// than return the number 40. Fix me! pub fn bytesToU32C(arg: RocList, position: usize) callconv(.C) u32 { - return @call(.{ .modifier = always_inline }, bytesToU32, .{arg, position}); + return @call(.{ .modifier = always_inline }, bytesToU32, .{ arg, position }); } fn bytesToU32(arg: RocList, position: usize) u32 { - const exampleAnswer: u32 = 41; - return 41; + const bytes = @ptrCast([*]const u8, arg.bytes); + return @bitCast(u32, [_]u8{ bytes[position], bytes[position + 1], bytes[position + 2], bytes[position + 3] }); } pub fn castToNat(num: i64) callconv(.C) usize { diff --git a/compiler/can/src/builtins.rs b/compiler/can/src/builtins.rs index c71a0cb2e7..9053999bc4 100644 --- a/compiler/can/src/builtins.rs +++ b/compiler/can/src/builtins.rs @@ -3389,7 +3389,7 @@ fn num_bytes_to(symbol: Symbol, var_store: &mut VarStore, offset: i64, low_level branches: vec![( // if-condition no_region( - // index + 1 < List.len list + // index + offset < List.len list RunLowLevel { op: LowLevel::NumLt, args: vec![ diff --git a/compiler/test_gen/src/gen_num.rs b/compiler/test_gen/src/gen_num.rs index 4d3b67cb29..ddba6dbcd2 100644 --- a/compiler/test_gen/src/gen_num.rs +++ b/compiler/test_gen/src/gen_num.rs @@ -1625,25 +1625,8 @@ mod gen_num { assert_evals_to!("Num.isMultipleOf -9223372036854775808 -1", true, bool); } - // TODO: Once we know what the function should do, let's give these real names! #[test] - fn potato_1() { - assert_evals_to!( - indoc!( - r#" - bytes = Str.toUtf8 "hello" - when Num.bytesToU16 bytes 0 is - Ok v -> v - Err OutOfBounds -> 1 - "# - ), - 40, - u16 - ); - } - - #[test] - fn potato_2() { + fn bytes_to_u16_clearly_out_of_bounds() { assert_evals_to!( indoc!( r#" @@ -1659,23 +1642,23 @@ mod gen_num { } #[test] - fn potato_3() { + fn bytes_to_u16_subtly_out_of_bounds() { assert_evals_to!( indoc!( r#" bytes = Str.toUtf8 "hello" - when Num.bytesToU32 bytes 0 is + when Num.bytesToU16 bytes 4 is Ok v -> v Err OutOfBounds -> 1 "# ), - 41, - u32 + 1, + u16 ); } #[test] - fn potato_4() { + fn bytes_to_u32_clearly_out_of_bounds() { assert_evals_to!( indoc!( r#" @@ -1690,9 +1673,8 @@ mod gen_num { ); } - #[test] - fn potato_5() { + fn bytes_to_u32_subtly_out_of_bounds() { assert_evals_to!( indoc!( r#" @@ -1706,4 +1688,96 @@ mod gen_num { u32 ); } + + #[test] + fn bytes_to_u16_max_u8s() { + assert_evals_to!( + indoc!( + r#" + when Num.bytesToU16 [255, 255] 0 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 65535, + u16 + ); + } + + #[test] + fn bytes_to_u16_min_u8s() { + assert_evals_to!( + indoc!( + r#" + when Num.bytesToU16 [0, 0] 0 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 0, + u16 + ); + } + + #[test] + fn bytes_to_u16_random_u8s() { + assert_evals_to!( + indoc!( + r#" + when Num.bytesToU16 [164, 215] 0 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 55_204, + u16 + ); + } + + + #[test] + fn bytes_to_u32_min_u8s() { + assert_evals_to!( + indoc!( + r#" + when Num.bytesToU32 [0, 0, 0, 0] 0 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 0, + u32 + ); + } + + #[test] + fn bytes_to_u32_max_u8s() { + assert_evals_to!( + indoc!( + r#" + when Num.bytesToU32 [255, 255, 255, 255] 0 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 4_294_967_295, + u32 + ); + } + + #[test] + fn bytes_to_u32_random_u8s() { + assert_evals_to!( + indoc!( + r#" + when Num.bytesToU32 [252, 124, 128, 121] 0 is + Ok v -> v + Err OutOfBounds -> 1 + "# + ), + 2_038_463_740, + u32 + ); + } + } From 6ad7dfc0f45210a4c91ca6af536a41de4b8b633f Mon Sep 17 00:00:00 2001 From: Joshua Hoeflich Date: Wed, 18 Aug 2021 17:40:17 -0500 Subject: [PATCH 15/19] Cargo fmt --- compiler/test_gen/src/gen_num.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/test_gen/src/gen_num.rs b/compiler/test_gen/src/gen_num.rs index ddba6dbcd2..2c4ff7d716 100644 --- a/compiler/test_gen/src/gen_num.rs +++ b/compiler/test_gen/src/gen_num.rs @@ -1734,7 +1734,6 @@ mod gen_num { ); } - #[test] fn bytes_to_u32_min_u8s() { assert_evals_to!( @@ -1779,5 +1778,4 @@ mod gen_num { u32 ); } - } From 06313a7736752f3c2c18ae6756c4c4eab60f1505 Mon Sep 17 00:00:00 2001 From: Joshua Hoeflich Date: Wed, 18 Aug 2021 18:05:47 -0500 Subject: [PATCH 16/19] cargo clippy --- compiler/gen_llvm/src/llvm/build.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/gen_llvm/src/llvm/build.rs b/compiler/gen_llvm/src/llvm/build.rs index bfa5f23ebb..472a8e1c8b 100644 --- a/compiler/gen_llvm/src/llvm/build.rs +++ b/compiler/gen_llvm/src/llvm/build.rs @@ -4756,7 +4756,7 @@ fn run_low_level<'a, 'ctx, 'env>( env.context.i128_type().into(), "to_i128", ), - position.into(), + position, ], bitcode::NUM_BYTES_TO_U16, ) @@ -4774,7 +4774,7 @@ fn run_low_level<'a, 'ctx, 'env>( env.context.i128_type().into(), "to_i128", ), - position.into(), + position, ], bitcode::NUM_BYTES_TO_U32, ) From 99feb7ce67f7f945c616b5d10775910eb3a8f596 Mon Sep 17 00:00:00 2001 From: Joshua Hoeflich Date: Wed, 18 Aug 2021 18:23:19 -0500 Subject: [PATCH 17/19] Fix typo in comment --- compiler/can/src/builtins.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/can/src/builtins.rs b/compiler/can/src/builtins.rs index 9053999bc4..35534d97a2 100644 --- a/compiler/can/src/builtins.rs +++ b/compiler/can/src/builtins.rs @@ -3382,7 +3382,7 @@ fn num_bytes_to(symbol: Symbol, var_store: &mut VarStore, offset: i64, low_level let add_var = var_store.fresh(); let cast_var = var_store.fresh(); - // Perform a bounds check. If it passes, run LowLevel::NumBytesToU16 + // Perform a bounds check. If it passes, run LowLevel::low_level let body = If { cond_var: bool_var, branch_var: var_store.fresh(), From b57ebb62296a61ba2594fe6468b83bbf500e99ee Mon Sep 17 00:00:00 2001 From: Joshua Hoeflich Date: Thu, 19 Aug 2021 16:04:20 -0500 Subject: [PATCH 18/19] Remove castToNat --- compiler/builtins/bitcode/src/main.zig | 1 - compiler/builtins/bitcode/src/num.zig | 4 ---- compiler/builtins/src/bitcode.rs | 1 - compiler/builtins/src/std.rs | 7 ------- compiler/can/src/builtins.rs | 2 +- compiler/gen_llvm/src/llvm/build.rs | 5 ----- compiler/module/src/low_level.rs | 3 +-- compiler/mono/src/borrow.rs | 1 - 8 files changed, 2 insertions(+), 22 deletions(-) diff --git a/compiler/builtins/bitcode/src/main.zig b/compiler/builtins/bitcode/src/main.zig index 26135c21ad..21fd75b19b 100644 --- a/compiler/builtins/bitcode/src/main.zig +++ b/compiler/builtins/bitcode/src/main.zig @@ -81,7 +81,6 @@ comptime { exportNumFn(num.asin, "asin"); exportNumFn(num.bytesToU16C, "bytes_to_u16"); exportNumFn(num.bytesToU32C, "bytes_to_u32"); - exportNumFn(num.castToNat, "cast_to_nat"); exportNumFn(num.round, "round"); } diff --git a/compiler/builtins/bitcode/src/num.zig b/compiler/builtins/bitcode/src/num.zig index 5afb88aa41..94873f2fe6 100644 --- a/compiler/builtins/bitcode/src/num.zig +++ b/compiler/builtins/bitcode/src/num.zig @@ -41,10 +41,6 @@ fn bytesToU32(arg: RocList, position: usize) u32 { return @bitCast(u32, [_]u8{ bytes[position], bytes[position + 1], bytes[position + 2], bytes[position + 3] }); } -pub fn castToNat(num: i64) callconv(.C) usize { - return @intCast(usize, num); -} - pub fn round(num: f64) callconv(.C) i64 { return @floatToInt(i32, (@round(num))); } diff --git a/compiler/builtins/src/bitcode.rs b/compiler/builtins/src/bitcode.rs index 18d695ae1b..8da5367bec 100644 --- a/compiler/builtins/src/bitcode.rs +++ b/compiler/builtins/src/bitcode.rs @@ -10,7 +10,6 @@ pub const NUM_IS_FINITE: &str = "roc_builtins.num.is_finite"; pub const NUM_POW_INT: &str = "roc_builtins.num.pow_int"; pub const NUM_BYTES_TO_U16: &str = "roc_builtins.num.bytes_to_u16"; pub const NUM_BYTES_TO_U32: &str = "roc_builtins.num.bytes_to_u32"; -pub const NUM_CAST_TO_NAT: &str = "roc_builtins.num.cast_to_nat"; pub const NUM_ROUND: &str = "roc_builtins.num.round"; pub const STR_INIT: &str = "roc_builtins.str.init"; diff --git a/compiler/builtins/src/std.rs b/compiler/builtins/src/std.rs index 0b32ca80b3..b14d1dd435 100644 --- a/compiler/builtins/src/std.rs +++ b/compiler/builtins/src/std.rs @@ -501,13 +501,6 @@ pub fn types() -> MutMap { Box::new(float_type(flex(TVAR1))), ); - // castToNat : Num a -> Nat - add_top_level_function_type!( - Symbol::NUM_CAST_TO_NAT, - vec![int_type(flex(TVAR1))], - Box::new(nat_type()), - ); - // bytesToU16 : List U8, Nat -> Result U16 [ OutOfBounds ] { let position_out_of_bounds = SolvedType::TagUnion( diff --git a/compiler/can/src/builtins.rs b/compiler/can/src/builtins.rs index 35534d97a2..d68f8dd85f 100644 --- a/compiler/can/src/builtins.rs +++ b/compiler/can/src/builtins.rs @@ -3404,7 +3404,7 @@ fn num_bytes_to(symbol: Symbol, var_store: &mut VarStore, offset: i64, low_level RunLowLevel { ret_var: cast_var, args: vec![(cast_var, Num(var_store.fresh(), offset))], - op: LowLevel::NumCastToNat, + op: LowLevel::NumIntCast, }, ), ], diff --git a/compiler/gen_llvm/src/llvm/build.rs b/compiler/gen_llvm/src/llvm/build.rs index b63b84c3e8..4983643b02 100644 --- a/compiler/gen_llvm/src/llvm/build.rs +++ b/compiler/gen_llvm/src/llvm/build.rs @@ -4740,11 +4740,6 @@ fn run_low_level<'a, 'ctx, 'env>( } } } - NumCastToNat => { - debug_assert_eq!(args.len(), 1); - let num = load_symbol(scope, &args[0]).into_int_value(); - call_bitcode_fn(env, &[num.into()], bitcode::NUM_CAST_TO_NAT) - } NumBytesToU16 => { debug_assert_eq!(args.len(), 2); let list = load_symbol(scope, &args[0]).into_struct_value(); diff --git a/compiler/module/src/low_level.rs b/compiler/module/src/low_level.rs index 2941fdd941..99a44971a3 100644 --- a/compiler/module/src/low_level.rs +++ b/compiler/module/src/low_level.rs @@ -89,7 +89,6 @@ pub enum LowLevel { NumAsin, NumBytesToU16, NumBytesToU32, - NumCastToNat, NumBitwiseAnd, NumBitwiseXor, NumBitwiseOr, @@ -126,7 +125,7 @@ impl LowLevel { | NumSqrtUnchecked | NumLogUnchecked | NumRound | NumToFloat | NumPow | NumCeiling | NumPowInt | NumFloor | NumIsFinite | NumAtan | NumAcos | NumAsin | NumBitwiseAnd | NumBitwiseXor | NumBitwiseOr | NumShiftLeftBy | NumShiftRightBy | NumBytesToU16 - | NumBytesToU32 | NumCastToNat | NumShiftRightZfBy | NumIntCast | Eq | NotEq | And + | NumBytesToU32 | NumShiftRightZfBy | NumIntCast | Eq | NotEq | And | Or | Not | Hash | ExpectTrue => false, ListMap | ListMap2 | ListMap3 | ListMapWithIndex | ListKeepIf | ListWalk diff --git a/compiler/mono/src/borrow.rs b/compiler/mono/src/borrow.rs index 17ce01ccee..9c5d6275ae 100644 --- a/compiler/mono/src/borrow.rs +++ b/compiler/mono/src/borrow.rs @@ -1011,7 +1011,6 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] { | NumIntCast => arena.alloc_slice_copy(&[irrelevant]), NumBytesToU16 => arena.alloc_slice_copy(&[borrowed, irrelevant]), NumBytesToU32 => arena.alloc_slice_copy(&[borrowed, irrelevant]), - NumCastToNat => arena.alloc_slice_copy(&[irrelevant]), StrStartsWith | StrEndsWith => arena.alloc_slice_copy(&[owned, borrowed]), StrStartsWithCodePt => arena.alloc_slice_copy(&[borrowed, irrelevant]), StrFromUtf8 => arena.alloc_slice_copy(&[owned]), From 8d6260672f8dfef29a5f2039e6d7f49e5493e7b6 Mon Sep 17 00:00:00 2001 From: Joshua Hoeflich Date: Thu, 19 Aug 2021 16:20:58 -0500 Subject: [PATCH 19/19] Cargo fmt --- compiler/module/src/low_level.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/module/src/low_level.rs b/compiler/module/src/low_level.rs index 99a44971a3..583e6017c1 100644 --- a/compiler/module/src/low_level.rs +++ b/compiler/module/src/low_level.rs @@ -125,8 +125,8 @@ impl LowLevel { | NumSqrtUnchecked | NumLogUnchecked | NumRound | NumToFloat | NumPow | NumCeiling | NumPowInt | NumFloor | NumIsFinite | NumAtan | NumAcos | NumAsin | NumBitwiseAnd | NumBitwiseXor | NumBitwiseOr | NumShiftLeftBy | NumShiftRightBy | NumBytesToU16 - | NumBytesToU32 | NumShiftRightZfBy | NumIntCast | Eq | NotEq | And - | Or | Not | Hash | ExpectTrue => false, + | NumBytesToU32 | NumShiftRightZfBy | NumIntCast | Eq | NotEq | And | Or | Not + | Hash | ExpectTrue => false, ListMap | ListMap2 | ListMap3 | ListMapWithIndex | ListKeepIf | ListWalk | ListWalkUntil | ListWalkBackwards | ListKeepOks | ListKeepErrs | ListSortWith