diff --git a/compiler/builtins/src/std.rs b/compiler/builtins/src/std.rs index 55ed8dc92f..7735290ce6 100644 --- a/compiler/builtins/src/std.rs +++ b/compiler/builtins/src/std.rs @@ -285,6 +285,12 @@ pub fn types() -> MutMap { SolvedType::Func(vec![int_type(), int_type()], Box::new(bool_type())), ); + // abs : Int -> Int + add_type( + Symbol::INT_ABS, + SolvedType::Func(vec![int_type()], Box::new(int_type())), + ); + // highest : Int add_type(Symbol::INT_HIGHEST, int_type()); @@ -336,6 +342,12 @@ pub fn types() -> MutMap { SolvedType::Func(vec![float_type()], Box::new(int_type())), ); + // abs : Float -> Float + add_type( + Symbol::FLOAT_ABS, + SolvedType::Func(vec![float_type()], Box::new(float_type())), + ); + // highest : Float add_type(Symbol::FLOAT_HIGHEST, float_type()); diff --git a/compiler/builtins/src/unique.rs b/compiler/builtins/src/unique.rs index 92330d31b7..e87739bb0c 100644 --- a/compiler/builtins/src/unique.rs +++ b/compiler/builtins/src/unique.rs @@ -354,6 +354,12 @@ pub fn types() -> MutMap { unique_function(vec![int_type(UVAR1), int_type(UVAR2)], bool_type(UVAR3)), ); + // abs :: Int -> Int + add_type( + Symbol::INT_ABS, + unique_function(vec![int_type(UVAR1)], int_type(UVAR2)), + ); + // highest : Int add_type(Symbol::INT_HIGHEST, int_type(UVAR1)); @@ -418,6 +424,12 @@ pub fn types() -> MutMap { unique_function(vec![float_type(UVAR1)], int_type(UVAR2)), ); + // abs : Float -> Float + add_type( + Symbol::FLOAT_ABS, + unique_function(vec![float_type(UVAR1)], float_type(UVAR2)), + ); + // highest : Float add_type(Symbol::FLOAT_HIGHEST, float_type(UVAR1)); diff --git a/compiler/gen/src/llvm/build.rs b/compiler/gen/src/llvm/build.rs index de5334c352..9adad722aa 100644 --- a/compiler/gen/src/llvm/build.rs +++ b/compiler/gen/src/llvm/build.rs @@ -80,10 +80,17 @@ fn add_intrinsics<'ctx>(ctx: &'ctx Context, module: &Module<'ctx>) { LLVM_LROUND_I64_F64, i64_type.fn_type(&[f64_type.into()], false), ); + + add_intrinsic( + module, + LLVM_FABS_F64, + f64_type.fn_type(&[f64_type.into()], false), + ); } static LLVM_SQRT_F64: &str = "llvm.sqrt.f64"; static LLVM_LROUND_I64_F64: &str = "llvm.lround.i64.f64"; +static LLVM_FABS_F64: &str = "llvm.fabs.f64"; fn add_intrinsic<'ctx>( module: &Module<'ctx>, @@ -1087,6 +1094,10 @@ fn call_with_args<'a, 'ctx, 'env>( BasicValueEnum::FloatValue(float_val) } + Symbol::NUM_ABS | Symbol::INT_ABS => { + todo!("implement intrinsic for int_abs") + }, + Symbol::FLOAT_ABS => call_intrinsic(LLVM_FABS_F64, env, args), Symbol::INT_GTE | Symbol::NUM_GTE => { debug_assert!(args.len() == 2); diff --git a/compiler/gen/tests/gen_builtins.rs b/compiler/gen/tests/gen_builtins.rs index 1c166c110c..5030ed3505 100644 --- a/compiler/gen/tests/gen_builtins.rs +++ b/compiler/gen/tests/gen_builtins.rs @@ -37,6 +37,12 @@ mod gen_builtins { assert_evals_to!("Float.round 3.6", 4, i64); } + #[test] + fn f64_abs() { + assert_evals_to!("Float.abs -4.7", 4.7, f64); + assert_evals_to!("Float.abs 5.8", 5.8, f64); + } + #[test] fn empty_list_literal() { assert_evals_to!("[]", &[], &'static [i64]); diff --git a/compiler/module/src/symbol.rs b/compiler/module/src/symbol.rs index bb2c11ff2d..4ea27186d4 100644 --- a/compiler/module/src/symbol.rs +++ b/compiler/module/src/symbol.rs @@ -609,6 +609,7 @@ define_builtins! { 19 INT_NEQ_I64: "#neqi64" 20 INT_NEQ_I1: "#neqi1" 21 INT_NEQ_I8: "#neqi8" + 22 INT_ABS: "abs" } 3 FLOAT: "Float" => { 0 FLOAT_FLOAT: "Float" imported // the Float.Float type alias @@ -627,6 +628,7 @@ define_builtins! { 13 FLOAT_LTE: "#lte" 14 FLOAT_GT: "#gt" 15 FLOAT_GTE: "#gte" + 16 FLOAT_ABS: "abs" } 4 BOOL: "Bool" => { 0 BOOL_BOOL: "Bool" imported // the Bool.Bool type alias diff --git a/compiler/solve/tests/test_uniq_solve.rs b/compiler/solve/tests/test_uniq_solve.rs index 717c518b4d..01bae0722e 100644 --- a/compiler/solve/tests/test_uniq_solve.rs +++ b/compiler/solve/tests/test_uniq_solve.rs @@ -2097,8 +2097,8 @@ mod test_uniq_solve { reverse "# ), - "Attr * (Attr * (List (Attr (a | b) c)) -> Attr (* | a | b) (List (Attr b c)))", - // "Attr * (Attr * (List (Attr (a | b) c)) -> Attr (* | a | b) (List (Attr a c)))", + // "Attr * (Attr * (List (Attr (a | b) c)) -> Attr (* | a | b) (List (Attr b c)))", + "Attr * (Attr * (List (Attr (a | b) c)) -> Attr (* | a | b) (List (Attr a c)))", ); }