From 1d5d5486cec2bef2359c737eee7e507c75b22de3 Mon Sep 17 00:00:00 2001 From: Natalia Ukhorskaya Date: Mon, 11 Nov 2013 15:20:52 +0400 Subject: [PATCH] Support compareTo in ConstantExpressionEvaluator --- .../evaluate/ConstantExpressionEvaluator.java | 69 ++++++++++++++++++- .../evaluate/constantExpressionEvaluator.kt | 52 +++++++++++++- .../lang/resolve/constants/ConstantUtils.kt | 51 -------------- .../parameters/expressions/gt.kt | 17 +++++ .../parameters/expressions/gteq.kt | 12 ++++ .../parameters/expressions/lt.kt | 17 +++++ .../parameters/expressions/lteq.kt | 12 ++++ 7 files changed, 176 insertions(+), 54 deletions(-) delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.kt create mode 100644 compiler/testData/resolveAnnotations/parameters/expressions/gt.kt create mode 100644 compiler/testData/resolveAnnotations/parameters/expressions/gteq.kt create mode 100644 compiler/testData/resolveAnnotations/parameters/expressions/lt.kt create mode 100644 compiler/testData/resolveAnnotations/parameters/expressions/lteq.kt diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.java b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.java index d011999e2ac..3f9e18f378f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.java @@ -17,6 +17,7 @@ package org.jetbrains.jet.lang.evaluate; import com.google.common.collect.Lists; +import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; @@ -203,15 +204,79 @@ public class ConstantExpressionEvaluator extends JetVisitor> arguments = Lists.newArrayList(); - for (Map.Entry argumentEntry : resolvedCall.getValueArguments() .entrySet()) { + for (Map.Entry argumentEntry : resolvedCall.getValueArguments().entrySet()) { arguments.addAll(resolveArguments(argumentEntry.getValue().getArguments(), argumentEntry.getKey().getType(), trace)); } - return ConstantsPackage.resolveCallToCompileTimeValue(resultingDescriptor.getName(), receiverValue, arguments, expectedType); + Name resultingDescriptorName = resultingDescriptor.getName(); + if (arguments.isEmpty()) { + Object result = EvaluatePackage.evaluateUnaryExpression(receiverValue, resultingDescriptorName); + if (result == null) { + return null; + } + return createCompileTimeConstant(result, expectedType); + } + else if (arguments.size() == 1) { + Object result = EvaluatePackage.evaluateBinaryExpression(receiverValue, arguments.iterator().next(), resultingDescriptorName); + if (result == null) { + return null; + } + if (OperatorConventions.COMPARE_TO.equals(resultingDescriptorName)) { + PsiElement parentExpression = resolvedCallExpression.getParent(); + if (parentExpression instanceof JetBinaryExpression) { + return createCompileTimeConstantForCompareTo(result, (JetBinaryExpression) parentExpression); + } + } + else { + return createCompileTimeConstant(result, expectedType); + } + } + + return null; } return null; } + @Nullable + private static CompileTimeConstant createCompileTimeConstantForCompareTo( + @NotNull Object result, + @NotNull JetBinaryExpression expression + ) { + if (result instanceof Integer) { + int resultCode = ((Integer) result).intValue(); + IElementType operationToken = expression.getOperationToken(); + if (resultCode == 0) { + if (operationToken == JetTokens.EQEQ || + operationToken == JetTokens.LTEQ || + operationToken == JetTokens.GTEQ) { + return BooleanValue.TRUE; + } + else { + return BooleanValue.FALSE; + } + } + if (resultCode == 1) { + if (operationToken == JetTokens.GT || + operationToken == JetTokens.GTEQ) { + return BooleanValue.TRUE; + } + else { + return BooleanValue.FALSE; + } + } + if (resultCode == -1) { + if (operationToken == JetTokens.LT || + operationToken == JetTokens.LTEQ) { + return BooleanValue.TRUE; + } + else { + return BooleanValue.FALSE; + } + } + } + return null; + } + @Override public CompileTimeConstant visitUnaryExpression(@NotNull JetUnaryExpression expression, Void data) { JetExpression leftExpression = expression.getBaseExpression(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/constantExpressionEvaluator.kt b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/constantExpressionEvaluator.kt index c88034662e6..4b0949e0f5a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/constantExpressionEvaluator.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/constantExpressionEvaluator.kt @@ -153,6 +153,7 @@ private val binaryOperations = hashMapOf, (Any?, Any?) -> bOp(STRING, DOUBLE, "plus", { a, b -> a + b }), bOp(STRING, FLOAT, "plus", { a, b -> a + b }), bOp(STRING, CHAR, "plus", { a, b -> a + b }), + bOp(STRING, STRING, "compareTo", { a, b -> a.compareTo(b) }), // Boolean bOp(BOOLEAN, BOOLEAN, "and", { a, b -> a and b }), @@ -197,6 +198,13 @@ private val binaryOperations = hashMapOf, (Any?, Any?) -> bOp(BYTE, SHORT, "mod", { a, b -> a % b }), bOp(BYTE, BYTE, "mod", { a, b -> a % b }), bOp(BYTE, CHAR, "mod", { a, b -> a % b }), + bOp(BYTE, DOUBLE, "compareTo", { a, b -> a.compareTo(b) }), + bOp(BYTE, FLOAT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(BYTE, LONG, "compareTo", { a, b -> a.compareTo(b) }), + bOp(BYTE, INT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(BYTE, SHORT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(BYTE, BYTE, "compareTo", { a, b -> a.compareTo(b) }), + bOp(BYTE, CHAR, "compareTo", { a, b -> a.compareTo(b) }), // Short bOp(SHORT, DOUBLE, "plus", { a, b -> a + b }), @@ -234,6 +242,13 @@ private val binaryOperations = hashMapOf, (Any?, Any?) -> bOp(SHORT, SHORT, "mod", { a, b -> a % b }), bOp(SHORT, BYTE, "mod", { a, b -> a % b }), bOp(SHORT, CHAR, "mod", { a, b -> a % b }), + bOp(SHORT, DOUBLE, "compareTo", { a, b -> a.compareTo(b) }), + bOp(SHORT, FLOAT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(SHORT, LONG, "compareTo", { a, b -> a.compareTo(b) }), + bOp(SHORT, INT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(SHORT, SHORT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(SHORT, BYTE, "compareTo", { a, b -> a.compareTo(b) }), + bOp(SHORT, CHAR, "compareTo", { a, b -> a.compareTo(b) }), // Int bOp(INT, DOUBLE, "plus", { a, b -> a + b }), @@ -277,6 +292,13 @@ private val binaryOperations = hashMapOf, (Any?, Any?) -> bOp(INT, INT, "and", { a, b -> a and b }), bOp(INT, INT, "or", { a, b -> a or b }), bOp(INT, INT, "xor", { a, b -> a xor b }), + bOp(INT, DOUBLE, "compareTo", { a, b -> a.compareTo(b) }), + bOp(INT, FLOAT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(INT, LONG, "compareTo", { a, b -> a.compareTo(b) }), + bOp(INT, INT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(INT, SHORT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(INT, BYTE, "compareTo", { a, b -> a.compareTo(b) }), + bOp(INT, CHAR, "compareTo", { a, b -> a.compareTo(b) }), // Long bOp(LONG, DOUBLE, "plus", { a, b -> a + b }), @@ -320,6 +342,13 @@ private val binaryOperations = hashMapOf, (Any?, Any?) -> bOp(LONG, LONG, "and", { a, b -> a and b }), bOp(LONG, LONG, "or", { a, b -> a or b }), bOp(LONG, LONG, "xor", { a, b -> a xor b }), + bOp(LONG, DOUBLE, "compareTo", { a, b -> a.compareTo(b) }), + bOp(LONG, FLOAT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(LONG, LONG, "compareTo", { a, b -> a.compareTo(b) }), + bOp(LONG, INT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(LONG, SHORT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(LONG, BYTE, "compareTo", { a, b -> a.compareTo(b) }), + bOp(LONG, CHAR, "compareTo", { a, b -> a.compareTo(b) }), // Double bOp(DOUBLE, DOUBLE, "plus", { a, b -> a + b }), @@ -356,6 +385,13 @@ private val binaryOperations = hashMapOf, (Any?, Any?) -> bOp(DOUBLE, INT, "mod", { a, b -> a % b }), bOp(DOUBLE, SHORT, "mod", { a, b -> a % b }), bOp(DOUBLE, BYTE, "mod", { a, b -> a % b }), + bOp(DOUBLE, DOUBLE, "compareTo", { a, b -> a.compareTo(b) }), + bOp(DOUBLE, FLOAT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(DOUBLE, LONG, "compareTo", { a, b -> a.compareTo(b) }), + bOp(DOUBLE, INT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(DOUBLE, SHORT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(DOUBLE, BYTE, "compareTo", { a, b -> a.compareTo(b) }), + bOp(DOUBLE, CHAR, "compareTo", { a, b -> a.compareTo(b) }), // Float bOp(FLOAT, DOUBLE, "plus", { a, b -> a + b }), @@ -393,6 +429,13 @@ private val binaryOperations = hashMapOf, (Any?, Any?) -> bOp(FLOAT, SHORT, "mod", { a, b -> a % b }), bOp(FLOAT, BYTE, "mod", { a, b -> a % b }), bOp(FLOAT, CHAR, "mod", { a, b -> a % b }), + bOp(FLOAT, DOUBLE, "compareTo", { a, b -> a.compareTo(b) }), + bOp(FLOAT, FLOAT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(FLOAT, LONG, "compareTo", { a, b -> a.compareTo(b) }), + bOp(FLOAT, INT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(FLOAT, SHORT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(FLOAT, BYTE, "compareTo", { a, b -> a.compareTo(b) }), + bOp(FLOAT, CHAR, "compareTo", { a, b -> a.compareTo(b) }), // Char bOp(CHAR, DOUBLE, "plus", { a, b -> a + b }), @@ -425,6 +468,13 @@ private val binaryOperations = hashMapOf, (Any?, Any?) -> bOp(CHAR, LONG, "mod", { a, b -> a % b }), bOp(CHAR, INT, "mod", { a, b -> a % b }), bOp(CHAR, SHORT, "mod", { a, b -> a % b }), - bOp(CHAR, BYTE, "mod", { a, b -> a % b }) + bOp(CHAR, BYTE, "mod", { a, b -> a % b }), + bOp(CHAR, DOUBLE, "compareTo", { a, b -> a.compareTo(b) }), + bOp(CHAR, FLOAT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(CHAR, LONG, "compareTo", { a, b -> a.compareTo(b) }), + bOp(CHAR, INT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(CHAR, SHORT, "compareTo", { a, b -> a.compareTo(b) }), + bOp(CHAR, BYTE, "compareTo", { a, b -> a.compareTo(b) }), + bOp(CHAR, CHAR, "compareTo", { a, b -> a.compareTo(b) }) ) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.kt deleted file mode 100644 index 2588c925352..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2010-2013 JetBrains s.r.o. - * - * 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 org.jetbrains.jet.lang.resolve.constants - -import org.jetbrains.jet.lang.types.expressions.OperatorConventions -import org.jetbrains.jet.lang.resolve.name.Name -import org.jetbrains.jet.lang.evaluate.evaluateBinaryExpression -import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator -import org.jetbrains.jet.lang.types.JetType -import org.jetbrains.jet.lang.evaluate.evaluateUnaryExpression - -public fun resolveCallToCompileTimeValue( - callName: Name, - receiverValue: CompileTimeConstant<*>, - arguments: Collection>, - expectedType: JetType -): CompileTimeConstant<*>? { - if (arguments.isEmpty()) { - val result = evaluateUnaryExpression(receiverValue, callName) - if (result == null) { - return null - } - return ConstantExpressionEvaluator.createCompileTimeConstant(result, expectedType) - } - else if (arguments.size() == 1) { - val result = evaluateBinaryExpression(receiverValue, arguments.iterator().next(), callName) - if (result == null) { - return null - } - return ConstantExpressionEvaluator.createCompileTimeConstant(result, expectedType) - } - - return null -} - - - diff --git a/compiler/testData/resolveAnnotations/parameters/expressions/gt.kt b/compiler/testData/resolveAnnotations/parameters/expressions/gt.kt new file mode 100644 index 00000000000..521da75b769 --- /dev/null +++ b/compiler/testData/resolveAnnotations/parameters/expressions/gt.kt @@ -0,0 +1,17 @@ +package test + +annotation class Ann( + val b1: Boolean, + val b2: Boolean, + val b3: Boolean, + val b4: Boolean, + val b5: Boolean, + val b6: Boolean +) + +val a = 1 +val b = 2 + +Ann(1 > 2, 1.0 > 2.0, 2 > a, b > a, 'b' > 'a', "a" > "b") class MyClass + +// EXPECTED: Ann[b1 = false: jet.Boolean, b2 = false: jet.Boolean, b3 = true: jet.Boolean, b4 = true: jet.Boolean, b5 = true: jet.Boolean, b6 = false: jet.Boolean] diff --git a/compiler/testData/resolveAnnotations/parameters/expressions/gteq.kt b/compiler/testData/resolveAnnotations/parameters/expressions/gteq.kt new file mode 100644 index 00000000000..51418138882 --- /dev/null +++ b/compiler/testData/resolveAnnotations/parameters/expressions/gteq.kt @@ -0,0 +1,12 @@ +package test + +annotation class Ann( + val b1: Boolean, + val b2: Boolean, + val b3: Boolean, + val b4: Boolean +) + +Ann(1 >= 2, 1.0 >= 2.0, 1 >= 1, 1.0 >= 1.0) class MyClass + +// EXPECTED: Ann[b1 = false: jet.Boolean, b2 = false: jet.Boolean, b3 = true: jet.Boolean, b4 = true: jet.Boolean] diff --git a/compiler/testData/resolveAnnotations/parameters/expressions/lt.kt b/compiler/testData/resolveAnnotations/parameters/expressions/lt.kt new file mode 100644 index 00000000000..a2320a209f9 --- /dev/null +++ b/compiler/testData/resolveAnnotations/parameters/expressions/lt.kt @@ -0,0 +1,17 @@ +package test + +annotation class Ann( + val b1: Boolean, + val b2: Boolean, + val b3: Boolean, + val b4: Boolean, + val b5: Boolean, + val b6: Boolean +) + +val a = 1 +val b = 2 + +Ann(1 < 2, 1.0 < 2.0, 2 < a, b < a, 'b' < 'a', "a" < "b") class MyClass + +// EXPECTED: Ann[b1 = true: jet.Boolean, b2 = true: jet.Boolean, b3 = false: jet.Boolean, b4 = false: jet.Boolean, b5 = false: jet.Boolean, b6 = true: jet.Boolean] diff --git a/compiler/testData/resolveAnnotations/parameters/expressions/lteq.kt b/compiler/testData/resolveAnnotations/parameters/expressions/lteq.kt new file mode 100644 index 00000000000..026f4ce59e8 --- /dev/null +++ b/compiler/testData/resolveAnnotations/parameters/expressions/lteq.kt @@ -0,0 +1,12 @@ +package test + +annotation class Ann( + val b1: Boolean, + val b2: Boolean, + val b3: Boolean, + val b4: Boolean +) + +Ann(1 <= 2, 1.0 <= 2.0, 1 <= 1, 1.0 <= 1.0) class MyClass + +// EXPECTED: Ann[b1 = true: jet.Boolean, b2 = true: jet.Boolean, b3 = true: jet.Boolean, b4 = true: jet.Boolean]