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