remove Num.mod and Num.modUnchecked

This commit is contained in:
Kevin Gillette 2022-04-18 13:54:40 -06:00
parent 1908ff41c3
commit 9ed4ca9739
No known key found for this signature in database
GPG Key ID: 9009F701BBC0D562
14 changed files with 17 additions and 156 deletions

View File

@ -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` |

View File

@ -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.

View File

@ -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].
##
## `

View File

@ -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

View File

@ -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,

View File

@ -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)

View File

@ -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
"#
),

View File

@ -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
//

View File

@ -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);

View File

@ -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),

View File

@ -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"

View File

@ -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

View File

@ -144,7 +144,6 @@ enum FirstOrder {
NumCompare,
NumDivUnchecked,
NumRemUnchecked,
NumModUnchecked,
NumIsMultipleOf,
NumAbs,
NumNeg,

View File

@ -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` |