mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-10 10:02:38 +03:00
remove Num.mod and Num.modUnchecked
This commit is contained in:
parent
1908ff41c3
commit
9ed4ca9739
@ -1944,7 +1944,6 @@ Here are various Roc expressions involving operators, and what they desugar to.
|
||||
| `a // b` | `Num.divFloor a b` |
|
||||
| `a ^ b` | `Num.pow a b` |
|
||||
| `a % b` | `Num.rem a b` |
|
||||
| `a %% b` | `Num.mod a b` |
|
||||
| `a >> b` | `Num.shr a b` |
|
||||
| `a << b` | `Num.shl a b` |
|
||||
| `-a` | `Num.neg a` |
|
||||
|
@ -4,7 +4,7 @@ Builtins are the functions and modules that are implicitly imported into every m
|
||||
|
||||
### module/src/symbol.rs
|
||||
|
||||
Towards the bottom of `symbol.rs` there is a `define_builtins!` macro being used that takes many modules and function names. The first level (`List`, `Int` ..) is the module name, and the second level is the function or value name (`reverse`, `mod` ..). If you wanted to add a `Int` function called `addTwo` go to `2 Int: "Int" => {` and inside that case add to the bottom `38 INT_ADD_TWO: "addTwo"` (assuming there are 37 existing ones).
|
||||
Towards the bottom of `symbol.rs` there is a `define_builtins!` macro being used that takes many modules and function names. The first level (`List`, `Int` ..) is the module name, and the second level is the function or value name (`reverse`, `rem` ..). If you wanted to add a `Int` function called `addTwo` go to `2 Int: "Int" => {` and inside that case add to the bottom `38 INT_ADD_TWO: "addTwo"` (assuming there are 37 existing ones).
|
||||
|
||||
Some of these have `#` inside their name (`first#list`, `#lt` ..). This is a trick we are doing to hide implementation details from Roc programmers. To a Roc programmer, a name with `#` in it is invalid, because `#` means everything after it is parsed to a comment. We are constructing these functions manually, so we are circumventing the parsing step and dont have such restrictions. We get to make functions and values with `#` which as a consequence are not accessible to Roc programmers. Roc programmers simply cannot reference them.
|
||||
|
||||
|
@ -82,8 +82,6 @@ interface Num
|
||||
minI64,
|
||||
minU64,
|
||||
minI128,
|
||||
mod,
|
||||
modChecked,
|
||||
mul,
|
||||
mulChecked,
|
||||
mulWrap,
|
||||
@ -807,27 +805,18 @@ toDec : Num * -> Dec
|
||||
## This is the same as the #// operator.
|
||||
divRound : Int a, Int a -> Int a
|
||||
|
||||
## Perform flooring modulo on two integers.
|
||||
## Obtain the remainder (truncating modulo) from the division of two integers.
|
||||
##
|
||||
## Modulo is the same as remainder when working with positive numbers,
|
||||
## but if either number is negative, then modulo works differently.
|
||||
## `a % b` is shorthand for `Num.rem a b`.
|
||||
##
|
||||
## Additionally, flooring modulo uses [Float].floor on the result.
|
||||
## >>> 5 % 7
|
||||
##
|
||||
## (Use [Float].mod for non-flooring modulo.)
|
||||
## >>> Num.rem 5 7
|
||||
##
|
||||
## Return `Err DivByZero` if the second integer is zero, because division by zero is undefined in mathematics.
|
||||
## >>> -8 % -3
|
||||
##
|
||||
## `a %% b` is shorthand for `Int.modFloor a b`.
|
||||
##
|
||||
## >>> 5 %% 7
|
||||
##
|
||||
## >>> Int.modFloor 5 7
|
||||
##
|
||||
## >>> -8 %% -3
|
||||
##
|
||||
## >>> Int.modFloor -8 -3
|
||||
#modFloor : Int a, Int a -> Result (Int a) [ DivByZero ]*
|
||||
## >>> Num.rem -8 -3
|
||||
rem : Int a, Int a -> Int a
|
||||
|
||||
|
||||
## Bitwise
|
||||
@ -1099,31 +1088,6 @@ atan : Float a -> Float a
|
||||
## >>> |> Num.div 2.0
|
||||
div : Float a, Float a -> Float a
|
||||
|
||||
## Perform modulo on two [Float]s.
|
||||
##
|
||||
## Modulo is the same as remainder when working with positive numbers,
|
||||
## but if either number is negative, then modulo works differently.
|
||||
##
|
||||
## `a % b` is shorthand for `Num.mod a b`.
|
||||
##
|
||||
## [Division by zero is undefined in mathematics](https://en.wikipedia.org/wiki/Division_by_zero),
|
||||
## and as such, so is modulo by zero. Because of this, you should make sure never
|
||||
## to pass zero for the second argument to this function!
|
||||
##
|
||||
## Passing [mod] a [Dec] value of zero for its second argument will cause a panic.
|
||||
## Passing [mod] a [F32] and [F64] value for its second argument will cause it
|
||||
## to return [*NaN*](Num.isNaN).
|
||||
##
|
||||
## >>> 5.0 % 7.0
|
||||
##
|
||||
## >>> Num.mod 5 7
|
||||
##
|
||||
## `Num.mod` can be convenient in pipelines.
|
||||
##
|
||||
## >>> Num.pi
|
||||
## >>> |> Num.mod 2.0
|
||||
mod : Float a, Float a -> Float a
|
||||
|
||||
## Raises a [Float] to the power of another [Float].
|
||||
##
|
||||
## `
|
||||
|
@ -71,8 +71,6 @@ interface Num
|
||||
remChecked,
|
||||
div,
|
||||
divChecked,
|
||||
mod,
|
||||
modChecked,
|
||||
sqrt,
|
||||
sqrtChecked,
|
||||
log,
|
||||
@ -247,8 +245,6 @@ divFloorChecked : Int a, Int a -> Result (Int a) [ DivByZero ]*
|
||||
|
||||
rem : Int a, Int a -> Int a
|
||||
remChecked : Int a, Int a -> Result (Int a) [ DivByZero ]*
|
||||
mod : Int a, Int a -> Int a
|
||||
modChecked : Int a, Int a -> Result (Int a) [ DivByZero ]*
|
||||
|
||||
isMultipleOf : Int a, Int a -> Bool
|
||||
|
||||
|
@ -407,20 +407,6 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||
Box::new(result_type(int_type(flex(TVAR1)), div_by_zero.clone())),
|
||||
);
|
||||
|
||||
// mod : Int a, Int a -> Int a
|
||||
add_top_level_function_type!(
|
||||
Symbol::NUM_MOD,
|
||||
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
|
||||
Box::new(int_type(flex(TVAR1))),
|
||||
);
|
||||
|
||||
// modChecked : Int a, Int a -> Result (Int a) [ DivByZero ]*
|
||||
add_top_level_function_type!(
|
||||
Symbol::NUM_MOD_CHECKED,
|
||||
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
|
||||
Box::new(result_type(int_type(flex(TVAR1)), div_by_zero.clone())),
|
||||
);
|
||||
|
||||
// isMultipleOf : Int a, Int a -> Bool
|
||||
add_top_level_function_type!(
|
||||
Symbol::NUM_IS_MULTIPLE_OF,
|
||||
|
@ -204,8 +204,6 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
|
||||
NUM_NEG => num_neg,
|
||||
NUM_REM => num_rem,
|
||||
NUM_REM_CHECKED => num_rem_checked,
|
||||
NUM_MOD => num_mod,
|
||||
NUM_MOD_CHECKED => num_mod_checked,
|
||||
NUM_IS_MULTIPLE_OF => num_is_multiple_of,
|
||||
NUM_SQRT => num_sqrt,
|
||||
NUM_SQRT_CHECKED => num_sqrt_checked,
|
||||
@ -4292,70 +4290,6 @@ fn num_rem_checked(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
)
|
||||
}
|
||||
|
||||
/// Num.mod : Int a, Int a -> Int a
|
||||
fn num_mod(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
num_binop(symbol, var_store, LowLevel::NumModUnchecked)
|
||||
}
|
||||
|
||||
/// Num.modChecked : Int a, Int a -> Result (Int a) [ DivByZero ]*
|
||||
fn num_mod_checked(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
let num_var = var_store.fresh();
|
||||
let unbound_zero_var = var_store.fresh();
|
||||
let bool_var = var_store.fresh();
|
||||
let ret_var = var_store.fresh();
|
||||
|
||||
let body = If {
|
||||
branch_var: ret_var,
|
||||
cond_var: bool_var,
|
||||
branches: vec![(
|
||||
// if condition
|
||||
no_region(
|
||||
// Num.isNeq arg2 0
|
||||
RunLowLevel {
|
||||
op: LowLevel::NotEq,
|
||||
args: vec![
|
||||
(num_var, Var(Symbol::ARG_2)),
|
||||
(num_var, num(unbound_zero_var, 0, num_no_bound())),
|
||||
],
|
||||
ret_var: bool_var,
|
||||
},
|
||||
),
|
||||
// arg1 was not zero
|
||||
no_region(
|
||||
// Ok (Int.#modUnsafe arg1 arg2)
|
||||
tag(
|
||||
"Ok",
|
||||
vec![
|
||||
// Num.#modUnsafe arg1 arg2
|
||||
RunLowLevel {
|
||||
op: LowLevel::NumModUnchecked,
|
||||
args: vec![
|
||||
(num_var, Var(Symbol::ARG_1)),
|
||||
(num_var, Var(Symbol::ARG_2)),
|
||||
],
|
||||
ret_var: num_var,
|
||||
},
|
||||
],
|
||||
var_store,
|
||||
),
|
||||
),
|
||||
)],
|
||||
final_else: Box::new(no_region(tag(
|
||||
"Err",
|
||||
vec![tag("DivByZero", Vec::new(), var_store)],
|
||||
var_store,
|
||||
))),
|
||||
};
|
||||
|
||||
defn(
|
||||
symbol,
|
||||
vec![(num_var, Symbol::ARG_1), (num_var, Symbol::ARG_2)],
|
||||
var_store,
|
||||
body,
|
||||
ret_var,
|
||||
)
|
||||
}
|
||||
|
||||
/// Num.isMultipleOf : Int a, Int a -> Bool
|
||||
fn num_is_multiple_of(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||
lowlevel_2(symbol, LowLevel::NumIsMultipleOf, var_store)
|
||||
|
@ -2537,7 +2537,7 @@ mod test_fmt {
|
||||
indoc!(
|
||||
r#"
|
||||
2 % 3
|
||||
%% 5
|
||||
// 5
|
||||
+ 7
|
||||
"#
|
||||
),
|
||||
@ -2545,7 +2545,7 @@ mod test_fmt {
|
||||
r#"
|
||||
2
|
||||
% 3
|
||||
%% 5
|
||||
// 5
|
||||
+ 7
|
||||
"#
|
||||
),
|
||||
|
@ -5814,9 +5814,9 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||
}
|
||||
|
||||
NumAdd | NumSub | NumMul | NumLt | NumLte | NumGt | NumGte | NumRemUnchecked
|
||||
| NumModUnchecked | NumIsMultipleOf | NumAddWrap | NumAddChecked | NumAddSaturated
|
||||
| NumDivUnchecked | NumDivCeilUnchecked | NumPow | NumPowInt | NumSubWrap
|
||||
| NumSubChecked | NumSubSaturated | NumMulWrap | NumMulChecked => {
|
||||
| NumIsMultipleOf | NumAddWrap | NumAddChecked | NumAddSaturated | NumDivUnchecked
|
||||
| NumDivCeilUnchecked | NumPow | NumPowInt | NumSubWrap | NumSubChecked
|
||||
| NumSubSaturated | NumMulWrap | NumMulChecked => {
|
||||
debug_assert_eq!(args.len(), 2);
|
||||
|
||||
let (lhs_arg, lhs_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
@ -6578,11 +6578,6 @@ fn build_int_binop<'a, 'ctx, 'env>(
|
||||
bd.build_int_unsigned_rem(lhs, rhs, "rem_uint").into()
|
||||
}
|
||||
}
|
||||
NumModUnchecked => {
|
||||
// there generally is not hardware support for flooring mod;
|
||||
// it could probably be implemented in pure Roc in terms of Num.rem.
|
||||
todo!("mod is not implemented")
|
||||
}
|
||||
NumIsMultipleOf => {
|
||||
// this builds the following construct
|
||||
//
|
||||
|
@ -434,11 +434,6 @@ impl<'a> LowLevelCall<'a> {
|
||||
_ => todo!("{:?} for {:?}", self.lowlevel, self.ret_layout),
|
||||
}
|
||||
}
|
||||
NumModUnchecked => {
|
||||
// wasm does not provide a flooring modulo instruction,
|
||||
// so it would need to be emulated.
|
||||
todo!("{:?}", self.lowlevel)
|
||||
}
|
||||
NumIsMultipleOf => todo!("{:?}", self.lowlevel),
|
||||
NumAbs => {
|
||||
self.load_args(backend);
|
||||
|
@ -85,7 +85,6 @@ pub enum LowLevel {
|
||||
NumDivUnchecked,
|
||||
NumDivCeilUnchecked,
|
||||
NumRemUnchecked,
|
||||
NumModUnchecked,
|
||||
NumIsMultipleOf,
|
||||
NumAbs,
|
||||
NumNeg,
|
||||
@ -296,8 +295,6 @@ impl LowLevelWrapperType {
|
||||
Symbol::NUM_DIV_CEIL_CHECKED => WrapperIsRequired,
|
||||
Symbol::NUM_REM => CanBeReplacedBy(NumRemUnchecked),
|
||||
Symbol::NUM_REM_CHECKED => WrapperIsRequired,
|
||||
Symbol::NUM_MOD => CanBeReplacedBy(NumModUnchecked),
|
||||
Symbol::NUM_MOD_CHECKED => WrapperIsRequired,
|
||||
Symbol::NUM_IS_MULTIPLE_OF => CanBeReplacedBy(NumIsMultipleOf),
|
||||
Symbol::NUM_ABS => CanBeReplacedBy(NumAbs),
|
||||
Symbol::NUM_NEG => CanBeReplacedBy(NumNeg),
|
||||
|
@ -950,10 +950,6 @@ define_builtins! {
|
||||
41 NUM_DIV_FLOAT_CHECKED: "divChecked"
|
||||
42 NUM_DIV_FLOOR: "divFloor"
|
||||
43 NUM_DIV_FLOOR_CHECKED: "divFloorChecked"
|
||||
44 NUM_MOD: "mod"
|
||||
45 NUM_MOD_CHECKED: "modChecked"
|
||||
46 NUM_MOD_FLOAT: "modFloat"
|
||||
47 NUM_MOD_FLOAT_CHECKED: "modFloatChecked"
|
||||
48 NUM_SQRT: "sqrt"
|
||||
49 NUM_SQRT_CHECKED: "sqrtChecked"
|
||||
50 NUM_LOG: "log"
|
||||
|
@ -994,9 +994,10 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
|
||||
And | Or | NumAdd | NumAddWrap | NumAddChecked | NumAddSaturated | NumSub | NumSubWrap
|
||||
| NumSubChecked | NumSubSaturated | NumMul | NumMulWrap | NumMulChecked | NumGt
|
||||
| NumGte | NumLt | NumLte | NumCompare | NumDivUnchecked | NumDivCeilUnchecked
|
||||
| NumRemUnchecked | NumModUnchecked | NumIsMultipleOf | NumPow | NumPowInt
|
||||
| NumBitwiseAnd | NumBitwiseXor | NumBitwiseOr | NumShiftLeftBy | NumShiftRightBy
|
||||
| NumShiftRightZfBy => arena.alloc_slice_copy(&[irrelevant, irrelevant]),
|
||||
| NumRemUnchecked | NumIsMultipleOf | NumPow | NumPowInt | NumBitwiseAnd
|
||||
| NumBitwiseXor | NumBitwiseOr | NumShiftLeftBy | NumShiftRightBy | NumShiftRightZfBy => {
|
||||
arena.alloc_slice_copy(&[irrelevant, irrelevant])
|
||||
}
|
||||
|
||||
NumToStr | NumAbs | NumNeg | NumSin | NumCos | NumSqrtUnchecked | NumLogUnchecked
|
||||
| NumRound | NumCeiling | NumFloor | NumToFloat | Not | NumIsFinite | NumAtan | NumAcos
|
||||
|
@ -144,7 +144,6 @@ enum FirstOrder {
|
||||
NumCompare,
|
||||
NumDivUnchecked,
|
||||
NumRemUnchecked,
|
||||
NumModUnchecked,
|
||||
NumIsMultipleOf,
|
||||
NumAbs,
|
||||
NumNeg,
|
||||
|
@ -1297,7 +1297,6 @@ Here are various Roc expressions involving operators, and what they desugar to.
|
||||
| `a // b` | `Num.divFloor a b` |
|
||||
| `a ^ b` | `Num.pow a b` |
|
||||
| `a % b` | `Num.rem a b` |
|
||||
| `a %% b` | `Num.mod a b` |
|
||||
| `a >> b` | `Num.shr a b` |
|
||||
| `a << b` | `Num.shl a b` |
|
||||
| `-a` | `Num.neg a` |
|
||||
|
Loading…
Reference in New Issue
Block a user