diff --git a/compiler/can/src/builtins.rs b/compiler/can/src/builtins.rs index 51cc825539..c4fcf9544f 100644 --- a/compiler/can/src/builtins.rs +++ b/compiler/can/src/builtins.rs @@ -32,9 +32,57 @@ pub fn builtin_defs(var_store: &VarStore) -> Vec { int_div(var_store), int_abs(var_store), int_rem(var_store), + int_is_odd(var_store), + int_is_even(var_store), ] } +/// Int.isOdd : Int -> Bool +fn int_is_odd(var_store: &VarStore) -> Def { + use crate::expr::Expr::*; + + defn( + Symbol::INT_IS_ODD, + vec![Symbol::INT_IS_ODD_ARG], + var_store, + call( + Symbol::INT_EQ_I64, + vec![ + call( + Symbol::INT_REM_UNSAFE, + vec![Var(Symbol::INT_IS_ODD_ARG), Int(var_store.fresh(), 2)], + var_store, + ), + Int(var_store.fresh(), 1), + ], + var_store, + ), + ) +} + +/// Int.isEven : Int -> Bool +fn int_is_even(var_store: &VarStore) -> Def { + use crate::expr::Expr::*; + + defn( + Symbol::INT_IS_EVEN, + vec![Symbol::INT_IS_EVEN_ARG], + var_store, + call( + Symbol::INT_EQ_I64, + vec![ + call( + Symbol::INT_REM_UNSAFE, + vec![Var(Symbol::INT_IS_EVEN_ARG), Int(var_store.fresh(), 2)], + var_store, + ), + Int(var_store.fresh(), 0), + ], + var_store, + ), + ) +} + /// List.get : List elem, Int -> Result elem [ OutOfBounds ]* fn list_get(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 cff3b2def5..dd9b928612 100644 --- a/compiler/gen/tests/gen_builtins.rs +++ b/compiler/gen/tests/gen_builtins.rs @@ -257,6 +257,18 @@ mod gen_builtins { ); } + #[test] + fn gen_is_odd() { + assert_evals_to!("Int.isOdd 4", false, bool); + assert_evals_to!("Int.isOdd 5", true, bool); + } + + #[test] + fn gen_is_even() { + assert_evals_to!("Int.isEven 6", true, bool); + assert_evals_to!("Int.isEven 7", false, bool); + } + #[test] fn lt_i64() { assert_evals_to!("1 < 2", true, bool); diff --git a/compiler/module/src/symbol.rs b/compiler/module/src/symbol.rs index 5b48f5c23e..efc2819356 100644 --- a/compiler/module/src/symbol.rs +++ b/compiler/module/src/symbol.rs @@ -615,6 +615,10 @@ define_builtins! { 25 INT_REM: "rem" 26 INT_REM_ARG_0: "rem#arg0" 27 INT_REM_ARG_1: "rem#arg1" + 28 INT_IS_ODD: "isOdd" + 29 INT_IS_ODD_ARG: "isOdd#arg" + 30 INT_IS_EVEN: "isEven" + 31 INT_IS_EVEN_ARG: "isEven#arg" } 3 FLOAT: "Float" => { 0 FLOAT_FLOAT: "Float" imported // the Float.Float type alias