diff --git a/compiler/builtins/src/std.rs b/compiler/builtins/src/std.rs index d7503fc605..985b95f0bc 100644 --- a/compiler/builtins/src/std.rs +++ b/compiler/builtins/src/std.rs @@ -331,6 +331,18 @@ pub fn types() -> MutMap { // Float module + // isGt or (>) : Num a, Num a -> Bool + add_type( + Symbol::FLOAT_GT, + SolvedType::Func(vec![float_type(), float_type()], Box::new(bool_type())), + ); + + // eq or (==) : Num a, Num a -> Bool + add_type( + Symbol::FLOAT_EQ, + SolvedType::Func(vec![float_type(), float_type()], Box::new(bool_type())), + ); + // div : Float, Float -> Float add_type( Symbol::FLOAT_DIV, diff --git a/compiler/builtins/src/unique.rs b/compiler/builtins/src/unique.rs index 5521db13d5..70c4198a5f 100644 --- a/compiler/builtins/src/unique.rs +++ b/compiler/builtins/src/unique.rs @@ -415,6 +415,18 @@ pub fn types() -> MutMap { // Float module + // isGt or (>) : Num a, Num a -> Bool + add_type( + Symbol::FLOAT_GT, + unique_function(vec![float_type(UVAR1), float_type(UVAR2)], bool_type(UVAR3)), + ); + + // eq or (==) : Num a, Num a -> Bool + add_type( + Symbol::FLOAT_EQ, + unique_function(vec![float_type(UVAR1), float_type(UVAR2)], bool_type(UVAR3)), + ); + // div : Float, Float -> Float add_type( Symbol::FLOAT_DIV, diff --git a/compiler/can/src/builtins.rs b/compiler/can/src/builtins.rs index 99a369171f..55feccc707 100644 --- a/compiler/can/src/builtins.rs +++ b/compiler/can/src/builtins.rs @@ -37,9 +37,69 @@ pub fn builtin_defs(var_store: &VarStore) -> Vec { int_is_zero(var_store), int_is_positive(var_store), int_is_negative(var_store), + float_is_positive(var_store), + float_is_negative(var_store), + float_is_zero(var_store), ] } +/// Float.isZero : Float -> Bool +fn float_is_zero(var_store: &VarStore) -> Def { + use crate::expr::Expr::*; + + defn( + Symbol::FLOAT_IS_ZERO, + vec![Symbol::FLOAT_IS_ZERO_ARG], + var_store, + call( + Symbol::FLOAT_EQ, + vec![ + Float(var_store.fresh(), 0.0), + Var(Symbol::FLOAT_IS_ZERO_ARG), + ], + var_store, + ), + ) +} + +/// Float.isNegative : Float -> Bool +fn float_is_negative(var_store: &VarStore) -> Def { + use crate::expr::Expr::*; + + defn( + Symbol::FLOAT_IS_NEGATIVE, + vec![Symbol::FLOAT_IS_NEGATIVE_ARG], + var_store, + call( + Symbol::FLOAT_GT, + vec![ + Float(var_store.fresh(), 0.0), + Var(Symbol::FLOAT_IS_NEGATIVE_ARG), + ], + var_store, + ), + ) +} + +/// Float.isPositive : Float -> Bool +fn float_is_positive(var_store: &VarStore) -> Def { + use crate::expr::Expr::*; + + defn( + Symbol::FLOAT_IS_POSITIVE, + vec![Symbol::FLOAT_IS_POSITIVE_ARG], + var_store, + call( + Symbol::FLOAT_GT, + vec![ + Var(Symbol::FLOAT_IS_POSITIVE_ARG), + Float(var_store.fresh(), 0.0), + ], + var_store, + ), + ) +} + /// Int.isNegative : Int -> Bool fn int_is_negative(var_store: &VarStore) -> Def { use crate::expr::Expr::*; diff --git a/compiler/gen/tests/gen_builtins.rs b/compiler/gen/tests/gen_builtins.rs index c3b9f849cc..015645326b 100644 --- a/compiler/gen/tests/gen_builtins.rs +++ b/compiler/gen/tests/gen_builtins.rs @@ -29,24 +29,18 @@ mod gen_builtins { #[test] fn f64_sqrt() { - with_larger_debug_stack(|| { - assert_evals_to!("Float.sqrt 144", 12.0, f64); - }) + assert_evals_to!("Float.sqrt 144", 12.0, f64); } #[test] fn f64_round() { - with_larger_debug_stack(|| { - assert_evals_to!("Float.round 3.6", 4, i64); - }) + assert_evals_to!("Float.round 3.6", 4, i64); } #[test] fn f64_abs() { - with_larger_debug_stack(|| { - assert_evals_to!("Float.abs -4.7", 4.7, f64); - assert_evals_to!("Float.abs 5.8", 5.8, f64); - }) + assert_evals_to!("Float.abs -4.7", 4.7, f64); + assert_evals_to!("Float.abs 5.8", 5.8, f64); } #[test] @@ -57,9 +51,7 @@ mod gen_builtins { #[test] fn empty_list_literal() { - with_larger_debug_stack(|| { - assert_evals_to!("[]", &[], &'static [i64]); - }) + assert_evals_to!("[]", &[], &'static [i64]); } #[test] @@ -69,10 +61,9 @@ mod gen_builtins { #[test] fn gen_if_fn() { - with_larger_debug_stack(|| { - assert_evals_to!( - indoc!( - r#" + assert_evals_to!( + indoc!( + r#" limitedNegate = \num -> if num == 1 then -1 @@ -83,11 +74,10 @@ mod gen_builtins { limitedNegate 1 "# - ), - -1, - i64 - ); - }) + ), + -1, + i64 + ); } #[test] @@ -272,23 +262,45 @@ mod gen_builtins { } #[test] - fn gen_is_zero() { + fn gen_is_zero_i64() { assert_evals_to!("Int.isZero 0", true, bool); assert_evals_to!("Int.isZero 1", false, bool); } #[test] - fn gen_is_positive() { + fn gen_is_positive_i64() { assert_evals_to!("Int.isPositive 0", false, bool); assert_evals_to!("Int.isPositive 1", true, bool); assert_evals_to!("Int.isPositive -5", false, bool); } #[test] - fn gen_is_negative() { + fn gen_is_negative_i64() { assert_evals_to!("Int.isNegative 0", false, bool); assert_evals_to!("Int.isNegative 3", false, bool); - assert_evals_to!("Int.isNegative -2", false, bool); + assert_evals_to!("Int.isNegative -2", true, bool); + } + + #[test] + fn gen_is_positive_f64() { + assert_evals_to!("Float.isPositive 0.0", false, bool); + assert_evals_to!("Float.isPositive 4.7", true, bool); + assert_evals_to!("Float.isPositive -8.5", false, bool); + } + + #[test] + fn gen_is_negative_f64() { + assert_evals_to!("Float.isNegative 0.0", false, bool); + assert_evals_to!("Float.isNegative 9.9", false, bool); + assert_evals_to!("Float.isNegative -4.4", true, bool); + } + + #[test] + fn gen_is_zero_f64() { + assert_evals_to!("Float.isZero 0", true, bool); + assert_evals_to!("Float.isZero 0_0", true, bool); + assert_evals_to!("Float.isZero 0.0", true, bool); + assert_evals_to!("Float.isZero 1", false, bool); } #[test] diff --git a/compiler/module/src/symbol.rs b/compiler/module/src/symbol.rs index 3f097b6d5b..852c6ddd37 100644 --- a/compiler/module/src/symbol.rs +++ b/compiler/module/src/symbol.rs @@ -641,13 +641,19 @@ define_builtins! { 7 FLOAT_LOWEST: "lowest" 8 FLOAT_ADD: "#add" 9 FLOAT_SUB: "#sub" - 10 FLOAT_EQ: "#eq" + 10 FLOAT_EQ: "eq" 11 FLOAT_ROUND: "round" 12 FLOAT_LT: "#lt" 13 FLOAT_LTE: "#lte" - 14 FLOAT_GT: "#gt" + 14 FLOAT_GT: "gt" 15 FLOAT_GTE: "#gte" 16 FLOAT_ABS: "abs" + 17 FLOAT_IS_POSITIVE: "isPositive" + 18 FLOAT_IS_POSITIVE_ARG: "isPositive#arg" + 19 FLOAT_IS_NEGATIVE: "isNegative" + 20 FLOAT_IS_NEGATIVE_ARG: "isNegative#arg" + 21 FLOAT_IS_ZERO: "isZero" + 22 FLOAT_IS_ZERO_ARG: "isZero#arg" } 4 BOOL: "Bool" => { 0 BOOL_BOOL: "Bool" imported // the Bool.Bool type alias