mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
Fix Num.toFloat
This commit is contained in:
parent
dd8dff0f9e
commit
30a95e90d1
5 changed files with 55 additions and 43 deletions
|
@ -77,6 +77,7 @@ pub fn builtin_defs(var_store: &mut VarStore) -> MutMap<Symbol, Def> {
|
||||||
Symbol::NUM_IS_ZERO => num_is_zero,
|
Symbol::NUM_IS_ZERO => num_is_zero,
|
||||||
Symbol::NUM_IS_POSITIVE => num_is_positive,
|
Symbol::NUM_IS_POSITIVE => num_is_positive,
|
||||||
Symbol::NUM_IS_NEGATIVE => num_is_negative,
|
Symbol::NUM_IS_NEGATIVE => num_is_negative,
|
||||||
|
Symbol::NUM_TO_FLOAT => num_to_float,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,12 +273,12 @@ fn num_tan(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
|
|
||||||
/// Num.isZero : Float -> Bool
|
/// Num.isZero : Float -> Bool
|
||||||
fn num_is_zero(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
fn num_is_zero(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let bool_var = var_store.fresh();
|
let arg_var = var_store.fresh();
|
||||||
let body = RunLowLevel {
|
let body = RunLowLevel {
|
||||||
op: LowLevel::Eq,
|
op: LowLevel::Eq,
|
||||||
args: vec![
|
args: vec![
|
||||||
(bool_var, Var(Symbol::ARG_1)),
|
(arg_var, Var(Symbol::ARG_1)),
|
||||||
(bool_var, Num(var_store.fresh(), 0)),
|
(arg_var, Num(var_store.fresh(), 0)),
|
||||||
],
|
],
|
||||||
ret_var: var_store.fresh(),
|
ret_var: var_store.fresh(),
|
||||||
};
|
};
|
||||||
|
@ -287,11 +288,12 @@ fn num_is_zero(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
|
|
||||||
/// Num.isNegative : Float -> Bool
|
/// Num.isNegative : Float -> Bool
|
||||||
fn num_is_negative(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
fn num_is_negative(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
|
let arg_var = var_store.fresh();
|
||||||
let body = RunLowLevel {
|
let body = RunLowLevel {
|
||||||
op: LowLevel::NumGt,
|
op: LowLevel::NumGt,
|
||||||
args: vec![
|
args: vec![
|
||||||
(var_store.fresh(), Num(var_store.fresh(), 0)),
|
(arg_var, Num(var_store.fresh(), 0)),
|
||||||
(var_store.fresh(), Var(Symbol::ARG_1)),
|
(arg_var, Var(Symbol::ARG_1)),
|
||||||
],
|
],
|
||||||
ret_var: var_store.fresh(),
|
ret_var: var_store.fresh(),
|
||||||
};
|
};
|
||||||
|
@ -301,11 +303,12 @@ fn num_is_negative(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
|
|
||||||
/// Num.isPositive : Float -> Bool
|
/// Num.isPositive : Float -> Bool
|
||||||
fn num_is_positive(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
fn num_is_positive(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
|
let arg_var = var_store.fresh();
|
||||||
let body = RunLowLevel {
|
let body = RunLowLevel {
|
||||||
op: LowLevel::NumGt,
|
op: LowLevel::NumGt,
|
||||||
args: vec![
|
args: vec![
|
||||||
(var_store.fresh(), Var(Symbol::ARG_1)),
|
(arg_var, Var(Symbol::ARG_1)),
|
||||||
(var_store.fresh(), Num(var_store.fresh(), 0)),
|
(arg_var, Num(var_store.fresh(), 0)),
|
||||||
],
|
],
|
||||||
ret_var: var_store.fresh(),
|
ret_var: var_store.fresh(),
|
||||||
};
|
};
|
||||||
|
@ -364,6 +367,17 @@ fn num_is_even(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
defn(symbol, vec![Symbol::ARG_1], var_store, body)
|
defn(symbol, vec![Symbol::ARG_1], var_store, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Num.toFloat : Num * -> Float
|
||||||
|
fn num_to_float(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
|
let body = RunLowLevel {
|
||||||
|
op: LowLevel::NumToFloat,
|
||||||
|
args: vec![(var_store.fresh(), Var(Symbol::ARG_1))],
|
||||||
|
ret_var: var_store.fresh(),
|
||||||
|
};
|
||||||
|
|
||||||
|
defn(symbol, vec![Symbol::ARG_1], var_store, body)
|
||||||
|
}
|
||||||
|
|
||||||
/// Num.sqrt : Float -> Result Float [ SqrtOfNegative ]*
|
/// Num.sqrt : Float -> Result Float [ SqrtOfNegative ]*
|
||||||
fn num_sqrt(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
fn num_sqrt(symbol: Symbol, var_store: &mut VarStore) -> Def {
|
||||||
let body = RunLowLevel {
|
let body = RunLowLevel {
|
||||||
|
|
|
@ -1021,31 +1021,6 @@ fn call_with_args<'a, 'ctx, 'env>(
|
||||||
args: &[(BasicValueEnum<'ctx>, &'a Layout<'a>)],
|
args: &[(BasicValueEnum<'ctx>, &'a Layout<'a>)],
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
match symbol {
|
match symbol {
|
||||||
Symbol::NUM_TO_FLOAT => {
|
|
||||||
// TODO specialize this to be not just for i64!
|
|
||||||
let builtin_fn_name = "i64_to_f64_";
|
|
||||||
|
|
||||||
let fn_val = env
|
|
||||||
.module
|
|
||||||
.get_function(builtin_fn_name)
|
|
||||||
.unwrap_or_else(|| panic!("Unrecognized builtin function: {:?} - if you're working on the Roc compiler, do you need to rebuild the bitcode? See compiler/builtins/bitcode/README.md", builtin_fn_name));
|
|
||||||
|
|
||||||
let mut arg_vals: Vec<BasicValueEnum> = Vec::with_capacity_in(args.len(), env.arena);
|
|
||||||
|
|
||||||
for (arg, _layout) in args.iter() {
|
|
||||||
arg_vals.push(*arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
let call = env
|
|
||||||
.builder
|
|
||||||
.build_call(fn_val, arg_vals.into_bump_slice(), "call_builtin");
|
|
||||||
|
|
||||||
call.set_call_convention(fn_val.get_call_conventions());
|
|
||||||
|
|
||||||
call.try_as_basic_value()
|
|
||||||
.left()
|
|
||||||
.unwrap_or_else(|| panic!("LLVM error: Invalid call for builtin {:?}", symbol))
|
|
||||||
}
|
|
||||||
Symbol::LIST_SINGLE => {
|
Symbol::LIST_SINGLE => {
|
||||||
// List.single : a -> List a
|
// List.single : a -> List a
|
||||||
debug_assert!(args.len() == 1);
|
debug_assert!(args.len() == 1);
|
||||||
|
@ -1399,7 +1374,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
BasicValueEnum::IntValue(answer)
|
BasicValueEnum::IntValue(answer)
|
||||||
}
|
}
|
||||||
NumAbs | NumNeg | NumRound | NumSqrt | NumSin | NumCos => {
|
NumAbs | NumNeg | NumRound | NumSqrt | NumSin | NumCos | NumToFloat => {
|
||||||
debug_assert_eq!(args.len(), 1);
|
debug_assert_eq!(args.len(), 1);
|
||||||
|
|
||||||
let arg = build_expr(env, layout_ids, scope, parent, &args[0].0);
|
let arg = build_expr(env, layout_ids, scope, parent, &args[0].0);
|
||||||
|
@ -1675,6 +1650,25 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
||||||
NumAbs => {
|
NumAbs => {
|
||||||
todo!("build_int_unary_op for integer absolute value. (possibly bitwise AND with 0b0111_1111_...)");
|
todo!("build_int_unary_op for integer absolute value. (possibly bitwise AND with 0b0111_1111_...)");
|
||||||
}
|
}
|
||||||
|
NumToFloat => {
|
||||||
|
// TODO specialize this to be not just for i64!
|
||||||
|
let builtin_fn_name = "i64_to_f64_";
|
||||||
|
|
||||||
|
let fn_val = env
|
||||||
|
.module
|
||||||
|
.get_function(builtin_fn_name)
|
||||||
|
.unwrap_or_else(|| panic!("Unrecognized builtin function: {:?} - if you're working on the Roc compiler, do you need to rebuild the bitcode? See compiler/builtins/bitcode/README.md", builtin_fn_name));
|
||||||
|
|
||||||
|
let call = env
|
||||||
|
.builder
|
||||||
|
.build_call(fn_val, &[arg.into()], "call_builtin");
|
||||||
|
|
||||||
|
call.set_call_convention(fn_val.get_call_conventions());
|
||||||
|
|
||||||
|
call.try_as_basic_value()
|
||||||
|
.left()
|
||||||
|
.unwrap_or_else(|| panic!("LLVM error: Invalid call for low-level op {:?}", op))
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!("Unrecognized int unary operation: {:?}", op);
|
unreachable!("Unrecognized int unary operation: {:?}", op);
|
||||||
}
|
}
|
||||||
|
@ -1698,6 +1692,7 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
|
||||||
NumRound => call_intrinsic(LLVM_LROUND_I64_F64, env, &[(arg.into(), arg_layout)]),
|
NumRound => call_intrinsic(LLVM_LROUND_I64_F64, env, &[(arg.into(), arg_layout)]),
|
||||||
NumSin => call_intrinsic(LLVM_SIN_F64, env, &[(arg.into(), arg_layout)]),
|
NumSin => call_intrinsic(LLVM_SIN_F64, env, &[(arg.into(), arg_layout)]),
|
||||||
NumCos => call_intrinsic(LLVM_COS_F64, env, &[(arg.into(), arg_layout)]),
|
NumCos => call_intrinsic(LLVM_COS_F64, env, &[(arg.into(), arg_layout)]),
|
||||||
|
NumToFloat => arg.into(), /* Converting from Float to Float is a no-op */
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!("Unrecognized int unary operation: {:?}", op);
|
unreachable!("Unrecognized int unary operation: {:?}", op);
|
||||||
}
|
}
|
||||||
|
|
|
@ -682,15 +682,17 @@ mod gen_builtins {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn int_to_float() {
|
fn int_to_float() {
|
||||||
assert_evals_to!(
|
assert_evals_to!("Num.toFloat 0x9", 9.0, f64);
|
||||||
indoc!(
|
}
|
||||||
r#"
|
|
||||||
Num.toFloat 0x9
|
#[test]
|
||||||
"#
|
fn num_to_float() {
|
||||||
),
|
assert_evals_to!("Num.toFloat 9", 9.0, f64);
|
||||||
9.0,
|
}
|
||||||
f64
|
|
||||||
);
|
#[test]
|
||||||
|
fn float_to_float() {
|
||||||
|
assert_evals_to!("Num.toFloat 0.5", 0.5, f64);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -23,6 +23,7 @@ pub enum LowLevel {
|
||||||
NumCos,
|
NumCos,
|
||||||
NumSqrt,
|
NumSqrt,
|
||||||
NumRound,
|
NumRound,
|
||||||
|
NumToFloat,
|
||||||
Eq,
|
Eq,
|
||||||
NotEq,
|
NotEq,
|
||||||
And,
|
And,
|
||||||
|
|
|
@ -757,7 +757,7 @@ fn annotate_low_level_usage(
|
||||||
|
|
||||||
NumAdd | NumSub | NumMul | NumGt | NumGte | NumLt | NumLte | NumAbs | NumNeg
|
NumAdd | NumSub | NumMul | NumGt | NumGte | NumLt | NumLte | NumAbs | NumNeg
|
||||||
| NumDivUnchecked | NumRemUnchecked | NumSqrt | NumRound | NumSin | NumCos | Eq | NotEq
|
| NumDivUnchecked | NumRemUnchecked | NumSqrt | NumRound | NumSin | NumCos | Eq | NotEq
|
||||||
| And | Or | Not => {
|
| And | Or | Not | NumToFloat => {
|
||||||
for (_, arg) in args {
|
for (_, arg) in args {
|
||||||
annotate_usage(&arg, usage);
|
annotate_usage(&arg, usage);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue