add bitwise xor

This commit is contained in:
Sébastien Besnier 2021-01-14 16:12:46 +01:00
parent c4e5af554b
commit fdc2b6ad86
9 changed files with 59 additions and 14 deletions

View file

@ -260,6 +260,17 @@ mod repl_eval {
expect_success("Num.bitwiseAnd 200 0", "0 : Int *") expect_success("Num.bitwiseAnd 200 0", "0 : Int *")
} }
#[test]
fn num_bitwise_xor() {
expect_success("Num.bitwiseXor 20 20", "0 : Int *");
expect_success("Num.bitwiseXor 15 14", "1 : Int *");
expect_success("Num.bitwiseXor 7 15", "8 : Int *");
expect_success("Num.bitwiseXor 200 0", "200 : Int *")
}
#[test] #[test]
fn num_add_wrap() { fn num_add_wrap() {
expect_success("Num.addWrap Num.maxInt 1", "-9223372036854775808 : Int *"); expect_success("Num.addWrap Num.maxInt 1", "-9223372036854775808 : Int *");

View file

@ -291,6 +291,15 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
), ),
); );
// bitwiseXor : Int a, Int a -> Int a
add_type(
Symbol::NUM_BITWISE_XOR,
top_level_function(
vec![int_type(flex(TVAR1)), int_type(flex(TVAR1))],
Box::new(int_type(flex(TVAR1))),
),
);
// rem : Int a, Int a -> Result (Int a) [ DivByZero ]* // rem : Int a, Int a -> Result (Int a) [ DivByZero ]*
add_type( add_type(
Symbol::NUM_REM, Symbol::NUM_REM,

View file

@ -294,6 +294,15 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
) )
}); });
// bitwiseAnd : Attr * Int, Attr * Int -> Attr * Int
add_type(Symbol::NUM_BITWISE_XOR, {
let_tvars! { star1, star2, star3, int };
unique_function(
vec![int_type(star1, int), int_type(star2, int)],
int_type(star3, int),
)
});
// divFloat : Float, Float -> Float // divFloat : Float, Float -> Float
add_type(Symbol::NUM_DIV_FLOAT, { add_type(Symbol::NUM_DIV_FLOAT, {
let_tvars! { star1, star2, star3, star4, star5}; let_tvars! { star1, star2, star3, star4, star5};

View file

@ -117,7 +117,8 @@ pub fn builtin_defs_map(symbol: Symbol, var_store: &mut VarStore) -> Option<Def>
NUM_ASIN => num_asin, NUM_ASIN => num_asin,
NUM_MAX_INT => num_max_int, NUM_MAX_INT => num_max_int,
NUM_MIN_INT => num_min_int, NUM_MIN_INT => num_min_int,
NUM_BITWISE_AND => num_bitwise_and NUM_BITWISE_AND => num_bitwise_and,
NUM_BITWISE_XOR => num_bitwise_xor
} }
} }
@ -1153,6 +1154,11 @@ fn num_bitwise_and(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_binop(symbol, var_store, LowLevel::NumBitwiseAnd) num_binop(symbol, var_store, LowLevel::NumBitwiseAnd)
} }
/// Num.bitwiseXor : Int, Int -> Int
fn num_bitwise_xor(symbol: Symbol, var_store: &mut VarStore) -> Def {
num_binop(symbol, var_store, LowLevel::NumBitwiseXor)
}
/// List.isEmpty : List * -> Bool /// List.isEmpty : List * -> Bool
fn list_is_empty(symbol: Symbol, var_store: &mut VarStore) -> Def { fn list_is_empty(symbol: Symbol, var_store: &mut VarStore) -> Def {
let list_var = var_store.fresh(); let list_var = var_store.fresh();

View file

@ -3346,7 +3346,7 @@ fn run_low_level<'a, 'ctx, 'env>(
build_num_binop(env, parent, lhs_arg, lhs_layout, rhs_arg, rhs_layout, op) build_num_binop(env, parent, lhs_arg, lhs_layout, rhs_arg, rhs_layout, op)
} }
NumBitwiseAnd => { NumBitwiseAnd | NumBitwiseXor => {
debug_assert_eq!(args.len(), 2); debug_assert_eq!(args.len(), 2);
let (lhs_arg, lhs_layout) = load_symbol_and_layout(env, scope, &args[0]); let (lhs_arg, lhs_layout) = load_symbol_and_layout(env, scope, &args[0]);
@ -3633,6 +3633,7 @@ fn build_int_binop<'a, 'ctx, 'env>(
NumDivUnchecked => bd.build_int_signed_div(lhs, rhs, "div_int").into(), NumDivUnchecked => bd.build_int_signed_div(lhs, rhs, "div_int").into(),
NumPowInt => call_bitcode_fn(env, &[lhs.into(), rhs.into()], &bitcode::NUM_POW_INT), NumPowInt => call_bitcode_fn(env, &[lhs.into(), rhs.into()], &bitcode::NUM_POW_INT),
NumBitwiseAnd => bd.build_and(lhs, rhs, "int_bitwise_and").into(), NumBitwiseAnd => bd.build_and(lhs, rhs, "int_bitwise_and").into(),
NumBitwiseXor => bd.build_xor(lhs, rhs, "int_bitwise_xor").into(),
_ => { _ => {
unreachable!("Unrecognized int binary operation: {:?}", op); unreachable!("Unrecognized int binary operation: {:?}", op);
} }

View file

@ -757,6 +757,14 @@ mod gen_num {
assert_evals_to!("Num.bitwiseAnd 200 0", 0, i64); assert_evals_to!("Num.bitwiseAnd 200 0", 0, i64);
} }
#[test]
fn bitwise_xor() {
assert_evals_to!("Num.bitwiseXor 20 20", 0, i64);
assert_evals_to!("Num.bitwiseXor 15 14", 1, i64);
assert_evals_to!("Num.bitwiseXor 7 15", 8, i64);
assert_evals_to!("Num.bitwiseXor 200 0", 200, i64);
}
#[test] #[test]
fn lt_i64() { fn lt_i64() {
assert_evals_to!("1 < 2", true, bool); assert_evals_to!("1 < 2", true, bool);

View file

@ -59,6 +59,7 @@ pub enum LowLevel {
NumAcos, NumAcos,
NumAsin, NumAsin,
NumBitwiseAnd, NumBitwiseAnd,
NumBitwiseXor,
Eq, Eq,
NotEq, NotEq,
And, And,

View file

@ -823,15 +823,16 @@ define_builtins! {
79 NUM_AT_BINARY32: "@Binary32" 79 NUM_AT_BINARY32: "@Binary32"
80 NUM_BINARY32: "Binary32" imported 80 NUM_BINARY32: "Binary32" imported
81 NUM_BITWISE_AND: "bitwiseAnd" 81 NUM_BITWISE_AND: "bitwiseAnd"
82 NUM_SUB_WRAP: "subWrap" 82 NUM_BITWISE_XOR: "bitwiseXor"
83 NUM_SUB_CHECKED: "subChecked" 83 NUM_SUB_WRAP: "subWrap"
84 NUM_MUL_WRAP: "mulWrap" 84 NUM_SUB_CHECKED: "subChecked"
85 NUM_MUL_CHECKED: "mulChecked" 85 NUM_MUL_WRAP: "mulWrap"
86 NUM_INT: "Int" imported 86 NUM_MUL_CHECKED: "mulChecked"
87 NUM_FLOAT: "Float" imported 87 NUM_INT: "Int" imported
88 NUM_AT_NATURAL: "@Natural" 88 NUM_FLOAT: "Float" imported
89 NUM_NATURAL: "Natural" imported 89 NUM_AT_NATURAL: "@Natural"
90 NUM_NAT: "Nat" imported 90 NUM_NATURAL: "Natural" imported
91 NUM_NAT: "Nat" imported
} }
2 BOOL: "Bool" => { 2 BOOL: "Bool" => {
0 BOOL_BOOL: "Bool" imported // the Bool.Bool type alias 0 BOOL_BOOL: "Bool" imported // the Bool.Bool type alias

View file

@ -578,9 +578,8 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
Eq | NotEq | And | Or | NumAdd | NumAddWrap | NumAddChecked | NumSub | NumSubWrap Eq | NotEq | And | Or | NumAdd | NumAddWrap | NumAddChecked | NumSub | NumSubWrap
| NumSubChecked | NumMul | NumMulWrap | NumMulChecked | NumGt | NumGte | NumLt | NumLte | NumSubChecked | NumMul | NumMulWrap | NumMulChecked | NumGt | NumGte | NumLt | NumLte
| NumCompare | NumDivUnchecked | NumRemUnchecked | NumPow | NumPowInt | NumBitwiseAnd => { | NumCompare | NumDivUnchecked | NumRemUnchecked | NumPow | NumPowInt | NumBitwiseAnd
arena.alloc_slice_copy(&[irrelevant, irrelevant]) | NumBitwiseXor => arena.alloc_slice_copy(&[irrelevant, irrelevant]),
}
NumAbs | NumNeg | NumSin | NumCos | NumSqrtUnchecked | NumRound | NumCeiling | NumFloor NumAbs | NumNeg | NumSin | NumCos | NumSqrtUnchecked | NumRound | NumCeiling | NumFloor
| NumToFloat | Not | NumIsFinite | NumAtan | NumAcos | NumAsin => { | NumToFloat | Not | NumIsFinite | NumAtan | NumAcos | NumAsin => {