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.psiUtil.endOffset
|
||||
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.model.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.newHashMapWithExpectedSize
|
||||
import java.util.*
|
||||
|
||||
class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenerator {
|
||||
class IrCallGenerator(
|
||||
private val irStatementGenerator: IrStatementGenerator
|
||||
) : IrGenerator {
|
||||
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) {
|
||||
temporaries[ktExpression] = temporaryVariableDescriptor
|
||||
fun putValue(ktExpression: KtExpression, irValue: IrValue) {
|
||||
expressionValues[ktExpression] = irValue
|
||||
}
|
||||
|
||||
private fun generateExpressionOrTemporary(ktExpression: KtExpression, expectedType: KotlinType?): IrExpression {
|
||||
val temporary = temporaries[ktExpression]
|
||||
return if (temporary != null)
|
||||
irStatementGenerator.smartCastTo(
|
||||
IrGetVariableExpressionImpl(ktExpression.startOffset, ktExpression.endOffset, temporary.type, temporary),
|
||||
expectedType
|
||||
)
|
||||
else
|
||||
irStatementGenerator.generateExpression(ktExpression, expectedType)
|
||||
fun putValue(receiver: ReceiverValue, irValue: IrValue) {
|
||||
receiverValues[receiver] = irValue
|
||||
}
|
||||
|
||||
fun putValue(valueArgument: ResolvedValueArgument, irValue: IrValue) {
|
||||
valueArgumentValues[valueArgument] = irValue
|
||||
}
|
||||
|
||||
fun generateCall(
|
||||
@@ -64,10 +65,8 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
|
||||
returnType,
|
||||
resolvedCall.call.isSafeCall(), descriptor
|
||||
).apply {
|
||||
dispatchReceiver = generateReceiver(ktExpression, resolvedCall.dispatchReceiver,
|
||||
descriptor.dispatchReceiverParameter?.type)
|
||||
extensionReceiver = generateReceiver(ktExpression, resolvedCall.extensionReceiver,
|
||||
descriptor.extensionReceiverParameter?.type)
|
||||
dispatchReceiver = generateReceiver(ktExpression, resolvedCall.dispatchReceiver, descriptor.dispatchReceiverParameter)
|
||||
extensionReceiver = generateReceiver(ktExpression, resolvedCall.extensionReceiver, descriptor.extensionReceiverParameter)
|
||||
}
|
||||
is FunctionDescriptor ->
|
||||
generateFunctionCall(descriptor, ktExpression, returnType, operator, resolvedCall, superQualifier)
|
||||
@@ -102,10 +101,8 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
|
||||
ktExpression.startOffset, ktExpression.endOffset, resultType,
|
||||
descriptor, resolvedCall.call.isSafeCall(), operator, superQualifier
|
||||
)
|
||||
irCall.dispatchReceiver = generateReceiver(ktExpression, resolvedCall.dispatchReceiver,
|
||||
descriptor.dispatchReceiverParameter?.type)
|
||||
irCall.extensionReceiver = generateReceiver(ktExpression, resolvedCall.extensionReceiver,
|
||||
descriptor.extensionReceiverParameter?.type)
|
||||
irCall.dispatchReceiver = generateReceiver(ktExpression, resolvedCall.dispatchReceiver, descriptor.dispatchReceiverParameter)
|
||||
irCall.extensionReceiver = generateReceiver(ktExpression, resolvedCall.extensionReceiver, descriptor.extensionReceiverParameter)
|
||||
|
||||
return if (resolvedCall.requiresArgumentReordering()) {
|
||||
generateCallWithArgumentReordering(irCall, ktExpression, resolvedCall, resultType)
|
||||
@@ -116,10 +113,7 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
|
||||
for (index in valueArguments!!.indices) {
|
||||
val valueArgument = valueArguments[index]
|
||||
val valueParameter = descriptor.valueParameters[index]
|
||||
val irArgument = generateValueArgument(
|
||||
valueArgument,
|
||||
valueParameter.varargElementType ?: valueParameter.type
|
||||
) ?: continue
|
||||
val irArgument = generateValueArgument(valueArgument, valueParameter) ?: continue
|
||||
irCall.putArgument(index, irArgument)
|
||||
}
|
||||
}
|
||||
@@ -140,21 +134,19 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
|
||||
hasResult = isUsedAsExpression(ktExpression),
|
||||
isDesugared = true)
|
||||
|
||||
val temporaryVariablesForValueArguments = HashMap<ResolvedValueArgument, Pair<VariableDescriptor, IrExpression>>()
|
||||
val temporariesForValueArguments = HashMap<ResolvedValueArgument, Pair<VariableDescriptor, IrExpression>>()
|
||||
for (valueArgument in valueArgumentsInEvaluationOrder) {
|
||||
val irArgument = generateValueArgument(valueArgument, null) ?: continue
|
||||
val irArgument = generateValueArgument(valueArgument) ?: continue
|
||||
val irTemporary = irStatementGenerator.declarationFactory.createTemporaryVariable(irArgument)
|
||||
temporariesForValueArguments[valueArgument] = Pair(irTemporary.descriptor, irArgument)
|
||||
irBlock.addStatement(irTemporary)
|
||||
|
||||
temporaryVariablesForValueArguments[valueArgument] = Pair(irTemporary.descriptor, irArgument)
|
||||
}
|
||||
|
||||
for ((index, valueArgument) in resolvedCall.valueArgumentsByIndex!!.withIndex()) {
|
||||
val (temporaryDescriptor, irArgument) = temporaryVariablesForValueArguments[valueArgument]!!
|
||||
val (temporaryDescriptor, irArgument) = temporariesForValueArguments[valueArgument]!!
|
||||
val valueParameter = resolvedCall.resultingDescriptor.valueParameters[index]
|
||||
val irGetTemporary = IrGetVariableExpressionImpl(irArgument.startOffset, irArgument.endOffset, irArgument.type,
|
||||
temporaryDescriptor)
|
||||
irCall.putArgument(index, irStatementGenerator.smartCastTo(irGetTemporary, valueParameter.type))
|
||||
val irGetTemporary = IrGetVariableExpressionImpl(irArgument.startOffset, irArgument.endOffset, temporaryDescriptor)
|
||||
irCall.putArgument(index, irGetTemporary.toExpectedType(valueParameter.type))
|
||||
}
|
||||
|
||||
irBlock.addStatement(irCall)
|
||||
@@ -162,8 +154,16 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
|
||||
return irBlock
|
||||
}
|
||||
|
||||
// TODO smart casts on implicit receivers
|
||||
fun generateReceiver(ktExpression: KtExpression, receiver: ReceiverValue?, expectedType: KotlinType?): IrExpression? =
|
||||
fun generateReceiver(ktExpression: KtExpression, receiver: ReceiverValue?, receiverParameterDescriptor: ReceiverParameterDescriptor?) =
|
||||
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) {
|
||||
is ImplicitClassReceiver ->
|
||||
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)
|
||||
} ?: TODO("Non-implicit ThisClassReceiver should be an expression receiver")
|
||||
is ExpressionReceiver ->
|
||||
generateExpressionOrTemporary(receiver.expression, expectedType)
|
||||
generateExpression(receiver.expression)
|
||||
is ClassValueReceiver ->
|
||||
IrGetObjectValueExpressionImpl(receiver.expression.startOffset, receiver.expression.endOffset, receiver.type,
|
||||
receiver.classQualifier.descriptor)
|
||||
@@ -185,15 +185,32 @@ class IrCallGenerator(val irStatementGenerator: IrStatementGenerator) : IrGenera
|
||||
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) {
|
||||
is DefaultValueArgument ->
|
||||
null
|
||||
is ExpressionValueArgument ->
|
||||
generateExpressionOrTemporary(valueArgument.valueArgument!!.getArgumentExpression()!!, expectedType)
|
||||
generateExpression(valueArgument.valueArgument!!.getArgumentExpression()!!)
|
||||
is VarargValueArgument ->
|
||||
TODO("vararg")
|
||||
else ->
|
||||
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 =
|
||||
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 =
|
||||
IrVariableImpl(irExpression.startOffset, irExpression.endOffset, IrDeclarationOriginKind.IR_TEMPORARY_VARIABLE,
|
||||
createDescriptorForTemporaryVariable(
|
||||
|
||||
+3
-1
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.psi2ir.toExpectedType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
|
||||
interface IrDeclarationGenerator : IrGenerator
|
||||
@@ -94,7 +95,8 @@ abstract class IrDeclarationGeneratorBase(
|
||||
|
||||
private fun generateExpressionWithinContext(ktExpression: KtExpression, scopeOwner: DeclarationDescriptor): IrExpression =
|
||||
IrStatementGenerator(context, scopeOwner, IrLocalDeclarationsFactory(scopeOwner))
|
||||
.generateExpression(ktExpression, getExpectedTypeForLastInferredCall(ktExpression))
|
||||
.generateExpression(ktExpression)
|
||||
.toExpectedType(getExpectedTypeForLastInferredCall(ktExpression))
|
||||
|
||||
private fun generateFunctionBody(scopeOwner: CallableDescriptor, ktBody: KtExpression): IrBody {
|
||||
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 =
|
||||
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? =
|
||||
context.bindingContext.getType(key)
|
||||
|
||||
|
||||
+48
-10
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.psi2ir.generators
|
||||
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
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.psi.KtBinaryExpression
|
||||
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.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 {
|
||||
override val context: IrGeneratorContext get() = irStatementGenerator.context
|
||||
@@ -33,18 +45,46 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
|
||||
|
||||
return when (ktOperator) {
|
||||
KtTokens.EQ -> generateAssignment(expression)
|
||||
in KtTokens.AUGMENTED_ASSIGNMENTS -> generateAugmentedAssignment(expression, ktOperator)
|
||||
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 {
|
||||
val ktLeft = expression.left!!
|
||||
val ktRight = expression.right!!
|
||||
val lhs = generateAssignmentLHS(ktLeft)
|
||||
return lhs.generateAssignment(expression, IrOperator.EQ, irStatementGenerator.generateExpression(ktRight, lhs.type))
|
||||
val lhsReference = generateReferenceForAssignmentLhs(ktLeft, IrOperator.EQ)
|
||||
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 descriptor = resolvedCall.candidateDescriptor
|
||||
|
||||
@@ -53,15 +93,13 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
|
||||
if (descriptor.isDelegated)
|
||||
TODO("Delegated local variable")
|
||||
else
|
||||
VariableLHS(descriptor)
|
||||
IrVariableReferenceValue(ktLeft, irOperator, descriptor)
|
||||
is PropertyDescriptor ->
|
||||
IrCallGenerator(irStatementGenerator).run {
|
||||
PropertyLHS(
|
||||
descriptor,
|
||||
generateReceiver(ktLeft, resolvedCall.dispatchReceiver,
|
||||
descriptor.dispatchReceiverParameter?.type),
|
||||
generateReceiver(ktLeft, resolvedCall.extensionReceiver,
|
||||
descriptor.extensionReceiverParameter?.type),
|
||||
IrPropertyReferenceValue(
|
||||
ktLeft, irOperator, descriptor,
|
||||
generateReceiver(ktLeft, resolvedCall.dispatchReceiver, descriptor.dispatchReceiverParameter),
|
||||
generateReceiver(ktLeft, resolvedCall.extensionReceiver, descriptor.extensionReceiverParameter),
|
||||
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.startOffset
|
||||
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.BindingContextUtils
|
||||
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.evaluate.ConstantExpressionEvaluator
|
||||
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
|
||||
|
||||
class IrStatementGenerator(
|
||||
@@ -42,32 +42,14 @@ class IrStatementGenerator(
|
||||
val declarationFactory: IrLocalDeclarationsFactory
|
||||
) : KtVisitor<IrStatement, Nothing?>(), IrGenerator {
|
||||
|
||||
fun generateExpression(ktExpression: KtExpression, expectedType: KotlinType?): IrExpression =
|
||||
ktExpression.genExpr(expectedType)
|
||||
fun generateExpression(ktExpression: KtExpression): IrExpression =
|
||||
ktExpression.genExpr()
|
||||
|
||||
private fun KtElement.genStmt(expectedType: KotlinType?): IrStatement {
|
||||
val irStatement = 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.genStmt(): IrStatement =
|
||||
deparenthesize().accept(this@IrStatementGenerator, null)
|
||||
|
||||
private fun KtElement.genExpr(): IrExpression =
|
||||
genStmt().assertCast()
|
||||
|
||||
override fun visitExpression(expression: KtExpression, data: Nothing?): IrStatement =
|
||||
createDummyExpression(expression, expression.javaClass.simpleName)
|
||||
@@ -78,7 +60,9 @@ class IrStatementGenerator(
|
||||
val variableDescriptor = getOrFail(BindingContext.VARIABLE, property)
|
||||
|
||||
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
|
||||
}
|
||||
@@ -89,10 +73,11 @@ class IrStatementGenerator(
|
||||
val irBlock = IrBlockExpressionImpl(multiDeclaration.startOffset, multiDeclaration.endOffset, null,
|
||||
hasResult = false, isDesugared = true)
|
||||
val ktInitializer = multiDeclaration.initializer!!
|
||||
val irInitializer = declarationFactory.createTemporaryVariable(ktInitializer.genExpr(null))
|
||||
irBlock.addStatement(irInitializer)
|
||||
val irInitializerVal = declarationFactory.createTemporaryVariable(ktInitializer.genExpr())
|
||||
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()) {
|
||||
val componentResolvedCall = getOrFail(BindingContext.COMPONENT_RESOLVED_CALL, ktEntry)
|
||||
@@ -108,7 +93,7 @@ class IrStatementGenerator(
|
||||
override fun visitBlockExpression(expression: KtBlockExpression, data: Nothing?): IrStatement {
|
||||
val irBlock = IrBlockExpressionImpl(expression.startOffset, expression.endOffset, getReturnType(expression),
|
||||
hasResult = isUsedAsExpression(expression), isDesugared = false)
|
||||
expression.statements.forEach { irBlock.addStatement(it.genStmt(null)) }
|
||||
expression.statements.forEach { irBlock.addStatement(it.genStmt()) }
|
||||
return irBlock
|
||||
}
|
||||
|
||||
@@ -117,7 +102,7 @@ class IrStatementGenerator(
|
||||
return IrReturnExpressionImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
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) {
|
||||
val entry0 = expression.entries[0]
|
||||
if (entry0 is KtLiteralStringTemplateEntry) {
|
||||
return entry0.genExpr(null)
|
||||
return entry0.genExpr()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,7 +185,7 @@ class IrStatementGenerator(
|
||||
IrCallGenerator(this).generateCall(expression, resolvedCall)
|
||||
}
|
||||
is VariableDescriptor ->
|
||||
IrGetVariableExpressionImpl(expression.startOffset, expression.endOffset, descriptor.type, descriptor)
|
||||
IrGetVariableExpressionImpl(expression.startOffset, expression.endOffset, descriptor)
|
||||
else ->
|
||||
IrDummyExpression(
|
||||
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
|
||||
|
||||
sealed class IrOperator {
|
||||
object INVOKE : IrOperator()
|
||||
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()
|
||||
sealed 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")
|
||||
object ELVIS : IrOperator("ELVIS")
|
||||
|
||||
object LT : IrOperator()
|
||||
object GT : IrOperator()
|
||||
object LTEQ : IrOperator()
|
||||
object GTEQ : IrOperator()
|
||||
object LT : IrOperator("LT")
|
||||
object GT : IrOperator("GT")
|
||||
object LTEQ : IrOperator("LTEQ")
|
||||
object GTEQ : IrOperator("GTEQ")
|
||||
|
||||
object EQEQ : IrOperator()
|
||||
object EQEQEQ : IrOperator()
|
||||
object EXCLEQ : IrOperator()
|
||||
object EXCLEQEQ : IrOperator()
|
||||
object IN : IrOperator()
|
||||
object NOT_IN : IrOperator()
|
||||
object ANDAND : IrOperator()
|
||||
object OROR : IrOperator()
|
||||
object RANGE : IrOperator()
|
||||
object EQEQ : IrOperator("EQEQ")
|
||||
object EQEQEQ : IrOperator("EQEQEQ")
|
||||
object EXCLEQ : IrOperator("EXCLEQ")
|
||||
object EXCLEQEQ : IrOperator("EXCLEQEQ")
|
||||
object IN : IrOperator("IN")
|
||||
object NOT_IN : IrOperator("NOT_IN")
|
||||
object ANDAND : IrOperator("ANDAND")
|
||||
object OROR : IrOperator("OROR")
|
||||
object RANGE : IrOperator("RANGE")
|
||||
|
||||
object PLUS : IrOperator()
|
||||
object MINUS : IrOperator()
|
||||
object MUL : IrOperator()
|
||||
object DIV : IrOperator()
|
||||
object MOD : IrOperator()
|
||||
object PLUS : IrOperator("PLUS")
|
||||
object MINUS : IrOperator("MINUS")
|
||||
object MUL : IrOperator("MUL")
|
||||
object DIV : IrOperator("DIV")
|
||||
object MOD : IrOperator("MOD")
|
||||
|
||||
object EQ : IrOperator()
|
||||
object PLUSEQ : IrOperator()
|
||||
object MINUSEQ : IrOperator()
|
||||
object MULEQ : IrOperator()
|
||||
object DIVEQ : IrOperator()
|
||||
object MODEQ : 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() {
|
||||
data class COMPONENT_N private constructor(val index: Int) : IrOperator("COMPONENT_$index") {
|
||||
companion object {
|
||||
private val precreatedComponents = Array(32, ::COMPONENT_N)
|
||||
private val precreatedComponents = Array(32) { i -> COMPONENT_N(i + 1) }
|
||||
|
||||
fun withIndex(index: Int) =
|
||||
if (index < precreatedComponents.size)
|
||||
precreatedComponents[index]
|
||||
precreatedComponents[index - 1]
|
||||
else
|
||||
COMPONENT_N(index)
|
||||
}
|
||||
|
||||
+5
-4
@@ -23,13 +23,13 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
interface IrPropertyAccessExpression : IrMemberAccessExpression {
|
||||
override val descriptor: PropertyDescriptor
|
||||
val operator: IrOperator?
|
||||
}
|
||||
|
||||
interface IrGetPropertyExpression : IrPropertyAccessExpression
|
||||
|
||||
interface IrSetPropertyExpression : IrPropertyAccessExpression {
|
||||
var value: IrExpression
|
||||
val operator: IrOperator
|
||||
}
|
||||
|
||||
class IrGetPropertyExpressionImpl(
|
||||
@@ -37,7 +37,8 @@ class IrGetPropertyExpressionImpl(
|
||||
endOffset: Int,
|
||||
type: KotlinType?,
|
||||
isSafe: Boolean,
|
||||
override val descriptor: PropertyDescriptor
|
||||
override val descriptor: PropertyDescriptor,
|
||||
override val operator: IrOperator? = null
|
||||
) : IrMemberAccessExpressionBase(startOffset, endOffset, type, isSafe), IrGetPropertyExpression {
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||
visitor.visitGetProperty(this, data)
|
||||
@@ -48,7 +49,7 @@ class IrSetPropertyExpressionImpl(
|
||||
endOffset: Int,
|
||||
isSafe: Boolean,
|
||||
override val descriptor: PropertyDescriptor,
|
||||
override val operator: IrOperator = IrOperator.EQ
|
||||
override val operator: IrOperator? = null
|
||||
) : IrMemberAccessExpressionBase(startOffset, endOffset, null, isSafe), IrSetPropertyExpression {
|
||||
constructor(
|
||||
startOffset: Int,
|
||||
@@ -56,7 +57,7 @@ class IrSetPropertyExpressionImpl(
|
||||
isSafe: Boolean,
|
||||
descriptor: PropertyDescriptor,
|
||||
value: IrExpression,
|
||||
operator: IrOperator = IrOperator.EQ
|
||||
operator: IrOperator? = null
|
||||
) : this(startOffset, endOffset, isSafe, descriptor, operator) {
|
||||
this.value = value
|
||||
}
|
||||
|
||||
+5
-5
@@ -21,11 +21,11 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
enum class IrTypeOperator {
|
||||
AS,
|
||||
SMART_AS,
|
||||
SAFE_AS,
|
||||
IS,
|
||||
NOT_IS;
|
||||
CAST,
|
||||
IMPLICIT_CAST,
|
||||
SAFE_CAST,
|
||||
INSTANCEOF,
|
||||
NOT_INSTANCEOF;
|
||||
}
|
||||
|
||||
interface IrTypeOperatorExpression : IrExpression {
|
||||
|
||||
+7
-7
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.expressions
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.ir.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
@@ -24,21 +23,22 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
interface IrVariableAccessExpression : IrDeclarationReference {
|
||||
override val descriptor: VariableDescriptor
|
||||
val operator: IrOperator?
|
||||
}
|
||||
|
||||
interface IrGetVariableExpression : IrVariableAccessExpression
|
||||
|
||||
interface IrSetVariableExpression : IrVariableAccessExpression {
|
||||
val value: IrExpression
|
||||
val operator: IrOperator?
|
||||
|
||||
}
|
||||
|
||||
class IrGetVariableExpressionImpl(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
type: KotlinType?,
|
||||
descriptor: VariableDescriptor
|
||||
) : IrTerminalDeclarationReferenceBase<VariableDescriptor>(startOffset, endOffset, type, descriptor), IrGetVariableExpression {
|
||||
descriptor: VariableDescriptor,
|
||||
override val operator: IrOperator? = null
|
||||
) : IrTerminalDeclarationReferenceBase<VariableDescriptor>(startOffset, endOffset, descriptor.type, descriptor), IrGetVariableExpression {
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||
visitor.visitGetVariable(this, data)
|
||||
}
|
||||
@@ -47,14 +47,14 @@ class IrSetVariableExpressionImpl(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
override val descriptor: VariableDescriptor,
|
||||
override val operator: IrOperator = IrOperator.EQ
|
||||
override val operator: IrOperator?
|
||||
) : IrExpressionBase(startOffset, endOffset, null), IrSetVariableExpression {
|
||||
constructor(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
descriptor: VariableDescriptor,
|
||||
value: IrExpression,
|
||||
operator: IrOperator = IrOperator.EQ
|
||||
operator: IrOperator?
|
||||
) : this(startOffset, endOffset, descriptor, operator) {
|
||||
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
|
||||
RETURN type=<no-type>
|
||||
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?
|
||||
|
||||
+6
-6
@@ -21,18 +21,18 @@ IrFile /smartCasts.kt
|
||||
DUMMY KtIfExpression type=kotlin.Unit
|
||||
CALL .println type=kotlin.Unit operator=
|
||||
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
|
||||
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
|
||||
CALL .expectsInt type=kotlin.Unit operator=
|
||||
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
|
||||
CALL .expectsString type=kotlin.Unit 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
|
||||
IrFunction public fun test2(/*0*/ x: kotlin.Any): kotlin.String
|
||||
IrExpressionBody
|
||||
@@ -40,12 +40,12 @@ IrFile /smartCasts.kt
|
||||
DUMMY KtIfExpression type=kotlin.Unit
|
||||
RETURN type=<no-type>
|
||||
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
|
||||
IrFunction public fun test3(/*0*/ x: kotlin.Any): kotlin.String
|
||||
IrExpressionBody
|
||||
BLOCK type=<no-type> hasResult=false isDesugared=false
|
||||
DUMMY KtIfExpression type=kotlin.Unit
|
||||
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
|
||||
|
||||
@@ -22,5 +22,5 @@ IrFile /smartCastsWithDestructuring.kt
|
||||
$receiver: GET_VAR tmp0 type=I1
|
||||
VAR val c2: kotlin.String
|
||||
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
|
||||
|
||||
@@ -41,6 +41,18 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
|
||||
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")
|
||||
public void testBoxOk() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/boxOk.kt");
|
||||
|
||||
Reference in New Issue
Block a user