Merge remote-tracking branch 'origin/trunk' into builtins-in-roc

This commit is contained in:
Folkert 2022-04-13 21:45:40 +02:00
commit 2b07b8c78d
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
20 changed files with 363 additions and 166 deletions

View file

@ -109,7 +109,7 @@ Alternatively, you can use `cargo test --no-fail-fast` or `cargo test -p specifi
For debugging LLVM IR, we use [DebugIR](https://github.com/vaivaswatha/debugir). This dependency is only required to build with the `--debug` flag, and for normal developtment you should be fine without it.
### libcxb libraries
### libxcb libraries
You may see an error like this during builds:

View file

@ -60,7 +60,7 @@ Its one thing to actually write these functions, its _another_ thing to let the
## Specifying how we pass args to the function
### builtins/mono/src/borrow.rs
After we have all of this, we need to specify if the arguments we're passing are owned, borrowed or irrelevant. Towards the bottom of this file, add a new case for you builtin and specify each arg. Be sure to read the comment, as it explains this in more detail.
After we have all of this, we need to specify if the arguments we're passing are owned, borrowed or irrelevant. Towards the bottom of this file, add a new case for your builtin and specify each arg. Be sure to read the comment, as it explains this in more detail.
## Testing it
### solve/tests/solve_expr.rs
@ -87,7 +87,7 @@ In this directory, there are a couple files like `gen_num.rs`, `gen_str.rs`, etc
fn atan() {
assert_evals_to!("Num.atan 10", 1.4711276743037347, f64);
}
```
```
But replace `Num.atan`, the return value, and the return type with your new builtin.
# Mistakes that are easy to make!!

View file

@ -310,9 +310,7 @@ pub const RocDec = extern struct {
// (n / 0) is an error
if (denominator_i128 == 0) {
// The compiler frontend does the `denominator == 0` check for us,
// therefore this case is unreachable from roc user code
unreachable;
@panic("TODO runtime exception for dividing by 0!");
}
// If they're both negative, or if neither is negative, the final answer

View file

@ -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 {
comptime var f = struct {
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;
@export(f, .{ .name = name ++ @typeName(T), .linkage = .Strong });

View file

@ -81,8 +81,6 @@ interface Num
minI64,
minU64,
minI128,
modInt,
modFloat,
mul,
mulChecked,
mulWrap,

View file

@ -67,6 +67,7 @@ interface Num
isNegative,
rem,
div,
divChecked,
sqrt,
log,
round,
@ -93,7 +94,9 @@ interface Num
bytesToU16,
bytesToU32,
divCeil,
divCeilChecked,
divFloor,
divFloorChecked,
toStr,
isMultipleOf,
minI8,
@ -238,10 +241,13 @@ atan : Float a -> Float a
sqrt : Float a -> Result (Float a) [ SqrtOfNegative ]*
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 ]*
divFloor: Int a, Int a -> Result (Int a) [ DivByZero ]*
divCeil : Int a, Int a -> Int a
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 ]*
rem : Int a, Int a -> Result (Int a) [ DivByZero ]*

View file

@ -316,17 +316,31 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
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!(
Symbol::NUM_DIV_INT,
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())),
);
// divCeil: Int a, Int a -> Result (Int a) [ DivByZero ]*
// divCeil : Int a, Int a -> Int a
add_top_level_function_type!(
Symbol::NUM_DIV_CEIL,
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())),
);
@ -659,6 +673,13 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
add_top_level_function_type!(
Symbol::NUM_DIV_FLOAT,
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())),
);

View file

@ -196,8 +196,11 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
NUM_COS => num_cos,
NUM_TAN => num_tan,
NUM_DIV_FLOAT => num_div_float,
NUM_DIV_FLOAT_CHECKED => num_div_float_checked,
NUM_DIV_INT => num_div_int,
NUM_DIV_INT_CHECKED => num_div_int_checked,
NUM_DIV_CEIL => num_div_ceil,
NUM_DIV_CEIL_CHECKED => num_div_ceil_checked,
NUM_ABS => num_abs,
NUM_NEG => num_neg,
NUM_REM => num_rem,
@ -4183,8 +4186,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 {
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 num_var = var_store.fresh();
let unbound_zero_var = var_store.fresh();
@ -4249,8 +4257,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 {
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 num_var = var_store.fresh();
let unbound_zero_var = var_store.fresh();
@ -4320,8 +4333,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 {
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 num_var = var_store.fresh();
let unbound_zero_var = var_store.fresh();

View file

@ -3598,17 +3598,14 @@ fn run_solve<'a>(
let (solved_subs, exposed_vars_by_symbol, problems) = {
if module_id.is_builtin() {
match cached_subs.lock().remove(&module_id) {
None => {
// this should never happen
run_solve_solve(
None => run_solve_solve(
imported_builtins,
exposed_for_module,
constraints,
constraint,
var_store,
module,
)
}
),
Some((subs, exposed_vars_by_symbol)) => {
(Solved(subs), exposed_vars_by_symbol.to_vec(), vec![])
}

View file

@ -426,12 +426,12 @@ mod test_load {
loaded_module,
hashmap! {
"floatTest" => "Float *",
"divisionFn" => "Float a, Float a -> Result (Float a) [ DivByZero ]*",
"divisionTest" => "Result (Float *) [ DivByZero ]*",
"divisionFn" => "Float a, Float a -> Float a",
"divisionTest" => "Float *",
"intTest" => "I64",
"x" => "Float *",
"constantNum" => "Num *",
"divDep1ByDep2" => "Result (Float *) [ DivByZero ]*",
"divDep1ByDep2" => "Float *",
"fromDep2" => "Float *",
},
);

View file

@ -290,8 +290,10 @@ impl LowLevelWrapperType {
Symbol::NUM_LT => CanBeReplacedBy(NumLt),
Symbol::NUM_LTE => CanBeReplacedBy(NumLte),
Symbol::NUM_COMPARE => CanBeReplacedBy(NumCompare),
Symbol::NUM_DIV_FLOAT => WrapperIsRequired,
Symbol::NUM_DIV_CEIL => WrapperIsRequired,
Symbol::NUM_DIV_FLOAT => CanBeReplacedBy(NumDivUnchecked),
Symbol::NUM_DIV_FLOAT_CHECKED => WrapperIsRequired,
Symbol::NUM_DIV_CEIL => CanBeReplacedBy(NumDivCeilUnchecked),
Symbol::NUM_DIV_CEIL_CHECKED => WrapperIsRequired,
Symbol::NUM_REM => WrapperIsRequired,
Symbol::NUM_IS_MULTIPLE_OF => CanBeReplacedBy(NumIsMultipleOf),
Symbol::NUM_ABS => CanBeReplacedBy(NumAbs),

View file

@ -945,118 +945,126 @@ define_builtins! {
36 NUM_IS_POSITIVE: "isPositive"
37 NUM_IS_NEGATIVE: "isNegative"
38 NUM_REM: "rem"
39 NUM_DIV_FLOAT: "div"
40 NUM_DIV_INT: "divFloor"
41 NUM_MOD_INT: "modInt"
42 NUM_MOD_FLOAT: "modFloat"
43 NUM_SQRT: "sqrt"
44 NUM_LOG: "log"
45 NUM_ROUND: "round"
46 NUM_COMPARE: "compare"
47 NUM_POW: "pow"
48 NUM_CEILING: "ceiling"
49 NUM_POW_INT: "powInt"
50 NUM_FLOOR: "floor"
51 NUM_ADD_WRAP: "addWrap"
52 NUM_ADD_CHECKED: "addChecked"
53 NUM_ADD_SATURATED: "addSaturated"
54 NUM_ATAN: "atan"
55 NUM_ACOS: "acos"
56 NUM_ASIN: "asin"
57 NUM_AT_SIGNED128: "@Signed128"
58 NUM_SIGNED128: "Signed128"
59 NUM_AT_SIGNED64: "@Signed64"
60 NUM_SIGNED64: "Signed64"
61 NUM_AT_SIGNED32: "@Signed32"
62 NUM_SIGNED32: "Signed32"
63 NUM_AT_SIGNED16: "@Signed16"
64 NUM_SIGNED16: "Signed16"
65 NUM_AT_SIGNED8: "@Signed8"
66 NUM_SIGNED8: "Signed8"
67 NUM_AT_UNSIGNED128: "@Unsigned128"
68 NUM_UNSIGNED128: "Unsigned128"
69 NUM_AT_UNSIGNED64: "@Unsigned64"
70 NUM_UNSIGNED64: "Unsigned64"
71 NUM_AT_UNSIGNED32: "@Unsigned32"
72 NUM_UNSIGNED32: "Unsigned32"
73 NUM_AT_UNSIGNED16: "@Unsigned16"
74 NUM_UNSIGNED16: "Unsigned16"
75 NUM_AT_UNSIGNED8: "@Unsigned8"
76 NUM_UNSIGNED8: "Unsigned8"
77 NUM_AT_BINARY64: "@Binary64"
78 NUM_BINARY64: "Binary64"
79 NUM_AT_BINARY32: "@Binary32"
80 NUM_BINARY32: "Binary32"
81 NUM_BITWISE_AND: "bitwiseAnd"
82 NUM_BITWISE_XOR: "bitwiseXor"
83 NUM_BITWISE_OR: "bitwiseOr"
84 NUM_SHIFT_LEFT: "shiftLeftBy"
85 NUM_SHIFT_RIGHT: "shiftRightBy"
86 NUM_SHIFT_RIGHT_ZERO_FILL: "shiftRightZfBy"
87 NUM_SUB_WRAP: "subWrap"
88 NUM_SUB_CHECKED: "subChecked"
89 NUM_SUB_SATURATED: "subSaturated"
90 NUM_MUL_WRAP: "mulWrap"
91 NUM_MUL_CHECKED: "mulChecked"
92 NUM_INT: "Int"
93 NUM_FLOAT: "Float"
94 NUM_AT_NATURAL: "@Natural"
95 NUM_NATURAL: "Natural"
96 NUM_NAT: "Nat"
97 NUM_INT_CAST: "intCast"
98 NUM_IS_MULTIPLE_OF: "isMultipleOf"
99 NUM_AT_DECIMAL: "@Decimal"
100 NUM_DECIMAL: "Decimal"
101 NUM_DEC: "Dec" // the Num.Dectype alias
102 NUM_BYTES_TO_U16: "bytesToU16"
103 NUM_BYTES_TO_U32: "bytesToU32"
104 NUM_CAST_TO_NAT: "#castToNat"
105 NUM_DIV_CEIL: "divCeil"
106 NUM_TO_STR: "toStr"
107 NUM_MIN_I8: "minI8"
108 NUM_MAX_I8: "maxI8"
109 NUM_MIN_U8: "minU8"
110 NUM_MAX_U8: "maxU8"
111 NUM_MIN_I16: "minI16"
112 NUM_MAX_I16: "maxI16"
113 NUM_MIN_U16: "minU16"
114 NUM_MAX_U16: "maxU16"
115 NUM_MIN_I32: "minI32"
116 NUM_MAX_I32: "maxI32"
117 NUM_MIN_U32: "minU32"
118 NUM_MAX_U32: "maxU32"
119 NUM_MIN_I64: "minI64"
120 NUM_MAX_I64: "maxI64"
121 NUM_MIN_U64: "minU64"
122 NUM_MAX_U64: "maxU64"
123 NUM_MIN_I128: "minI128"
124 NUM_MAX_I128: "maxI128"
125 NUM_TO_I8: "toI8"
126 NUM_TO_I8_CHECKED: "toI8Checked"
127 NUM_TO_I16: "toI16"
128 NUM_TO_I16_CHECKED: "toI16Checked"
129 NUM_TO_I32: "toI32"
130 NUM_TO_I32_CHECKED: "toI32Checked"
131 NUM_TO_I64: "toI64"
132 NUM_TO_I64_CHECKED: "toI64Checked"
133 NUM_TO_I128: "toI128"
134 NUM_TO_I128_CHECKED: "toI128Checked"
135 NUM_TO_U8: "toU8"
136 NUM_TO_U8_CHECKED: "toU8Checked"
137 NUM_TO_U16: "toU16"
138 NUM_TO_U16_CHECKED: "toU16Checked"
139 NUM_TO_U32: "toU32"
140 NUM_TO_U32_CHECKED: "toU32Checked"
141 NUM_TO_U64: "toU64"
142 NUM_TO_U64_CHECKED: "toU64Checked"
143 NUM_TO_U128: "toU128"
144 NUM_TO_U128_CHECKED: "toU128Checked"
145 NUM_TO_NAT: "toNat"
146 NUM_TO_NAT_CHECKED: "toNatChecked"
147 NUM_TO_F32: "toF32"
148 NUM_TO_F32_CHECKED: "toF32Checked"
149 NUM_TO_F64: "toF64"
150 NUM_TO_F64_CHECKED: "toF64Checked"
39 NUM_REM_CHECKED: "remChecked"
40 NUM_DIV_FLOAT: "div"
41 NUM_DIV_FLOAT_CHECKED: "divChecked"
42 NUM_DIV_INT: "divFloor"
43 NUM_DIV_INT_CHECKED: "divFloorChecked"
44 NUM_MOD_INT: "modInt"
45 NUM_MOD_INT_CHECKED: "modIntChecked"
46 NUM_MOD_FLOAT: "modFloat"
47 NUM_MOD_FLOAT_CHECKED: "modFloatChecked"
48 NUM_SQRT: "sqrt"
49 NUM_SQRT_CHECKED: "sqrtChecked"
50 NUM_LOG: "log"
51 NUM_LOG_CHECKED: "logChecked"
52 NUM_ROUND: "round"
53 NUM_COMPARE: "compare"
54 NUM_POW: "pow"
55 NUM_CEILING: "ceiling"
56 NUM_POW_INT: "powInt"
57 NUM_FLOOR: "floor"
58 NUM_ADD_WRAP: "addWrap"
59 NUM_ADD_CHECKED: "addChecked"
60 NUM_ADD_SATURATED: "addSaturated"
61 NUM_ATAN: "atan"
62 NUM_ACOS: "acos"
63 NUM_ASIN: "asin"
64 NUM_AT_SIGNED128: "@Signed128"
65 NUM_SIGNED128: "Signed128"
66 NUM_AT_SIGNED64: "@Signed64"
67 NUM_SIGNED64: "Signed64"
68 NUM_AT_SIGNED32: "@Signed32"
69 NUM_SIGNED32: "Signed32"
70 NUM_AT_SIGNED16: "@Signed16"
71 NUM_SIGNED16: "Signed16"
72 NUM_AT_SIGNED8: "@Signed8"
73 NUM_SIGNED8: "Signed8"
74 NUM_AT_UNSIGNED128: "@Unsigned128"
75 NUM_UNSIGNED128: "Unsigned128"
76 NUM_AT_UNSIGNED64: "@Unsigned64"
77 NUM_UNSIGNED64: "Unsigned64"
78 NUM_AT_UNSIGNED32: "@Unsigned32"
79 NUM_UNSIGNED32: "Unsigned32"
80 NUM_AT_UNSIGNED16: "@Unsigned16"
81 NUM_UNSIGNED16: "Unsigned16"
82 NUM_AT_UNSIGNED8: "@Unsigned8"
83 NUM_UNSIGNED8: "Unsigned8"
84 NUM_AT_BINARY64: "@Binary64"
85 NUM_BINARY64: "Binary64"
86 NUM_AT_BINARY32: "@Binary32"
87 NUM_BINARY32: "Binary32"
88 NUM_BITWISE_AND: "bitwiseAnd"
89 NUM_BITWISE_XOR: "bitwiseXor"
90 NUM_BITWISE_OR: "bitwiseOr"
91 NUM_SHIFT_LEFT: "shiftLeftBy"
92 NUM_SHIFT_RIGHT: "shiftRightBy"
93 NUM_SHIFT_RIGHT_ZERO_FILL: "shiftRightZfBy"
94 NUM_SUB_WRAP: "subWrap"
95 NUM_SUB_CHECKED: "subChecked"
96 NUM_SUB_SATURATED: "subSaturated"
97 NUM_MUL_WRAP: "mulWrap"
98 NUM_MUL_CHECKED: "mulChecked"
99 NUM_INT: "Int"
100 NUM_FLOAT: "Float"
101 NUM_AT_NATURAL: "@Natural"
102 NUM_NATURAL: "Natural"
103 NUM_NAT: "Nat"
104 NUM_INT_CAST: "intCast"
105 NUM_IS_MULTIPLE_OF: "isMultipleOf"
106 NUM_AT_DECIMAL: "@Decimal"
107 NUM_DECIMAL: "Decimal"
108 NUM_DEC: "Dec" // the Num.Dectype alias
109 NUM_BYTES_TO_U16: "bytesToU16"
110 NUM_BYTES_TO_U32: "bytesToU32"
111 NUM_CAST_TO_NAT: "#castToNat"
112 NUM_DIV_CEIL: "divCeil"
113 NUM_DIV_CEIL_CHECKED: "divCeilChecked"
114 NUM_TO_STR: "toStr"
115 NUM_MIN_I8: "minI8"
116 NUM_MAX_I8: "maxI8"
117 NUM_MIN_U8: "minU8"
118 NUM_MAX_U8: "maxU8"
119 NUM_MIN_I16: "minI16"
120 NUM_MAX_I16: "maxI16"
121 NUM_MIN_U16: "minU16"
122 NUM_MAX_U16: "maxU16"
123 NUM_MIN_I32: "minI32"
124 NUM_MAX_I32: "maxI32"
125 NUM_MIN_U32: "minU32"
126 NUM_MAX_U32: "maxU32"
127 NUM_MIN_I64: "minI64"
128 NUM_MAX_I64: "maxI64"
129 NUM_MIN_U64: "minU64"
130 NUM_MAX_U64: "maxU64"
131 NUM_MIN_I128: "minI128"
132 NUM_MAX_I128: "maxI128"
133 NUM_TO_I8: "toI8"
134 NUM_TO_I8_CHECKED: "toI8Checked"
135 NUM_TO_I16: "toI16"
136 NUM_TO_I16_CHECKED: "toI16Checked"
137 NUM_TO_I32: "toI32"
138 NUM_TO_I32_CHECKED: "toI32Checked"
139 NUM_TO_I64: "toI64"
140 NUM_TO_I64_CHECKED: "toI64Checked"
141 NUM_TO_I128: "toI128"
142 NUM_TO_I128_CHECKED: "toI128Checked"
143 NUM_TO_U8: "toU8"
144 NUM_TO_U8_CHECKED: "toU8Checked"
145 NUM_TO_U16: "toU16"
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"
155 NUM_TO_F32: "toF32"
156 NUM_TO_F32_CHECKED: "toF32Checked"
157 NUM_TO_F64: "toF64"
158 NUM_TO_F64_CHECKED: "toF64Checked"
}
2 BOOL: "Bool" => {
0 BOOL_BOOL: "Bool" // the Bool.Bool type alias

View file

@ -3300,6 +3300,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]
fn div_ceil() {
infer_eq_without_problem(
@ -3308,22 +3332,46 @@ mod solve_expr {
Num.divCeil
"#
),
"Int a, Int a -> Int a",
);
}
#[test]
fn div_ceil_checked() {
infer_eq_without_problem(
indoc!(
r#"
Num.divCeilChecked
"#
),
"Int a, Int a -> Result (Int a) [ DivByZero ]*",
);
}
#[test]
fn pow_int() {
fn div_floor() {
infer_eq_without_problem(
indoc!(
r#"
Num.powInt
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) [ DivByZero ]*",
);
}
#[test]
fn atan() {
infer_eq_without_problem(

View file

@ -723,11 +723,24 @@ fn gen_wrap_add_nums() {
#[test]
#[cfg(any(feature = "gen-llvm"))]
fn gen_div_f64() {
// FIXME this works with normal types, but fails when checking uniqueness types
assert_evals_to!(
indoc!(
r#"
when 48 / 2 is
48 / 2
"#
),
24.0,
f64
);
}
#[test]
#[cfg(any(feature = "gen-llvm"))]
fn gen_div_checked_f64() {
assert_evals_to!(
indoc!(
r#"
when Num.divChecked 48 2 is
Ok val -> val
Err _ -> -1
"#
@ -736,6 +749,23 @@ fn gen_div_f64() {
f64
);
}
#[test]
#[cfg(any(feature = "gen-llvm"))]
fn gen_div_checked_by_zero_f64() {
assert_evals_to!(
indoc!(
r#"
when Num.divChecked 47 0 is
Ok val -> val
Err _ -> -1
"#
),
-1.0,
f64
);
}
#[test]
#[cfg(any(feature = "gen-llvm"))]
fn gen_div_dec() {
@ -748,7 +778,27 @@ fn gen_div_dec() {
y : Dec
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
Err _ -> -1
"#
@ -757,6 +807,27 @@ fn gen_div_dec() {
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
"#
),
RocDec::from_str_to_i128_unsafe("-1"),
i128
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
@ -965,7 +1036,21 @@ fn gen_div_i64() {
assert_evals_to!(
indoc!(
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
Err _ -> -1
"#
@ -977,11 +1062,11 @@ fn gen_div_i64() {
#[test]
#[cfg(any(feature = "gen-llvm"))]
fn gen_div_by_zero_i64() {
fn gen_div_checked_by_zero_i64() {
assert_evals_to!(
indoc!(
r#"
when 1000 // 0 is
when Num.divFloorChecked 1000 0 is
Err DivByZero -> 99
_ -> -24
"#

View file

@ -274,7 +274,7 @@ fn ir_round() {
#[mono_test]
fn ir_when_idiv() {
r#"
when 1000 // 10 is
when Num.divFloorChecked 1000 10 is
Ok val -> val
Err _ -> -1
"#

View file

@ -42,7 +42,7 @@ Expr : [ Val I64, Var Str, Add Expr Expr, Mul Expr Expr, Pow Expr Expr, Ln Expr
divmod : I64, I64 -> Result { div : I64, mod : I64 } [ DivByZero ]*
divmod = \l, r ->
when Pair (l // r) (l % r) is
Pair (Ok div) (Ok mod) ->
Pair div (Ok mod) ->
Ok { div, mod }
_ ->

View file

@ -47,7 +47,7 @@ makeMapHelp = \total, n, m ->
isFrequency =
n |> Num.isMultipleOf 4
key = n1 + ((total - n1) // 5 |> resultWithDefault 0)
key = n1 + ((total - n1) // 5)
t2 = if isFrequency then delete t1 key else t1
makeMapHelp total n1 t2

View file

@ -434,7 +434,7 @@ stepExecCtx = \ctx, char ->
(
(T popCtx1 numR) <- Result.after (popNumber ctx)
(T popCtx2 numL) <- Result.after (popNumber popCtx1)
res <- Result.after (Num.divFloor numL numR)
res <- Result.after (Num.divFloorChecked numL numR)
Ok (Context.pushStack popCtx2 (Number res))
)

View file

@ -4,9 +4,7 @@ app "hello-gui"
provides [ render ] to pf
render =
div0 = \numerator, denominator -> (numerator / denominator) |> Result.withDefault 0
rgba = \r, g, b, a -> { r: div0 r 255, g: div0 g 255, b: div0 b 255, a }
rgba = \r, g, b, a -> { r: r / 255, g: g / 255, b: b / 255, a }
styles = { bgColor: rgba 100 50 50 1, borderColor: rgba 10 20 30 1, borderWidth: 10, textColor: rgba 220 220 250 1 }

View file

@ -61,23 +61,41 @@ fn num_rem() {
#[cfg(not(feature = "wasm"))]
#[test]
fn num_floor_division_success() {
expect_success("Num.divFloor 4 3", "Ok 1 : Result (Int *) [ DivByZero ]*");
fn num_floor_division() {
expect_success("Num.divFloor 4 3", "1 : Int *");
}
#[cfg(not(feature = "wasm"))]
#[test]
fn num_floor_division_divby_zero() {
fn num_floor_checked_division_success() {
expect_success(
"Num.divFloor 4 0",
"Num.divFloorChecked 4 3",
"Ok 1 : Result (Int *) [ DivByZero ]*",
);
}
#[cfg(not(feature = "wasm"))]
#[test]
fn num_floor_checked_division_divby_zero() {
expect_success(
"Num.divFloorChecked 4 0",
"Err DivByZero : Result (Int *) [ DivByZero ]*",
);
}
#[cfg(not(feature = "wasm"))]
#[test]
fn num_ceil_division_success() {
expect_success("Num.divCeil 4 3", "Ok 2 : Result (Int *) [ DivByZero ]*")
fn num_ceil_division() {
expect_success("Num.divCeil 4 3", "2 : Int *")
}
#[cfg(not(feature = "wasm"))]
#[test]
fn num_ceil_checked_division_success() {
expect_success(
"Num.divCeilChecked 4 3",
"Ok 2 : Result (Int *) [ DivByZero ]*",
)
}
#[test]