diff options
author | brandjon <brandjon@google.com> | 2017-06-27 15:05:35 +0200 |
---|---|---|
committer | Marcel Hlopko <hlopko@google.com> | 2017-06-28 10:16:30 +0200 |
commit | f2ed858ee37b4694b2c29851509d1f33847e1608 (patch) | |
tree | 870ea1e2cb9db2d289af1a24c5e19ded494597aa /src/main/java/com/google/devtools | |
parent | 7b85122c9ed1c5bc32ef9c6ac213910adee735e2 (diff) |
Turn unary minus into a proper AST node
This unifies unary minus with NotExpression, and moves the minus logic from a fake builtin function into the interpreter proper.
RELNOTES: None
PiperOrigin-RevId: 160266266
Diffstat (limited to 'src/main/java/com/google/devtools')
8 files changed, 127 insertions, 80 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 2274076d88..de3bf92c2b 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 @@ -102,7 +102,6 @@ public final class BinaryOperatorExpression extends Expression { } } - /** Helper method. Reused from the LValue class. */ public static Object evaluate( Operator operator, Object lval, diff --git a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java index b9c76641f4..8f466b7ff0 100644 --- a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java @@ -1547,23 +1547,6 @@ public class MethodLibrary { } }; - // unary minus - @SkylarkSignature( - name = "-", - returnType = Integer.class, - documented = false, - doc = "Unary minus operator.", - parameters = { - @Param(name = "num", type = Integer.class, doc = "The number to negate.") - } - ) - private static final BuiltinFunction minus = - new BuiltinFunction("-") { - public Integer invoke(Integer num) throws ConversionException { - return -num; - } - }; - @SkylarkSignature( name = "tuple", returnType = Tuple.class, @@ -2221,7 +2204,7 @@ public class MethodLibrary { static final List<BaseFunction> defaultGlobalFunctions = ImmutableList.<BaseFunction>of( all, any, bool, dict, dir, fail, getattr, hasattr, hash, enumerate, int_, len, list, max, - min, minus, print, range, repr, reversed, sorted, str, tuple, zip); + min, print, range, repr, reversed, sorted, str, tuple, zip); static { SkylarkSignatureProcessor.configureSkylarkFunctions(MethodLibrary.class); diff --git a/src/main/java/com/google/devtools/build/lib/syntax/NotExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/NotExpression.java deleted file mode 100644 index 069e92dbcf..0000000000 --- a/src/main/java/com/google/devtools/build/lib/syntax/NotExpression.java +++ /dev/null @@ -1,50 +0,0 @@ -// 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; - -/** - * Syntax node for the not boolean operation. - */ -public final class NotExpression extends Expression { - - private final Expression expression; - - public NotExpression(Expression expression) { - this.expression = expression; - } - - public Expression getExpression() { - return expression; - } - - @Override - Object doEval(Environment env) throws EvalException, InterruptedException { - return !EvalUtils.toBoolean(expression.eval(env)); - } - - @Override - public String toString() { - return "not " + expression; - } - - @Override - public void accept(SyntaxTreeVisitor visitor) { - visitor.visit(this); - } - - @Override - void validate(ValidationEnvironment env) throws EvalException { - expression.validate(env); - } -} 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 b839865ad6..c0740e9dd9 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 @@ -11,11 +11,10 @@ // 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; -/** - * Infix operators supported by the build language. - */ +/** Infix binary operators. */ public enum Operator { AND("and"), @@ -39,7 +38,7 @@ public enum Operator { private final String name; - private Operator(String name) { + Operator(String name) { this.name = name; } @@ -47,5 +46,4 @@ public enum Operator { public String toString() { return 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 46de9a9933..1416d8f0c9 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 @@ -697,10 +697,9 @@ public class Parser { case MINUS: { nextToken(); - List<Argument.Passed> args = new ArrayList<>(); Expression expr = parsePrimaryWithSuffix(); - args.add(setLocation(new Argument.Positional(expr), start, expr)); - return makeFuncallExpression(null, new Identifier("-"), args, start, token.right); + UnaryOperatorExpression minus = new UnaryOperatorExpression(UnaryOperator.MINUS, expr); + return setLocation(minus, start, expr); } default: { @@ -1061,7 +1060,8 @@ public class Parser { int start = token.left; expect(TokenKind.NOT); Expression expression = parseNonTupleExpression(prec + 1); - NotExpression notExpression = new NotExpression(expression); + UnaryOperatorExpression notExpression = + new UnaryOperatorExpression(UnaryOperator.NOT, expression); return setLocation(notExpression, start, token.right); } 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 387268a590..5ef0e177e3 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 @@ -139,8 +139,8 @@ public class SyntaxTreeVisitor { visit(node.getValue()); } - public void visit(NotExpression node) { - visit(node.getExpression()); + public void visit(UnaryOperatorExpression node) { + visit(node.getOperand()); } public void visit(DotExpression node) { diff --git a/src/main/java/com/google/devtools/build/lib/syntax/UnaryOperator.java b/src/main/java/com/google/devtools/build/lib/syntax/UnaryOperator.java new file mode 100644 index 0000000000..85fe9217c9 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/syntax/UnaryOperator.java @@ -0,0 +1,34 @@ +// Copyright 2017 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; + +/** Unary operators. */ +public enum UnaryOperator { + + // Include trailing whitespace in name for non-symbolic operators (for pretty printing). + NOT("not "), + MINUS("-"); + + private final String name; + + UnaryOperator(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } +} diff --git a/src/main/java/com/google/devtools/build/lib/syntax/UnaryOperatorExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/UnaryOperatorExpression.java new file mode 100644 index 0000000000..5c36be48f9 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/syntax/UnaryOperatorExpression.java @@ -0,0 +1,83 @@ +// Copyright 2017 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 a unary operator expression. */ +public final class UnaryOperatorExpression extends Expression { + + private final UnaryOperator operator; + + private final Expression operand; + + public UnaryOperatorExpression(UnaryOperator operator, Expression operand) { + this.operator = operator; + this.operand = operand; + } + + public UnaryOperator getOperator() { + return operator; + } + + public Expression getOperand() { + return operand; + } + + @Override + public String toString() { + // All current and planned unary operators happen to be prefix operators. + // Non-symbolic operators have trailing whitespace built into their name. + return operator.toString() + operand; + } + + private static Object evaluate( + UnaryOperator operator, + Object value, + Environment env, + Location loc) + throws EvalException, InterruptedException { + switch (operator) { + case NOT: + return !EvalUtils.toBoolean(value); + + case MINUS: + if (!(value instanceof Integer)) { + throw new EvalException( + loc, + String.format("unsupported operand type for -: '%s'", + EvalUtils.getDataTypeName(value))); + } + return -((Integer) value); + + default: + throw new AssertionError("Unsupported unary operator: " + operator); + } + } + + @Override + Object doEval(Environment env) throws EvalException, InterruptedException { + return evaluate(operator, operand.eval(env), env, getLocation()); + } + + @Override + public void accept(SyntaxTreeVisitor visitor) { + visitor.visit(this); + } + + @Override + void validate(ValidationEnvironment env) throws EvalException { + operand.validate(env); + } +} |