diff --git a/compiler/module/src/symbol.rs b/compiler/module/src/symbol.rs index dea7b585d6..4ab921501f 100644 --- a/compiler/module/src/symbol.rs +++ b/compiler/module/src/symbol.rs @@ -575,6 +575,7 @@ define_builtins! { 4 INT_MOD: "mod" 5 INT_HIGHEST: "highest" 6 INT_LOWEST: "lowest" + 7 INT_ADD: "add" } 3 FLOAT: "Float" => { 0 FLOAT_FLOAT: "Float" imported // the Float.Float type alias @@ -585,6 +586,7 @@ define_builtins! { 5 FLOAT_SQRT: "sqrt" 6 FLOAT_HIGHEST: "highest" 7 FLOAT_LOWEST: "lowest" + 8 FLOAT_ADD: "add" } 4 BOOL: "Bool" => { 0 BOOL_BOOL: "Bool" imported // the Bool.Bool type alias diff --git a/compiler/mono/src/expr.rs b/compiler/mono/src/expr.rs index d9b6c9a928..a45af92586 100644 --- a/compiler/mono/src/expr.rs +++ b/compiler/mono/src/expr.rs @@ -264,13 +264,23 @@ fn from_can<'a>( } Call(boxed, loc_args, _) => { - let (fn_var, loc_expr, _) = *boxed; + let (fn_var, loc_expr, ret_var) = *boxed; + + let specialize_builtin_functions = { + |symbol, subs: &Subs| match dbg!(symbol) { + Symbol::NUM_ADD => match to_int_or_float(subs, ret_var) { + IntOrFloat::FloatType => Symbol::FLOAT_ADD, + IntOrFloat::IntType => Symbol::INT_ADD, + }, + _ => symbol, + } + }; match from_can(env, loc_expr.value, procs, None) { Expr::Load(proc_name) => { // Some functions can potentially mutate in-place. // If we have one of those, switch to the in-place version if appropriate. - match proc_name { + match specialize_builtin_functions(proc_name, &env.subs) { Symbol::LIST_SET => { let subs = &env.subs; // The first arg is the one with the List in it. @@ -302,7 +312,9 @@ fn from_can<'a>( _ => call_by_name(env, procs, proc_name, loc_args), } } - _ => call_by_name(env, procs, proc_name, loc_args), + specialized_proc_symbol => { + call_by_name(env, procs, specialized_proc_symbol, loc_args) + } } } ptr => { diff --git a/compiler/mono/tests/test_mono.rs b/compiler/mono/tests/test_mono.rs index 04e8156933..47a7efedce 100644 --- a/compiler/mono/tests/test_mono.rs +++ b/compiler/mono/tests/test_mono.rs @@ -78,6 +78,49 @@ mod test_mono { compiles_to("0.5", Float(0.5)); } + #[test] + fn float_addition() { + compiles_to( + "3.0 + 4", + CallByName( + Symbol::FLOAT_ADD, + &[ + (Float(3.0), Layout::Builtin(Builtin::Float64)), + (Float(4.0), Layout::Builtin(Builtin::Float64)), + ], + ), + ); + } + + #[test] + fn int_addition() { + compiles_to( + "0xDEADBEEF + 4", + CallByName( + Symbol::INT_ADD, + &[ + (Int(3735928559), Layout::Builtin(Builtin::Int64)), + (Int(4), Layout::Builtin(Builtin::Int64)), + ], + ), + ); + } + + #[test] + fn num_addition() { + // Default to Int for `Num *` + compiles_to( + "3 + 5", + CallByName( + Symbol::INT_ADD, + &[ + (Int(3), Layout::Builtin(Builtin::Int64)), + (Int(5), Layout::Builtin(Builtin::Int64)), + ], + ), + ); + } + #[test] fn bool_literal() { let arena = Bump::new();