mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 15:51:12 +00:00
Code gen numeric comparisons
This commit is contained in:
parent
d751327914
commit
c39b43a265
6 changed files with 197 additions and 13 deletions
|
@ -241,7 +241,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
|||
|
||||
// isLte or (<=) : Num a, Num a -> Bool
|
||||
add_type(
|
||||
Symbol::NUM_LE,
|
||||
Symbol::NUM_LTE,
|
||||
SolvedType::Func(
|
||||
vec![num_type(flex(TVAR1)), num_type(flex(TVAR1))],
|
||||
Box::new(bool_type()),
|
||||
|
@ -259,7 +259,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
|||
|
||||
// isGte or (>=) : Num a, Num a -> Bool
|
||||
add_type(
|
||||
Symbol::NUM_GE,
|
||||
Symbol::NUM_GTE,
|
||||
SolvedType::Func(
|
||||
vec![num_type(flex(TVAR1)), num_type(flex(TVAR1))],
|
||||
Box::new(bool_type()),
|
||||
|
|
|
@ -309,7 +309,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
|||
|
||||
// isLte or (<=) : Num a, Num a -> Bool
|
||||
add_type(
|
||||
Symbol::NUM_LE,
|
||||
Symbol::NUM_LTE,
|
||||
unique_function(
|
||||
vec![num_type(UVAR1, TVAR1), num_type(UVAR2, TVAR1)],
|
||||
bool_type(UVAR3),
|
||||
|
@ -327,7 +327,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
|
|||
|
||||
// isGte or (>=) : Num a, Num a -> Bool
|
||||
add_type(
|
||||
Symbol::NUM_GE,
|
||||
Symbol::NUM_GTE,
|
||||
unique_function(
|
||||
vec![num_type(UVAR1, TVAR1), num_type(UVAR2, TVAR1)],
|
||||
bool_type(UVAR3),
|
||||
|
|
|
@ -1060,11 +1060,22 @@ fn call_with_args<'a, 'ctx, 'env>(
|
|||
let int_val = env.builder.build_int_sub(
|
||||
args[0].0.into_int_value(),
|
||||
args[1].0.into_int_value(),
|
||||
"sub_I64",
|
||||
"sub_i64",
|
||||
);
|
||||
|
||||
BasicValueEnum::IntValue(int_val)
|
||||
}
|
||||
Symbol::FLOAT_DIV => {
|
||||
debug_assert!(args.len() == 2);
|
||||
|
||||
let float_val = env.builder.build_float_div(
|
||||
args[0].0.into_float_value(),
|
||||
args[1].0.into_float_value(),
|
||||
"div_f64",
|
||||
);
|
||||
|
||||
BasicValueEnum::FloatValue(float_val)
|
||||
}
|
||||
Symbol::FLOAT_SUB => {
|
||||
debug_assert!(args.len() == 2);
|
||||
|
||||
|
@ -1076,16 +1087,101 @@ fn call_with_args<'a, 'ctx, 'env>(
|
|||
|
||||
BasicValueEnum::FloatValue(float_val)
|
||||
}
|
||||
Symbol::FLOAT_DIV => {
|
||||
Symbol::INT_GTE | Symbol::NUM_GTE => {
|
||||
debug_assert!(args.len() == 2);
|
||||
|
||||
let float_val = env.builder.build_float_div(
|
||||
args[0].0.into_float_value(),
|
||||
args[1].0.into_float_value(),
|
||||
"div_f64",
|
||||
let bool_val = env.builder.build_int_compare(
|
||||
IntPredicate::SGE,
|
||||
args[0].0.into_int_value(),
|
||||
args[1].0.into_int_value(),
|
||||
"gte_i64",
|
||||
);
|
||||
|
||||
BasicValueEnum::FloatValue(float_val)
|
||||
BasicValueEnum::IntValue(bool_val)
|
||||
}
|
||||
Symbol::FLOAT_GTE => {
|
||||
debug_assert!(args.len() == 2);
|
||||
|
||||
let bool_val = env.builder.build_float_compare(
|
||||
FloatPredicate::OGE,
|
||||
args[0].0.into_float_value(),
|
||||
args[1].0.into_float_value(),
|
||||
"gte_F64",
|
||||
);
|
||||
|
||||
BasicValueEnum::IntValue(bool_val)
|
||||
}
|
||||
Symbol::INT_GT | Symbol::NUM_GT => {
|
||||
debug_assert!(args.len() == 2);
|
||||
|
||||
let bool_val = env.builder.build_int_compare(
|
||||
IntPredicate::SGT,
|
||||
args[0].0.into_int_value(),
|
||||
args[1].0.into_int_value(),
|
||||
"gt_i64",
|
||||
);
|
||||
|
||||
BasicValueEnum::IntValue(bool_val)
|
||||
}
|
||||
Symbol::FLOAT_GT => {
|
||||
debug_assert!(args.len() == 2);
|
||||
|
||||
let bool_val = env.builder.build_float_compare(
|
||||
FloatPredicate::OGT,
|
||||
args[0].0.into_float_value(),
|
||||
args[1].0.into_float_value(),
|
||||
"gt_f64",
|
||||
);
|
||||
|
||||
BasicValueEnum::IntValue(bool_val)
|
||||
}
|
||||
Symbol::INT_LTE | Symbol::NUM_LTE => {
|
||||
debug_assert!(args.len() == 2);
|
||||
|
||||
let bool_val = env.builder.build_int_compare(
|
||||
IntPredicate::SLE,
|
||||
args[0].0.into_int_value(),
|
||||
args[1].0.into_int_value(),
|
||||
"lte_i64",
|
||||
);
|
||||
|
||||
BasicValueEnum::IntValue(bool_val)
|
||||
}
|
||||
Symbol::FLOAT_LTE => {
|
||||
debug_assert!(args.len() == 2);
|
||||
|
||||
let bool_val = env.builder.build_float_compare(
|
||||
FloatPredicate::OLE,
|
||||
args[0].0.into_float_value(),
|
||||
args[1].0.into_float_value(),
|
||||
"lte_f64",
|
||||
);
|
||||
|
||||
BasicValueEnum::IntValue(bool_val)
|
||||
}
|
||||
Symbol::INT_LT | Symbol::NUM_LT => {
|
||||
debug_assert!(args.len() == 2);
|
||||
|
||||
let bool_val = env.builder.build_int_compare(
|
||||
IntPredicate::SLT,
|
||||
args[0].0.into_int_value(),
|
||||
args[1].0.into_int_value(),
|
||||
"lt_i64",
|
||||
);
|
||||
|
||||
BasicValueEnum::IntValue(bool_val)
|
||||
}
|
||||
Symbol::FLOAT_LT => {
|
||||
debug_assert!(args.len() == 2);
|
||||
|
||||
let bool_val = env.builder.build_float_compare(
|
||||
FloatPredicate::OLT,
|
||||
args[0].0.into_float_value(),
|
||||
args[1].0.into_float_value(),
|
||||
"lt_f64",
|
||||
);
|
||||
|
||||
BasicValueEnum::IntValue(bool_val)
|
||||
}
|
||||
Symbol::NUM_MUL => {
|
||||
debug_assert!(args.len() == 2);
|
||||
|
|
|
@ -172,6 +172,70 @@ mod gen_builtins {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lt_i64() {
|
||||
assert_evals_to!("1 < 2", true, bool);
|
||||
assert_evals_to!("1 < 1", false, bool);
|
||||
assert_evals_to!("2 < 1", false, bool);
|
||||
assert_evals_to!("0 < 0", false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lte_i64() {
|
||||
assert_evals_to!("1 <= 1", true, bool);
|
||||
assert_evals_to!("2 <= 1", false, bool);
|
||||
assert_evals_to!("1 <= 2", true, bool);
|
||||
assert_evals_to!("0 <= 0", true, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gt_i64() {
|
||||
assert_evals_to!("2 > 1", true, bool);
|
||||
assert_evals_to!("2 > 2", false, bool);
|
||||
assert_evals_to!("1 > 1", false, bool);
|
||||
assert_evals_to!("0 > 0", false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gte_i64() {
|
||||
assert_evals_to!("1 >= 1", true, bool);
|
||||
assert_evals_to!("1 >= 2", false, bool);
|
||||
assert_evals_to!("2 >= 1", true, bool);
|
||||
assert_evals_to!("0 >= 0", true, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lt_f64() {
|
||||
assert_evals_to!("1.1 < 1.2", true, bool);
|
||||
assert_evals_to!("1.1 < 1.1", false, bool);
|
||||
assert_evals_to!("1.2 < 1.1", false, bool);
|
||||
assert_evals_to!("0.0 < 0.0", false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lte_f64() {
|
||||
assert_evals_to!("1.1 <= 1.1", true, bool);
|
||||
assert_evals_to!("1.2 <= 1.1", false, bool);
|
||||
assert_evals_to!("1.1 <= 1.2", true, bool);
|
||||
assert_evals_to!("0.0 <= 0.0", true, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gt_f64() {
|
||||
assert_evals_to!("2.2 > 1.1", true, bool);
|
||||
assert_evals_to!("2.2 > 2.2", false, bool);
|
||||
assert_evals_to!("1.1 > 2.2", false, bool);
|
||||
assert_evals_to!("0.0 > 0.0", false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gte_f64() {
|
||||
assert_evals_to!("1.1 >= 1.1", true, bool);
|
||||
assert_evals_to!("1.1 >= 1.2", false, bool);
|
||||
assert_evals_to!("1.2 >= 1.1", true, bool);
|
||||
assert_evals_to!("0.0 >= 0.0", true, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gen_order_of_arithmetic_ops() {
|
||||
assert_evals_to!(
|
||||
|
|
|
@ -581,9 +581,9 @@ define_builtins! {
|
|||
5 NUM_SUB: "sub"
|
||||
6 NUM_MUL: "mul"
|
||||
7 NUM_LT: "isLt"
|
||||
8 NUM_LE: "isLte"
|
||||
8 NUM_LTE: "isLte"
|
||||
9 NUM_GT: "isGt"
|
||||
10 NUM_GE: "isGte"
|
||||
10 NUM_GTE: "isGte"
|
||||
11 NUM_TO_FLOAT: "toFloat"
|
||||
}
|
||||
2 INT: "Int" => {
|
||||
|
@ -600,6 +600,10 @@ define_builtins! {
|
|||
10 INT_EQ_I1: "#eqi1" // Equality on boolean (theoretically i1) values
|
||||
11 INT_EQ_I8: "#eqi8" // Equality on byte (theoretically i8) values
|
||||
12 INT_DIV_UNSAFE: "divUnsafe" // TODO remove once we can code gen Result
|
||||
13 INT_LT: "#lt"
|
||||
14 INT_LTE: "#lte"
|
||||
15 INT_GT: "#gt"
|
||||
16 INT_GTE: "#gte"
|
||||
}
|
||||
3 FLOAT: "Float" => {
|
||||
0 FLOAT_FLOAT: "Float" imported // the Float.Float type alias
|
||||
|
@ -614,6 +618,10 @@ define_builtins! {
|
|||
9 FLOAT_SUB: "#sub"
|
||||
10 FLOAT_EQ: "#eq"
|
||||
11 FLOAT_ROUND: "round"
|
||||
12 FLOAT_LT: "#lt"
|
||||
13 FLOAT_LTE: "#lte"
|
||||
14 FLOAT_GT: "#gt"
|
||||
15 FLOAT_GTE: "#gte"
|
||||
}
|
||||
4 BOOL: "Bool" => {
|
||||
0 BOOL_BOOL: "Bool" imported // the Bool.Bool type alias
|
||||
|
|
|
@ -499,6 +499,22 @@ fn from_can<'a>(
|
|||
FloatType => Symbol::FLOAT_SUB,
|
||||
IntType => Symbol::INT_SUB,
|
||||
},
|
||||
Symbol::NUM_LTE => match to_int_or_float(env.subs, loc_args[0].0) {
|
||||
FloatType => Symbol::FLOAT_LTE,
|
||||
IntType => Symbol::INT_LTE,
|
||||
},
|
||||
Symbol::NUM_LT => match to_int_or_float(env.subs, loc_args[0].0) {
|
||||
FloatType => Symbol::FLOAT_LT,
|
||||
IntType => Symbol::INT_LT,
|
||||
},
|
||||
Symbol::NUM_GTE => match to_int_or_float(env.subs, loc_args[0].0) {
|
||||
FloatType => Symbol::FLOAT_GTE,
|
||||
IntType => Symbol::INT_GTE,
|
||||
},
|
||||
Symbol::NUM_GT => match to_int_or_float(env.subs, loc_args[0].0) {
|
||||
FloatType => Symbol::FLOAT_GT,
|
||||
IntType => Symbol::INT_GT,
|
||||
},
|
||||
// TODO make this work for more than just int/float
|
||||
Symbol::BOOL_EQ => {
|
||||
match Layout::from_var(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue