mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
Merge branch 'trunk' into singleton-to-single
This commit is contained in:
commit
1e9cf7ba89
7 changed files with 74 additions and 6 deletions
|
@ -384,6 +384,15 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
|||
),
|
||||
);
|
||||
|
||||
// isMultipleOf : Int a, Int a -> Bool
|
||||
add_type(
|
||||
Symbol::NUM_IS_MULTIPLE_OF,
|
||||
top_level_function(
|
||||
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
|
||||
Box::new(bool_type()),
|
||||
),
|
||||
);
|
||||
|
||||
// maxI128 : I128
|
||||
add_type(Symbol::NUM_MAX_I128, i128_type());
|
||||
|
||||
|
|
|
@ -136,6 +136,7 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
|
|||
NUM_ABS => num_abs,
|
||||
NUM_NEG => num_neg,
|
||||
NUM_REM => num_rem,
|
||||
NUM_IS_MULTIPLE_OF => num_is_multiple_of,
|
||||
NUM_SQRT => num_sqrt,
|
||||
NUM_ROUND => num_round,
|
||||
NUM_IS_ODD => num_is_odd,
|
||||
|
@ -271,6 +272,7 @@ pub fn builtin_defs(var_store: &mut VarStore) -> MutMap<Symbol, Def> {
|
|||
Symbol::NUM_ABS => num_abs,
|
||||
Symbol::NUM_NEG => num_neg,
|
||||
Symbol::NUM_REM => num_rem,
|
||||
Symbol::NUM_IS_MULTIPLE_OF => num_is_multiple_of,
|
||||
Symbol::NUM_SQRT => num_sqrt,
|
||||
Symbol::NUM_ROUND => num_round,
|
||||
Symbol::NUM_IS_ODD => num_is_odd,
|
||||
|
@ -2611,6 +2613,11 @@ fn num_rem(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
|||
)
|
||||
}
|
||||
|
||||
/// Num.isMultipleOf : Int, Int -> Bool
|
||||
fn num_is_multiple_of(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
lowlevel_2(symbol, LowLevel::NumIsMultipleOf, var_store)
|
||||
}
|
||||
|
||||
/// Num.neg : Num a -> Num a
|
||||
fn num_neg(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
let num_var = var_store.fresh();
|
||||
|
|
|
@ -4075,8 +4075,8 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
}
|
||||
|
||||
NumAdd | NumSub | NumMul | NumLt | NumLte | NumGt | NumGte | NumRemUnchecked
|
||||
| NumAddWrap | NumAddChecked | NumDivUnchecked | NumPow | NumPowInt | NumSubWrap
|
||||
| NumSubChecked | NumMulWrap | NumMulChecked => {
|
||||
| NumIsMultipleOf | NumAddWrap | NumAddChecked | NumDivUnchecked | NumPow | NumPowInt
|
||||
| NumSubWrap | NumSubChecked | NumMulWrap | NumMulChecked => {
|
||||
debug_assert_eq!(args.len(), 2);
|
||||
|
||||
let (lhs_arg, lhs_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
|
@ -4778,6 +4778,44 @@ fn build_int_binop<'a, 'ctx, 'env>(
|
|||
NumLt => bd.build_int_compare(SLT, lhs, rhs, "int_lt").into(),
|
||||
NumLte => bd.build_int_compare(SLE, lhs, rhs, "int_lte").into(),
|
||||
NumRemUnchecked => bd.build_int_signed_rem(lhs, rhs, "rem_int").into(),
|
||||
NumIsMultipleOf => {
|
||||
/* this builds the following construct
|
||||
|
||||
if rhs == 0 {
|
||||
lhs == 0
|
||||
} else {
|
||||
let rem = lhs % rhs;
|
||||
rem == 0
|
||||
}
|
||||
*/
|
||||
let zero = rhs.get_type().const_zero();
|
||||
let condition_rhs = bd.build_int_compare(IntPredicate::EQ, rhs, zero, "is_zero_rhs");
|
||||
let condition_lhs = bd.build_int_compare(IntPredicate::EQ, lhs, zero, "is_zero_lhs");
|
||||
|
||||
let current_block = bd.get_insert_block().unwrap(); //block that we are in right now;
|
||||
let else_block = env.context.append_basic_block(parent, "else"); //
|
||||
let cont_block = env.context.append_basic_block(parent, "branchcont");
|
||||
|
||||
bd.build_conditional_branch(condition_rhs, cont_block, else_block);
|
||||
|
||||
bd.position_at_end(else_block);
|
||||
|
||||
let rem = bd.build_int_signed_rem(lhs, rhs, "int_rem");
|
||||
let condition_rem = bd.build_int_compare(IntPredicate::EQ, rem, zero, "is_zero_rem");
|
||||
|
||||
bd.build_unconditional_branch(cont_block);
|
||||
|
||||
bd.position_at_end(cont_block);
|
||||
|
||||
let phi = bd.build_phi(env.context.bool_type(), "branch");
|
||||
|
||||
phi.add_incoming(&[
|
||||
(&condition_lhs, current_block),
|
||||
(&condition_rem, else_block),
|
||||
]);
|
||||
|
||||
phi.as_basic_value()
|
||||
}
|
||||
NumDivUnchecked => bd.build_int_signed_div(lhs, rhs, "div_int").into(),
|
||||
NumPowInt => call_bitcode_fn(env, &[lhs.into(), rhs.into()], &bitcode::NUM_POW_INT),
|
||||
NumBitwiseAnd => bd.build_and(lhs, rhs, "int_bitwise_and").into(),
|
||||
|
|
|
@ -65,6 +65,7 @@ pub enum LowLevel {
|
|||
NumCompare,
|
||||
NumDivUnchecked,
|
||||
NumRemUnchecked,
|
||||
NumIsMultipleOf,
|
||||
NumAbs,
|
||||
NumNeg,
|
||||
NumSin,
|
||||
|
|
|
@ -856,6 +856,7 @@ define_builtins! {
|
|||
95 NUM_NAT: "Nat" imported
|
||||
96 NUM_INT_CAST: "intCast"
|
||||
97 NUM_MAX_I128: "maxI128"
|
||||
98 NUM_IS_MULTIPLE_OF: "isMultipleOf"
|
||||
|
||||
}
|
||||
2 BOOL: "Bool" => {
|
||||
|
|
|
@ -667,10 +667,9 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
|
|||
|
||||
And | Or | NumAdd | NumAddWrap | NumAddChecked | NumSub | NumSubWrap | NumSubChecked
|
||||
| NumMul | NumMulWrap | NumMulChecked | NumGt | NumGte | NumLt | NumLte | NumCompare
|
||||
| NumDivUnchecked | NumRemUnchecked | NumPow | NumPowInt | NumBitwiseAnd
|
||||
| NumBitwiseXor | NumBitwiseOr | NumShiftLeftBy | NumShiftRightBy | NumShiftRightZfBy => {
|
||||
arena.alloc_slice_copy(&[irrelevant, irrelevant])
|
||||
}
|
||||
| NumDivUnchecked | NumRemUnchecked | NumIsMultipleOf | NumPow | NumPowInt
|
||||
| NumBitwiseAnd | NumBitwiseXor | NumBitwiseOr | NumShiftLeftBy | NumShiftRightBy
|
||||
| NumShiftRightZfBy => arena.alloc_slice_copy(&[irrelevant, irrelevant]),
|
||||
|
||||
NumAbs | NumNeg | NumSin | NumCos | NumSqrtUnchecked | NumRound | NumCeiling | NumFloor
|
||||
| NumToFloat | Not | NumIsFinite | NumAtan | NumAcos | NumAsin | NumIntCast => {
|
||||
|
|
|
@ -1377,4 +1377,17 @@ mod gen_num {
|
|||
i128
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_multiple_of() {
|
||||
// true
|
||||
assert_evals_to!("Num.isMultipleOf 5 1", true, bool);
|
||||
assert_evals_to!("Num.isMultipleOf 5 -1", true, bool);
|
||||
assert_evals_to!("Num.isMultipleOf 0 0", true, bool);
|
||||
assert_evals_to!("Num.isMultipleOf 0 1", true, bool);
|
||||
assert_evals_to!("Num.isMultipleOf 0 -1", true, bool);
|
||||
// false
|
||||
assert_evals_to!("Num.isMultipleOf 5 2", false, bool);
|
||||
assert_evals_to!("Num.isMultipleOf 5 0", false, bool);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue