diff options
author | Vladimir Moskva <vladmos@google.com> | 2016-12-19 13:51:57 +0000 |
---|---|---|
committer | Klaus Aehlig <aehlig@google.com> | 2016-12-19 16:15:34 +0000 |
commit | 71536648ac4dbbb68b9cb8f8f87f959343b21d15 (patch) | |
tree | 18f2196a9cacf3cd8b5bad2800770c0f36083638 /src/main/java/com/google | |
parent | 7bb3cae694c80a54ce6c21aa8af8858c365c0edc (diff) |
Add a new AST node for augmented assignments in Skylark
--
PiperOrigin-RevId: 142438943
MOS_MIGRATED_REVID=142438943
Diffstat (limited to 'src/main/java/com/google')
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()); } |