Support all primitive literal types.
Apply simple unary operators to constants.
This commit is contained in:
committed by
Dmitry Petrov
parent
b3f605c4c4
commit
fe46a02885
+12
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
+14
-8
@@ -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
@@ -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
@@ -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
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user