Build language supports list comparison.

--
MOS_MIGRATED_REVID=91289047
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java
index 210d1f5..6eaf45e 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java
@@ -62,8 +62,29 @@
     return lhs + " " + operator + " " + rhs;
   }
 
+  /**
+   * Compares two lists, following on Python semantics.
+   *
+   * <p>Elements are compared until two elements are not equal or we reach the end of a list.
+   */
+  private int compareLists(SkylarkList lval, SkylarkList rval) throws EvalException {
+    for (int i = 0; i < Math.min(lval.size(), rval.size()); i++) {
+      int cmp = compare(lval.get(i), rval.get(i));
+      if (cmp != 0) {
+        return cmp;
+      }
+    }
+    return Integer.compare(lval.size(), rval.size());
+  }
+
   @SuppressWarnings("unchecked")
   private int compare(Object lval, Object rval) throws EvalException {
+    lval = SkylarkType.convertToSkylark(lval, getLocation());
+    rval = SkylarkType.convertToSkylark(rval, getLocation());
+
+    if (lval instanceof SkylarkList && rval instanceof SkylarkList) {
+      return compareLists((SkylarkList) lval, (SkylarkList) rval);
+    }
     if (!(lval instanceof Comparable)) {
       throw new EvalException(getLocation(), lval + " is not comparable");
     }
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 37042ed..cb54532 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
@@ -190,13 +190,33 @@
   }
 
   @Test
-  public void testCompareStringInt() throws Exception {
-    checkEvalError("Cannot compare string with int", "'a' >= 1");
+  public void testListComparison() throws Exception {
+    assertThat(eval("[] < [1]")).isEqualTo(true);
+    assertThat(eval("[1] < [1, 1]")).isEqualTo(true);
+    assertThat(eval("[1, 1] < [1, 2]")).isEqualTo(true);
+    assertThat(eval("[1, 2] < [1, 2, 3]")).isEqualTo(true);
+    assertThat(eval("[1, 2, 3] <= [1, 2, 3]")).isEqualTo(true);
+
+    assertThat(eval("['a', 'b'] > ['a']")).isEqualTo(true);
+    assertThat(eval("['a', 'b'] >= ['a']")).isEqualTo(true);
+    assertThat(eval("['a', 'b'] < ['a']")).isEqualTo(false);
+    assertThat(eval("['a', 'b'] <= ['a']")).isEqualTo(false);
+
+    assertThat(eval("('a', 'b') > ('a', 'b')")).isEqualTo(false);
+    assertThat(eval("('a', 'b') >= ('a', 'b')")).isEqualTo(true);
+    assertThat(eval("('a', 'b') < ('a', 'b')")).isEqualTo(false);
+    assertThat(eval("('a', 'b') <= ('a', 'b')")).isEqualTo(true);
+
+    assertThat(eval("[[1, 1]] > [[1, 1], []]")).isEqualTo(false);
+    assertThat(eval("[[1, 1]] < [[1, 1], []]")).isEqualTo(true);
+
+    checkEvalError("Cannot compare int with string", "[1] < ['a']");
+    checkEvalError("[1] is not comparable", "[1] < 1");
   }
 
   @Test
-  public void testNotComparable() throws Exception {
-    checkEvalError("[1, 2] is not comparable", "[1, 2] < [1, 3]");
+  public void testCompareStringInt() throws Exception {
+    checkEvalError("Cannot compare string with int", "'a' >= 1");
   }
 
   @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 904eb70..c08f1a3 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
@@ -839,12 +839,6 @@
 
   @Override
   @Test
-  public void testNotComparable() throws Exception {
-    checkEvalError("[1, 2] is not comparable", "[1, 2] < [1, 3]");
-  }
-
-  @Override
-  @Test
   public void testListComprehensionsMultipleVariablesFail() throws Exception {
     checkEvalError("lvalue has length 3, but rvalue has has length 2",
         "def foo (): return [x + y for x, y, z in [(1, 2), (3, 4)]]",