diff --git a/CHANGELOG.md b/CHANGELOG.md index bea380fc63..1587e0c0c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ #### :rocket: New Feature - Add shift (`<<`, `>>`, `>>>`) operators for `int` and `bigint`. https://github.com/rescript-lang/rescript/pull/7183 +- Add bitwise AND (`&`) operator for `int` and `bigint`. https://github.com/rescript-lang/rescript/pull/7415 - Significantly reduced the download size by splitting binaries into optional platform-specific dependencies (e.g, `@rescript/linux-x64`). https://github.com/rescript-lang/rescript/pull/7395 #### :bug: Bug fix diff --git a/compiler/ml/unified_ops.ml b/compiler/ml/unified_ops.ml index 25f19c1ade..2b0bd4e59c 100644 --- a/compiler/ml/unified_ops.ml +++ b/compiler/ml/unified_ops.ml @@ -207,6 +207,19 @@ let entries = string = None; }; }; + { + path = builtin "&"; + name = "%bitand"; + form = Binary; + specialization = + { + int = Pandint; + bool = None; + float = None; + bigint = Some Pandbigint; + string = None; + }; + }; { path = builtin "^"; name = "%bitxor"; diff --git a/compiler/syntax/src/res_parsetree_viewer.ml b/compiler/syntax/src/res_parsetree_viewer.ml index b2d6444e59..451e879862 100644 --- a/compiler/syntax/src/res_parsetree_viewer.ml +++ b/compiler/syntax/src/res_parsetree_viewer.ml @@ -273,12 +273,13 @@ let operator_precedence operator = | "||" -> 2 | "&&" -> 3 | "^" -> 4 - | "==" | "===" | "<" | ">" | "!=" | "<>" | "!==" | "<=" | ">=" | "|>" -> 5 - | "<<" | ">>" | ">>>" -> 6 - | "+" | "+." | "-" | "-." | "++" -> 7 - | "*" | "*." | "/" | "/." | "%" -> 8 - | "**" -> 9 - | "#" | "##" | "->" -> 10 + | "&" -> 5 + | "==" | "===" | "<" | ">" | "!=" | "<>" | "!==" | "<=" | ">=" | "|>" -> 6 + | "<<" | ">>" | ">>>" -> 7 + | "+" | "+." | "-" | "-." | "++" -> 8 + | "*" | "*." | "/" | "/." | "%" -> 9 + | "**" -> 10 + | "#" | "##" | "->" -> 11 | _ -> 0 let is_unary_operator operator = @@ -301,7 +302,7 @@ let is_binary_operator operator = match operator with | ":=" | "||" | "&&" | "==" | "===" | "<" | ">" | "!=" | "!==" | "<=" | ">=" | "|>" | "+" | "+." | "-" | "-." | "++" | "*" | "*." | "/" | "/." | "**" - | "->" | "<>" | "%" | "^" | "<<" | ">>" | ">>>" -> + | "->" | "<>" | "%" | "&" | "^" | "<<" | ">>" | ">>>" -> true | _ -> false diff --git a/compiler/syntax/src/res_token.ml b/compiler/syntax/src/res_token.ml index f3e8ad1cbc..9aa63a1716 100644 --- a/compiler/syntax/src/res_token.ml +++ b/compiler/syntax/src/res_token.ml @@ -107,15 +107,16 @@ let precedence = function | Lor -> 2 | Land -> 3 | Caret -> 4 + | Band -> 5 | Equal | EqualEqual | EqualEqualEqual | LessThan | GreaterThan | BangEqual | BangEqualEqual | LessEqual | GreaterEqual | BarGreater -> - 5 - | LeftShift | RightShift | RightShiftUnsigned -> 6 - | Plus | PlusDot | Minus | MinusDot | PlusPlus -> 7 - | Asterisk | AsteriskDot | Forwardslash | ForwardslashDot | Percent -> 8 - | Exponentiation -> 9 - | MinusGreater -> 10 - | Dot -> 11 + 6 + | LeftShift | RightShift | RightShiftUnsigned -> 7 + | Plus | PlusDot | Minus | MinusDot | PlusPlus -> 8 + | Asterisk | AsteriskDot | Forwardslash | ForwardslashDot | Percent -> 9 + | Exponentiation -> 10 + | MinusGreater -> 11 + | Dot -> 12 | _ -> 0 let to_string = function diff --git a/runtime/Pervasives.res b/runtime/Pervasives.res index 1edd2cc01c..bdeb7d8f23 100644 --- a/runtime/Pervasives.res +++ b/runtime/Pervasives.res @@ -68,6 +68,7 @@ external \"%": ('a, 'a) => 'a = "%mod" external \"<<": ('a, 'a) => 'a = "%lsl" external mod: ('a, 'a) => 'a = "%mod" external \"**": ('a, 'a) => 'a = "%pow" +external \"&": ('a, 'a) => 'a = "%bitand" external \"^": ('a, 'a) => 'a = "%bitxor" external \">>": ('a, 'a) => 'a = "%asr" external \">>>": ('a, 'a) => 'a = "%lsr" diff --git a/tests/syntax_tests/data/parsing/grammar/expressions/binary.res b/tests/syntax_tests/data/parsing/grammar/expressions/binary.res index 92eae96eb8..5cc0a02871 100644 --- a/tests/syntax_tests/data/parsing/grammar/expressions/binary.res +++ b/tests/syntax_tests/data/parsing/grammar/expressions/binary.res @@ -29,6 +29,7 @@ let x = a + -1 + -2 let x = a + @attr -1 + @attr -2 let x = a % a == 0 let x = a ^ a == 0 +let x = a & a == 0 let x = a << a == 0 let x = a >> a == 0 let x = a >>> a == 0 diff --git a/tests/syntax_tests/data/parsing/grammar/expressions/expected/binary.res.txt b/tests/syntax_tests/data/parsing/grammar/expressions/expected/binary.res.txt index 7f85025c99..2fe0214e9a 100644 --- a/tests/syntax_tests/data/parsing/grammar/expressions/expected/binary.res.txt +++ b/tests/syntax_tests/data/parsing/grammar/expressions/expected/binary.res.txt @@ -15,6 +15,7 @@ let x = (a + (-1)) + (-2) let x = (a + (((-1))[@attr ])) + (((-2))[@attr ]) let x = (a % a) == 0 let x = a ^ (a == 0) +let x = a & (a == 0) let x = (a << a) == 0 let x = (a >> a) == 0 let x = (a >>> a) == 0 diff --git a/tests/syntax_tests/data/printer/expr/binary.res b/tests/syntax_tests/data/printer/expr/binary.res index b36e4a70fc..ffc7f666e3 100644 --- a/tests/syntax_tests/data/printer/expr/binary.res +++ b/tests/syntax_tests/data/printer/expr/binary.res @@ -50,11 +50,11 @@ let () = x.left = value |> logMutation let () = x.left = (value |> process) |> x.right = value |> process let () = (x: int) |> (print_int: int => unit) -// math x + y / z x / y + z x % y * z x ^ y + z +x & y + z x << y + z x >> y + z x >>> y + z diff --git a/tests/syntax_tests/data/printer/expr/expected/binary.res.txt b/tests/syntax_tests/data/printer/expr/expected/binary.res.txt index e1918cd184..8be085d480 100644 --- a/tests/syntax_tests/data/printer/expr/expected/binary.res.txt +++ b/tests/syntax_tests/data/printer/expr/expected/binary.res.txt @@ -81,11 +81,11 @@ let () = x.left = logMutation(value) let () = x.left = (x.right = process(value))(process(value)) let () = (print_int: int => unit)((x: int)) -// math x + y / z x / y + z x % y * z x ^ y + z +x & y + z x << y + z x >> y + z x >>> y + z diff --git a/tests/tests/src/unified_ops_test.mjs b/tests/tests/src/unified_ops_test.mjs index 5cae89378f..d1479454a6 100644 --- a/tests/tests/src/unified_ops_test.mjs +++ b/tests/tests/src/unified_ops_test.mjs @@ -75,6 +75,14 @@ function bxor_bigint(a, b) { return a ^ b; } +function band_int(a, b) { + return a & b; +} + +function band_bigint(a, b) { + return a & b; +} + let bigintShiftLeft = (1n << 2n); let bigintShiftRight = (8n >> 2n); @@ -111,6 +119,8 @@ export { pow_overflow, bxor_int, bxor_bigint, + band_int, + band_bigint, intShiftLeft, intShiftRight, intShiftRightUnsigned, diff --git a/tests/tests/src/unified_ops_test.res b/tests/tests/src/unified_ops_test.res index 6d814f0a23..765919c9c0 100644 --- a/tests/tests/src/unified_ops_test.res +++ b/tests/tests/src/unified_ops_test.res @@ -30,6 +30,9 @@ let pow_overflow = 2147483647 ** 2 let bxor_int = (a, b) => a ^ b let bxor_bigint = (a: bigint, b) => a ^ b +let band_int = (a, b) => a & b +let band_bigint = (a: bigint, b) => a & b + let intShiftLeft = 1 << 2 let intShiftRight = 8 >> 2 let intShiftRightUnsigned = -2 >>> 1