aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main
diff options
context:
space:
mode:
authorGravatar Vladimir Moskva <vladmos@google.com>2016-12-19 13:51:57 +0000
committerGravatar Klaus Aehlig <aehlig@google.com>2016-12-19 16:15:34 +0000
commit71536648ac4dbbb68b9cb8f8f87f959343b21d15 (patch)
tree18f2196a9cacf3cd8b5bad2800770c0f36083638 /src/main
parent7bb3cae694c80a54ce6c21aa8af8858c365c0edc (diff)
Add a new AST node for augmented assignments in Skylark
-- PiperOrigin-RevId: 142438943 MOS_MIGRATED_REVID=142438943
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/AugmentedAssignmentStatement.java73
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java38
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/Parser.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/SyntaxTreeVisitor.java6
4 files changed, 106 insertions, 21 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/AugmentedAssignmentStatement.java b/src/main/java/com/google/devtools/build/lib/syntax/AugmentedAssignmentStatement.java
new file mode 100644
index 0000000000..a33482f82f
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/syntax/AugmentedAssignmentStatement.java
@@ -0,0 +1,73 @@
+// Copyright 2014 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.syntax;
+
+import com.google.devtools.build.lib.events.Location;
+
+/** Syntax node for an augmented assignment statement. */
+public final class AugmentedAssignmentStatement extends Statement {
+
+ private final Operator operator;
+
+ private final LValue lvalue;
+
+ private final Expression expression;
+
+ /** Constructs an augmented assignment: "lvalue ::= value". */
+ AugmentedAssignmentStatement(Operator operator, Expression lhs, Expression expression) {
+ this.operator = operator;
+ this.lvalue = new LValue(lhs);
+ this.expression = expression;
+ }
+
+ /** Returns the operator of the assignment. */
+ public Operator getOperator() {
+ return operator;
+ }
+
+ /** Returns the LValue of the assignment. */
+ public LValue getLValue() {
+ return lvalue;
+ }
+
+ /** Returns the RHS of the assignment. */
+ public Expression getExpression() {
+ return expression;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s %s= %s\n", lvalue, operator, expression);
+ }
+
+ @Override
+ void doExec(Environment env) throws EvalException, InterruptedException {
+ Location loc = getLocation();
+ Object result =
+ BinaryOperatorExpression.evaluate(operator, lvalue.getExpression(), expression, env, loc);
+ lvalue.assign(env, loc, result);
+ }
+
+ @Override
+ public void accept(SyntaxTreeVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ void validate(ValidationEnvironment env) throws EvalException {
+ lvalue.validate(env, getLocation());
+ expression.validate(env);
+ }
+}
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 864f3dc860..1e9f02352a 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
@@ -110,8 +110,13 @@ public final class BinaryOperatorExpression extends Expression {
}
}
- @Override
- Object doEval(Environment env) throws EvalException, InterruptedException {
+ /**
+ * Helper method. Reused from AugmentedAssignmentStatement class which falls back to this method
+ * in most of the cases.
+ */
+ public static Object evaluate(
+ Operator operator, Expression lhs, Expression rhs, Environment env, Location location)
+ throws EvalException, InterruptedException {
Object lval = lhs.eval(env);
// Short-circuit operators
@@ -135,22 +140,22 @@ public final class BinaryOperatorExpression extends Expression {
switch (operator) {
case PLUS:
- return plus(lval, rval, env, getLocation());
+ return plus(lval, rval, env, location);
case PIPE:
- return pipe(lval, rval, getLocation());
+ return pipe(lval, rval, location);
case MINUS:
- return minus(lval, rval, getLocation());
+ return minus(lval, rval, location);
case MULT:
- return mult(lval, rval, env, getLocation());
+ return mult(lval, rval, env, location);
case DIVIDE:
- return divide(lval, rval, getLocation());
+ return divide(lval, rval, location);
case PERCENT:
- return percent(lval, rval, getLocation());
+ return percent(lval, rval, location);
case EQUALS_EQUALS:
return lval.equals(rval);
@@ -159,22 +164,22 @@ public final class BinaryOperatorExpression extends Expression {
return !lval.equals(rval);
case LESS:
- return compare(lval, rval, getLocation()) < 0;
+ return compare(lval, rval, location) < 0;
case LESS_EQUALS:
- return compare(lval, rval, getLocation()) <= 0;
+ return compare(lval, rval, location) <= 0;
case GREATER:
- return compare(lval, rval, getLocation()) > 0;
+ return compare(lval, rval, location) > 0;
case GREATER_EQUALS:
- return compare(lval, rval, getLocation()) >= 0;
+ return compare(lval, rval, location) >= 0;
case IN:
- return in(lval, rval, getLocation());
+ return in(lval, rval, location);
case NOT_IN:
- return !in(lval, rval, getLocation());
+ return !in(lval, rval, location);
default:
throw new AssertionError("Unsupported binary operator: " + operator);
@@ -182,6 +187,11 @@ public final class BinaryOperatorExpression extends Expression {
}
@Override
+ Object doEval(Environment env) throws EvalException, InterruptedException {
+ return evaluate(operator, lhs, rhs, env, getLocation());
+ }
+
+ @Override
public void accept(SyntaxTreeVisitor visitor) {
visitor.visit(this);
}
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 8b28b3ef47..267808d792 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
@@ -1156,9 +1156,9 @@ public class Parser {
// | RETURN expr
// | flow_stmt
// assign_stmt ::= expr ('=' | augassign) expr
- // augassign ::= ('+=' )
+ // augassign ::= ('+=' | '-=' | '*=' | '/=' | '%=')
// Note that these are in Python, but not implemented here (at least for now):
- // '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |'<<=' | '>>=' | '**=' | '//='
+ // '&=' | '|=' | '^=' |'<<=' | '>>=' | '**=' | '//='
// Semantic difference from Python:
// In Skylark, x += y is simple syntactic sugar for x = x + y.
// In Python, x += y is more or less equivalent to x = x + y, but if a method is defined
@@ -1185,10 +1185,8 @@ public class Parser {
nextToken();
Expression operand = parseExpression();
int end = operand.getLocation().getEndOffset();
- return setLocation(new AssignmentStatement(expression,
- setLocation(new BinaryOperatorExpression(
- operator, expression, operand), start, end)),
- start, end);
+ return setLocation(
+ new AugmentedAssignmentStatement(operator, expression, operand), start, end);
} else {
return setLocation(new ExpressionStatement(expression), start, expression);
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SyntaxTreeVisitor.java b/src/main/java/com/google/devtools/build/lib/syntax/SyntaxTreeVisitor.java
index d18615c61c..387268a590 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SyntaxTreeVisitor.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SyntaxTreeVisitor.java
@@ -15,7 +15,6 @@ package com.google.devtools.build.lib.syntax;
import com.google.devtools.build.lib.syntax.DictionaryLiteral.DictionaryEntryLiteral;
import com.google.devtools.build.lib.syntax.IfStatement.ConditionalStatements;
-
import java.util.List;
/**
@@ -102,6 +101,11 @@ public class SyntaxTreeVisitor {
visit(node.getExpression());
}
+ public void visit(AugmentedAssignmentStatement node) {
+ visit(node.getLValue());
+ visit(node.getExpression());
+ }
+
public void visit(ExpressionStatement node) {
visit(node.getExpression());
}