aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/syntax
diff options
context:
space:
mode:
authorGravatar Laurent Le Brun <laurentlb@google.com>2015-04-15 14:23:35 +0000
committerGravatar Han-Wen Nienhuys <hanwen@google.com>2015-04-15 16:21:36 +0000
commit8a52826b593b8e46aa4a09829c9ce979cacb6f67 (patch)
tree3cb26557245e0ba5e0d17e6800590bdee17babf6 /src/main/java/com/google/devtools/build/lib/syntax
parentfc9140ecc662f46a415df11b35430fcd264328ad (diff)
Build language: Implement integer division
-- MOS_MIGRATED_REVID=91192716
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/syntax')
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java26
-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.java4
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/TokenKind.java1
5 files changed, 34 insertions, 2 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 ac47b63731..210d1f5027 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
@@ -184,13 +184,37 @@ public final class BinaryOperatorExpression extends Expression {
break;
}
+ case DIVIDE: {
+ // int / int
+ if (lval instanceof Integer && rval instanceof Integer) {
+ if (rval.equals(0)) {
+ throw new EvalException(getLocation(), "integer division by zero");
+ }
+ // Integer division doesn't give the same result in Java and in Python 2 with
+ // negative numbers.
+ // Java: -7/3 = -2
+ // Python: -7/3 = -3
+ // We want to follow Python semantics, so we use float division and round down.
+ return (int) Math.floor(new Double((Integer) lval) / (Integer) rval);
+ }
+ }
+
case PERCENT: {
// int % int
if (lval instanceof Integer && rval instanceof Integer) {
if (rval.equals(0)) {
throw new EvalException(getLocation(), "integer modulo by zero");
}
- return ((Integer) lval).intValue() % ((Integer) rval).intValue();
+ // Python and Java implement division differently, wrt negative numbers.
+ // In Python, sign of the result is the sign of the divisor.
+ int div = (Integer) rval;
+ int result = ((Integer) lval).intValue() % Math.abs(div);
+ if (result > 0 && div < 0) {
+ result += div; // make the result negative
+ } else if (result < 0 && div > 0) {
+ result += div; // make the result positive
+ }
+ return result;
}
// string % tuple, string % dict, string % anything-else
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 86b8de7b1d..77cdf3f5ee 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
@@ -685,6 +685,10 @@ public final class Lexer {
addToken(new Token(TokenKind.PERCENT, pos - 1, pos));
break;
}
+ case '/': {
+ addToken(new Token(TokenKind.SLASH, pos - 1, pos));
+ break;
+ }
case ';': {
addToken(new Token(TokenKind.SEMI, 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 628570e2d5..8849583ac2 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
@@ -19,6 +19,7 @@ package com.google.devtools.build.lib.syntax;
public enum Operator {
AND("and"),
+ DIVIDE("/"),
EQUALS_EQUALS("=="),
GREATER(">"),
GREATER_EQUALS(">="),
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 75b8db8b4c..e993821dd8 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
@@ -87,6 +87,7 @@ class Parser {
TokenKind.PLUS,
TokenKind.MINUS,
TokenKind.PERCENT,
+ TokenKind.SLASH,
TokenKind.RPAREN,
TokenKind.RBRACKET);
@@ -115,6 +116,7 @@ class Parser {
.put(TokenKind.NOT_EQUALS, Operator.NOT_EQUALS)
.put(TokenKind.OR, Operator.OR)
.put(TokenKind.PERCENT, Operator.PERCENT)
+ .put(TokenKind.SLASH, Operator.DIVIDE)
.put(TokenKind.PLUS, Operator.PLUS)
.put(TokenKind.STAR, Operator.MULT)
.build();
@@ -134,7 +136,7 @@ class Parser {
EnumSet.of(Operator.EQUALS_EQUALS, Operator.NOT_EQUALS, Operator.LESS, Operator.LESS_EQUALS,
Operator.GREATER, Operator.GREATER_EQUALS, Operator.IN),
EnumSet.of(Operator.MINUS, Operator.PLUS),
- EnumSet.of(Operator.MULT, Operator.PERCENT));
+ EnumSet.of(Operator.DIVIDE, Operator.MULT, Operator.PERCENT));
private Iterator<Token> tokens = null;
private int errorsCount;
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 866b9b978d..57f5fc4876 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
@@ -74,6 +74,7 @@ public enum TokenKind {
RETURN("return"),
RPAREN(")"),
SEMI(";"),
+ SLASH("/"),
STAR("*"),
STAR_STAR("**"),
STRING("string"),