Prefix increment / decrement.

Refactor IrLValue.
This commit is contained in:
Dmitry Petrov
2016-08-18 14:57:18 +03:00
committed by Dmitry Petrov
parent 68cdcfa853
commit 4a62a6b7c3
14 changed files with 313 additions and 112 deletions
@@ -38,5 +38,5 @@ fun IrExpression.toExpectedType(expectedType: KotlinType?): IrExpression {
)
}
fun IrVariable.createDefaultGetExpression(): IrExpression =
fun IrVariable.load(): IrExpression =
IrGetVariableExpressionImpl(startOffset, endOffset, descriptor)
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.generators.values.IrTemporaryVariableValue
import org.jetbrains.kotlin.psi2ir.generators.values.IrVariableValue
import org.jetbrains.kotlin.psi2ir.generators.values.IrValue
import org.jetbrains.kotlin.psi2ir.generators.values.createRematerializableValue
import org.jetbrains.kotlin.psi2ir.toExpectedType
@@ -51,7 +51,7 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
}
val irTmpVar = temporaryVariableFactory.createTemporaryVariable(irExpression, nameHint)
putValue(ktExpression, IrTemporaryVariableValue(irTmpVar))
putValue(ktExpression, IrVariableValue(irTmpVar))
return irTmpVar
}
@@ -63,7 +63,7 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
}
val irTmpVar = temporaryVariableFactory.createTemporaryVariable(irExpression, valueParameterDescriptor.name.asString())
putValue(valueParameterDescriptor, IrTemporaryVariableValue(irTmpVar))
putValue(valueParameterDescriptor, IrVariableValue(irTmpVar))
return irTmpVar
}
@@ -21,64 +21,87 @@ import org.jetbrains.kotlin.ir.expressions.IrOperator
import org.jetbrains.kotlin.lexer.KtTokens
fun getIrBinaryOperator(ktOperator: IElementType): IrOperator? =
KT_TOKEN_TO_IR_BINARY_OPERATOR[ktOperator]
internal fun getIrOperator(ktOperator: IElementType): IrOperator? =
KT_TOKEN_TO_IR_OPERATOR[ktOperator]
fun getIrPrefixOperator(ktOperator: IElementType): IrOperator? =
KT_TOKEN_TO_IR_PREFIX_OPERATOR[ktOperator]
internal val KT_TOKEN_TO_IR_OPERATOR =
mapOf(
KtTokens.EQ to IrOperator.EQ,
fun getIrPostfixOperator(ktOperator: IElementType): IrOperator? =
KT_TOKEN_TO_IR_POSTFIX_OPERATOR[ktOperator]
KtTokens.PLUSEQ to IrOperator.PLUSEQ,
KtTokens.MINUSEQ to IrOperator.MINUSEQ,
KtTokens.MULTEQ to IrOperator.MULTEQ,
KtTokens.DIVEQ to IrOperator.DIVEQ,
KtTokens.PERCEQ to IrOperator.PERCEQ,
private val KT_TOKEN_TO_IR_BINARY_OPERATOR = mapOf(
KtTokens.EQ to IrOperator.EQ,
KtTokens.PLUS to IrOperator.PLUS,
KtTokens.MINUS to IrOperator.MINUS,
KtTokens.MUL to IrOperator.MUL,
KtTokens.DIV to IrOperator.DIV,
KtTokens.PERC to IrOperator.PERC,
KtTokens.RANGE to IrOperator.RANGE,
KtTokens.PLUSEQ to IrOperator.PLUSEQ,
KtTokens.MINUSEQ to IrOperator.MINUSEQ,
KtTokens.MULTEQ to IrOperator.MULTEQ,
KtTokens.DIVEQ to IrOperator.DIVEQ,
KtTokens.PERCEQ to IrOperator.PERCEQ,
KtTokens.LT to IrOperator.LT,
KtTokens.LTEQ to IrOperator.LTEQ,
KtTokens.GT to IrOperator.GT,
KtTokens.GTEQ to IrOperator.GTEQ,
KtTokens.PLUS to IrOperator.PLUS,
KtTokens.MINUS to IrOperator.MINUS,
KtTokens.MUL to IrOperator.MUL,
KtTokens.DIV to IrOperator.DIV,
KtTokens.PERC to IrOperator.PERC,
KtTokens.RANGE to IrOperator.RANGE,
KtTokens.EQEQ to IrOperator.EQEQ,
KtTokens.EXCLEQ to IrOperator.EXCLEQ,
KtTokens.LT to IrOperator.LT,
KtTokens.LTEQ to IrOperator.LTEQ,
KtTokens.GT to IrOperator.GT,
KtTokens.GTEQ to IrOperator.GTEQ,
KtTokens.EQEQEQ to IrOperator.EQEQEQ,
KtTokens.EXCLEQEQEQ to IrOperator.EXCLEQEQ,
KtTokens.EQEQ to IrOperator.EQEQ,
KtTokens.EXCLEQ to IrOperator.EXCLEQ,
KtTokens.IN_KEYWORD to IrOperator.IN,
KtTokens.NOT_IN to IrOperator.NOT_IN,
KtTokens.EQEQEQ to IrOperator.EQEQEQ,
KtTokens.EXCLEQEQEQ to IrOperator.EXCLEQEQ,
KtTokens.ANDAND to IrOperator.ANDAND,
KtTokens.OROR to IrOperator.OROR,
KtTokens.IN_KEYWORD to IrOperator.IN,
KtTokens.NOT_IN to IrOperator.NOT_IN,
KtTokens.ELVIS to IrOperator.ELVIS
)
KtTokens.ANDAND to IrOperator.ANDAND,
KtTokens.OROR to IrOperator.OROR,
internal val AUGMENTED_ASSIGNMENTS =
KtTokens.ELVIS to IrOperator.ELVIS
)
private val KT_TOKEN_TO_IR_PREFIX_OPERATOR = mapOf(
KtTokens.PLUSPLUS to IrOperator.PREFIX_INCR,
KtTokens.MINUSMINUS to IrOperator.PREFIX_DECR,
KtTokens.EXCL to IrOperator.EXCL,
KtTokens.MINUS to IrOperator.UMINUS
)
private val KT_TOKEN_TO_IR_POSTFIX_OPERATOR = mapOf(
KtTokens.PLUSPLUS to IrOperator.POSTFIX_INCR,
KtTokens.MINUSMINUS to IrOperator.POSTFIX_DECR,
KtTokens.EXCLEXCL to IrOperator.EXCLEXCL
)
val AUGMENTED_ASSIGNMENTS =
setOf(IrOperator.PLUSEQ, IrOperator.MINUSEQ, IrOperator.MULTEQ, IrOperator.DIVEQ, IrOperator.PERCEQ)
internal val BINARY_OPERATORS_DESUGARED_TO_CALLS =
val BINARY_OPERATORS_DESUGARED_TO_CALLS =
setOf(IrOperator.PLUS, IrOperator.MINUS, IrOperator.MUL, IrOperator.DIV, IrOperator.PERC, IrOperator.RANGE)
internal val COMPARISON_OPERATORS =
val COMPARISON_OPERATORS =
setOf(IrOperator.LT, IrOperator.LTEQ, IrOperator.GT, IrOperator.GTEQ)
internal val EQUALITY_OPERATORS =
val EQUALITY_OPERATORS =
setOf(IrOperator.EQEQ, IrOperator.EXCLEQ)
internal val IDENTITY_OPERATORS =
val IDENTITY_OPERATORS =
setOf(IrOperator.EQEQEQ, IrOperator.EXCLEQEQ)
internal val IN_OPERATORS =
val IN_OPERATORS =
setOf(IrOperator.IN, IrOperator.NOT_IN)
internal val BINARY_BOOLEAN_OPERATORS =
setOf(IrOperator.ANDAND, IrOperator.OROR)
val BINARY_BOOLEAN_OPERATORS =
setOf(IrOperator.ANDAND, IrOperator.OROR)
val PREFIX_INCREMENT_DECREMENT_OPERATORS =
setOf(IrOperator.PREFIX_INCR, IrOperator.PREFIX_DECR)
val POSTFIX_INCREMENT_DECREMENT_OPERATORS =
setOf(IrOperator.POSTFIX_INCR, IrOperator.POSTFIX_DECR)
@@ -18,15 +18,14 @@ package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.ir.expressions.IrBinaryOperatorExpressionImpl
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrOperator
import org.jetbrains.kotlin.ir.expressions.IrUnaryOperatorExpressionImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPrefixExpression
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.load
import org.jetbrains.kotlin.psi2ir.generators.values.*
import org.jetbrains.kotlin.psi2ir.toExpectedType
import org.jetbrains.kotlin.resolve.BindingContext
@@ -37,9 +36,20 @@ import org.jetbrains.kotlin.types.typeUtil.makeNullable
class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerator): IrGenerator {
override val context: IrGeneratorContext get() = irStatementGenerator.context
fun generatePrefixExpression(expression: KtPrefixExpression): IrExpression {
val ktOperator = expression.operationReference.getReferencedNameElementType()
val irOperator = getIrPrefixOperator(ktOperator)
return when (irOperator) {
null -> createDummyExpression(expression, ktOperator.toString())
in PREFIX_INCREMENT_DECREMENT_OPERATORS -> generatePrefixIncrementDecrementOperator(expression, irOperator)
else -> createDummyExpression(expression, ktOperator.toString())
}
}
fun generateBinaryExpression(expression: KtBinaryExpression): IrExpression {
val ktOperator = expression.operationReference.getReferencedNameElementType()
val irOperator = getIrOperator(ktOperator)
val irOperator = getIrBinaryOperator(ktOperator)
return when (irOperator) {
null -> createDummyExpression(expression, ktOperator.toString())
@@ -142,25 +152,42 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
return IrCallGenerator(irStatementGenerator).generateCall(expression, operatorCall, irOperator)
}
private fun generatePrefixIncrementDecrementOperator(expression: KtPrefixExpression, irOperator: IrOperator): IrExpression {
val ktBaseExpression = expression.baseExpression!!
val irLValue = generateLValue(ktBaseExpression, irOperator)
val operatorCall = getResolvedCall(expression)!!
if (irLValue is IrLValueWithAugmentedStore) {
return irLValue.prefixAugmentedStore(operatorCall)
}
val opCallGenerator = IrCallGenerator(irStatementGenerator).apply { putValue(ktBaseExpression, irLValue) }
val irBlock = IrBlockExpressionImpl(expression.startOffset, expression.endOffset, irLValue.type, true, true)
val irOpCall = opCallGenerator.generateCall(expression, operatorCall, irOperator)
val irTmp = irStatementGenerator.temporaryVariableFactory.createTemporaryVariable(irOpCall)
irBlock.addStatement(irTmp)
irBlock.addStatement(irLValue.store(irTmp.load()))
irBlock.addStatement(irTmp.load())
return irBlock
}
private fun generateAugmentedAssignment(expression: KtBinaryExpression, irOperator: IrOperator): IrExpression {
val ktLeft = expression.left!!
val irLhs = generateLValue(ktLeft, irOperator)
val irLValue = generateLValue(ktLeft, irOperator)
val operatorCall = getResolvedCall(expression)!!
val isSimpleAssignment = get(BindingContext.VARIABLE_REASSIGNMENT, expression) ?: false
val operatorCall = getResolvedCall(expression)!!
if (isSimpleAssignment && irLhs is IrLValueWithAugmentedStore) {
return irLhs.augmentedStore(operatorCall, irStatementGenerator.generateExpression(expression.right!!))
if (isSimpleAssignment && irLValue is IrLValueWithAugmentedStore) {
return irLValue.augmentedStore(operatorCall, irStatementGenerator.generateExpression(expression.right!!))
}
val opCallGenerator = IrCallGenerator(irStatementGenerator).apply { putValue(ktLeft, irLhs) }
val opCallGenerator = IrCallGenerator(irStatementGenerator).apply { putValue(ktLeft, irLValue) }
val irOpCall = opCallGenerator.generateCall(expression, operatorCall, irOperator)
return if (isSimpleAssignment) {
// Set( Op( Get(), RHS ) )
irLhs.store(irOpCall)
irLValue.store(irOpCall)
}
else {
// Op( Get(), RHS )
@@ -171,8 +198,8 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
private fun generateAssignment(expression: KtBinaryExpression): IrExpression {
val ktLeft = expression.left!!
val ktRight = expression.right!!
val lhsReference = generateLValue(ktLeft, IrOperator.EQ)
return lhsReference.store(irStatementGenerator.generateExpression(ktRight))
val irLValue = generateLValue(ktLeft, IrOperator.EQ)
return irLValue.store(irStatementGenerator.generateExpression(ktRight))
}
private fun generateLValue(ktLeft: KtExpression, irOperator: IrOperator?): IrLValue {
@@ -181,8 +208,11 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
val indexExpressions = ktLeft.indexExpressions.map { it to irStatementGenerator.generateExpression(it) }
val indexedGetCall = get(BindingContext.INDEXED_LVALUE_GET, ktLeft)
val indexedSetCall = get(BindingContext.INDEXED_LVALUE_SET, ktLeft)
val type = indexedGetCall?.run { resultingDescriptor.returnType }
?: indexedSetCall?.run { resultingDescriptor.valueParameters.last().type }
?: throw AssertionError("Either 'get' or 'set' call should be present for an indexed LValue: ${ktLeft.text}")
return IrIndexedLValue(irStatementGenerator, ktLeft, irOperator,
irArrayValue, indexExpressions, indexedGetCall, indexedSetCall)
irArrayValue, type, indexExpressions, indexedGetCall, indexedSetCall)
}
val resolvedCall = getResolvedCall(ktLeft) ?: TODO("no resolved call for LHS")
@@ -193,7 +223,7 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
if (descriptor.isDelegated)
TODO("Delegated local variable")
else
IrVariableLValueValue(ktLeft, irOperator, descriptor)
IrVariableValue(ktLeft.startOffset, ktLeft.endOffset, descriptor, irOperator)
is PropertyDescriptor ->
IrCallGenerator(irStatementGenerator).run {
IrPropertyLValueValue(
@@ -207,4 +237,5 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
TODO("Other cases of LHS")
}
}
}
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.deparenthesize
import org.jetbrains.kotlin.psi2ir.generators.values.IrTemporaryVariableValue
import org.jetbrains.kotlin.psi2ir.generators.values.IrVariableValue
import org.jetbrains.kotlin.psi2ir.toExpectedType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContextUtils
@@ -79,7 +79,7 @@ class IrStatementGenerator(
irBlock.addStatement(irTmpInitializer)
val irCallGenerator = IrCallGenerator(this)
irCallGenerator.putValue(ktInitializer, IrTemporaryVariableValue(irTmpInitializer))
irCallGenerator.putValue(ktInitializer, IrVariableValue(irTmpInitializer))
for ((index, ktEntry) in multiDeclaration.entries.withIndex()) {
val componentResolvedCall = getOrFail(BindingContext.COMPONENT_RESOLVED_CALL, ktEntry)
@@ -241,4 +241,7 @@ class IrStatementGenerator(
override fun visitBinaryExpression(expression: KtBinaryExpression, data: Nothing?): IrStatement =
IrOperatorExpressionGenerator(this).generateBinaryExpression(expression)
override fun visitPrefixExpression(expression: KtPrefixExpression, data: Nothing?): IrStatement =
IrOperatorExpressionGenerator(this).generatePrefixExpression(expression)
}
@@ -21,15 +21,18 @@ import org.jetbrains.kotlin.psi.KtArrayAccessExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.load
import org.jetbrains.kotlin.psi2ir.generators.IrCallGenerator
import org.jetbrains.kotlin.psi2ir.generators.IrStatementGenerator
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType
class IrIndexedLValue(
var irStatementGenerator: IrStatementGenerator,
val ktArrayAccessExpression: KtArrayAccessExpression,
val irOperator: IrOperator?,
val irArray: IrExpression,
override val type: KotlinType?,
val indexValues: List<Pair<KtExpression, IrExpression>>,
val indexedGetCall: ResolvedCall<*>?,
val indexedSetCall: ResolvedCall<*>?
@@ -37,50 +40,64 @@ class IrIndexedLValue(
override fun load(): IrExpression {
if (indexedGetCall == null) throw AssertionError("Indexed LValue has no 'get' call: ${ktArrayAccessExpression.text}")
val irBlock = IrBlockExpressionImpl(ktArrayAccessExpression.startOffset, ktArrayAccessExpression.endOffset,
indexedGetCall.resultingDescriptor.returnType,
hasResult = true, isDesugared = true)
val callGenerator = IrCallGenerator(irStatementGenerator)
defineContextVariables(irBlock, callGenerator)
irBlock.addStatement(callGenerator.generateCall(ktArrayAccessExpression, indexedGetCall, irOperator))
return irBlock
return generateGetOrSetCallAsDesugaredBlock(indexedGetCall)
}
override fun store(irExpression: IrExpression): IrExpression {
if (indexedSetCall == null) throw AssertionError("Indexed LValue has no 'set' call: ${ktArrayAccessExpression.text}")
val irBlock = IrBlockExpressionImpl(ktArrayAccessExpression.startOffset, ktArrayAccessExpression.endOffset,
indexedSetCall.resultingDescriptor.returnType,
hasResult = true, isDesugared = true)
return generateGetOrSetCallAsDesugaredBlock(indexedSetCall)
}
private fun generateGetOrSetCallAsDesugaredBlock(call: ResolvedCall<*>, irArgument: IrExpression? = null): IrExpression {
val callGenerator = IrCallGenerator(irStatementGenerator)
defineContextVariables(irBlock, callGenerator)
val hasResult = irArgument == null
val irBlock = createDesugaredBlock(call, callGenerator, hasResult)
callGenerator.putValue(indexedSetCall.resultingDescriptor.valueParameters.last(), IrSingleExpressionValue(irExpression))
if (irArgument != null) {
callGenerator.putValue(call.resultingDescriptor.valueParameters.last(), IrSingleExpressionValue(irArgument))
}
irBlock.addStatement(callGenerator.generateCall(ktArrayAccessExpression, indexedSetCall, irOperator))
irBlock.addStatement(callGenerator.generateCall(ktArrayAccessExpression, call, irOperator))
return irBlock
}
override fun augmentedStore(operatorCall: ResolvedCall<*>, irRhs: IrExpression): IrExpression {
override fun prefixAugmentedStore(operatorCall: ResolvedCall<*>): IrExpression {
if (indexedGetCall == null) throw AssertionError("Indexed LValue has no 'get' call: ${ktArrayAccessExpression.text}")
if (indexedSetCall == null) throw AssertionError("Indexed LValue has no 'set' call: ${ktArrayAccessExpression.text}")
val irBlock = IrBlockExpressionImpl(ktArrayAccessExpression.startOffset, ktArrayAccessExpression.endOffset,
indexedSetCall.resultingDescriptor.returnType,
hasResult = true, isDesugared = true)
val callGenerator = IrCallGenerator(irStatementGenerator)
val irBlock = createDesugaredBlock(indexedSetCall, callGenerator, true)
val operatorCallReceiver = operatorCall.extensionReceiver ?: operatorCall.dispatchReceiver
callGenerator.putValue(operatorCallReceiver!!,
IrSingleExpressionValue(callGenerator.generateCall(ktArrayAccessExpression, indexedGetCall, irOperator)))
val irTmp = irStatementGenerator.temporaryVariableFactory.createTemporaryVariable(
callGenerator.generateCall(ktArrayAccessExpression, operatorCall, irOperator))
irBlock.addStatement(irTmp)
callGenerator.putValue(indexedSetCall.resultingDescriptor.valueParameters.last(),
IrVariableValue(irTmp))
irBlock.addStatement(callGenerator.generateCall(ktArrayAccessExpression, indexedSetCall, irOperator))
irBlock.addStatement(irTmp.load())
return irBlock
}
override fun augmentedStore(operatorCall: ResolvedCall<*>, irOperatorArgument: IrExpression): IrExpression {
if (indexedGetCall == null) throw AssertionError("Indexed LValue has no 'get' call: ${ktArrayAccessExpression.text}")
if (indexedSetCall == null) throw AssertionError("Indexed LValue has no 'set' call: ${ktArrayAccessExpression.text}")
val callGenerator = IrCallGenerator(irStatementGenerator)
defineContextVariables(irBlock, callGenerator)
val irBlock = createDesugaredBlock(indexedSetCall, callGenerator, false)
callGenerator.putValue(operatorCall.resultingDescriptor.valueParameters[0], IrSingleExpressionValue(irRhs))
callGenerator.putValue(operatorCall.resultingDescriptor.valueParameters[0], IrSingleExpressionValue(irOperatorArgument))
val operatorCallReceiver = operatorCall.extensionReceiver ?: operatorCall.dispatchReceiver
callGenerator.putValue(operatorCallReceiver!!,
@@ -94,6 +111,16 @@ class IrIndexedLValue(
return irBlock
}
private fun createDesugaredBlock(call: ResolvedCall<*>, callGenerator: IrCallGenerator, hasResult: Boolean): IrBlockExpressionImpl {
val irBlock = IrBlockExpressionImpl(ktArrayAccessExpression.startOffset, ktArrayAccessExpression.endOffset,
call.resultingDescriptor.returnType,
hasResult, true)
defineContextVariables(irBlock, callGenerator)
return irBlock
}
private fun defineContextVariables(irBlock: IrBlockExpression, callGenerator: IrCallGenerator) {
irBlock.addIfNotNull(callGenerator.introduceTemporary(ktArrayAccessExpression.arrayExpression!!, irArray, "array"))
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.toExpectedType
import org.jetbrains.kotlin.types.KotlinType
class IrPropertyLValueValue(
val ktElement: KtElement,
@@ -31,6 +32,9 @@ class IrPropertyLValueValue(
val extensionReceiver: IrExpression?,
val isSafe: Boolean
) : IrLValue {
override val type: KotlinType?
get() = descriptor.type
private fun IrPropertyAccessExpression.setReceivers() =
apply {
dispatchReceiver = this@IrPropertyLValueValue.dispatchReceiver
@@ -17,8 +17,14 @@
package org.jetbrains.kotlin.psi2ir.generators.values
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.types.KotlinType
interface IrRematerializableValue : IrValue
interface IrRematerializableValue : IrValue {
val irExpression: IrExpression
override val type: KotlinType?
get() = irExpression.type
}
fun createRematerializableValue(irExpression: IrExpression): IrRematerializableValue? =
when (irExpression) {
@@ -29,23 +35,23 @@ fun createRematerializableValue(irExpression: IrExpression): IrRematerializableV
else -> null
}
class IrRematerializableLiteralValue(val irExpression: IrLiteralExpression<*>): IrRematerializableValue {
class IrRematerializableLiteralValue(override val irExpression: IrLiteralExpression<*>): IrRematerializableValue {
override fun load(): IrExpression =
IrLiteralExpressionImpl(irExpression.startOffset, irExpression.endOffset, irExpression.type,
irExpression.kind, irExpression.kind.valueOf(irExpression))
}
class IrRematerializableVariableValue(val irExpression: IrGetVariableExpression) : IrRematerializableValue {
class IrRematerializableVariableValue(override val irExpression: IrGetVariableExpression) : IrRematerializableValue {
override fun load(): IrExpression =
IrGetVariableExpressionImpl(irExpression.startOffset, irExpression.endOffset, irExpression.descriptor)
}
class IrRematerializableExtensionReceiverValue(val irExpression: IrGetExtensionReceiverExpression) : IrRematerializableValue {
class IrRematerializableExtensionReceiverValue(override val irExpression: IrGetExtensionReceiverExpression) : IrRematerializableValue {
override fun load(): IrExpression =
IrGetExtensionReceiverExpressionImpl(irExpression.startOffset, irExpression.endOffset, irExpression.type, irExpression.descriptor)
}
class IrRematerializableThisValue(val irExpression: IrThisExpression): IrRematerializableValue {
class IrRematerializableThisValue(override val irExpression: IrThisExpression): IrRematerializableValue {
override fun load(): IrExpression =
IrThisExpressionImpl(irExpression.startOffset, irExpression.endOffset, irExpression.type, irExpression.classDescriptor)
}
@@ -17,18 +17,13 @@
package org.jetbrains.kotlin.psi2ir.generators.values
import org.jetbrains.kotlin.ir.assertDetached
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.psi2ir.createDefaultGetExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType
interface IrValue {
fun load(): IrExpression
}
class IrTemporaryVariableValue(val irVariable: IrVariable) : IrValue {
override fun load(): IrExpression =
irVariable.createDefaultGetExpression()
val type: KotlinType?
}
class IrSingleExpressionValue(val irExpression: IrExpression) : IrValue {
@@ -45,6 +40,8 @@ class IrSingleExpressionValue(val irExpression: IrExpression) : IrValue {
}
else
throw AssertionError("Single exprssion value is already instantiated")
override val type: KotlinType? get() = irExpression.type
}
interface IrLValue : IrValue {
@@ -52,6 +49,7 @@ interface IrLValue : IrValue {
}
interface IrLValueWithAugmentedStore : IrLValue {
fun augmentedStore(operatorCall: ResolvedCall<*>, irRhs: IrExpression): IrExpression
fun prefixAugmentedStore(operatorCall: ResolvedCall<*>): IrExpression
fun augmentedStore(operatorCall: ResolvedCall<*>, irOperatorArgument: IrExpression): IrExpression
}
@@ -17,29 +17,31 @@
package org.jetbrains.kotlin.psi2ir.generators.values
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetVariableExpressionImpl
import org.jetbrains.kotlin.ir.expressions.IrOperator
import org.jetbrains.kotlin.ir.expressions.IrSetVariableExpressionImpl
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.toExpectedType
import org.jetbrains.kotlin.types.KotlinType
class IrVariableLValueValue(
val ktElement: KtElement,
val irOperator: IrOperator?,
val descriptor: VariableDescriptor
class IrVariableValue(
val startOffset: Int,
val endOffset: Int,
val descriptor: VariableDescriptor,
val irOperator: IrOperator? = null
) : IrLValue {
constructor(
irVariable: IrVariable,
irOperator: IrOperator? = null
) : this(irVariable.startOffset, irVariable.endOffset, irVariable.descriptor, irOperator)
override val type: KotlinType? get() = descriptor.type
override fun load(): IrExpression =
IrGetVariableExpressionImpl(
ktElement.startOffset, ktElement.endOffset,
descriptor, irOperator
)
IrGetVariableExpressionImpl(startOffset, endOffset, descriptor, irOperator)
override fun store(irExpression: IrExpression): IrExpression =
IrSetVariableExpressionImpl(
ktElement.startOffset, ktElement.endOffset,
descriptor, irExpression.toExpectedType(descriptor.type), irOperator
)
IrSetVariableExpressionImpl(startOffset, endOffset, descriptor,
irExpression.toExpectedType(descriptor.type), irOperator)
}
@@ -20,10 +20,12 @@ abstract class IrOperator(val debugName: String) {
override fun toString(): String = debugName
object INVOKE : IrOperator("INVOKE")
object PREFIX_INCR : IrOperator("PREFIX_INCR")
object PREFIX_DECR : IrOperator("PREFIX_DECR")
object POSTFIX_INCR : IrOperator("POSTFIX_INCR")
object POSTFIX_DECR : IrOperator("POSTFIX_DECR")
object UMINUS : IrOperator("UMINUS")
object EXCL : IrOperator("EXCL")
object EXCLEXCL : IrOperator("EXCLEXCL")
+18
View File
@@ -0,0 +1,18 @@
var p: Int = 0
val arr = intArrayOf(1, 2, 3)
fun testVar() {
var x = 0
val x1 = ++x
val x2 = --x
}
fun testProp() {
val p1 = ++p
val p2 = --p
}
fun testArray() {
val a1 = ++arr[0]
val a2 = --arr[0]
}
+81
View File
@@ -0,0 +1,81 @@
IrFile /incrementDecrement.kt
IrProperty public var p: kotlin.Int getter=null setter=null
IrExpressionBody
LITERAL Int type=kotlin.Int value='0'
IrProperty public val arr: kotlin.IntArray getter=null setter=null
IrExpressionBody
CALL .intArrayOf type=kotlin.IntArray operator=
elements: DUMMY vararg type=kotlin.Int
IrFunction public fun testVar(): kotlin.Unit
IrExpressionBody
BLOCK type=<no-type> hasResult=false isDesugared=false
VAR var x: kotlin.Int
LITERAL Int type=kotlin.Int value='0'
VAR val x1: kotlin.Int
BLOCK type=kotlin.Int hasResult=true isDesugared=true
VAR val tmp0: kotlin.Int
CALL .inc type=kotlin.Int operator=PREFIX_INCR
$this: GET_VAR x type=kotlin.Int
SET_VAR x type=<no-type>
GET_VAR tmp0 type=kotlin.Int
GET_VAR tmp0 type=kotlin.Int
VAR val x2: kotlin.Int
BLOCK type=kotlin.Int hasResult=true isDesugared=true
VAR val tmp1: kotlin.Int
CALL .dec type=kotlin.Int operator=PREFIX_DECR
$this: GET_VAR x type=kotlin.Int
SET_VAR x type=<no-type>
GET_VAR tmp1 type=kotlin.Int
GET_VAR tmp1 type=kotlin.Int
IrFunction public fun testProp(): kotlin.Unit
IrExpressionBody
BLOCK type=<no-type> hasResult=false isDesugared=false
VAR val p1: kotlin.Int
BLOCK type=kotlin.Int hasResult=true isDesugared=true
VAR val tmp0: kotlin.Int
CALL .inc type=kotlin.Int operator=PREFIX_INCR
$this: GET_PROPERTY .p type=kotlin.Int
SET_PROPERTY .ptype=<no-type>
$value: GET_VAR tmp0 type=kotlin.Int
GET_VAR tmp0 type=kotlin.Int
VAR val p2: kotlin.Int
BLOCK type=kotlin.Int hasResult=true isDesugared=true
VAR val tmp1: kotlin.Int
CALL .dec type=kotlin.Int operator=PREFIX_DECR
$this: GET_PROPERTY .p type=kotlin.Int
SET_PROPERTY .ptype=<no-type>
$value: GET_VAR tmp1 type=kotlin.Int
GET_VAR tmp1 type=kotlin.Int
IrFunction public fun testArray(): kotlin.Unit
IrExpressionBody
BLOCK type=<no-type> hasResult=false isDesugared=false
VAR val a1: kotlin.Int
TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.Int
BLOCK type=kotlin.Unit hasResult=true isDesugared=true
VAR val tmp0_array: kotlin.IntArray
GET_PROPERTY .arr type=kotlin.IntArray
VAR val tmp1: kotlin.Int
CALL .inc type=kotlin.Int operator=PREFIX_INCR
$this: CALL .get type=kotlin.Int operator=PREFIX_INCR
$this: GET_VAR tmp0_array type=kotlin.IntArray
index: LITERAL Int type=kotlin.Int value='0'
CALL .set type=kotlin.Unit operator=PREFIX_INCR
$this: GET_VAR tmp0_array type=kotlin.IntArray
index: LITERAL Int type=kotlin.Int value='0'
value: GET_VAR tmp1 type=kotlin.Int
GET_VAR tmp1 type=kotlin.Int
VAR val a2: kotlin.Int
TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.Int
BLOCK type=kotlin.Unit hasResult=true isDesugared=true
VAR val tmp2_array: kotlin.IntArray
GET_PROPERTY .arr type=kotlin.IntArray
VAR val tmp3: kotlin.Int
CALL .dec type=kotlin.Int operator=PREFIX_DECR
$this: CALL .get type=kotlin.Int operator=PREFIX_DECR
$this: GET_VAR tmp2_array type=kotlin.IntArray
index: LITERAL Int type=kotlin.Int value='0'
CALL .set type=kotlin.Unit operator=PREFIX_DECR
$this: GET_VAR tmp2_array type=kotlin.IntArray
index: LITERAL Int type=kotlin.Int value='0'
value: GET_VAR tmp3 type=kotlin.Int
GET_VAR tmp3 type=kotlin.Int
@@ -137,6 +137,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
doTest(fileName);
}
@TestMetadata("incrementDecrement.kt")
public void testIncrementDecrement() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/incrementDecrement.kt");
doTest(fileName);
}
@TestMetadata("primitiveComparisons.kt")
public void testPrimitiveComparisons() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/primitiveComparisons.kt");