Support all primitive literal types.

Apply simple unary operators to constants.
This commit is contained in:
Dmitry Petrov
2016-08-30 10:35:27 +03:00
committed by Dmitry Petrov
parent b3f605c4c4
commit fe46a02885
7 changed files with 65 additions and 19 deletions
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.lexer.KtTokens
@@ -24,6 +25,7 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.intermediate.createTemporaryVariableInBlock
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import java.lang.AssertionError
@@ -234,6 +236,16 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
private fun generatePrefixOperatorAsCall(expression: KtPrefixExpression, irOperator: IrOperator): IrExpression {
val resolvedCall = getResolvedCall(expression)!!
if (expression.baseExpression is KtConstantExpression) {
ConstantExpressionEvaluator.getConstant(expression, context.bindingContext)?.let { constant ->
val receiverType = resolvedCall.dispatchReceiver?.type
if (receiverType != null && KotlinBuiltIns.isPrimitiveType(receiverType)) {
return statementGenerator.generateConstantExpression(expression, constant)
}
}
}
return CallGenerator(statementGenerator).generateCall(expression, statementGenerator.pregenerateCall(resolvedCall), irOperator)
}
}
@@ -35,10 +35,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import org.jetbrains.kotlin.resolve.constants.BooleanValue
import org.jetbrains.kotlin.resolve.constants.IntValue
import org.jetbrains.kotlin.resolve.constants.NullValue
import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.resolve.constants.*
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
@@ -151,10 +148,13 @@ class StatementGenerator(
return IrThrowImpl(expression.startOffset, expression.endOffset, context.builtIns.nothingType, expression.thrownExpression!!.genExpr())
}
override fun visitConstantExpression(expression: KtConstantExpression, data: Nothing?): IrExpression {
val compileTimeConstant = ConstantExpressionEvaluator.getConstant(expression, context.bindingContext)
?: error("KtConstantExpression was not evaluated: ${expression.text}")
val constantValue = compileTimeConstant.toConstantValue(getInferredTypeWithImplicitCastsOrFail(expression))
override fun visitConstantExpression(expression: KtConstantExpression, data: Nothing?): IrExpression =
generateConstantExpression(expression,
ConstantExpressionEvaluator.getConstant(expression, context.bindingContext) ?:
error("KtConstantExpression was not evaluated: ${expression.text}"))
fun generateConstantExpression(expression: KtExpression, constant: CompileTimeConstant<*>): IrExpression {
val constantValue = constant.toConstantValue(getInferredTypeWithImplicitCastsOrFail(expression))
val constantType = constantValue.type
return when (constantValue) {
@@ -166,6 +166,12 @@ class StatementGenerator(
IrConstImpl.constNull(expression.startOffset, expression.endOffset, constantType)
is BooleanValue ->
IrConstImpl.boolean(expression.startOffset, expression.endOffset, constantType, constantValue.value)
is LongValue ->
IrConstImpl.long(expression.startOffset, expression.endOffset, constantType, constantValue.value)
is DoubleValue ->
IrConstImpl.double(expression.startOffset, expression.endOffset, constantType, constantValue.value)
is FloatValue ->
IrConstImpl.float(expression.startOffset, expression.endOffset, constantType, constantValue.value)
else ->
TODO("handle other literal types: ${constantValue.type}")
}
@@ -75,6 +75,15 @@ class IrConstImpl<out T> (
fun constFalse(startOffset: Int, endOffset: Int, type: KotlinType): IrConstImpl<Boolean> =
boolean(startOffset, endOffset, type, false)
fun long(startOffset: Int, endOffset: Int, type: KotlinType, value: Long): IrExpression =
IrConstImpl(startOffset, endOffset, type, IrConstKind.Long, value)
fun float(startOffset: Int, endOffset: Int, type: KotlinType, value: Float): IrExpression =
IrConstImpl(startOffset, endOffset, type, IrConstKind.Float, value)
fun double(startOffset: Int, endOffset: Int, type: KotlinType, value: Double): IrExpression =
IrConstImpl(startOffset, endOffset, type, IrConstKind.Double, value)
}
}
+1 -2
View File
@@ -12,6 +12,5 @@ FILE /ifElseIf.kt
arg0: CALL .compareTo type=kotlin.Int operator=LT
$this: GET_VAR i type=kotlin.Int operator=null
other: CONST Int type=kotlin.Int value='0'
then: CALL .unaryMinus type=kotlin.Int operator=UMINUS
$this: CONST Int type=kotlin.Int value='1'
then: CONST Int type=kotlin.Int value='-1'
else: CONST Int type=kotlin.Int value='0'
+7 -1
View File
@@ -3,4 +3,10 @@ val test2 = -1
val test3 = true
val test4 = false
val test5 = "abc"
val test6 = null
val test6 = null
val test7 = 1L
val test8 = -1L
val test9 = 1.0
val test10 = -1.0
val test11 = 1.0f
val test12 = -1.0f
+19 -2
View File
@@ -4,8 +4,7 @@ FILE /literals.kt
CONST Int type=kotlin.Int value='1'
PROPERTY public val test2: kotlin.Int = -1 getter=null setter=null
EXPRESSION_BODY
CALL .unaryMinus type=kotlin.Int operator=UMINUS
$this: CONST Int type=kotlin.Int value='1'
CONST Int type=kotlin.Int value='-1'
PROPERTY public val test3: kotlin.Boolean = true getter=null setter=null
EXPRESSION_BODY
CONST Boolean type=kotlin.Boolean value='true'
@@ -18,3 +17,21 @@ FILE /literals.kt
PROPERTY public val test6: kotlin.Nothing? = null getter=null setter=null
EXPRESSION_BODY
CONST Null type=kotlin.Nothing? value='null'
PROPERTY public val test7: kotlin.Long = 1.toLong() getter=null setter=null
EXPRESSION_BODY
CONST Long type=kotlin.Long value='1'
PROPERTY public val test8: kotlin.Long = -1.toLong() getter=null setter=null
EXPRESSION_BODY
CONST Long type=kotlin.Long value='-1'
PROPERTY public val test9: kotlin.Double = 1.0.toDouble() getter=null setter=null
EXPRESSION_BODY
CONST Double type=kotlin.Double value='1.0'
PROPERTY public val test10: kotlin.Double = -1.0.toDouble() getter=null setter=null
EXPRESSION_BODY
CONST Double type=kotlin.Double value='-1.0'
PROPERTY public val test11: kotlin.Float = 1.0.toFloat() getter=null setter=null
EXPRESSION_BODY
CONST Float type=kotlin.Float value='1.0'
PROPERTY public val test12: kotlin.Float = -1.0.toFloat() getter=null setter=null
EXPRESSION_BODY
CONST Float type=kotlin.Float value='-1.0'
@@ -7,8 +7,7 @@ FILE /simpleUnaryOperators.kt
FUN public fun test2(): kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from=test2
CALL .unaryMinus type=kotlin.Int operator=UMINUS
$this: CONST Int type=kotlin.Int value='42'
CONST Int type=kotlin.Int value='-42'
FUN public fun test3(/*0*/ x: kotlin.Int): kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from=test3
@@ -17,8 +16,7 @@ FILE /simpleUnaryOperators.kt
FUN public fun test4(): kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from=test4
CALL .unaryPlus type=kotlin.Int operator=UPLUS
$this: CONST Int type=kotlin.Int value='42'
CONST Int type=kotlin.Int value='42'
FUN public fun test5(/*0*/ x: kotlin.Boolean): kotlin.Boolean
BLOCK_BODY
RETURN type=kotlin.Nothing from=test5
@@ -27,5 +25,4 @@ FILE /simpleUnaryOperators.kt
FUN public fun test6(): kotlin.Boolean
BLOCK_BODY
RETURN type=kotlin.Nothing from=test6
CALL .not type=kotlin.Boolean operator=EXCL
$this: CONST Boolean type=kotlin.Boolean value='true'
CONST Boolean type=kotlin.Boolean value='false'