diff --git a/compiler/gen/src/crane/build.rs b/compiler/gen/src/crane/build.rs index 090f46b780..b1112b1d4e 100644 --- a/compiler/gen/src/crane/build.rs +++ b/compiler/gen/src/crane/build.rs @@ -576,7 +576,7 @@ fn call_by_name<'a, B: Backend>( builder.ins().ineg(num) } - Symbol::INT_EQ => { + Symbol::INT_EQ_I64 | Symbol::INT_EQ_I8 | Symbol::INT_EQ_I1 => { debug_assert!(args.len() == 2); let a = build_arg(&args[0], env, scope, module, builder, procs); let b = build_arg(&args[1], env, scope, module, builder, procs); diff --git a/compiler/gen/src/llvm/build.rs b/compiler/gen/src/llvm/build.rs index b75379c804..600672945a 100644 --- a/compiler/gen/src/llvm/build.rs +++ b/compiler/gen/src/llvm/build.rs @@ -46,6 +46,7 @@ pub fn build_expr<'a, 'ctx, 'env>( Int(num) => env.context.i64_type().const_int(*num as u64, true).into(), Float(num) => env.context.f64_type().const_float(*num).into(), Bool(b) => env.context.bool_type().const_int(*b as u64, false).into(), + Byte(b) => env.context.i8_type().const_int(*b as u64, false).into(), Cond { cond, pass, @@ -513,6 +514,7 @@ pub fn verify_fn(fn_val: FunctionValue<'_>) { } #[inline(always)] +#[allow(clippy::cognitive_complexity)] fn call_with_args<'a, 'ctx, 'env>( symbol: Symbol, args: &[BasicValueEnum<'ctx>], @@ -583,7 +585,7 @@ fn call_with_args<'a, 'ctx, 'env>( BasicValueEnum::IntValue(int_val) } - Symbol::INT_EQ => { + Symbol::INT_EQ_I64 => { debug_assert!(args.len() == 2); let int_val = env.builder.build_int_compare( @@ -595,6 +597,30 @@ fn call_with_args<'a, 'ctx, 'env>( BasicValueEnum::IntValue(int_val) } + Symbol::INT_EQ_I1 => { + debug_assert!(args.len() == 2); + + let int_val = env.builder.build_int_compare( + IntPredicate::EQ, + args[0].into_int_value(), + args[1].into_int_value(), + "cmp_i1", + ); + + BasicValueEnum::IntValue(int_val) + } + Symbol::INT_EQ_I8 => { + debug_assert!(args.len() == 2); + + let int_val = env.builder.build_int_compare( + IntPredicate::EQ, + args[0].into_int_value(), + args[1].into_int_value(), + "cmp_i8", + ); + + BasicValueEnum::IntValue(int_val) + } Symbol::FLOAT_EQ => { debug_assert!(args.len() == 2); diff --git a/compiler/gen/tests/test_gen.rs b/compiler/gen/tests/test_gen.rs index 918927d3bc..f1c4a69c13 100644 --- a/compiler/gen/tests/test_gen.rs +++ b/compiler/gen/tests/test_gen.rs @@ -970,6 +970,27 @@ mod test_gen { ); } + #[test] + fn basic_enum() { + assert_evals_to!( + indoc!( + r#" + Fruit : [ Apple, Orange, Banana ] + + apple : Fruit + apple = Apple + + orange : Fruit + orange = Orange + + apple == orange + "# + ), + false, + bool + ); + } + // #[test] // fn basic_record() { // assert_evals_to!( diff --git a/compiler/module/src/symbol.rs b/compiler/module/src/symbol.rs index 6ba11959e0..fe26b534fd 100644 --- a/compiler/module/src/symbol.rs +++ b/compiler/module/src/symbol.rs @@ -591,7 +591,9 @@ define_builtins! { 6 INT_LOWEST: "lowest" 7 INT_ADD: "#add" 8 INT_SUB: "#sub" - 9 INT_EQ: "#eq" + 9 INT_EQ_I64: "#eqi64" // Equality on 64-bit integers, the standard in Roc + 10 INT_EQ_I1: "#eqi1" // Equality on boolean (theoretically i1) values + 11 INT_EQ_I8: "#eqi8" // Equality on byte (theoretically i8) values } 3 FLOAT: "Float" => { 0 FLOAT_FLOAT: "Float" imported // the Float.Float type alias diff --git a/compiler/mono/src/expr.rs b/compiler/mono/src/expr.rs index aec5c87247..6764b6f988 100644 --- a/compiler/mono/src/expr.rs +++ b/compiler/mono/src/expr.rs @@ -497,9 +497,11 @@ fn from_can<'a>( match Layout::from_var(env.arena, loc_args[0].0, env.subs, env.pointer_size) { Ok(Layout::Builtin(builtin)) => match builtin { - Builtin::Int64 => Symbol::INT_EQ, + Builtin::Int64 => Symbol::INT_EQ_I64, Builtin::Float64 => Symbol::FLOAT_EQ, - _ => panic!("Equality not unimplemented for {:?}", builtin), + Builtin::Bool(_, _) => Symbol::INT_EQ_I1, + Builtin::Byte(_) => Symbol::INT_EQ_I8, + _ => panic!("Equality not implemented for {:?}", builtin), }, Ok(complex) => panic!( "TODO support equality on complex layouts like {:?}", @@ -831,7 +833,9 @@ fn from_can_when<'a>( let (fn_symbol, builtin, cond_rhs_expr) = match to_int_or_float(env.subs, *var) { - IntOrFloat::IntType => (Symbol::INT_EQ, Builtin::Int64, Expr::Int(*num)), + IntOrFloat::IntType => { + (Symbol::INT_EQ_I64, Builtin::Int64, Expr::Int(*num)) + } IntOrFloat::FloatType => { (Symbol::FLOAT_EQ, Builtin::Float64, Expr::Float(*num as f64)) }