Support bitwise operations Add support for `~`, `&`, `|`, `^`, `<<`, `>>` bitwise operations. Implements: https://github.com/bazelbuild/starlark/issues/20#issuecomment-456647994 Closes #8903. PiperOrigin-RevId: 259732302
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java b/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java index d199a91..544a583 100644 --- a/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java +++ b/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTest.java
@@ -62,7 +62,7 @@ .testStatement("8 % 3", 2) .testIfErrorContains("unsupported operand type(s) for %: 'int' and 'string'", "3 % 'foo'") .testStatement("-5", -5) - .testIfErrorContains("unsupported operand type for -: 'string'", "-'foo'"); + .testIfErrorContains("unsupported unary operation: -string", "-'foo'"); } @Test
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/ParserTest.java b/src/test/java/com/google/devtools/build/lib/syntax/ParserTest.java index bc4d8cc..2e14cb8 100644 --- a/src/test/java/com/google/devtools/build/lib/syntax/ParserTest.java +++ b/src/test/java/com/google/devtools/build/lib/syntax/ParserTest.java
@@ -473,6 +473,10 @@ assertThat(parseFile("x *= 1").toString()).isEqualTo("[x *= 1\n]"); assertThat(parseFile("x /= 1").toString()).isEqualTo("[x /= 1\n]"); assertThat(parseFile("x %= 1").toString()).isEqualTo("[x %= 1\n]"); + assertThat(parseFile("x |= 1").toString()).isEqualTo("[x |= 1\n]"); + assertThat(parseFile("x &= 1").toString()).isEqualTo("[x &= 1\n]"); + assertThat(parseFile("x <<= 1").toString()).isEqualTo("[x <<= 1\n]"); + assertThat(parseFile("x >>= 1").toString()).isEqualTo("[x >>= 1\n]"); } @Test
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java index 87ba491..a0f9cab 100644 --- a/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java +++ b/src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java
@@ -1504,7 +1504,7 @@ new SkylarkTest("--incompatible_depset_union=false") .testStatement("str(depset([1, 3]) | depset([1, 2]))", "depset([1, 2, 3])") .testStatement("str(depset([1, 2]) | [1, 3])", "depset([1, 2, 3])") - .testIfExactError("unsupported operand type(s) for |: 'int' and 'int'", "2 | 4"); + .testIfExactError("unsupported operand type(s) for |: 'int' and 'bool'", "2 | False"); } @Test
diff --git a/src/test/starlark/testdata/int.sky b/src/test/starlark/testdata/int.sky index 91212da..d4710cf 100644 --- a/src/test/starlark/testdata/int.sky +++ b/src/test/starlark/testdata/int.sky
@@ -73,3 +73,66 @@ 1 // 0 ### integer division by zero --- 1 % 0 ### integer modulo by zero +--- + +# bitwise + +def f(): + x = 2 + x &= 1 + assert_eq(x, 0) + x = 0 + x |= 2 + assert_eq(x, 2) + x ^= 3 + assert_eq(x, 1) + x <<= 2 + assert_eq(x, 4) + x >>=2 + assert_eq(x, 1) + +f() +--- +assert_eq(1 | 2, 3) +assert_eq(3 | 6, 7) +assert_eq(7 | 0, 7) +assert_eq(7 & 0, 0) +assert_eq(7 & 7, 7) +assert_eq(7 & 2, 2) +assert_eq((1|2) & (2|4), 2) +assert_eq(1 ^ 2, 3) +assert_eq(2 ^ 2, 0) +assert_eq(-6 ^ 0, -6) +assert_eq(1 | 0 ^ 1, 1) # check | and ^ operators precedence +assert_eq(~1, -2) +assert_eq(~-2, 1) +assert_eq(~0, -1) +assert_eq(~6, -7) +assert_eq(~0, -1) +assert_eq(~2147483647, -2147483647 - 1); +assert_eq(1 << 2, 4) +assert_eq(7 << 0, 7) +assert_eq(-1 << 31, -2147483647 - 1) +assert_eq(2 >> 1, 1) +assert_eq(7 >> 0, 7) +assert_eq(0 >> 0, 0) +assert_eq(1000 >> 100, 0) +assert_eq(-10 >> 1000, -1) + +# precedence + +assert_eq(8 | 3 ^ 4 & -2, 15) +assert_eq(~8 >> 1 | 3 ^ 4 & -2 << 2 * 3 + 4 // -2, -5) + +--- +1 & False ### unsupported operand type(s) for &: 'int' and 'bool' +--- +"a" ^ 5 ### unsupported operand type(s) for ^: 'string' and 'int' +--- +~False ### unsupported unary operation: ~bool +--- +1 << 31 ### integer overflow +--- +1 << -4 ### negative shift count: -4 +--- +2 >> -1 ### negative shift count: -1