Move type operations in DeepCopyIrTreeWithDescriptors

This commit is contained in:
Konstantin Anisimov
2017-04-04 14:39:59 +07:00
committed by KonstantinAnisimov
parent 276c14a896
commit c7de1d452f
2 changed files with 69 additions and 106 deletions
@@ -43,12 +43,15 @@ import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.typeUtil.makeNullable
internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val typeSubstitutor: TypeSubstitutor?, val context: Context) {
internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, typeArgsMap: Map <TypeParameterDescriptor, KotlinType>?, val context: Context) {
private val descriptorSubstituteMap: MutableMap<DeclarationDescriptor, DeclarationDescriptor> = mutableMapOf()
private var typeSubstitutor = createTypeSubstitutor(typeArgsMap)
private var inlinedFunctionName = ""
private var nameIndex = 0
@@ -425,6 +428,51 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val
return newDeclaration
}
//---------------------------------------------------------------------//
fun getTypeOperatorReturnType(operator: IrTypeOperator, type: KotlinType) : KotlinType {
return when (operator) {
IrTypeOperator.CAST,
IrTypeOperator.IMPLICIT_CAST,
IrTypeOperator.IMPLICIT_NOTNULL,
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
IrTypeOperator.IMPLICIT_INTEGER_COERCION -> type
IrTypeOperator.SAFE_CAST -> type.makeNullable()
IrTypeOperator.INSTANCEOF,
IrTypeOperator.NOT_INSTANCEOF -> context.builtIns.booleanType
}
}
//---------------------------------------------------------------------//
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression {
val oldExpression = super.visitTypeOperator(expression) as IrTypeOperatorCall
if (typeArgsMap == null) return oldExpression
if (oldExpression.operator == IrTypeOperator.IMPLICIT_COERCION_TO_UNIT) { // Nothing to do for IMPLICIT_COERCION_TO_UNIT
return oldExpression
}
val typeOperand = oldExpression.typeOperand
val operandTypeDescriptor = typeOperand.constructor.declarationDescriptor
if (operandTypeDescriptor !is TypeParameterDescriptor) return oldExpression // It is not TypeParameter - do nothing
var newType = typeArgsMap[operandTypeDescriptor] ?: return expression
if (typeOperand.isMarkedNullable) newType = newType.makeNullable()
val operator = oldExpression.operator
val returnType = getTypeOperatorReturnType(operator, newType)
return IrTypeOperatorCallImpl(
oldExpression.startOffset,
oldExpression.endOffset,
returnType,
oldExpression.operator,
newType,
oldExpression.argument
)
}
//--- Copy declarations -----------------------------------------------//
private fun copyIrFunctionImpl(oldDeclaration: IrFunction, newDescriptor: DeclarationDescriptor): IrFunction {
@@ -449,7 +497,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val
private fun substituteType(oldType: KotlinType?): KotlinType? {
if (typeSubstitutor == null) return oldType
if (oldType == null) return oldType
return typeSubstitutor.substitute(oldType, Variance.INVARIANT) ?: oldType
return typeSubstitutor!!.substitute(oldType, Variance.INVARIANT) ?: oldType
}
//---------------------------------------------------------------------//
@@ -467,6 +515,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val
}
return newTypeArguments
}
//---------------------------------------------------------------------//
private fun copyValueParameters(oldValueParameters: List <ValueParameterDescriptor>, containingDeclaration: CallableDescriptor): List <ValueParameterDescriptor> {
@@ -489,4 +538,16 @@ internal class DeepCopyIrTreeWithDescriptors(val targetFunction: IrFunction, val
newDescriptor
}
}
//-------------------------------------------------------------------------//
private fun createTypeSubstitutor(typeArgsMap: Map <TypeParameterDescriptor, KotlinType>?): TypeSubstitutor? {
if (typeArgsMap == null) return null
val substitutionContext = typeArgsMap.entries.associate {
(typeParameter, typeArgument) ->
typeParameter.typeConstructor to TypeProjectionImpl(typeArgument)
}
return TypeSubstitutor.create(substitutionContext)
}
}
@@ -185,14 +185,13 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
//-------------------------------------------------------------------------//
private fun createInlineFunctionBody(functionDeclaration: IrFunction): IrInlineFunctionBody? {
functionDeclaration.transformChildrenVoid(this) // Inline recursively.
private fun createInlineFunctionBody(functionDeclaration: IrFunction, typeArgsMap: Map <TypeParameterDescriptor, KotlinType>?): IrInlineFunctionBody? {
functionDeclaration.transformChildrenVoid(this) // TODO recursive inline is already processed in visitCall. Check
val originBlockBody = functionDeclaration.body
if (originBlockBody == null) return null // TODO workaround
val typeSubstitutor = createTypeSubstitutor(typeArgsMap)
copyWithDescriptors = DeepCopyIrTreeWithDescriptors(currentFunction!!, typeSubstitutor, context)
copyWithDescriptors = DeepCopyIrTreeWithDescriptors(currentFunction!!, typeArgsMap, context)
val functionName = functionDeclaration.descriptor.name.toString()
val copyBlockBody = originBlockBody.accept(InlineCopyIr(), null) as IrBlockBody // Create copy of original function body.
@@ -225,7 +224,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
val lambdaInliner = LambdaInliner(parameterToArgument)
inlineBody.transformChildrenVoid(lambdaInliner)
val transformer = ParametersTransformer(parameterToArgument, typeArgsMap, evaluationStatements)
val transformer = ParametersTransformer(parameterToArgument)
inlineBody.transformChildrenVoid(transformer) // Replace parameters with expression.
inlineBody.statements.addAll(0, evaluationStatements)
@@ -234,56 +233,12 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
//-------------------------------------------------------------------------//
private inner class ParametersTransformer(val substituteMap: MutableMap <ValueDescriptor, IrExpression>,
val typeArgsMap: Map <TypeParameterDescriptor, KotlinType>?,
val statements: MutableList<IrStatement>): IrElementTransformerVoid() {
private inner class ParametersTransformer(val substituteMap: MutableMap <ValueDescriptor, IrExpression>): IrElementTransformerVoid() {
override fun visitElement(element: IrElement) = element.accept(this, null)
//---------------------------------------------------------------------//
fun getTypeOperatorReturnType(operator: IrTypeOperator, type: KotlinType) : KotlinType {
return when (operator) {
IrTypeOperator.CAST,
IrTypeOperator.IMPLICIT_CAST,
IrTypeOperator.IMPLICIT_NOTNULL,
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
IrTypeOperator.IMPLICIT_INTEGER_COERCION -> type
IrTypeOperator.SAFE_CAST -> type.makeNullable()
IrTypeOperator.INSTANCEOF,
IrTypeOperator.NOT_INSTANCEOF -> context.builtIns.booleanType
}
}
//---------------------------------------------------------------------//
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression {
val newExpression = super.visitTypeOperator(expression) as IrTypeOperatorCall
if (typeArgsMap == null) return newExpression
if (newExpression.operator == IrTypeOperator.IMPLICIT_COERCION_TO_UNIT) { // Nothing to do for IMPLICIT_COERCION_TO_UNIT
return newExpression
}
val operandTypeDescriptor = newExpression.typeOperand.constructor.declarationDescriptor
if (operandTypeDescriptor !is TypeParameterDescriptor) return newExpression // It is not TypeParameter - do nothing
var typeNew = typeArgsMap[operandTypeDescriptor]
?: return expression
if (newExpression.typeOperand.isMarkedNullable)
typeNew = typeNew.makeNullable()
val startOffset = newExpression.startOffset
val endOffset = newExpression.endOffset
val operator = newExpression.operator
val argument = newExpression.argument
val type = getTypeOperatorReturnType(operator, typeNew)
return IrTypeOperatorCallImpl(startOffset, endOffset, type, operator, typeNew, argument)
}
//---------------------------------------------------------------------//
override fun visitGetValue(expression: IrGetValue): IrExpression {
val newExpression = super.visitGetValue(expression) as IrGetValue
@@ -293,59 +248,6 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
return argument
}
//---------------------------------------------------------------------//
private fun createTypeSubstitutor(): TypeSubstitutor {
val substitutionContext = typeArgsMap!!.entries.associate {
(typeParameter, typeArgument) ->
typeParameter.typeConstructor to TypeProjectionImpl(typeArgument)
}
return TypeSubstitutor.create(substitutionContext)
}
//---------------------------------------------------------------------//
private fun substituteTypeArguments(irCall: IrCall, typeSubstitutor: TypeSubstitutor): Map <TypeParameterDescriptor, KotlinType>? {
val oldTypeArguments = (irCall as IrMemberAccessExpressionBase).typeArguments
if (oldTypeArguments == null) return null
val newTypeArguments = oldTypeArguments.map {
val typeParameterDescriptor = it.key
val oldTypeArgument = it.value
val newTypeArgument = typeSubstitutor.substitute(oldTypeArgument, Variance.INVARIANT) ?: oldTypeArgument
typeParameterDescriptor to newTypeArgument
}.toMap()
return newTypeArguments
}
//---------------------------------------------------------------------//
override fun visitCall(expression: IrCall): IrExpression {
val irCall = super.visitCall(expression) as IrCall
if (irCall !is IrCallImpl) return irCall
if (typeArgsMap == null) return irCall
val typeSubstitutor = createTypeSubstitutor()
val typeArguments = substituteTypeArguments(irCall, typeSubstitutor)
val returnType = typeSubstitutor.substitute(irCall.type, Variance.INVARIANT) ?: irCall.type
val descriptor = irCall.descriptor.substitute(typeSubstitutor)!!
val superQualifier = irCall.superQualifier?.substitute(typeSubstitutor)
return IrCallImpl(irCall.startOffset, irCall.endOffset, returnType, descriptor,
typeArguments, irCall.origin, superQualifier).apply {
irCall.descriptor.valueParameters.forEach {
val valueArgument = irCall.getValueArgument(it)
putValueArgument(it.index, valueArgument)
}
extensionReceiver = irCall.extensionReceiver
dispatchReceiver = irCall.dispatchReceiver
}
}
}
//-------------------------------------------------------------------------//
@@ -438,7 +340,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
val lambdaReturnType = copyLambdaFunction.descriptor.returnType!!
val inlineBody = IrInlineFunctionBody(0, 0, lambdaReturnType, lambdaFunction.descriptor, null, lambdaStatements)
val transformer = ParametersTransformer(parameterToArgument, null, lambdaStatements)
val transformer = ParametersTransformer(parameterToArgument)
inlineBody.accept(transformer, null) // Replace parameters with expression.
inlineBody.statements.addAll(0, evaluationStatements)