mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
Modify division behaviour to panic when dividing by 0, and add divChecked
, divFloorChecked and
divCeilingChecked` for safe alternatives which return a Result, mimicking the previous behaviour.
This commit is contained in:
parent
23bc8aab49
commit
4ecf2a8c24
9 changed files with 318 additions and 129 deletions
|
@ -310,9 +310,7 @@ pub const RocDec = extern struct {
|
||||||
|
|
||||||
// (n / 0) is an error
|
// (n / 0) is an error
|
||||||
if (denominator_i128 == 0) {
|
if (denominator_i128 == 0) {
|
||||||
// The compiler frontend does the `denominator == 0` check for us,
|
@panic("TODO runtime exception for dividing by 0!");
|
||||||
// therefore this case is unreachable from roc user code
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If they're both negative, or if neither is negative, the final answer
|
// If they're both negative, or if neither is negative, the final answer
|
||||||
|
|
|
@ -102,7 +102,7 @@ pub fn exportRound(comptime T: type, comptime name: []const u8) void {
|
||||||
pub fn exportDivCeil(comptime T: type, comptime name: []const u8) void {
|
pub fn exportDivCeil(comptime T: type, comptime name: []const u8) void {
|
||||||
comptime var f = struct {
|
comptime var f = struct {
|
||||||
fn func(a: T, b: T) callconv(.C) T {
|
fn func(a: T, b: T) callconv(.C) T {
|
||||||
return math.divCeil(T, a, b) catch unreachable;
|
return math.divCeil(T, a, b) catch @panic("TODO runtime exception for dividing by 0!");
|
||||||
}
|
}
|
||||||
}.func;
|
}.func;
|
||||||
@export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong });
|
@export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong });
|
||||||
|
|
|
@ -69,6 +69,7 @@ interface Num
|
||||||
isNegative,
|
isNegative,
|
||||||
rem,
|
rem,
|
||||||
div,
|
div,
|
||||||
|
divChecked,
|
||||||
modInt,
|
modInt,
|
||||||
modFloat,
|
modFloat,
|
||||||
sqrt,
|
sqrt,
|
||||||
|
@ -97,7 +98,9 @@ interface Num
|
||||||
bytesToU16,
|
bytesToU16,
|
||||||
bytesToU32,
|
bytesToU32,
|
||||||
divCeil,
|
divCeil,
|
||||||
|
divCeilChecked,
|
||||||
divFloor,
|
divFloor,
|
||||||
|
divFloorChecked,
|
||||||
toStr,
|
toStr,
|
||||||
isMultipleOf,
|
isMultipleOf,
|
||||||
minI8,
|
minI8,
|
||||||
|
@ -229,10 +232,13 @@ atan : Float a -> Float a
|
||||||
|
|
||||||
sqrt : Float a -> Result (Float a) [ SqrtOfNegative ]*
|
sqrt : Float a -> Result (Float a) [ SqrtOfNegative ]*
|
||||||
log : Float a -> Result (Float a) [ LogNeedsPositive ]*
|
log : Float a -> Result (Float a) [ LogNeedsPositive ]*
|
||||||
div : Float a, Float a -> Result (Float a) [ DivByZero ]*
|
div : Float a, Float a -> Float a
|
||||||
|
divChecked : Float a, Float a -> Result (Float a) [ DivByZero ]*
|
||||||
|
|
||||||
divCeil: Int a, Int a -> Result (Int a) [ DivByZero ]*
|
divCeil : Int a, Int a -> Int a
|
||||||
divFloor: Int a, Int a -> Result (Int a) [ DivByZero ]*
|
divCeilChecked : Int a, Int a -> Result (Int a) [ DivByZero ]*
|
||||||
|
divFloor : Int a, Int a -> Int a
|
||||||
|
divFloorChecked : Int a, Int a -> Result (Int a) [ DivByZero ]*
|
||||||
# mod : Float a, Float a -> Result (Float a) [ DivByZero ]*
|
# mod : Float a, Float a -> Result (Float a) [ DivByZero ]*
|
||||||
|
|
||||||
rem : Int a, Int a -> Result (Int a) [ DivByZero ]*
|
rem : Int a, Int a -> Result (Int a) [ DivByZero ]*
|
||||||
|
|
|
@ -316,17 +316,31 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
Box::new(SolvedType::Wildcard),
|
Box::new(SolvedType::Wildcard),
|
||||||
);
|
);
|
||||||
|
|
||||||
// divInt : Int a, Int a -> Result (Int a) [ DivByZero ]*
|
// divInt : Int a, Int a -> Int a
|
||||||
add_top_level_function_type!(
|
add_top_level_function_type!(
|
||||||
Symbol::NUM_DIV_INT,
|
Symbol::NUM_DIV_INT,
|
||||||
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
|
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
|
||||||
|
Box::new(int_type(flex(TVAR1)))
|
||||||
|
);
|
||||||
|
|
||||||
|
// divIntChecked : Int a, Int a -> Result (Int a) [ DivByZero ]*
|
||||||
|
add_top_level_function_type!(
|
||||||
|
Symbol::NUM_DIV_INT_CHECKED,
|
||||||
|
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
|
||||||
Box::new(result_type(int_type(flex(TVAR1)), div_by_zero.clone())),
|
Box::new(result_type(int_type(flex(TVAR1)), div_by_zero.clone())),
|
||||||
);
|
);
|
||||||
|
|
||||||
//divCeil: Int a, Int a -> Result (Int a) [ DivByZero ]*
|
// divCeil : Int a, Int a -> Int a
|
||||||
add_top_level_function_type!(
|
add_top_level_function_type!(
|
||||||
Symbol::NUM_DIV_CEIL,
|
Symbol::NUM_DIV_CEIL,
|
||||||
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
|
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
|
||||||
|
Box::new(int_type(flex(TVAR1)))
|
||||||
|
);
|
||||||
|
|
||||||
|
//divCeilChecked : Int a, Int a -> Result (Int a) [ DivByZero ]*
|
||||||
|
add_top_level_function_type!(
|
||||||
|
Symbol::NUM_DIV_CEIL_CHECKED,
|
||||||
|
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
|
||||||
Box::new(result_type(int_type(flex(TVAR1)), div_by_zero.clone())),
|
Box::new(result_type(int_type(flex(TVAR1)), div_by_zero.clone())),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -631,6 +645,13 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
||||||
add_top_level_function_type!(
|
add_top_level_function_type!(
|
||||||
Symbol::NUM_DIV_FLOAT,
|
Symbol::NUM_DIV_FLOAT,
|
||||||
vec![float_type(flex(TVAR1)), float_type(flex(TVAR1))],
|
vec![float_type(flex(TVAR1)), float_type(flex(TVAR1))],
|
||||||
|
Box::new(float_type(flex(TVAR1)))
|
||||||
|
);
|
||||||
|
|
||||||
|
// divChecked : Float a, Float a -> Result (Float a) [ DivByZero ]*
|
||||||
|
add_top_level_function_type!(
|
||||||
|
Symbol::NUM_DIV_FLOAT_CHECKED,
|
||||||
|
vec![float_type(flex(TVAR1)), float_type(flex(TVAR1))],
|
||||||
Box::new(result_type(float_type(flex(TVAR1)), div_by_zero.clone())),
|
Box::new(result_type(float_type(flex(TVAR1)), div_by_zero.clone())),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -195,8 +195,11 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
|
||||||
NUM_COS => num_cos,
|
NUM_COS => num_cos,
|
||||||
NUM_TAN => num_tan,
|
NUM_TAN => num_tan,
|
||||||
NUM_DIV_FLOAT => num_div_float,
|
NUM_DIV_FLOAT => num_div_float,
|
||||||
|
NUM_DIV_FLOAT_CHECKED => num_div_float_checked,
|
||||||
NUM_DIV_INT => num_div_int,
|
NUM_DIV_INT => num_div_int,
|
||||||
|
NUM_DIV_INT_CHECKED => num_div_int_checked,
|
||||||
NUM_DIV_CEIL => num_div_ceil,
|
NUM_DIV_CEIL => num_div_ceil,
|
||||||
|
NUM_DIV_CEIL_CHECKED => num_div_ceil_checked,
|
||||||
NUM_ABS => num_abs,
|
NUM_ABS => num_abs,
|
||||||
NUM_NEG => num_neg,
|
NUM_NEG => num_neg,
|
||||||
NUM_REM => num_rem,
|
NUM_REM => num_rem,
|
||||||
|
@ -4277,8 +4280,13 @@ fn num_abs(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Num.div : Float, Float -> Result Float [ DivByZero ]*
|
/// Num.div : Float, Float -> Float
|
||||||
fn num_div_float(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
fn num_div_float(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
|
num_binop(symbol, var_store, LowLevel::NumDivUnchecked)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Num.divChecked : Float, Float -> Result Float [ DivByZero ]*
|
||||||
|
fn num_div_float_checked(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let bool_var = var_store.fresh();
|
let bool_var = var_store.fresh();
|
||||||
let num_var = var_store.fresh();
|
let num_var = var_store.fresh();
|
||||||
let unbound_zero_var = var_store.fresh();
|
let unbound_zero_var = var_store.fresh();
|
||||||
|
@ -4343,8 +4351,13 @@ fn num_div_float(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Num.div : Int a , Int a -> Result (Int a) [ DivByZero ]*
|
/// Num.div : Int a, Int a -> Int a
|
||||||
fn num_div_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
fn num_div_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
|
num_binop(symbol, var_store, LowLevel::NumDivUnchecked)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Num.divChecked : Int a , Int a -> Result (Int a) [ DivByZero ]*
|
||||||
|
fn num_div_int_checked(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let bool_var = var_store.fresh();
|
let bool_var = var_store.fresh();
|
||||||
let num_var = var_store.fresh();
|
let num_var = var_store.fresh();
|
||||||
let unbound_zero_var = var_store.fresh();
|
let unbound_zero_var = var_store.fresh();
|
||||||
|
@ -4414,8 +4427,13 @@ fn num_div_int(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Num.divCeil : Int a , Int a -> Result (Int a) [ DivByZero ]*
|
/// Num.divCeil : Int a, Int a -> Int a
|
||||||
fn num_div_ceil(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
fn num_div_ceil(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
|
num_binop(symbol, var_store, LowLevel::NumDivCeilUnchecked)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Num.divCeilChecked : Int a , Int a -> Result (Int a) [ DivByZero ]*
|
||||||
|
fn num_div_ceil_checked(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let bool_var = var_store.fresh();
|
let bool_var = var_store.fresh();
|
||||||
let num_var = var_store.fresh();
|
let num_var = var_store.fresh();
|
||||||
let unbound_zero_var = var_store.fresh();
|
let unbound_zero_var = var_store.fresh();
|
||||||
|
|
|
@ -287,8 +287,10 @@ impl LowLevelWrapperType {
|
||||||
Symbol::NUM_LT => CanBeReplacedBy(NumLt),
|
Symbol::NUM_LT => CanBeReplacedBy(NumLt),
|
||||||
Symbol::NUM_LTE => CanBeReplacedBy(NumLte),
|
Symbol::NUM_LTE => CanBeReplacedBy(NumLte),
|
||||||
Symbol::NUM_COMPARE => CanBeReplacedBy(NumCompare),
|
Symbol::NUM_COMPARE => CanBeReplacedBy(NumCompare),
|
||||||
Symbol::NUM_DIV_FLOAT => WrapperIsRequired,
|
Symbol::NUM_DIV_FLOAT => CanBeReplacedBy(NumDivUnchecked),
|
||||||
Symbol::NUM_DIV_CEIL => WrapperIsRequired,
|
Symbol::NUM_DIV_FLOAT_CHECKED => WrapperIsRequired,
|
||||||
|
Symbol::NUM_DIV_CEIL => CanBeReplacedBy(NumDivCeilUnchecked),
|
||||||
|
Symbol::NUM_DIV_CEIL_CHECKED => WrapperIsRequired,
|
||||||
Symbol::NUM_REM => WrapperIsRequired,
|
Symbol::NUM_REM => WrapperIsRequired,
|
||||||
Symbol::NUM_IS_MULTIPLE_OF => CanBeReplacedBy(NumIsMultipleOf),
|
Symbol::NUM_IS_MULTIPLE_OF => CanBeReplacedBy(NumIsMultipleOf),
|
||||||
Symbol::NUM_ABS => CanBeReplacedBy(NumAbs),
|
Symbol::NUM_ABS => CanBeReplacedBy(NumAbs),
|
||||||
|
|
|
@ -945,114 +945,122 @@ define_builtins! {
|
||||||
36 NUM_IS_POSITIVE: "isPositive"
|
36 NUM_IS_POSITIVE: "isPositive"
|
||||||
37 NUM_IS_NEGATIVE: "isNegative"
|
37 NUM_IS_NEGATIVE: "isNegative"
|
||||||
38 NUM_REM: "rem"
|
38 NUM_REM: "rem"
|
||||||
39 NUM_DIV_FLOAT: "div"
|
39 NUM_REM_CHECKED: "remChecked"
|
||||||
40 NUM_DIV_INT: "divFloor"
|
40 NUM_DIV_FLOAT: "div"
|
||||||
41 NUM_MOD_INT: "modInt"
|
41 NUM_DIV_FLOAT_CHECKED: "divChecked"
|
||||||
42 NUM_MOD_FLOAT: "modFloat"
|
42 NUM_DIV_INT: "divFloor"
|
||||||
43 NUM_SQRT: "sqrt"
|
43 NUM_DIV_INT_CHECKED: "divFloorChecked"
|
||||||
44 NUM_LOG: "log"
|
44 NUM_MOD_INT: "modInt"
|
||||||
45 NUM_ROUND: "round"
|
45 NUM_MOD_INT_CHECKED: "modIntChecked"
|
||||||
46 NUM_COMPARE: "compare"
|
46 NUM_MOD_FLOAT: "modFloat"
|
||||||
47 NUM_POW: "pow"
|
47 NUM_MOD_FLOAT_CHECKED: "modFloatChecked"
|
||||||
48 NUM_CEILING: "ceiling"
|
48 NUM_SQRT: "sqrt"
|
||||||
49 NUM_POW_INT: "powInt"
|
49 NUM_SQRT_CHECKED: "sqrtChecked"
|
||||||
50 NUM_FLOOR: "floor"
|
50 NUM_LOG: "log"
|
||||||
51 NUM_ADD_WRAP: "addWrap"
|
51 NUM_LOG_CHECKED: "logChecked"
|
||||||
52 NUM_ADD_CHECKED: "addChecked"
|
52 NUM_ROUND: "round"
|
||||||
53 NUM_ADD_SATURATED: "addSaturated"
|
53 NUM_COMPARE: "compare"
|
||||||
54 NUM_ATAN: "atan"
|
54 NUM_POW: "pow"
|
||||||
55 NUM_ACOS: "acos"
|
55 NUM_CEILING: "ceiling"
|
||||||
56 NUM_ASIN: "asin"
|
56 NUM_POW_INT: "powInt"
|
||||||
57 NUM_AT_SIGNED128: "@Signed128"
|
57 NUM_FLOOR: "floor"
|
||||||
58 NUM_SIGNED128: "Signed128" imported
|
58 NUM_ADD_WRAP: "addWrap"
|
||||||
59 NUM_AT_SIGNED64: "@Signed64"
|
59 NUM_ADD_CHECKED: "addChecked"
|
||||||
60 NUM_SIGNED64: "Signed64" imported
|
60 NUM_ADD_SATURATED: "addSaturated"
|
||||||
61 NUM_AT_SIGNED32: "@Signed32"
|
61 NUM_ATAN: "atan"
|
||||||
62 NUM_SIGNED32: "Signed32" imported
|
62 NUM_ACOS: "acos"
|
||||||
63 NUM_AT_SIGNED16: "@Signed16"
|
63 NUM_ASIN: "asin"
|
||||||
64 NUM_SIGNED16: "Signed16" imported
|
64 NUM_AT_SIGNED128: "@Signed128"
|
||||||
65 NUM_AT_SIGNED8: "@Signed8"
|
65 NUM_SIGNED128: "Signed128" imported
|
||||||
66 NUM_SIGNED8: "Signed8" imported
|
66 NUM_AT_SIGNED64: "@Signed64"
|
||||||
67 NUM_AT_UNSIGNED128: "@Unsigned128"
|
67 NUM_SIGNED64: "Signed64" imported
|
||||||
68 NUM_UNSIGNED128: "Unsigned128" imported
|
68 NUM_AT_SIGNED32: "@Signed32"
|
||||||
69 NUM_AT_UNSIGNED64: "@Unsigned64"
|
69 NUM_SIGNED32: "Signed32" imported
|
||||||
70 NUM_UNSIGNED64: "Unsigned64" imported
|
70 NUM_AT_SIGNED16: "@Signed16"
|
||||||
71 NUM_AT_UNSIGNED32: "@Unsigned32"
|
71 NUM_SIGNED16: "Signed16" imported
|
||||||
72 NUM_UNSIGNED32: "Unsigned32" imported
|
72 NUM_AT_SIGNED8: "@Signed8"
|
||||||
73 NUM_AT_UNSIGNED16: "@Unsigned16"
|
73 NUM_SIGNED8: "Signed8" imported
|
||||||
74 NUM_UNSIGNED16: "Unsigned16" imported
|
74 NUM_AT_UNSIGNED128: "@Unsigned128"
|
||||||
75 NUM_AT_UNSIGNED8: "@Unsigned8"
|
75 NUM_UNSIGNED128: "Unsigned128" imported
|
||||||
76 NUM_UNSIGNED8: "Unsigned8" imported
|
76 NUM_AT_UNSIGNED64: "@Unsigned64"
|
||||||
77 NUM_AT_BINARY64: "@Binary64"
|
77 NUM_UNSIGNED64: "Unsigned64" imported
|
||||||
78 NUM_BINARY64: "Binary64" imported
|
78 NUM_AT_UNSIGNED32: "@Unsigned32"
|
||||||
79 NUM_AT_BINARY32: "@Binary32"
|
79 NUM_UNSIGNED32: "Unsigned32" imported
|
||||||
80 NUM_BINARY32: "Binary32" imported
|
80 NUM_AT_UNSIGNED16: "@Unsigned16"
|
||||||
81 NUM_BITWISE_AND: "bitwiseAnd"
|
81 NUM_UNSIGNED16: "Unsigned16" imported
|
||||||
82 NUM_BITWISE_XOR: "bitwiseXor"
|
82 NUM_AT_UNSIGNED8: "@Unsigned8"
|
||||||
83 NUM_BITWISE_OR: "bitwiseOr"
|
83 NUM_UNSIGNED8: "Unsigned8" imported
|
||||||
84 NUM_SHIFT_LEFT: "shiftLeftBy"
|
84 NUM_AT_BINARY64: "@Binary64"
|
||||||
85 NUM_SHIFT_RIGHT: "shiftRightBy"
|
85 NUM_BINARY64: "Binary64" imported
|
||||||
86 NUM_SHIFT_RIGHT_ZERO_FILL: "shiftRightZfBy"
|
86 NUM_AT_BINARY32: "@Binary32"
|
||||||
87 NUM_SUB_WRAP: "subWrap"
|
87 NUM_BINARY32: "Binary32" imported
|
||||||
88 NUM_SUB_CHECKED: "subChecked"
|
88 NUM_BITWISE_AND: "bitwiseAnd"
|
||||||
89 NUM_SUB_SATURATED: "subSaturated"
|
89 NUM_BITWISE_XOR: "bitwiseXor"
|
||||||
90 NUM_MUL_WRAP: "mulWrap"
|
90 NUM_BITWISE_OR: "bitwiseOr"
|
||||||
91 NUM_MUL_CHECKED: "mulChecked"
|
91 NUM_SHIFT_LEFT: "shiftLeftBy"
|
||||||
92 NUM_INT: "Int" imported
|
92 NUM_SHIFT_RIGHT: "shiftRightBy"
|
||||||
93 NUM_FLOAT: "Float" imported
|
93 NUM_SHIFT_RIGHT_ZERO_FILL: "shiftRightZfBy"
|
||||||
94 NUM_AT_NATURAL: "@Natural"
|
94 NUM_SUB_WRAP: "subWrap"
|
||||||
95 NUM_NATURAL: "Natural" imported
|
95 NUM_SUB_CHECKED: "subChecked"
|
||||||
96 NUM_NAT: "Nat" imported
|
96 NUM_SUB_SATURATED: "subSaturated"
|
||||||
97 NUM_INT_CAST: "intCast"
|
97 NUM_MUL_WRAP: "mulWrap"
|
||||||
98 NUM_IS_MULTIPLE_OF: "isMultipleOf"
|
98 NUM_MUL_CHECKED: "mulChecked"
|
||||||
99 NUM_AT_DECIMAL: "@Decimal"
|
99 NUM_INT: "Int" imported
|
||||||
100 NUM_DECIMAL: "Decimal" imported
|
100 NUM_FLOAT: "Float" imported
|
||||||
101 NUM_DEC: "Dec" imported // the Num.Dectype alias
|
101 NUM_AT_NATURAL: "@Natural"
|
||||||
102 NUM_BYTES_TO_U16: "bytesToU16"
|
102 NUM_NATURAL: "Natural" imported
|
||||||
103 NUM_BYTES_TO_U32: "bytesToU32"
|
103 NUM_NAT: "Nat" imported
|
||||||
104 NUM_CAST_TO_NAT: "#castToNat"
|
104 NUM_INT_CAST: "intCast"
|
||||||
105 NUM_DIV_CEIL: "divCeil"
|
105 NUM_IS_MULTIPLE_OF: "isMultipleOf"
|
||||||
106 NUM_TO_STR: "toStr"
|
106 NUM_AT_DECIMAL: "@Decimal"
|
||||||
107 NUM_MIN_I8: "minI8"
|
107 NUM_DECIMAL: "Decimal" imported
|
||||||
108 NUM_MAX_I8: "maxI8"
|
108 NUM_DEC: "Dec" imported // the Num.Dectype alias
|
||||||
109 NUM_MIN_U8: "minU8"
|
109 NUM_BYTES_TO_U16: "bytesToU16"
|
||||||
110 NUM_MAX_U8: "maxU8"
|
110 NUM_BYTES_TO_U32: "bytesToU32"
|
||||||
111 NUM_MIN_I16: "minI16"
|
111 NUM_CAST_TO_NAT: "#castToNat"
|
||||||
112 NUM_MAX_I16: "maxI16"
|
112 NUM_DIV_CEIL: "divCeil"
|
||||||
113 NUM_MIN_U16: "minU16"
|
113 NUM_DIV_CEIL_CHECKED: "divCeilChecked"
|
||||||
114 NUM_MAX_U16: "maxU16"
|
114 NUM_TO_STR: "toStr"
|
||||||
115 NUM_MIN_I32: "minI32"
|
115 NUM_MIN_I8: "minI8"
|
||||||
116 NUM_MAX_I32: "maxI32"
|
116 NUM_MAX_I8: "maxI8"
|
||||||
117 NUM_MIN_U32: "minU32"
|
117 NUM_MIN_U8: "minU8"
|
||||||
118 NUM_MAX_U32: "maxU32"
|
118 NUM_MAX_U8: "maxU8"
|
||||||
119 NUM_MIN_I64: "minI64"
|
119 NUM_MIN_I16: "minI16"
|
||||||
120 NUM_MAX_I64: "maxI64"
|
120 NUM_MAX_I16: "maxI16"
|
||||||
121 NUM_MIN_U64: "minU64"
|
121 NUM_MIN_U16: "minU16"
|
||||||
122 NUM_MAX_U64: "maxU64"
|
122 NUM_MAX_U16: "maxU16"
|
||||||
123 NUM_MIN_I128: "minI128"
|
123 NUM_MIN_I32: "minI32"
|
||||||
124 NUM_MAX_I128: "maxI128"
|
124 NUM_MAX_I32: "maxI32"
|
||||||
125 NUM_TO_I8: "toI8"
|
125 NUM_MIN_U32: "minU32"
|
||||||
126 NUM_TO_I8_CHECKED: "toI8Checked"
|
126 NUM_MAX_U32: "maxU32"
|
||||||
127 NUM_TO_I16: "toI16"
|
127 NUM_MIN_I64: "minI64"
|
||||||
128 NUM_TO_I16_CHECKED: "toI16Checked"
|
128 NUM_MAX_I64: "maxI64"
|
||||||
129 NUM_TO_I32: "toI32"
|
129 NUM_MIN_U64: "minU64"
|
||||||
130 NUM_TO_I32_CHECKED: "toI32Checked"
|
130 NUM_MAX_U64: "maxU64"
|
||||||
131 NUM_TO_I64: "toI64"
|
131 NUM_MIN_I128: "minI128"
|
||||||
132 NUM_TO_I64_CHECKED: "toI64Checked"
|
132 NUM_MAX_I128: "maxI128"
|
||||||
133 NUM_TO_I128: "toI128"
|
133 NUM_TO_I8: "toI8"
|
||||||
134 NUM_TO_I128_CHECKED: "toI128Checked"
|
134 NUM_TO_I8_CHECKED: "toI8Checked"
|
||||||
135 NUM_TO_U8: "toU8"
|
135 NUM_TO_I16: "toI16"
|
||||||
136 NUM_TO_U8_CHECKED: "toU8Checked"
|
136 NUM_TO_I16_CHECKED: "toI16Checked"
|
||||||
137 NUM_TO_U16: "toU16"
|
137 NUM_TO_I32: "toI32"
|
||||||
138 NUM_TO_U16_CHECKED: "toU16Checked"
|
138 NUM_TO_I32_CHECKED: "toI32Checked"
|
||||||
139 NUM_TO_U32: "toU32"
|
139 NUM_TO_I64: "toI64"
|
||||||
140 NUM_TO_U32_CHECKED: "toU32Checked"
|
140 NUM_TO_I64_CHECKED: "toI64Checked"
|
||||||
141 NUM_TO_U64: "toU64"
|
141 NUM_TO_I128: "toI128"
|
||||||
142 NUM_TO_U64_CHECKED: "toU64Checked"
|
142 NUM_TO_I128_CHECKED: "toI128Checked"
|
||||||
143 NUM_TO_U128: "toU128"
|
143 NUM_TO_U8: "toU8"
|
||||||
144 NUM_TO_U128_CHECKED: "toU128Checked"
|
144 NUM_TO_U8_CHECKED: "toU8Checked"
|
||||||
145 NUM_TO_NAT: "toNat"
|
145 NUM_TO_U16: "toU16"
|
||||||
146 NUM_TO_NAT_CHECKED: "toNatChecked"
|
146 NUM_TO_U16_CHECKED: "toU16Checked"
|
||||||
|
147 NUM_TO_U32: "toU32"
|
||||||
|
148 NUM_TO_U32_CHECKED: "toU32Checked"
|
||||||
|
149 NUM_TO_U64: "toU64"
|
||||||
|
150 NUM_TO_U64_CHECKED: "toU64Checked"
|
||||||
|
151 NUM_TO_U128: "toU128"
|
||||||
|
152 NUM_TO_U128_CHECKED: "toU128Checked"
|
||||||
|
153 NUM_TO_NAT: "toNat"
|
||||||
|
154 NUM_TO_NAT_CHECKED: "toNatChecked"
|
||||||
}
|
}
|
||||||
2 BOOL: "Bool" => {
|
2 BOOL: "Bool" => {
|
||||||
0 BOOL_BOOL: "Bool" imported // the Bool.Bool type alias
|
0 BOOL_BOOL: "Bool" imported // the Bool.Bool type alias
|
||||||
|
|
|
@ -3296,6 +3296,30 @@ mod solve_expr {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn div() {
|
||||||
|
infer_eq_without_problem(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
Num.div
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
"Float a, Float a -> Float a"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn div_checked() {
|
||||||
|
infer_eq_without_problem(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
Num.divChecked
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
"Float a, Float a -> Result (Float a) [ DivByZero ]*"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn div_ceil() {
|
fn div_ceil() {
|
||||||
infer_eq_without_problem(
|
infer_eq_without_problem(
|
||||||
|
@ -3304,22 +3328,46 @@ mod solve_expr {
|
||||||
Num.divCeil
|
Num.divCeil
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"Int a, Int a -> Result (Int a) [ DivByZero ]*",
|
"Int a, Int a -> Int a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pow_int() {
|
fn div_ceil_checked() {
|
||||||
infer_eq_without_problem(
|
infer_eq_without_problem(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
Num.powInt
|
Num.divCeilChecked
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
"Int a, Int a -> Int a",
|
"Int a, Int a -> Int a",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn div_floor() {
|
||||||
|
infer_eq_without_problem(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
Num.divFloor
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
"Int a, Int a -> Int a"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn div_floor_checked() {
|
||||||
|
infer_eq_without_problem(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
Num.divFloorChecked
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
"Int a, Int a -> Result (Int a) [ DivByZer ]*"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn atan() {
|
fn atan() {
|
||||||
infer_eq_without_problem(
|
infer_eq_without_problem(
|
||||||
|
|
|
@ -723,6 +723,21 @@ fn gen_wrap_add_nums() {
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm"))]
|
||||||
fn gen_div_f64() {
|
fn gen_div_f64() {
|
||||||
|
// FIXME this works with normal types, but fails when checking uniqueness types
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
48 / 2
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
24.0,
|
||||||
|
f64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm"))]
|
||||||
|
fn gen_div_checked_f64() {
|
||||||
// FIXME this works with normal types, but fails when checking uniqueness types
|
// FIXME this works with normal types, but fails when checking uniqueness types
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
@ -736,6 +751,24 @@ fn gen_div_f64() {
|
||||||
f64
|
f64
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm"))]
|
||||||
|
fn gen_div_checked_by_zero_f64() {
|
||||||
|
// FIXME this works with normal types, but fails when checking uniqueness types
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
when 48 / 0 is
|
||||||
|
Ok val -> val
|
||||||
|
Err _ -> -1
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
-1,
|
||||||
|
f64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm"))]
|
||||||
fn gen_div_dec() {
|
fn gen_div_dec() {
|
||||||
|
@ -748,7 +781,27 @@ fn gen_div_dec() {
|
||||||
y : Dec
|
y : Dec
|
||||||
y = 3
|
y = 3
|
||||||
|
|
||||||
when x / y is
|
x / y
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
RocDec::from_str_to_i128_unsafe("3.333333333333333333"),
|
||||||
|
i128
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm"))]
|
||||||
|
fn gen_div_checked_dec() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
x : Dec
|
||||||
|
x = 10
|
||||||
|
|
||||||
|
y : Dec
|
||||||
|
y = 3
|
||||||
|
|
||||||
|
when Num.divChecked x y is
|
||||||
Ok val -> val
|
Ok val -> val
|
||||||
Err _ -> -1
|
Err _ -> -1
|
||||||
"#
|
"#
|
||||||
|
@ -757,6 +810,27 @@ fn gen_div_dec() {
|
||||||
i128
|
i128
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm"))]
|
||||||
|
fn gen_div_checked_by_zero_dec() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
x : Dec
|
||||||
|
x = 10
|
||||||
|
|
||||||
|
y : Dec
|
||||||
|
y = 0
|
||||||
|
|
||||||
|
when Num.divChecked x y is
|
||||||
|
Ok val -> val
|
||||||
|
Err _ -> -1
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
-1,
|
||||||
|
i128
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||||
|
@ -965,7 +1039,21 @@ fn gen_div_i64() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when 1000 // 10 is
|
1000 // 10
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
100,
|
||||||
|
i64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm"))]
|
||||||
|
fn gen_div_checked_i64() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
when Num.divFloorChecked 1000 10 is
|
||||||
Ok val -> val
|
Ok val -> val
|
||||||
Err _ -> -1
|
Err _ -> -1
|
||||||
"#
|
"#
|
||||||
|
@ -977,11 +1065,11 @@ fn gen_div_i64() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm"))]
|
||||||
fn gen_div_by_zero_i64() {
|
fn gen_div_checked_by_zero_i64() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
when 1000 // 0 is
|
when Num.divFloorChecked 1000 0 is
|
||||||
Err DivByZero -> 99
|
Err DivByZero -> 99
|
||||||
_ -> -24
|
_ -> -24
|
||||||
"#
|
"#
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue