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 f4bb7e2d748..d011999e2ac 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.java @@ -212,6 +212,15 @@ public class ConstantExpressionEvaluator extends JetVisitor visitUnaryExpression(@NotNull JetUnaryExpression expression, Void data) { + JetExpression leftExpression = expression.getBaseExpression(); + if (leftExpression == null) { + return null; + } + return getCallConstant(expression.getOperationReference(), leftExpression); + } + public static CompileTimeConstant createCompileTimeConstant(@NotNull Object value, @NotNull JetType expectedType) { if (value instanceof Integer) { return getIntegerValue(((Integer) value).longValue(), expectedType); 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 fe19188c502..7489c31a02b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/constantExpressionEvaluator.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/constantExpressionEvaluator.kt @@ -21,6 +21,22 @@ fun evaluateBinaryExpression(firstCompileTimeConstant: CompileTimeConstant<*>, s return null } +fun evaluateUnaryExpression(compileTimeConstant: CompileTimeConstant<*>, functionName: Name): Any? { + val compileTimeType = getCompileTimeType(compileTimeConstant) + if (compileTimeType == null) { + return null + } + + val value = compileTimeConstant.getValue() + + val function = unaryOperations[UnaryOperation(compileTimeType, functionName)] + if (function != null) { + return function(value) + } + + return null +} + fun getCompileTimeType(c: CompileTimeConstant<*>): CompileTimeType? = when (c.getValue()) { is Int -> INT is Byte -> BYTE @@ -47,8 +63,29 @@ private val BOOLEAN = CompileTimeType() private val STRING = CompileTimeType() private fun bOp(a: CompileTimeType, b: CompileTimeType, functionNameAsString: String, f: (A, B) -> Any) = BinaryOperation(a, b, Name.identifier(functionNameAsString)) to f as Function2 +private fun uOp(a: CompileTimeType, functionNameAsString: String, f: (A) -> Any) = UnaryOperation(a, Name.identifier(functionNameAsString)) to f as Function1 private data class BinaryOperation(val f: CompileTimeType, val s: CompileTimeType, val functionName: Name) +private data class UnaryOperation(val f: CompileTimeType, val functionName: Name) + +private val unaryOperations = hashMapOf, (Any?) -> Any>( + uOp(DOUBLE, "minus", { a -> a.minus() }), + uOp(FLOAT, "minus", { a -> a.minus() }), + uOp(LONG, "minus", { a -> a.minus() }), + uOp(INT, "minus", { a -> a.minus() }), + uOp(SHORT, "minus", { a -> a.minus() }), + uOp(BYTE, "minus", { a -> a.minus() }), + uOp(CHAR, "minus", { a -> a.minus() }), + uOp(DOUBLE, "plus", { a -> a.plus() }), + uOp(FLOAT, "plus", { a -> a.plus() }), + uOp(LONG, "plus", { a -> a.plus() }), + uOp(INT, "plus", { a -> a.plus() }), + uOp(SHORT, "plus", { a -> a.plus() }), + uOp(BYTE, "plus", { a -> a.plus() }), + uOp(CHAR, "plus", { a -> a.plus() }), + + uOp(BOOLEAN, "not", { a -> a.not() }) +) private val binaryOperations = hashMapOf, (Any?, Any?) -> Any>( // String 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 index 5edbd7f36e2..a367a0a06ea 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/constants/ConstantUtils.kt @@ -21,6 +21,7 @@ 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, @@ -30,7 +31,7 @@ public fun resolveCallToCompileTimeValue( ): CompileTimeConstant<*>? { if (arguments.isEmpty()) { val value = receiverValue.getValue() - return when (value) { + val toTypeConstant = when (value) { is Number -> { when(callName) { OperatorConventions.DOUBLE -> DoubleValue(value.toDouble()) @@ -57,6 +58,14 @@ public fun resolveCallToCompileTimeValue( } else -> null } + if (toTypeConstant != null) { + return toTypeConstant + } + 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) diff --git a/compiler/testData/resolveAnnotations/parameters/expressions/not.kt b/compiler/testData/resolveAnnotations/parameters/expressions/not.kt new file mode 100644 index 00000000000..c99ce6b8bbc --- /dev/null +++ b/compiler/testData/resolveAnnotations/parameters/expressions/not.kt @@ -0,0 +1,11 @@ +package test + +annotation class Ann( + val b1: Boolean, + val b2: Boolean, + val b3: Boolean +) + +Ann(!true, !false) class MyClass + +// EXPECTED: Ann[b1 = false: jet.Boolean, b2 = true: jet.Boolean] diff --git a/compiler/testData/resolveAnnotations/parameters/expressions/unaryMinus.kt b/compiler/testData/resolveAnnotations/parameters/expressions/unaryMinus.kt new file mode 100644 index 00000000000..03501dc8f47 --- /dev/null +++ b/compiler/testData/resolveAnnotations/parameters/expressions/unaryMinus.kt @@ -0,0 +1,15 @@ +package test + +annotation class Ann( + val b1: Byte, + val b2: Short, + val b3: Int, + val b4: Long, + val b5: Double, + val b6: Float, + val b7: Char +) + +Ann(-1, -1, -1, -1, -1.0, -1.0, -'c') class MyClass + +// EXPECTED: Ann[b1 = -1.toByte(): jet.Byte, b2 = -1.toShort(): jet.Short, b3 = -1.toInt(): jet.Int, b4 = -1.toLong(): jet.Long, b5 = -1.0.toDouble(): jet.Double, b6 = -1.0.toDouble(): jet.Double, b7 = -99.toInt(): jet.Int] diff --git a/compiler/testData/resolveAnnotations/parameters/expressions/unaryPlus.kt b/compiler/testData/resolveAnnotations/parameters/expressions/unaryPlus.kt new file mode 100644 index 00000000000..f1db2dfc6ca --- /dev/null +++ b/compiler/testData/resolveAnnotations/parameters/expressions/unaryPlus.kt @@ -0,0 +1,15 @@ +package test + +annotation class Ann( + val b1: Byte, + val b2: Short, + val b3: Int, + val b4: Long, + val b5: Double, + val b6: Float, + val b7: Char +) + +Ann(+1, +1, +1, +1, +1.0, +1.0, +'c') class MyClass + +// EXPECTED: Ann[b1 = 1.toByte(): jet.Byte, b2 = 1.toShort(): jet.Short, b3 = 1.toInt(): jet.Int, b4 = 1.toLong(): jet.Long, b5 = 1.0.toDouble(): jet.Double, b6 = 1.0.toDouble(): jet.Double, b7 = 99.toInt(): jet.Int] diff --git a/compiler/tests/org/jetbrains/jet/resolve/annotation/AnnotationParameterTestGenerated.java b/compiler/tests/org/jetbrains/jet/resolve/annotation/AnnotationParameterTestGenerated.java index e9993630830..ebacca2526d 100644 --- a/compiler/tests/org/jetbrains/jet/resolve/annotation/AnnotationParameterTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/resolve/annotation/AnnotationParameterTestGenerated.java @@ -198,6 +198,11 @@ public class AnnotationParameterTestGenerated extends AbstractAnnotationParamete doTest("compiler/testData/resolveAnnotations/parameters/expressions/multilineString.kt"); } + @TestMetadata("not.kt") + public void testNot() throws Exception { + doTest("compiler/testData/resolveAnnotations/parameters/expressions/not.kt"); + } + @TestMetadata("orOr.kt") public void testOrOr() throws Exception { doTest("compiler/testData/resolveAnnotations/parameters/expressions/orOr.kt"); @@ -233,6 +238,16 @@ public class AnnotationParameterTestGenerated extends AbstractAnnotationParamete doTest("compiler/testData/resolveAnnotations/parameters/expressions/strings.kt"); } + @TestMetadata("unaryMinus.kt") + public void testUnaryMinus() throws Exception { + doTest("compiler/testData/resolveAnnotations/parameters/expressions/unaryMinus.kt"); + } + + @TestMetadata("unaryPlus.kt") + public void testUnaryPlus() throws Exception { + doTest("compiler/testData/resolveAnnotations/parameters/expressions/unaryPlus.kt"); + } + } public static Test suite() {