Support for unary expressions
This commit is contained in:
@@ -212,6 +212,15 @@ public class ConstantExpressionEvaluator extends JetVisitor<CompileTimeConstant<
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompileTimeConstant<?> 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) {
|
public static CompileTimeConstant<?> createCompileTimeConstant(@NotNull Object value, @NotNull JetType expectedType) {
|
||||||
if (value instanceof Integer) {
|
if (value instanceof Integer) {
|
||||||
return getIntegerValue(((Integer) value).longValue(), expectedType);
|
return getIntegerValue(((Integer) value).longValue(), expectedType);
|
||||||
|
|||||||
@@ -21,6 +21,22 @@ fun evaluateBinaryExpression(firstCompileTimeConstant: CompileTimeConstant<*>, s
|
|||||||
return null
|
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<out Any>? = when (c.getValue()) {
|
fun getCompileTimeType(c: CompileTimeConstant<*>): CompileTimeType<out Any>? = when (c.getValue()) {
|
||||||
is Int -> INT
|
is Int -> INT
|
||||||
is Byte -> BYTE
|
is Byte -> BYTE
|
||||||
@@ -47,8 +63,29 @@ private val BOOLEAN = CompileTimeType<Boolean>()
|
|||||||
private val STRING = CompileTimeType<String>()
|
private val STRING = CompileTimeType<String>()
|
||||||
|
|
||||||
private fun <A, B> bOp(a: CompileTimeType<A>, b: CompileTimeType<B>, functionNameAsString: String, f: (A, B) -> Any) = BinaryOperation(a, b, Name.identifier(functionNameAsString)) to f as Function2<Any?, Any?, Any>
|
private fun <A, B> bOp(a: CompileTimeType<A>, b: CompileTimeType<B>, functionNameAsString: String, f: (A, B) -> Any) = BinaryOperation(a, b, Name.identifier(functionNameAsString)) to f as Function2<Any?, Any?, Any>
|
||||||
|
private fun <A> uOp(a: CompileTimeType<A>, functionNameAsString: String, f: (A) -> Any) = UnaryOperation(a, Name.identifier(functionNameAsString)) to f as Function1<Any?, Any>
|
||||||
|
|
||||||
private data class BinaryOperation<A, B>(val f: CompileTimeType<out A>, val s: CompileTimeType<out B>, val functionName: Name)
|
private data class BinaryOperation<A, B>(val f: CompileTimeType<out A>, val s: CompileTimeType<out B>, val functionName: Name)
|
||||||
|
private data class UnaryOperation<A>(val f: CompileTimeType<out A>, val functionName: Name)
|
||||||
|
|
||||||
|
private val unaryOperations = hashMapOf<UnaryOperation<*>, (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<BinaryOperation<*, *>, (Any?, Any?) -> Any>(
|
private val binaryOperations = hashMapOf<BinaryOperation<*, *>, (Any?, Any?) -> Any>(
|
||||||
// String
|
// String
|
||||||
|
|||||||
@@ -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.evaluateBinaryExpression
|
||||||
import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator
|
import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator
|
||||||
import org.jetbrains.jet.lang.types.JetType
|
import org.jetbrains.jet.lang.types.JetType
|
||||||
|
import org.jetbrains.jet.lang.evaluate.evaluateUnaryExpression
|
||||||
|
|
||||||
public fun resolveCallToCompileTimeValue(
|
public fun resolveCallToCompileTimeValue(
|
||||||
callName: Name,
|
callName: Name,
|
||||||
@@ -30,7 +31,7 @@ public fun resolveCallToCompileTimeValue(
|
|||||||
): CompileTimeConstant<*>? {
|
): CompileTimeConstant<*>? {
|
||||||
if (arguments.isEmpty()) {
|
if (arguments.isEmpty()) {
|
||||||
val value = receiverValue.getValue()
|
val value = receiverValue.getValue()
|
||||||
return when (value) {
|
val toTypeConstant = when (value) {
|
||||||
is Number -> {
|
is Number -> {
|
||||||
when(callName) {
|
when(callName) {
|
||||||
OperatorConventions.DOUBLE -> DoubleValue(value.toDouble())
|
OperatorConventions.DOUBLE -> DoubleValue(value.toDouble())
|
||||||
@@ -57,6 +58,14 @@ public fun resolveCallToCompileTimeValue(
|
|||||||
}
|
}
|
||||||
else -> null
|
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) {
|
else if (arguments.size() == 1) {
|
||||||
val result = evaluateBinaryExpression(receiverValue, arguments.iterator().next(), callName)
|
val result = evaluateBinaryExpression(receiverValue, arguments.iterator().next(), callName)
|
||||||
|
|||||||
@@ -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]
|
||||||
@@ -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]
|
||||||
@@ -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]
|
||||||
+15
@@ -198,6 +198,11 @@ public class AnnotationParameterTestGenerated extends AbstractAnnotationParamete
|
|||||||
doTest("compiler/testData/resolveAnnotations/parameters/expressions/multilineString.kt");
|
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")
|
@TestMetadata("orOr.kt")
|
||||||
public void testOrOr() throws Exception {
|
public void testOrOr() throws Exception {
|
||||||
doTest("compiler/testData/resolveAnnotations/parameters/expressions/orOr.kt");
|
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");
|
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() {
|
public static Test suite() {
|
||||||
|
|||||||
Reference in New Issue
Block a user