aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Laurent Le Brun <laurentlb@google.com>2015-08-24 14:50:00 +0000
committerGravatar Laszlo Csomor <laszlocsomor@google.com>2015-08-25 07:39:59 +0000
commit092f13b79ac6a1b5ef065e83929eb1403d69f975 (patch)
tree3e5e753cfe6860f8cfd5a347c36c35c404578025 /src
parented5955c5a16996a3b630d7f95206d67d0d0c6380 (diff)
Introduce '|' operator for set union.
-- MOS_MIGRATED_REVID=101363350
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java50
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/Lexer.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/Operator.java1
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/Parser.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/TokenKind.java1
-rw-r--r--src/test/java/com/google/devtools/build/lib/syntax/EvaluationTestCase.java6
-rw-r--r--src/test/java/com/google/devtools/build/lib/syntax/SkylarkEvaluationTest.java8
7 files changed, 41 insertions, 31 deletions
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 65ea8df75d..9d489e04a3 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
@@ -121,18 +121,22 @@ public final class BinaryOperatorExpression extends Expression {
Object rval = rhs.eval(env);
switch (operator) {
- case PLUS: {
+ case PLUS:
return plus(lval, rval);
- }
- case MINUS: {
+ case PIPE:
+ if (lval instanceof SkylarkNestedSet) {
+ return new SkylarkNestedSet((SkylarkNestedSet) lval, rval, getLocation());
+ }
+ break;
+
+ case MINUS:
if (lval instanceof Integer && rval instanceof Integer) {
return ((Integer) lval).intValue() - ((Integer) rval).intValue();
}
break;
- }
- case MULT: {
+ case MULT:
// int * int
if (lval instanceof Integer && rval instanceof Integer) {
return ((Integer) lval).intValue() * ((Integer) rval).intValue();
@@ -148,9 +152,8 @@ public final class BinaryOperatorExpression extends Expression {
return Strings.repeat((String) rval, ((Integer) lval).intValue());
}
break;
- }
- case DIVIDE: {
+ case DIVIDE:
// int / int
if (lval instanceof Integer && rval instanceof Integer) {
if (rval.equals(0)) {
@@ -163,9 +166,9 @@ public final class BinaryOperatorExpression extends Expression {
// We want to follow Python semantics, so we use float division and round down.
return (int) Math.floor(new Double((Integer) lval) / (Integer) rval);
}
- }
+ break;
- case PERCENT: {
+ case PERCENT:
// int % int
if (lval instanceof Integer && rval instanceof Integer) {
if (rval.equals(0)) {
@@ -207,43 +210,33 @@ public final class BinaryOperatorExpression extends Expression {
}
}
break;
- }
- case EQUALS_EQUALS: {
+ case EQUALS_EQUALS:
return lval.equals(rval);
- }
- case NOT_EQUALS: {
+ case NOT_EQUALS:
return !lval.equals(rval);
- }
- case LESS: {
+ case LESS:
return compare(lval, rval) < 0;
- }
- case LESS_EQUALS: {
+ case LESS_EQUALS:
return compare(lval, rval) <= 0;
- }
- case GREATER: {
+ case GREATER:
return compare(lval, rval) > 0;
- }
- case GREATER_EQUALS: {
+ case GREATER_EQUALS:
return compare(lval, rval) >= 0;
- }
- case IN: {
+ case IN:
return evalIn(lval, rval);
- }
- case NOT_IN: {
+ case NOT_IN:
return !evalIn(lval, rval);
- }
- default: {
+ default:
throw new AssertionError("Unsupported binary operator: " + operator);
- }
} // endswitch
// NB: this message format is identical to that used by CPython 2.7.6 or 3.4.0,
@@ -310,6 +303,7 @@ public final class BinaryOperatorExpression extends Expression {
getLocation());
}
+ // TODO(bazel-team): Remove this case. Union of sets should use '|' instead of '+'.
if (lval instanceof SkylarkNestedSet) {
return new SkylarkNestedSet((SkylarkNestedSet) lval, rval, getLocation());
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Lexer.java b/src/main/java/com/google/devtools/build/lib/syntax/Lexer.java
index 90b40e3f2c..9d148861bf 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Lexer.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Lexer.java
@@ -698,6 +698,10 @@ public final class Lexer {
addToken(new Token(TokenKind.MINUS, pos - 1, pos));
break;
}
+ case '|': {
+ addToken(new Token(TokenKind.PIPE, pos - 1, pos));
+ break;
+ }
case '=': {
addToken(new Token(TokenKind.EQUALS, pos - 1, pos));
break;
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Operator.java b/src/main/java/com/google/devtools/build/lib/syntax/Operator.java
index 73b37cf717..218eee8e7d 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Operator.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Operator.java
@@ -33,6 +33,7 @@ public enum Operator {
NOT_IN("not in"),
OR("or"),
PERCENT("%"),
+ PIPE("|"),
PLUS("+");
private final String name;
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
index 8f590472dc..6334673aa1 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
@@ -134,6 +134,7 @@ class Parser {
.put(TokenKind.PERCENT, Operator.PERCENT)
.put(TokenKind.SLASH, Operator.DIVIDE)
.put(TokenKind.PLUS, Operator.PLUS)
+ .put(TokenKind.PIPE, Operator.PIPE)
.put(TokenKind.STAR, Operator.MULT)
.build();
@@ -151,6 +152,7 @@ class Parser {
EnumSet.of(Operator.NOT),
EnumSet.of(Operator.EQUALS_EQUALS, Operator.NOT_EQUALS, Operator.LESS, Operator.LESS_EQUALS,
Operator.GREATER, Operator.GREATER_EQUALS, Operator.IN, Operator.NOT_IN),
+ EnumSet.of(Operator.PIPE),
EnumSet.of(Operator.MINUS, Operator.PLUS),
EnumSet.of(Operator.DIVIDE, Operator.MULT, Operator.PERCENT));
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/TokenKind.java b/src/main/java/com/google/devtools/build/lib/syntax/TokenKind.java
index 0ada226f53..18ba037799 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/TokenKind.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/TokenKind.java
@@ -67,6 +67,7 @@ public enum TokenKind {
OUTDENT("outdent"),
PASS("pass"),
PERCENT("%"),
+ PIPE("|"),
PLUS("+"),
PLUS_EQUALS("+="),
RAISE("raise"),
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTestCase.java b/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTestCase.java
index 7be1c86545..b2d661b7d4 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/EvaluationTestCase.java
@@ -128,7 +128,7 @@ public class EvaluationTestCase {
setFailFast(true);
try {
eval(input);
- fail();
+ fail("Expected error '" + msg + "' but got no error");
} catch (IllegalArgumentException | EvalException e) {
assertThat(e).hasMessage(msg);
}
@@ -137,7 +137,7 @@ public class EvaluationTestCase {
public void checkEvalErrorContains(String msg, String... input) throws Exception {
try {
eval(input);
- fail();
+ fail("Expected error containing '" + msg + "' but got no error");
} catch (IllegalArgumentException | EvalException e) {
assertThat(e.getMessage()).contains(msg);
}
@@ -146,7 +146,7 @@ public class EvaluationTestCase {
public void checkEvalErrorStartsWith(String msg, String... input) throws Exception {
try {
eval(input);
- fail();
+ fail("Expected error starting with '" + msg + "' but got no error");
} catch (IllegalArgumentException | EvalException e) {
assertThat(e.getMessage()).startsWith(msg);
}
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 e794aa7799..22c715358e 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
@@ -609,6 +609,14 @@ public class SkylarkEvaluationTest extends EvaluationTest {
}
@Test
+ public void testUnionSet() throws Exception {
+ new SkylarkTest()
+ .testStatement("str(set([1, 3]) | set([1, 2]))", "set([1, 2, 3])")
+ .testStatement("str(set([1, 2]) | [1, 3])", "set([1, 2, 3])")
+ .testIfExactError("unsupported operand type(s) for |: 'int' and 'int'", "2 | 4");
+ }
+
+ @Test
public void testClassObjectCannotAccessNestedSet() throws Exception {
new SkylarkTest()
.update("mock", new MockClassObject())