IR:
- smart casts handling separated from expression generation - improved infrastructure for desugaring
This commit is contained in:
committed by
Dmitry Petrov
parent
ecf6ab9e25
commit
0a57eb8ea4
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.psi2ir
|
||||||
|
|
||||||
|
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.IrTypeOperator
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorExpressionImpl
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
|
|
||||||
|
fun IrExpression.toExpectedType(expectedType: KotlinType?): IrExpression {
|
||||||
|
if (expectedType == null) return this
|
||||||
|
val valueType = type ?: throw AssertionError("expectedType != null, valueType == null: $this")
|
||||||
|
if (KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, expectedType)) {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
return IrTypeOperatorExpressionImpl(
|
||||||
|
startOffset, endOffset, expectedType,
|
||||||
|
IrTypeOperator.IMPLICIT_CAST, expectedType,
|
||||||
|
this
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun IrVariable.implicitGetExpression(): IrExpression =
|
||||||
|
IrGetVariableExpressionImpl(startOffset, endOffset, descriptor)
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2016 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.psi2ir.generators
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrOperator
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrSetPropertyExpressionImpl
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrSetVariableExpressionImpl
|
|
||||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
|
|
||||||
interface AssignmentLHS {
|
|
||||||
val type: KotlinType?
|
|
||||||
|
|
||||||
fun generateAssignment(ktOperation: KtBinaryExpression, irOperator: IrOperator, irRight: IrExpression): IrExpression
|
|
||||||
}
|
|
||||||
|
|
||||||
class VariableLHS(
|
|
||||||
val descriptor: VariableDescriptor
|
|
||||||
) : AssignmentLHS {
|
|
||||||
override val type: KotlinType? = descriptor.type
|
|
||||||
|
|
||||||
override fun generateAssignment(ktOperation: KtBinaryExpression, irOperator: IrOperator, irRight: IrExpression) =
|
|
||||||
IrSetVariableExpressionImpl(ktOperation.startOffset, ktOperation.endOffset, descriptor, irRight, irOperator)
|
|
||||||
}
|
|
||||||
|
|
||||||
class PropertyLHS(
|
|
||||||
val descriptor: PropertyDescriptor,
|
|
||||||
val dispatchReceiver: IrExpression?,
|
|
||||||
val extensionReceiver: IrExpression?,
|
|
||||||
val isSafe: Boolean
|
|
||||||
) : AssignmentLHS {
|
|
||||||
override val type: KotlinType? = descriptor.type
|
|
||||||
|
|
||||||
override fun generateAssignment(ktOperation: KtBinaryExpression, irOperator: IrOperator, irRight: IrExpression): IrExpression =
|
|
||||||
IrSetPropertyExpressionImpl(ktOperation.startOffset, ktOperation.endOffset, isSafe, descriptor, irOperator).apply {
|
|
||||||
dispatchReceiver = this@PropertyLHS.dispatchReceiver
|
|
||||||
extensionReceiver = this@PropertyLHS.extensionReceiver
|
|
||||||
value = irRight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
+58
-41
@@ -21,31 +21,32 @@ import org.jetbrains.kotlin.ir.expressions.*
|
|||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
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.toExpectedType
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.*
|
import org.jetbrains.kotlin.resolve.scopes.receivers.*
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.utils.newHashMapWithExpectedSize
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenerator {
|
class IrCallGenerator(
|
||||||
|
private val irStatementGenerator: IrStatementGenerator
|
||||||
|
) : IrGenerator {
|
||||||
override val context: IrGeneratorContext get() = irStatementGenerator.context
|
override val context: IrGeneratorContext get() = irStatementGenerator.context
|
||||||
|
|
||||||
private val temporaries = newHashMapWithExpectedSize<KtExpression, VariableDescriptor>(3)
|
private val expressionValues = HashMap<KtExpression, IrValue>()
|
||||||
|
private val receiverValues = HashMap<ReceiverValue, IrValue>()
|
||||||
|
private val valueArgumentValues = HashMap<ResolvedValueArgument, IrValue>()
|
||||||
|
|
||||||
fun putTemporary(ktExpression: KtExpression, temporaryVariableDescriptor: VariableDescriptor) {
|
fun putValue(ktExpression: KtExpression, irValue: IrValue) {
|
||||||
temporaries[ktExpression] = temporaryVariableDescriptor
|
expressionValues[ktExpression] = irValue
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateExpressionOrTemporary(ktExpression: KtExpression, expectedType: KotlinType?): IrExpression {
|
fun putValue(receiver: ReceiverValue, irValue: IrValue) {
|
||||||
val temporary = temporaries[ktExpression]
|
receiverValues[receiver] = irValue
|
||||||
return if (temporary != null)
|
}
|
||||||
irStatementGenerator.smartCastTo(
|
|
||||||
IrGetVariableExpressionImpl(ktExpression.startOffset, ktExpression.endOffset, temporary.type, temporary),
|
fun putValue(valueArgument: ResolvedValueArgument, irValue: IrValue) {
|
||||||
expectedType
|
valueArgumentValues[valueArgument] = irValue
|
||||||
)
|
|
||||||
else
|
|
||||||
irStatementGenerator.generateExpression(ktExpression, expectedType)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateCall(
|
fun generateCall(
|
||||||
@@ -64,10 +65,8 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
|
|||||||
returnType,
|
returnType,
|
||||||
resolvedCall.call.isSafeCall(), descriptor
|
resolvedCall.call.isSafeCall(), descriptor
|
||||||
).apply {
|
).apply {
|
||||||
dispatchReceiver = generateReceiver(ktExpression, resolvedCall.dispatchReceiver,
|
dispatchReceiver = generateReceiver(ktExpression, resolvedCall.dispatchReceiver, descriptor.dispatchReceiverParameter)
|
||||||
descriptor.dispatchReceiverParameter?.type)
|
extensionReceiver = generateReceiver(ktExpression, resolvedCall.extensionReceiver, descriptor.extensionReceiverParameter)
|
||||||
extensionReceiver = generateReceiver(ktExpression, resolvedCall.extensionReceiver,
|
|
||||||
descriptor.extensionReceiverParameter?.type)
|
|
||||||
}
|
}
|
||||||
is FunctionDescriptor ->
|
is FunctionDescriptor ->
|
||||||
generateFunctionCall(descriptor, ktExpression, returnType, operator, resolvedCall, superQualifier)
|
generateFunctionCall(descriptor, ktExpression, returnType, operator, resolvedCall, superQualifier)
|
||||||
@@ -102,10 +101,8 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
|
|||||||
ktExpression.startOffset, ktExpression.endOffset, resultType,
|
ktExpression.startOffset, ktExpression.endOffset, resultType,
|
||||||
descriptor, resolvedCall.call.isSafeCall(), operator, superQualifier
|
descriptor, resolvedCall.call.isSafeCall(), operator, superQualifier
|
||||||
)
|
)
|
||||||
irCall.dispatchReceiver = generateReceiver(ktExpression, resolvedCall.dispatchReceiver,
|
irCall.dispatchReceiver = generateReceiver(ktExpression, resolvedCall.dispatchReceiver, descriptor.dispatchReceiverParameter)
|
||||||
descriptor.dispatchReceiverParameter?.type)
|
irCall.extensionReceiver = generateReceiver(ktExpression, resolvedCall.extensionReceiver, descriptor.extensionReceiverParameter)
|
||||||
irCall.extensionReceiver = generateReceiver(ktExpression, resolvedCall.extensionReceiver,
|
|
||||||
descriptor.extensionReceiverParameter?.type)
|
|
||||||
|
|
||||||
return if (resolvedCall.requiresArgumentReordering()) {
|
return if (resolvedCall.requiresArgumentReordering()) {
|
||||||
generateCallWithArgumentReordering(irCall, ktExpression, resolvedCall, resultType)
|
generateCallWithArgumentReordering(irCall, ktExpression, resolvedCall, resultType)
|
||||||
@@ -116,10 +113,7 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
|
|||||||
for (index in valueArguments!!.indices) {
|
for (index in valueArguments!!.indices) {
|
||||||
val valueArgument = valueArguments[index]
|
val valueArgument = valueArguments[index]
|
||||||
val valueParameter = descriptor.valueParameters[index]
|
val valueParameter = descriptor.valueParameters[index]
|
||||||
val irArgument = generateValueArgument(
|
val irArgument = generateValueArgument(valueArgument, valueParameter) ?: continue
|
||||||
valueArgument,
|
|
||||||
valueParameter.varargElementType ?: valueParameter.type
|
|
||||||
) ?: continue
|
|
||||||
irCall.putArgument(index, irArgument)
|
irCall.putArgument(index, irArgument)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,21 +134,19 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
|
|||||||
hasResult = isUsedAsExpression(ktExpression),
|
hasResult = isUsedAsExpression(ktExpression),
|
||||||
isDesugared = true)
|
isDesugared = true)
|
||||||
|
|
||||||
val temporaryVariablesForValueArguments = HashMap<ResolvedValueArgument, Pair<VariableDescriptor, IrExpression>>()
|
val temporariesForValueArguments = HashMap<ResolvedValueArgument, Pair<VariableDescriptor, IrExpression>>()
|
||||||
for (valueArgument in valueArgumentsInEvaluationOrder) {
|
for (valueArgument in valueArgumentsInEvaluationOrder) {
|
||||||
val irArgument = generateValueArgument(valueArgument, null) ?: continue
|
val irArgument = generateValueArgument(valueArgument) ?: continue
|
||||||
val irTemporary = irStatementGenerator.declarationFactory.createTemporaryVariable(irArgument)
|
val irTemporary = irStatementGenerator.declarationFactory.createTemporaryVariable(irArgument)
|
||||||
|
temporariesForValueArguments[valueArgument] = Pair(irTemporary.descriptor, irArgument)
|
||||||
irBlock.addStatement(irTemporary)
|
irBlock.addStatement(irTemporary)
|
||||||
|
|
||||||
temporaryVariablesForValueArguments[valueArgument] = Pair(irTemporary.descriptor, irArgument)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for ((index, valueArgument) in resolvedCall.valueArgumentsByIndex!!.withIndex()) {
|
for ((index, valueArgument) in resolvedCall.valueArgumentsByIndex!!.withIndex()) {
|
||||||
val (temporaryDescriptor, irArgument) = temporaryVariablesForValueArguments[valueArgument]!!
|
val (temporaryDescriptor, irArgument) = temporariesForValueArguments[valueArgument]!!
|
||||||
val valueParameter = resolvedCall.resultingDescriptor.valueParameters[index]
|
val valueParameter = resolvedCall.resultingDescriptor.valueParameters[index]
|
||||||
val irGetTemporary = IrGetVariableExpressionImpl(irArgument.startOffset, irArgument.endOffset, irArgument.type,
|
val irGetTemporary = IrGetVariableExpressionImpl(irArgument.startOffset, irArgument.endOffset, temporaryDescriptor)
|
||||||
temporaryDescriptor)
|
irCall.putArgument(index, irGetTemporary.toExpectedType(valueParameter.type))
|
||||||
irCall.putArgument(index, irStatementGenerator.smartCastTo(irGetTemporary, valueParameter.type))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
irBlock.addStatement(irCall)
|
irBlock.addStatement(irCall)
|
||||||
@@ -162,8 +154,16 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
|
|||||||
return irBlock
|
return irBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO smart casts on implicit receivers
|
fun generateReceiver(ktExpression: KtExpression, receiver: ReceiverValue?, receiverParameterDescriptor: ReceiverParameterDescriptor?) =
|
||||||
fun generateReceiver(ktExpression: KtExpression, receiver: ReceiverValue?, expectedType: KotlinType?): IrExpression? =
|
generateReceiver(ktExpression, receiver)?.toExpectedType(receiverParameterDescriptor?.type)
|
||||||
|
|
||||||
|
fun generateReceiver(ktExpression: KtExpression, receiver: ReceiverValue?): IrExpression? =
|
||||||
|
if (receiver == null)
|
||||||
|
null
|
||||||
|
else
|
||||||
|
receiverValues[receiver]?.load() ?: doGenerateReceiver(ktExpression, receiver)
|
||||||
|
|
||||||
|
fun doGenerateReceiver(ktExpression: KtExpression, receiver: ReceiverValue?): IrExpression? =
|
||||||
when (receiver) {
|
when (receiver) {
|
||||||
is ImplicitClassReceiver ->
|
is ImplicitClassReceiver ->
|
||||||
IrThisExpressionImpl(ktExpression.startOffset, ktExpression.startOffset, receiver.type, receiver.classDescriptor)
|
IrThisExpressionImpl(ktExpression.startOffset, ktExpression.startOffset, receiver.type, receiver.classDescriptor)
|
||||||
@@ -172,7 +172,7 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
|
|||||||
IrThisExpressionImpl(receiverExpression.startOffset, receiverExpression.endOffset, receiver.type, receiver.classDescriptor)
|
IrThisExpressionImpl(receiverExpression.startOffset, receiverExpression.endOffset, receiver.type, receiver.classDescriptor)
|
||||||
} ?: TODO("Non-implicit ThisClassReceiver should be an expression receiver")
|
} ?: TODO("Non-implicit ThisClassReceiver should be an expression receiver")
|
||||||
is ExpressionReceiver ->
|
is ExpressionReceiver ->
|
||||||
generateExpressionOrTemporary(receiver.expression, expectedType)
|
generateExpression(receiver.expression)
|
||||||
is ClassValueReceiver ->
|
is ClassValueReceiver ->
|
||||||
IrGetObjectValueExpressionImpl(receiver.expression.startOffset, receiver.expression.endOffset, receiver.type,
|
IrGetObjectValueExpressionImpl(receiver.expression.startOffset, receiver.expression.endOffset, receiver.type,
|
||||||
receiver.classQualifier.descriptor)
|
receiver.classQualifier.descriptor)
|
||||||
@@ -185,15 +185,32 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
|
|||||||
TODO("Receiver: ${receiver.javaClass.simpleName}")
|
TODO("Receiver: ${receiver.javaClass.simpleName}")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateValueArgument(valueArgument: ResolvedValueArgument, expectedType: KotlinType?) =
|
fun generateValueArgument(valueArgument: ResolvedValueArgument, valueParameterDescriptor: ValueParameterDescriptor): IrExpression? =
|
||||||
|
if (valueParameterDescriptor.varargElementType != null) {
|
||||||
|
generateValueArgument(valueArgument)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
generateValueArgument(valueArgument)?.toExpectedType(valueParameterDescriptor.type)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateValueArgument(valueArgument: ResolvedValueArgument): IrExpression? =
|
||||||
|
if (valueArgument is DefaultValueArgument)
|
||||||
|
null
|
||||||
|
else
|
||||||
|
valueArgumentValues[valueArgument]?.load() ?: doGenerateValueArgument(valueArgument)
|
||||||
|
|
||||||
|
|
||||||
|
private fun doGenerateValueArgument(valueArgument: ResolvedValueArgument): IrExpression? =
|
||||||
when (valueArgument) {
|
when (valueArgument) {
|
||||||
is DefaultValueArgument ->
|
|
||||||
null
|
|
||||||
is ExpressionValueArgument ->
|
is ExpressionValueArgument ->
|
||||||
generateExpressionOrTemporary(valueArgument.valueArgument!!.getArgumentExpression()!!, expectedType)
|
generateExpression(valueArgument.valueArgument!!.getArgumentExpression()!!)
|
||||||
is VarargValueArgument ->
|
is VarargValueArgument ->
|
||||||
TODO("vararg")
|
TODO("vararg")
|
||||||
else ->
|
else ->
|
||||||
TODO("Unexpected valueArgument: ${valueArgument.javaClass.simpleName}")
|
TODO("Unexpected valueArgument: ${valueArgument.javaClass.simpleName}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun generateExpression(ktExpression: KtExpression): IrExpression =
|
||||||
|
expressionValues[ktExpression]?.load() ?: irStatementGenerator.generateExpression(ktExpression)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
-4
@@ -70,10 +70,6 @@ class IrLocalDeclarationsFactory(val scopeOwner: DeclarationDescriptor) : IrDecl
|
|||||||
fun createDescriptorForTemporaryVariable(type: KotlinType): IrTemporaryVariableDescriptor =
|
fun createDescriptorForTemporaryVariable(type: KotlinType): IrTemporaryVariableDescriptor =
|
||||||
IrTemporaryVariableDescriptorImpl(scopeOwner, Name.identifier("tmp${nextTemporaryIndex()}"), type)
|
IrTemporaryVariableDescriptorImpl(scopeOwner, Name.identifier("tmp${nextTemporaryIndex()}"), type)
|
||||||
|
|
||||||
fun createTemporaryVariable(ktElement: KtElement, type: KotlinType): IrVariable =
|
|
||||||
IrVariableImpl(ktElement.startOffset, ktElement.endOffset, IrDeclarationOriginKind.IR_TEMPORARY_VARIABLE,
|
|
||||||
createDescriptorForTemporaryVariable(type))
|
|
||||||
|
|
||||||
fun createTemporaryVariable(irExpression: IrExpression): IrVariable =
|
fun createTemporaryVariable(irExpression: IrExpression): IrVariable =
|
||||||
IrVariableImpl(irExpression.startOffset, irExpression.endOffset, IrDeclarationOriginKind.IR_TEMPORARY_VARIABLE,
|
IrVariableImpl(irExpression.startOffset, irExpression.endOffset, IrDeclarationOriginKind.IR_TEMPORARY_VARIABLE,
|
||||||
createDescriptorForTemporaryVariable(
|
createDescriptorForTemporaryVariable(
|
||||||
|
|||||||
+3
-1
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.ir.expressions.*
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
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.toExpectedType
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
|
||||||
interface IrDeclarationGenerator : IrGenerator
|
interface IrDeclarationGenerator : IrGenerator
|
||||||
@@ -94,7 +95,8 @@ abstract class IrDeclarationGeneratorBase(
|
|||||||
|
|
||||||
private fun generateExpressionWithinContext(ktExpression: KtExpression, scopeOwner: DeclarationDescriptor): IrExpression =
|
private fun generateExpressionWithinContext(ktExpression: KtExpression, scopeOwner: DeclarationDescriptor): IrExpression =
|
||||||
IrStatementGenerator(context, scopeOwner, IrLocalDeclarationsFactory(scopeOwner))
|
IrStatementGenerator(context, scopeOwner, IrLocalDeclarationsFactory(scopeOwner))
|
||||||
.generateExpression(ktExpression, getExpectedTypeForLastInferredCall(ktExpression))
|
.generateExpression(ktExpression)
|
||||||
|
.toExpectedType(getExpectedTypeForLastInferredCall(ktExpression))
|
||||||
|
|
||||||
private fun generateFunctionBody(scopeOwner: CallableDescriptor, ktBody: KtExpression): IrBody {
|
private fun generateFunctionBody(scopeOwner: CallableDescriptor, ktBody: KtExpression): IrBody {
|
||||||
val irRhs = generateExpressionWithinContext(ktBody, scopeOwner)
|
val irRhs = generateExpressionWithinContext(ktBody, scopeOwner)
|
||||||
|
|||||||
@@ -45,9 +45,6 @@ fun <K, V : Any> IrGenerator.getOrFail(slice: ReadOnlySlice<K, V>, key: K): V =
|
|||||||
inline fun <K, V : Any> IrGenerator.getOrFail(slice: ReadOnlySlice<K, V>, key: K, message: (K) -> String): V =
|
inline fun <K, V : Any> IrGenerator.getOrFail(slice: ReadOnlySlice<K, V>, key: K, message: (K) -> String): V =
|
||||||
context.bindingContext[slice, key] ?: throw RuntimeException(message(key))
|
context.bindingContext[slice, key] ?: throw RuntimeException(message(key))
|
||||||
|
|
||||||
inline fun <K, V : Any> IrGenerator.getOrElse(slice: ReadOnlySlice<K, V>, key: K, otherwise: (K) -> V): V =
|
|
||||||
context.bindingContext[slice, key] ?: otherwise(key)
|
|
||||||
|
|
||||||
fun IrGenerator.getInferredTypeWithSmartcasts(key: KtExpression): KotlinType? =
|
fun IrGenerator.getInferredTypeWithSmartcasts(key: KtExpression): KotlinType? =
|
||||||
context.bindingContext.getType(key)
|
context.bindingContext.getType(key)
|
||||||
|
|
||||||
|
|||||||
+48
-10
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.psi2ir.generators
|
package org.jetbrains.kotlin.psi2ir.generators
|
||||||
|
|
||||||
|
import com.intellij.psi.tree.IElementType
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
@@ -23,7 +24,18 @@ import org.jetbrains.kotlin.ir.expressions.IrOperator
|
|||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
|
val KT_OPERATOR_TO_IR_OPERATOR = hashMapOf(
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerator): IrGenerator {
|
class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerator): IrGenerator {
|
||||||
override val context: IrGeneratorContext get() = irStatementGenerator.context
|
override val context: IrGeneratorContext get() = irStatementGenerator.context
|
||||||
@@ -33,18 +45,46 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
|
|||||||
|
|
||||||
return when (ktOperator) {
|
return when (ktOperator) {
|
||||||
KtTokens.EQ -> generateAssignment(expression)
|
KtTokens.EQ -> generateAssignment(expression)
|
||||||
|
in KtTokens.AUGMENTED_ASSIGNMENTS -> generateAugmentedAssignment(expression, ktOperator)
|
||||||
else -> createDummyExpression(expression, ktOperator.toString())
|
else -> createDummyExpression(expression, ktOperator.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun generateAugmentedAssignment(expression: KtBinaryExpression, ktOperator: IElementType): IrExpression {
|
||||||
|
val ktLeft = expression.left!!
|
||||||
|
|
||||||
|
val irOperator = getIrOperator(ktOperator)
|
||||||
|
val lhs = generateReferenceForAssignmentLhs(ktLeft, irOperator)
|
||||||
|
|
||||||
|
val isSimpleAssignment = get(BindingContext.VARIABLE_REASSIGNMENT, expression) ?: false
|
||||||
|
|
||||||
|
val operatorCall = getResolvedCall(expression)!!
|
||||||
|
|
||||||
|
val opCallGenerator = IrCallGenerator(irStatementGenerator).apply { putValue(ktLeft, lhs) }
|
||||||
|
val irOpCall = opCallGenerator.generateCall(expression, operatorCall, irOperator)
|
||||||
|
|
||||||
|
return if (isSimpleAssignment) {
|
||||||
|
// Set( Op( Get(), RHS ) )
|
||||||
|
lhs.store(irOpCall)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Op( Get(), RHS )
|
||||||
|
irOpCall
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getIrOperator(ktOperator: IElementType): IrOperator {
|
||||||
|
return KT_OPERATOR_TO_IR_OPERATOR[ktOperator] ?: TODO("Operator: $ktOperator")
|
||||||
|
}
|
||||||
|
|
||||||
private fun generateAssignment(expression: KtBinaryExpression): IrExpression {
|
private fun generateAssignment(expression: KtBinaryExpression): IrExpression {
|
||||||
val ktLeft = expression.left!!
|
val ktLeft = expression.left!!
|
||||||
val ktRight = expression.right!!
|
val ktRight = expression.right!!
|
||||||
val lhs = generateAssignmentLHS(ktLeft)
|
val lhsReference = generateReferenceForAssignmentLhs(ktLeft, IrOperator.EQ)
|
||||||
return lhs.generateAssignment(expression, IrOperator.EQ, irStatementGenerator.generateExpression(ktRight, lhs.type))
|
return lhsReference.store(irStatementGenerator.generateExpression(ktRight))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateAssignmentLHS(ktLeft: KtExpression): AssignmentLHS {
|
private fun generateReferenceForAssignmentLhs(ktLeft: KtExpression, irOperator: IrOperator?): IrReference {
|
||||||
val resolvedCall = getResolvedCall(ktLeft) ?: TODO("no resolved call for LHS")
|
val resolvedCall = getResolvedCall(ktLeft) ?: TODO("no resolved call for LHS")
|
||||||
val descriptor = resolvedCall.candidateDescriptor
|
val descriptor = resolvedCall.candidateDescriptor
|
||||||
|
|
||||||
@@ -53,15 +93,13 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
|
|||||||
if (descriptor.isDelegated)
|
if (descriptor.isDelegated)
|
||||||
TODO("Delegated local variable")
|
TODO("Delegated local variable")
|
||||||
else
|
else
|
||||||
VariableLHS(descriptor)
|
IrVariableReferenceValue(ktLeft, irOperator, descriptor)
|
||||||
is PropertyDescriptor ->
|
is PropertyDescriptor ->
|
||||||
IrCallGenerator(irStatementGenerator).run {
|
IrCallGenerator(irStatementGenerator).run {
|
||||||
PropertyLHS(
|
IrPropertyReferenceValue(
|
||||||
descriptor,
|
ktLeft, irOperator, descriptor,
|
||||||
generateReceiver(ktLeft, resolvedCall.dispatchReceiver,
|
generateReceiver(ktLeft, resolvedCall.dispatchReceiver, descriptor.dispatchReceiverParameter),
|
||||||
descriptor.dispatchReceiverParameter?.type),
|
generateReceiver(ktLeft, resolvedCall.extensionReceiver, descriptor.extensionReceiverParameter),
|
||||||
generateReceiver(ktLeft, resolvedCall.extensionReceiver,
|
|
||||||
descriptor.extensionReceiverParameter?.type),
|
|
||||||
resolvedCall.call.isSafeCall()
|
resolvedCall.call.isSafeCall()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-34
@@ -24,6 +24,8 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
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.deparenthesize
|
import org.jetbrains.kotlin.psi2ir.deparenthesize
|
||||||
|
import org.jetbrains.kotlin.psi2ir.implicitGetExpression
|
||||||
|
import org.jetbrains.kotlin.psi2ir.toExpectedType
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.BindingContextUtils
|
import org.jetbrains.kotlin.resolve.BindingContextUtils
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
@@ -32,8 +34,6 @@ import org.jetbrains.kotlin.resolve.constants.IntValue
|
|||||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
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.KotlinType
|
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||||
|
|
||||||
class IrStatementGenerator(
|
class IrStatementGenerator(
|
||||||
@@ -42,32 +42,14 @@ class IrStatementGenerator(
|
|||||||
val declarationFactory: IrLocalDeclarationsFactory
|
val declarationFactory: IrLocalDeclarationsFactory
|
||||||
) : KtVisitor<IrStatement, Nothing?>(), IrGenerator {
|
) : KtVisitor<IrStatement, Nothing?>(), IrGenerator {
|
||||||
|
|
||||||
fun generateExpression(ktExpression: KtExpression, expectedType: KotlinType?): IrExpression =
|
fun generateExpression(ktExpression: KtExpression): IrExpression =
|
||||||
ktExpression.genExpr(expectedType)
|
ktExpression.genExpr()
|
||||||
|
|
||||||
private fun KtElement.genStmt(expectedType: KotlinType?): IrStatement {
|
private fun KtElement.genStmt(): IrStatement =
|
||||||
val irStatement = deparenthesize().accept(this@IrStatementGenerator, null)
|
deparenthesize().accept(this@IrStatementGenerator, null)
|
||||||
if (irStatement is IrExpression) {
|
|
||||||
return smartCastTo(irStatement, expectedType)
|
|
||||||
}
|
|
||||||
return irStatement
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun KtElement.genExpr(expectedType: KotlinType?): IrExpression =
|
|
||||||
genStmt(expectedType).assertCast()
|
|
||||||
|
|
||||||
fun smartCastTo(irExpression: IrExpression, expectedType: KotlinType?): IrExpression {
|
|
||||||
val actualType = irExpression.type
|
|
||||||
if (expectedType != null && actualType != null && !KotlinTypeChecker.DEFAULT.isSubtypeOf(actualType, expectedType)) {
|
|
||||||
return IrTypeOperatorExpressionImpl(
|
|
||||||
irExpression.startOffset, irExpression.endOffset, expectedType,
|
|
||||||
IrTypeOperator.SMART_AS, expectedType,
|
|
||||||
irExpression
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return irExpression
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private fun KtElement.genExpr(): IrExpression =
|
||||||
|
genStmt().assertCast()
|
||||||
|
|
||||||
override fun visitExpression(expression: KtExpression, data: Nothing?): IrStatement =
|
override fun visitExpression(expression: KtExpression, data: Nothing?): IrStatement =
|
||||||
createDummyExpression(expression, expression.javaClass.simpleName)
|
createDummyExpression(expression, expression.javaClass.simpleName)
|
||||||
@@ -78,7 +60,9 @@ class IrStatementGenerator(
|
|||||||
val variableDescriptor = getOrFail(BindingContext.VARIABLE, property)
|
val variableDescriptor = getOrFail(BindingContext.VARIABLE, property)
|
||||||
|
|
||||||
val irLocalVariable = declarationFactory.createLocalVariable(property, variableDescriptor)
|
val irLocalVariable = declarationFactory.createLocalVariable(property, variableDescriptor)
|
||||||
irLocalVariable.initializer = property.initializer?.genExpr(variableDescriptor.type)
|
irLocalVariable.initializer = property.initializer?.let {
|
||||||
|
it.genExpr().toExpectedType(variableDescriptor.type)
|
||||||
|
}
|
||||||
|
|
||||||
return irLocalVariable
|
return irLocalVariable
|
||||||
}
|
}
|
||||||
@@ -89,10 +73,11 @@ class IrStatementGenerator(
|
|||||||
val irBlock = IrBlockExpressionImpl(multiDeclaration.startOffset, multiDeclaration.endOffset, null,
|
val irBlock = IrBlockExpressionImpl(multiDeclaration.startOffset, multiDeclaration.endOffset, null,
|
||||||
hasResult = false, isDesugared = true)
|
hasResult = false, isDesugared = true)
|
||||||
val ktInitializer = multiDeclaration.initializer!!
|
val ktInitializer = multiDeclaration.initializer!!
|
||||||
val irInitializer = declarationFactory.createTemporaryVariable(ktInitializer.genExpr(null))
|
val irInitializerVal = declarationFactory.createTemporaryVariable(ktInitializer.genExpr())
|
||||||
irBlock.addStatement(irInitializer)
|
irBlock.addStatement(irInitializerVal)
|
||||||
|
|
||||||
val irCallGenerator = IrCallGenerator(this).apply { putTemporary(ktInitializer, irInitializer.descriptor) }
|
val irCallGenerator = IrCallGenerator(this)
|
||||||
|
irCallGenerator.putValue(ktInitializer, justExpressionValue { irInitializerVal.implicitGetExpression() })
|
||||||
|
|
||||||
for ((index, ktEntry) in multiDeclaration.entries.withIndex()) {
|
for ((index, ktEntry) in multiDeclaration.entries.withIndex()) {
|
||||||
val componentResolvedCall = getOrFail(BindingContext.COMPONENT_RESOLVED_CALL, ktEntry)
|
val componentResolvedCall = getOrFail(BindingContext.COMPONENT_RESOLVED_CALL, ktEntry)
|
||||||
@@ -108,7 +93,7 @@ class IrStatementGenerator(
|
|||||||
override fun visitBlockExpression(expression: KtBlockExpression, data: Nothing?): IrStatement {
|
override fun visitBlockExpression(expression: KtBlockExpression, data: Nothing?): IrStatement {
|
||||||
val irBlock = IrBlockExpressionImpl(expression.startOffset, expression.endOffset, getReturnType(expression),
|
val irBlock = IrBlockExpressionImpl(expression.startOffset, expression.endOffset, getReturnType(expression),
|
||||||
hasResult = isUsedAsExpression(expression), isDesugared = false)
|
hasResult = isUsedAsExpression(expression), isDesugared = false)
|
||||||
expression.statements.forEach { irBlock.addStatement(it.genStmt(null)) }
|
expression.statements.forEach { irBlock.addStatement(it.genStmt()) }
|
||||||
return irBlock
|
return irBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +102,7 @@ class IrStatementGenerator(
|
|||||||
return IrReturnExpressionImpl(
|
return IrReturnExpressionImpl(
|
||||||
expression.startOffset, expression.endOffset,
|
expression.startOffset, expression.endOffset,
|
||||||
returnTarget,
|
returnTarget,
|
||||||
expression.returnedExpression?.let { it.genExpr(returnTarget.returnType) }
|
expression.returnedExpression?.let { it.genExpr().toExpectedType(returnTarget.returnType) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +145,7 @@ class IrStatementGenerator(
|
|||||||
if (expression.entries.size == 1) {
|
if (expression.entries.size == 1) {
|
||||||
val entry0 = expression.entries[0]
|
val entry0 = expression.entries[0]
|
||||||
if (entry0 is KtLiteralStringTemplateEntry) {
|
if (entry0 is KtLiteralStringTemplateEntry) {
|
||||||
return entry0.genExpr(null)
|
return entry0.genExpr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,7 +185,7 @@ class IrStatementGenerator(
|
|||||||
IrCallGenerator(this).generateCall(expression, resolvedCall)
|
IrCallGenerator(this).generateCall(expression, resolvedCall)
|
||||||
}
|
}
|
||||||
is VariableDescriptor ->
|
is VariableDescriptor ->
|
||||||
IrGetVariableExpressionImpl(expression.startOffset, expression.endOffset, descriptor.type, descriptor)
|
IrGetVariableExpressionImpl(expression.startOffset, expression.endOffset, descriptor)
|
||||||
else ->
|
else ->
|
||||||
IrDummyExpression(
|
IrDummyExpression(
|
||||||
expression.startOffset, expression.endOffset, getInferredTypeWithSmartcasts(expression),
|
expression.startOffset, expression.endOffset, getInferredTypeWithSmartcasts(expression),
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.psi2ir.generators
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
|
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
|
||||||
|
|
||||||
|
interface IrValue {
|
||||||
|
fun load(): IrExpression
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun justExpressionValue(crossinline makeExpression: () -> IrExpression) =
|
||||||
|
object : IrValue {
|
||||||
|
override fun load() = makeExpression()
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IrReference : IrValue {
|
||||||
|
fun store(value: IrExpression): IrExpression
|
||||||
|
}
|
||||||
|
|
||||||
|
class IrVariableReferenceValue(
|
||||||
|
val ktElement: KtElement,
|
||||||
|
val irOperator: IrOperator?,
|
||||||
|
val descriptor: VariableDescriptor
|
||||||
|
) : IrReference {
|
||||||
|
override fun load(): IrExpression =
|
||||||
|
IrGetVariableExpressionImpl(
|
||||||
|
ktElement.startOffset, ktElement.endOffset,
|
||||||
|
descriptor, irOperator
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun store(value: IrExpression): IrExpression =
|
||||||
|
IrSetVariableExpressionImpl(
|
||||||
|
ktElement.startOffset, ktElement.endOffset,
|
||||||
|
descriptor, value.toExpectedType(descriptor.type), irOperator
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
class IrPropertyReferenceValue(
|
||||||
|
val ktElement: KtElement,
|
||||||
|
val irOperator: IrOperator?,
|
||||||
|
val descriptor: PropertyDescriptor,
|
||||||
|
val dispatchReceiver: IrExpression?,
|
||||||
|
val extensionReceiver: IrExpression?,
|
||||||
|
val isSafe: Boolean
|
||||||
|
) : IrReference {
|
||||||
|
private fun IrPropertyAccessExpression.setReceivers() =
|
||||||
|
apply {
|
||||||
|
dispatchReceiver = this@IrPropertyReferenceValue.dispatchReceiver
|
||||||
|
extensionReceiver = this@IrPropertyReferenceValue.extensionReceiver
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun load(): IrExpression =
|
||||||
|
IrGetPropertyExpressionImpl(
|
||||||
|
ktElement.startOffset, ktElement.endOffset,
|
||||||
|
descriptor.type, isSafe, descriptor, irOperator
|
||||||
|
).setReceivers()
|
||||||
|
|
||||||
|
override fun store(value: IrExpression): IrExpression =
|
||||||
|
IrSetPropertyExpressionImpl(
|
||||||
|
ktElement.startOffset, ktElement.endOffset,
|
||||||
|
isSafe, descriptor, value.toExpectedType(descriptor.type), irOperator
|
||||||
|
).setReceivers()
|
||||||
|
}
|
||||||
@@ -16,52 +16,54 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.expressions
|
package org.jetbrains.kotlin.ir.expressions
|
||||||
|
|
||||||
sealed class IrOperator {
|
sealed class IrOperator(val debugName: String) {
|
||||||
object INVOKE : IrOperator()
|
override fun toString(): String = debugName
|
||||||
object PREFIX_INCR : IrOperator()
|
|
||||||
object PREFIX_DECR : IrOperator()
|
|
||||||
object POSTFIX_INCR : IrOperator()
|
|
||||||
object POSTFIX_DECR : IrOperator()
|
|
||||||
object UMINUS : IrOperator()
|
|
||||||
object EXCL : IrOperator()
|
|
||||||
object EXCLEXCL : IrOperator()
|
|
||||||
object ELVIS : IrOperator()
|
|
||||||
|
|
||||||
object LT : IrOperator()
|
object INVOKE : IrOperator("INVOKE")
|
||||||
object GT : IrOperator()
|
object PREFIX_INCR : IrOperator("PREFIX_INCR")
|
||||||
object LTEQ : IrOperator()
|
object PREFIX_DECR : IrOperator("PREFIX_DECR")
|
||||||
object GTEQ : IrOperator()
|
object POSTFIX_INCR : IrOperator("POSTFIX_INCR")
|
||||||
|
object POSTFIX_DECR : IrOperator("POSTFIX_DECR")
|
||||||
|
object UMINUS : IrOperator("UMINUS")
|
||||||
|
object EXCL : IrOperator("EXCL")
|
||||||
|
object EXCLEXCL : IrOperator("EXCLEXCL")
|
||||||
|
object ELVIS : IrOperator("ELVIS")
|
||||||
|
|
||||||
object EQEQ : IrOperator()
|
object LT : IrOperator("LT")
|
||||||
object EQEQEQ : IrOperator()
|
object GT : IrOperator("GT")
|
||||||
object EXCLEQ : IrOperator()
|
object LTEQ : IrOperator("LTEQ")
|
||||||
object EXCLEQEQ : IrOperator()
|
object GTEQ : IrOperator("GTEQ")
|
||||||
object IN : IrOperator()
|
|
||||||
object NOT_IN : IrOperator()
|
|
||||||
object ANDAND : IrOperator()
|
|
||||||
object OROR : IrOperator()
|
|
||||||
object RANGE : IrOperator()
|
|
||||||
|
|
||||||
object PLUS : IrOperator()
|
object EQEQ : IrOperator("EQEQ")
|
||||||
object MINUS : IrOperator()
|
object EQEQEQ : IrOperator("EQEQEQ")
|
||||||
object MUL : IrOperator()
|
object EXCLEQ : IrOperator("EXCLEQ")
|
||||||
object DIV : IrOperator()
|
object EXCLEQEQ : IrOperator("EXCLEQEQ")
|
||||||
object MOD : IrOperator()
|
object IN : IrOperator("IN")
|
||||||
|
object NOT_IN : IrOperator("NOT_IN")
|
||||||
|
object ANDAND : IrOperator("ANDAND")
|
||||||
|
object OROR : IrOperator("OROR")
|
||||||
|
object RANGE : IrOperator("RANGE")
|
||||||
|
|
||||||
object EQ : IrOperator()
|
object PLUS : IrOperator("PLUS")
|
||||||
object PLUSEQ : IrOperator()
|
object MINUS : IrOperator("MINUS")
|
||||||
object MINUSEQ : IrOperator()
|
object MUL : IrOperator("MUL")
|
||||||
object MULEQ : IrOperator()
|
object DIV : IrOperator("DIV")
|
||||||
object DIVEQ : IrOperator()
|
object MOD : IrOperator("MOD")
|
||||||
object MODEQ : IrOperator()
|
|
||||||
|
|
||||||
data class COMPONENT_N private constructor(val index: Int) : IrOperator() {
|
object EQ : IrOperator("EQ")
|
||||||
|
object PLUSEQ : IrOperator("PLUSEQ")
|
||||||
|
object MINUSEQ : IrOperator("MINUSEQ")
|
||||||
|
object MULTEQ : IrOperator("MULTEQ")
|
||||||
|
object DIVEQ : IrOperator("DIVEQ")
|
||||||
|
object PERCEQ : IrOperator("PERCEQ")
|
||||||
|
|
||||||
|
data class COMPONENT_N private constructor(val index: Int) : IrOperator("COMPONENT_$index") {
|
||||||
companion object {
|
companion object {
|
||||||
private val precreatedComponents = Array(32, ::COMPONENT_N)
|
private val precreatedComponents = Array(32) { i -> COMPONENT_N(i + 1) }
|
||||||
|
|
||||||
fun withIndex(index: Int) =
|
fun withIndex(index: Int) =
|
||||||
if (index < precreatedComponents.size)
|
if (index < precreatedComponents.size)
|
||||||
precreatedComponents[index]
|
precreatedComponents[index - 1]
|
||||||
else
|
else
|
||||||
COMPONENT_N(index)
|
COMPONENT_N(index)
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -23,13 +23,13 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
|
|
||||||
interface IrPropertyAccessExpression : IrMemberAccessExpression {
|
interface IrPropertyAccessExpression : IrMemberAccessExpression {
|
||||||
override val descriptor: PropertyDescriptor
|
override val descriptor: PropertyDescriptor
|
||||||
|
val operator: IrOperator?
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IrGetPropertyExpression : IrPropertyAccessExpression
|
interface IrGetPropertyExpression : IrPropertyAccessExpression
|
||||||
|
|
||||||
interface IrSetPropertyExpression : IrPropertyAccessExpression {
|
interface IrSetPropertyExpression : IrPropertyAccessExpression {
|
||||||
var value: IrExpression
|
var value: IrExpression
|
||||||
val operator: IrOperator
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class IrGetPropertyExpressionImpl(
|
class IrGetPropertyExpressionImpl(
|
||||||
@@ -37,7 +37,8 @@ class IrGetPropertyExpressionImpl(
|
|||||||
endOffset: Int,
|
endOffset: Int,
|
||||||
type: KotlinType?,
|
type: KotlinType?,
|
||||||
isSafe: Boolean,
|
isSafe: Boolean,
|
||||||
override val descriptor: PropertyDescriptor
|
override val descriptor: PropertyDescriptor,
|
||||||
|
override val operator: IrOperator? = null
|
||||||
) : IrMemberAccessExpressionBase(startOffset, endOffset, type, isSafe), IrGetPropertyExpression {
|
) : IrMemberAccessExpressionBase(startOffset, endOffset, type, isSafe), IrGetPropertyExpression {
|
||||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||||
visitor.visitGetProperty(this, data)
|
visitor.visitGetProperty(this, data)
|
||||||
@@ -48,7 +49,7 @@ class IrSetPropertyExpressionImpl(
|
|||||||
endOffset: Int,
|
endOffset: Int,
|
||||||
isSafe: Boolean,
|
isSafe: Boolean,
|
||||||
override val descriptor: PropertyDescriptor,
|
override val descriptor: PropertyDescriptor,
|
||||||
override val operator: IrOperator = IrOperator.EQ
|
override val operator: IrOperator? = null
|
||||||
) : IrMemberAccessExpressionBase(startOffset, endOffset, null, isSafe), IrSetPropertyExpression {
|
) : IrMemberAccessExpressionBase(startOffset, endOffset, null, isSafe), IrSetPropertyExpression {
|
||||||
constructor(
|
constructor(
|
||||||
startOffset: Int,
|
startOffset: Int,
|
||||||
@@ -56,7 +57,7 @@ class IrSetPropertyExpressionImpl(
|
|||||||
isSafe: Boolean,
|
isSafe: Boolean,
|
||||||
descriptor: PropertyDescriptor,
|
descriptor: PropertyDescriptor,
|
||||||
value: IrExpression,
|
value: IrExpression,
|
||||||
operator: IrOperator = IrOperator.EQ
|
operator: IrOperator? = null
|
||||||
) : this(startOffset, endOffset, isSafe, descriptor, operator) {
|
) : this(startOffset, endOffset, isSafe, descriptor, operator) {
|
||||||
this.value = value
|
this.value = value
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -21,11 +21,11 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
|||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
enum class IrTypeOperator {
|
enum class IrTypeOperator {
|
||||||
AS,
|
CAST,
|
||||||
SMART_AS,
|
IMPLICIT_CAST,
|
||||||
SAFE_AS,
|
SAFE_CAST,
|
||||||
IS,
|
INSTANCEOF,
|
||||||
NOT_IS;
|
NOT_INSTANCEOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IrTypeOperatorExpression : IrExpression {
|
interface IrTypeOperatorExpression : IrExpression {
|
||||||
|
|||||||
+7
-7
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.expressions
|
package org.jetbrains.kotlin.ir.expressions
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||||
import org.jetbrains.kotlin.ir.*
|
import org.jetbrains.kotlin.ir.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||||
@@ -24,21 +23,22 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
|
|
||||||
interface IrVariableAccessExpression : IrDeclarationReference {
|
interface IrVariableAccessExpression : IrDeclarationReference {
|
||||||
override val descriptor: VariableDescriptor
|
override val descriptor: VariableDescriptor
|
||||||
|
val operator: IrOperator?
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IrGetVariableExpression : IrVariableAccessExpression
|
interface IrGetVariableExpression : IrVariableAccessExpression
|
||||||
|
|
||||||
interface IrSetVariableExpression : IrVariableAccessExpression {
|
interface IrSetVariableExpression : IrVariableAccessExpression {
|
||||||
val value: IrExpression
|
val value: IrExpression
|
||||||
val operator: IrOperator?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class IrGetVariableExpressionImpl(
|
class IrGetVariableExpressionImpl(
|
||||||
startOffset: Int,
|
startOffset: Int,
|
||||||
endOffset: Int,
|
endOffset: Int,
|
||||||
type: KotlinType?,
|
descriptor: VariableDescriptor,
|
||||||
descriptor: VariableDescriptor
|
override val operator: IrOperator? = null
|
||||||
) : IrTerminalDeclarationReferenceBase<VariableDescriptor>(startOffset, endOffset, type, descriptor), IrGetVariableExpression {
|
) : IrTerminalDeclarationReferenceBase<VariableDescriptor>(startOffset, endOffset, descriptor.type, descriptor), IrGetVariableExpression {
|
||||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||||
visitor.visitGetVariable(this, data)
|
visitor.visitGetVariable(this, data)
|
||||||
}
|
}
|
||||||
@@ -47,14 +47,14 @@ class IrSetVariableExpressionImpl(
|
|||||||
startOffset: Int,
|
startOffset: Int,
|
||||||
endOffset: Int,
|
endOffset: Int,
|
||||||
override val descriptor: VariableDescriptor,
|
override val descriptor: VariableDescriptor,
|
||||||
override val operator: IrOperator = IrOperator.EQ
|
override val operator: IrOperator?
|
||||||
) : IrExpressionBase(startOffset, endOffset, null), IrSetVariableExpression {
|
) : IrExpressionBase(startOffset, endOffset, null), IrSetVariableExpression {
|
||||||
constructor(
|
constructor(
|
||||||
startOffset: Int,
|
startOffset: Int,
|
||||||
endOffset: Int,
|
endOffset: Int,
|
||||||
descriptor: VariableDescriptor,
|
descriptor: VariableDescriptor,
|
||||||
value: IrExpression,
|
value: IrExpression,
|
||||||
operator: IrOperator = IrOperator.EQ
|
operator: IrOperator?
|
||||||
) : this(startOffset, endOffset, descriptor, operator) {
|
) : this(startOffset, endOffset, descriptor, operator) {
|
||||||
this.value = value
|
this.value = value
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// <<< augmentedAssignment1.txt
|
||||||
|
fun test(): Int {
|
||||||
|
var x = 0
|
||||||
|
x += 10
|
||||||
|
return x
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
IrFile /augmentedAssignment1.kt
|
||||||
|
IrFunction public fun test(): kotlin.Int
|
||||||
|
IrExpressionBody
|
||||||
|
BLOCK type=<no-type> hasResult=false isDesugared=false
|
||||||
|
VAR var x: kotlin.Int
|
||||||
|
LITERAL Int type=kotlin.Int value='0'
|
||||||
|
SET_VAR x type=<no-type>
|
||||||
|
CALL .plus type=kotlin.Int operator=PLUSEQ
|
||||||
|
$this: GET_VAR x type=kotlin.Int
|
||||||
|
other: LITERAL Int type=kotlin.Int value='10'
|
||||||
|
RETURN type=<no-type>
|
||||||
|
GET_VAR x type=kotlin.Int
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
class A
|
||||||
|
|
||||||
|
operator fun A.plusAssign(s: String) {}
|
||||||
|
|
||||||
|
fun test() { // <<< augmentedAssignment2.txt
|
||||||
|
val a = A()
|
||||||
|
a += ""
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
IrFunction public fun test(): kotlin.Unit
|
||||||
|
IrExpressionBody
|
||||||
|
BLOCK type=<no-type> hasResult=false isDesugared=false
|
||||||
|
VAR val a: A
|
||||||
|
CALL .<init> type=A operator=
|
||||||
|
CALL .plusAssign type=kotlin.Unit operator=PLUSEQ
|
||||||
|
$receiver: GET_VAR a type=A
|
||||||
|
s: ? IrStringConcatenationExpressionImpl type=kotlin.String
|
||||||
+1
-1
@@ -10,5 +10,5 @@ IrFile /dotQualified.kt
|
|||||||
BLOCK type=<no-type> hasResult=false isDesugared=true
|
BLOCK type=<no-type> hasResult=false isDesugared=true
|
||||||
RETURN type=<no-type>
|
RETURN type=<no-type>
|
||||||
GET_PROPERTY ?.length type=kotlin.Int?
|
GET_PROPERTY ?.length type=kotlin.Int?
|
||||||
$this: TYPE_OP operator=SMART_AS typeOperand=kotlin.String
|
$this: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String
|
||||||
GET_VAR s type=kotlin.String?
|
GET_VAR s type=kotlin.String?
|
||||||
|
|||||||
+6
-6
@@ -21,18 +21,18 @@ IrFile /smartCasts.kt
|
|||||||
DUMMY KtIfExpression type=kotlin.Unit
|
DUMMY KtIfExpression type=kotlin.Unit
|
||||||
CALL .println type=kotlin.Unit operator=
|
CALL .println type=kotlin.Unit operator=
|
||||||
message: GET_PROPERTY .length type=kotlin.Int
|
message: GET_PROPERTY .length type=kotlin.Int
|
||||||
$this: TYPE_OP operator=SMART_AS typeOperand=kotlin.String
|
$this: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String
|
||||||
GET_VAR x type=kotlin.Any
|
GET_VAR x type=kotlin.Any
|
||||||
CALL .expectsString type=kotlin.Unit operator=
|
CALL .expectsString type=kotlin.Unit operator=
|
||||||
s: TYPE_OP operator=SMART_AS typeOperand=kotlin.String
|
s: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String
|
||||||
GET_VAR x type=kotlin.Any
|
GET_VAR x type=kotlin.Any
|
||||||
CALL .expectsInt type=kotlin.Unit operator=
|
CALL .expectsInt type=kotlin.Unit operator=
|
||||||
i: GET_PROPERTY .length type=kotlin.Int
|
i: GET_PROPERTY .length type=kotlin.Int
|
||||||
$this: TYPE_OP operator=SMART_AS typeOperand=kotlin.String
|
$this: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String
|
||||||
GET_VAR x type=kotlin.Any
|
GET_VAR x type=kotlin.Any
|
||||||
CALL .expectsString type=kotlin.Unit operator=
|
CALL .expectsString type=kotlin.Unit operator=
|
||||||
s: CALL .overloaded type=kotlin.String operator=
|
s: CALL .overloaded type=kotlin.String operator=
|
||||||
s: TYPE_OP operator=SMART_AS typeOperand=kotlin.String
|
s: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String
|
||||||
GET_VAR x type=kotlin.Any
|
GET_VAR x type=kotlin.Any
|
||||||
IrFunction public fun test2(/*0*/ x: kotlin.Any): kotlin.String
|
IrFunction public fun test2(/*0*/ x: kotlin.Any): kotlin.String
|
||||||
IrExpressionBody
|
IrExpressionBody
|
||||||
@@ -40,12 +40,12 @@ IrFile /smartCasts.kt
|
|||||||
DUMMY KtIfExpression type=kotlin.Unit
|
DUMMY KtIfExpression type=kotlin.Unit
|
||||||
RETURN type=<no-type>
|
RETURN type=<no-type>
|
||||||
CALL .overloaded type=kotlin.String operator=
|
CALL .overloaded type=kotlin.String operator=
|
||||||
s: TYPE_OP operator=SMART_AS typeOperand=kotlin.String
|
s: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String
|
||||||
GET_VAR x type=kotlin.Any
|
GET_VAR x type=kotlin.Any
|
||||||
IrFunction public fun test3(/*0*/ x: kotlin.Any): kotlin.String
|
IrFunction public fun test3(/*0*/ x: kotlin.Any): kotlin.String
|
||||||
IrExpressionBody
|
IrExpressionBody
|
||||||
BLOCK type=<no-type> hasResult=false isDesugared=false
|
BLOCK type=<no-type> hasResult=false isDesugared=false
|
||||||
DUMMY KtIfExpression type=kotlin.Unit
|
DUMMY KtIfExpression type=kotlin.Unit
|
||||||
RETURN type=<no-type>
|
RETURN type=<no-type>
|
||||||
TYPE_OP operator=SMART_AS typeOperand=kotlin.String
|
TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String
|
||||||
GET_VAR x type=kotlin.Any
|
GET_VAR x type=kotlin.Any
|
||||||
|
|||||||
@@ -22,5 +22,5 @@ IrFile /smartCastsWithDestructuring.kt
|
|||||||
$receiver: GET_VAR tmp0 type=I1
|
$receiver: GET_VAR tmp0 type=I1
|
||||||
VAR val c2: kotlin.String
|
VAR val c2: kotlin.String
|
||||||
CALL .component2 type=kotlin.String operator=COMPONENT_N(index=2)
|
CALL .component2 type=kotlin.String operator=COMPONENT_N(index=2)
|
||||||
$receiver: TYPE_OP operator=SMART_AS typeOperand=I2
|
$receiver: TYPE_OP operator=IMPLICIT_CAST typeOperand=I2
|
||||||
GET_VAR tmp0 type=I1
|
GET_VAR tmp0 type=I1
|
||||||
|
|||||||
@@ -41,6 +41,18 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("augmentedAssignment1.kt")
|
||||||
|
public void testAugmentedAssignment1() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/augmentedAssignment1.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("augmentedAssignment2.kt")
|
||||||
|
public void testAugmentedAssignment2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/augmentedAssignment2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("boxOk.kt")
|
@TestMetadata("boxOk.kt")
|
||||||
public void testBoxOk() throws Exception {
|
public void testBoxOk() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/boxOk.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/boxOk.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user