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
|
package org.jetbrains.kotlin.psi2ir.generators
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
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.psi.psiUtil.startOffset
|
||||||
import org.jetbrains.kotlin.psi2ir.intermediate.createTemporaryVariableInBlock
|
import org.jetbrains.kotlin.psi2ir.intermediate.createTemporaryVariableInBlock
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
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.makeNotNullable
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||||
import java.lang.AssertionError
|
import java.lang.AssertionError
|
||||||
@@ -234,6 +236,16 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
|
|||||||
|
|
||||||
private fun generatePrefixOperatorAsCall(expression: KtPrefixExpression, irOperator: IrOperator): IrExpression {
|
private fun generatePrefixOperatorAsCall(expression: KtPrefixExpression, irOperator: IrOperator): IrExpression {
|
||||||
val resolvedCall = getResolvedCall(expression)!!
|
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)
|
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.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
||||||
import org.jetbrains.kotlin.resolve.constants.BooleanValue
|
import org.jetbrains.kotlin.resolve.constants.*
|
||||||
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.evaluate.ConstantExpressionEvaluator
|
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
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())
|
return IrThrowImpl(expression.startOffset, expression.endOffset, context.builtIns.nothingType, expression.thrownExpression!!.genExpr())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitConstantExpression(expression: KtConstantExpression, data: Nothing?): IrExpression {
|
override fun visitConstantExpression(expression: KtConstantExpression, data: Nothing?): IrExpression =
|
||||||
val compileTimeConstant = ConstantExpressionEvaluator.getConstant(expression, context.bindingContext)
|
generateConstantExpression(expression,
|
||||||
?: error("KtConstantExpression was not evaluated: ${expression.text}")
|
ConstantExpressionEvaluator.getConstant(expression, context.bindingContext) ?:
|
||||||
val constantValue = compileTimeConstant.toConstantValue(getInferredTypeWithImplicitCastsOrFail(expression))
|
error("KtConstantExpression was not evaluated: ${expression.text}"))
|
||||||
|
|
||||||
|
fun generateConstantExpression(expression: KtExpression, constant: CompileTimeConstant<*>): IrExpression {
|
||||||
|
val constantValue = constant.toConstantValue(getInferredTypeWithImplicitCastsOrFail(expression))
|
||||||
val constantType = constantValue.type
|
val constantType = constantValue.type
|
||||||
|
|
||||||
return when (constantValue) {
|
return when (constantValue) {
|
||||||
@@ -166,6 +166,12 @@ class StatementGenerator(
|
|||||||
IrConstImpl.constNull(expression.startOffset, expression.endOffset, constantType)
|
IrConstImpl.constNull(expression.startOffset, expression.endOffset, constantType)
|
||||||
is BooleanValue ->
|
is BooleanValue ->
|
||||||
IrConstImpl.boolean(expression.startOffset, expression.endOffset, constantType, constantValue.value)
|
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 ->
|
else ->
|
||||||
TODO("handle other literal types: ${constantValue.type}")
|
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> =
|
fun constFalse(startOffset: Int, endOffset: Int, type: KotlinType): IrConstImpl<Boolean> =
|
||||||
boolean(startOffset, endOffset, type, false)
|
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
|
arg0: CALL .compareTo type=kotlin.Int operator=LT
|
||||||
$this: GET_VAR i type=kotlin.Int operator=null
|
$this: GET_VAR i type=kotlin.Int operator=null
|
||||||
other: CONST Int type=kotlin.Int value='0'
|
other: CONST Int type=kotlin.Int value='0'
|
||||||
then: CALL .unaryMinus type=kotlin.Int operator=UMINUS
|
then: CONST Int type=kotlin.Int value='-1'
|
||||||
$this: CONST Int type=kotlin.Int value='1'
|
|
||||||
else: CONST Int type=kotlin.Int value='0'
|
else: CONST Int type=kotlin.Int value='0'
|
||||||
|
|||||||
@@ -4,3 +4,9 @@ val test3 = true
|
|||||||
val test4 = false
|
val test4 = false
|
||||||
val test5 = "abc"
|
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'
|
CONST Int type=kotlin.Int value='1'
|
||||||
PROPERTY public val test2: kotlin.Int = -1 getter=null setter=null
|
PROPERTY public val test2: kotlin.Int = -1 getter=null setter=null
|
||||||
EXPRESSION_BODY
|
EXPRESSION_BODY
|
||||||
CALL .unaryMinus type=kotlin.Int operator=UMINUS
|
CONST Int type=kotlin.Int value='-1'
|
||||||
$this: CONST Int type=kotlin.Int value='1'
|
|
||||||
PROPERTY public val test3: kotlin.Boolean = true getter=null setter=null
|
PROPERTY public val test3: kotlin.Boolean = true getter=null setter=null
|
||||||
EXPRESSION_BODY
|
EXPRESSION_BODY
|
||||||
CONST Boolean type=kotlin.Boolean value='true'
|
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
|
PROPERTY public val test6: kotlin.Nothing? = null getter=null setter=null
|
||||||
EXPRESSION_BODY
|
EXPRESSION_BODY
|
||||||
CONST Null type=kotlin.Nothing? value='null'
|
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
|
FUN public fun test2(): kotlin.Int
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing from=test2
|
RETURN type=kotlin.Nothing from=test2
|
||||||
CALL .unaryMinus type=kotlin.Int operator=UMINUS
|
CONST Int type=kotlin.Int value='-42'
|
||||||
$this: CONST Int type=kotlin.Int value='42'
|
|
||||||
FUN public fun test3(/*0*/ x: kotlin.Int): kotlin.Int
|
FUN public fun test3(/*0*/ x: kotlin.Int): kotlin.Int
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing from=test3
|
RETURN type=kotlin.Nothing from=test3
|
||||||
@@ -17,8 +16,7 @@ FILE /simpleUnaryOperators.kt
|
|||||||
FUN public fun test4(): kotlin.Int
|
FUN public fun test4(): kotlin.Int
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing from=test4
|
RETURN type=kotlin.Nothing from=test4
|
||||||
CALL .unaryPlus type=kotlin.Int operator=UPLUS
|
CONST Int type=kotlin.Int value='42'
|
||||||
$this: CONST Int type=kotlin.Int value='42'
|
|
||||||
FUN public fun test5(/*0*/ x: kotlin.Boolean): kotlin.Boolean
|
FUN public fun test5(/*0*/ x: kotlin.Boolean): kotlin.Boolean
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing from=test5
|
RETURN type=kotlin.Nothing from=test5
|
||||||
@@ -27,5 +25,4 @@ FILE /simpleUnaryOperators.kt
|
|||||||
FUN public fun test6(): kotlin.Boolean
|
FUN public fun test6(): kotlin.Boolean
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing from=test6
|
RETURN type=kotlin.Nothing from=test6
|
||||||
CALL .not type=kotlin.Boolean operator=EXCL
|
CONST Boolean type=kotlin.Boolean value='false'
|
||||||
$this: CONST Boolean type=kotlin.Boolean value='true'
|
|
||||||
|
|||||||
Reference in New Issue
Block a user