Move most of ir utils from backend.common to ir.tree
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.ir
|
||||
|
||||
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
||||
import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols
|
||||
import org.jetbrains.kotlin.ir.util.DeepCopySymbolRemapper
|
||||
import org.jetbrains.kotlin.ir.util.DeepCopyTypeRemapper
|
||||
import org.jetbrains.kotlin.ir.util.NullDescriptorsRemapper
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T : IrElement> T.deepCopyWithVariables(): T {
|
||||
val symbolsRemapper = DeepCopySymbolRemapper(NullDescriptorsRemapper)
|
||||
acceptVoid(symbolsRemapper)
|
||||
|
||||
val typesRemapper = DeepCopyTypeRemapper(symbolsRemapper)
|
||||
|
||||
return this.transform(
|
||||
object : DeepCopyIrTreeWithSymbols(symbolsRemapper, typesRemapper) {
|
||||
override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop {
|
||||
return irLoop
|
||||
}
|
||||
},
|
||||
null
|
||||
) as T
|
||||
}
|
||||
@@ -18,13 +18,16 @@ package org.jetbrains.kotlin.ir.builders
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrContainerExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildVariable
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import java.util.*
|
||||
|
||||
@@ -176,3 +179,60 @@ inline fun IrGeneratorWithScope.irBlockBody(
|
||||
endOffset
|
||||
).blockBody(body)
|
||||
|
||||
fun IrBuilderWithScope.irWhile(origin: IrStatementOrigin? = null) =
|
||||
IrWhileLoopImpl(startOffset, endOffset, context.irBuiltIns.unitType, origin)
|
||||
|
||||
fun IrBuilderWithScope.irDoWhile(origin: IrStatementOrigin? = null) =
|
||||
IrDoWhileLoopImpl(startOffset, endOffset, context.irBuiltIns.unitType, origin)
|
||||
|
||||
fun IrBuilderWithScope.irBreak(loop: IrLoop) =
|
||||
IrBreakImpl(startOffset, endOffset, context.irBuiltIns.nothingType, loop)
|
||||
|
||||
fun IrBuilderWithScope.irContinue(loop: IrLoop) =
|
||||
IrContinueImpl(startOffset, endOffset, context.irBuiltIns.nothingType, loop)
|
||||
|
||||
fun IrBuilderWithScope.irGetObject(classSymbol: IrClassSymbol) =
|
||||
IrGetObjectValueImpl(startOffset, endOffset, IrSimpleTypeImpl(classSymbol, false, emptyList(), emptyList()), classSymbol)
|
||||
|
||||
// Also adds created variable into building block
|
||||
fun <T : IrElement> IrStatementsBuilder<T>.createTmpVariable(
|
||||
irExpression: IrExpression,
|
||||
nameHint: String? = null,
|
||||
isMutable: Boolean = false,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
|
||||
irType: IrType? = null
|
||||
): IrVariable {
|
||||
val variable = scope.createTmpVariable(irExpression, nameHint, isMutable, origin, irType)
|
||||
+variable
|
||||
return variable
|
||||
}
|
||||
|
||||
fun Scope.createTmpVariable(
|
||||
irType: IrType,
|
||||
nameHint: String? = null,
|
||||
isMutable: Boolean = false,
|
||||
initializer: IrExpression? = null,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
|
||||
startOffset: Int = UNDEFINED_OFFSET,
|
||||
endOffset: Int = UNDEFINED_OFFSET
|
||||
): IrVariable =
|
||||
buildVariable(
|
||||
getLocalDeclarationParent(), startOffset, endOffset, origin, Name.identifier(nameHint ?: "tmp"),
|
||||
irType, isMutable
|
||||
).apply {
|
||||
this.initializer = initializer
|
||||
}
|
||||
|
||||
fun Scope.createTmpVariable(
|
||||
irExpression: IrExpression,
|
||||
nameHint: String? = null,
|
||||
isMutable: Boolean = false,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
|
||||
irType: IrType? = null
|
||||
): IrVariable =
|
||||
buildVariable(
|
||||
getLocalDeclarationParent(), irExpression.startOffset, irExpression.endOffset, origin, Name.identifier(nameHint ?: "tmp"),
|
||||
irType ?: irExpression.type, isMutable
|
||||
).apply {
|
||||
initializer = irExpression
|
||||
}
|
||||
+339
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.ir.builders.declarations
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.copyTo
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
@PublishedApi
|
||||
internal fun IrFactory.buildClass(builder: IrClassBuilder): IrClass = with(builder) {
|
||||
createClass(
|
||||
startOffset, endOffset, origin,
|
||||
IrClassSymbolImpl(),
|
||||
name, kind, visibility, modality,
|
||||
isCompanion, isInner, isData, isExternal, isValue, isExpect, isFun
|
||||
)
|
||||
}
|
||||
|
||||
inline fun IrFactory.buildClass(builder: IrClassBuilder.() -> Unit) =
|
||||
IrClassBuilder().run {
|
||||
builder()
|
||||
buildClass(this)
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal fun IrFactory.buildField(builder: IrFieldBuilder): IrField = with(builder) {
|
||||
createField(
|
||||
startOffset, endOffset, origin,
|
||||
IrFieldSymbolImpl(),
|
||||
name, type, visibility, isFinal, isExternal, isStatic,
|
||||
).also {
|
||||
it.metadata = metadata
|
||||
}
|
||||
}
|
||||
|
||||
inline fun IrFactory.buildField(builder: IrFieldBuilder.() -> Unit) =
|
||||
IrFieldBuilder().run {
|
||||
builder()
|
||||
buildField(this)
|
||||
}
|
||||
|
||||
inline fun IrClass.addField(builder: IrFieldBuilder.() -> Unit) =
|
||||
factory.buildField(builder).also { field ->
|
||||
field.parent = this
|
||||
declarations.add(field)
|
||||
}
|
||||
|
||||
fun IrClass.addField(fieldName: Name, fieldType: IrType, fieldVisibility: DescriptorVisibility = DescriptorVisibilities.PRIVATE): IrField =
|
||||
addField {
|
||||
name = fieldName
|
||||
type = fieldType
|
||||
visibility = fieldVisibility
|
||||
}
|
||||
|
||||
fun IrClass.addField(
|
||||
fieldName: String,
|
||||
fieldType: IrType,
|
||||
fieldVisibility: DescriptorVisibility = DescriptorVisibilities.PRIVATE
|
||||
): IrField =
|
||||
addField(Name.identifier(fieldName), fieldType, fieldVisibility)
|
||||
|
||||
@PublishedApi
|
||||
internal fun IrFactory.buildProperty(builder: IrPropertyBuilder): IrProperty = with(builder) {
|
||||
createProperty(
|
||||
startOffset, endOffset, origin,
|
||||
IrPropertySymbolImpl(),
|
||||
name, visibility, modality,
|
||||
isVar, isConst, isLateinit, isDelegated, isExternal, isExpect, isFakeOverride,
|
||||
containerSource,
|
||||
)
|
||||
}
|
||||
|
||||
inline fun IrFactory.buildProperty(builder: IrPropertyBuilder.() -> Unit) =
|
||||
IrPropertyBuilder().run {
|
||||
builder()
|
||||
buildProperty(this)
|
||||
}
|
||||
|
||||
inline fun IrClass.addProperty(builder: IrPropertyBuilder.() -> Unit): IrProperty =
|
||||
factory.buildProperty(builder).also { property ->
|
||||
declarations.add(property)
|
||||
property.parent = this@addProperty
|
||||
}
|
||||
|
||||
inline fun IrProperty.addGetter(builder: IrFunctionBuilder.() -> Unit = {}): IrSimpleFunction =
|
||||
IrFunctionBuilder().run {
|
||||
name = Name.special("<get-${this@addGetter.name}>")
|
||||
builder()
|
||||
factory.buildFunction(this).also { getter ->
|
||||
this@addGetter.getter = getter
|
||||
getter.correspondingPropertySymbol = this@addGetter.symbol
|
||||
getter.parent = this@addGetter.parent
|
||||
}
|
||||
}
|
||||
|
||||
fun IrProperty.addDefaultGetter(parentClass: IrClass, builtIns: IrBuiltIns) {
|
||||
val field = backingField!!
|
||||
addGetter {
|
||||
origin = IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
|
||||
returnType = field.type
|
||||
}.apply {
|
||||
dispatchReceiverParameter = parentClass.thisReceiver!!.copyTo(this)
|
||||
body = factory.createBlockBody(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf(
|
||||
IrReturnImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
builtIns.nothingType,
|
||||
symbol,
|
||||
IrGetFieldImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
field.symbol,
|
||||
field.type,
|
||||
IrGetValueImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
dispatchReceiverParameter!!.type,
|
||||
dispatchReceiverParameter!!.symbol
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal fun IrFactory.buildFunction(builder: IrFunctionBuilder): IrSimpleFunction = with(builder) {
|
||||
createFunction(
|
||||
startOffset, endOffset, origin,
|
||||
IrSimpleFunctionSymbolImpl(),
|
||||
name, visibility, modality, returnType,
|
||||
isInline, isExternal, isTailrec, isSuspend, isOperator, isInfix, isExpect, isFakeOverride,
|
||||
containerSource,
|
||||
)
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal fun IrFactory.buildConstructor(builder: IrFunctionBuilder): IrConstructor = with(builder) {
|
||||
return createConstructor(
|
||||
startOffset, endOffset, origin,
|
||||
IrConstructorSymbolImpl(),
|
||||
SpecialNames.INIT,
|
||||
visibility, returnType,
|
||||
isInline = isInline, isExternal = isExternal, isPrimary = isPrimary, isExpect = isExpect,
|
||||
containerSource = containerSource
|
||||
)
|
||||
}
|
||||
|
||||
inline fun IrFactory.buildFun(builder: IrFunctionBuilder.() -> Unit): IrSimpleFunction =
|
||||
IrFunctionBuilder().run {
|
||||
builder()
|
||||
buildFunction(this)
|
||||
}
|
||||
|
||||
inline fun IrFactory.addFunction(klass: IrDeclarationContainer, builder: IrFunctionBuilder.() -> Unit): IrSimpleFunction =
|
||||
buildFun(builder).also { function ->
|
||||
klass.declarations.add(function)
|
||||
function.parent = klass
|
||||
}
|
||||
|
||||
inline fun IrClass.addFunction(builder: IrFunctionBuilder.() -> Unit): IrSimpleFunction =
|
||||
factory.addFunction(this, builder)
|
||||
|
||||
fun IrClass.addFunction(
|
||||
name: String,
|
||||
returnType: IrType,
|
||||
modality: Modality = Modality.FINAL,
|
||||
visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC,
|
||||
isStatic: Boolean = false,
|
||||
isSuspend: Boolean = false,
|
||||
isFakeOverride: Boolean = false,
|
||||
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED,
|
||||
startOffset: Int = UNDEFINED_OFFSET,
|
||||
endOffset: Int = UNDEFINED_OFFSET
|
||||
): IrSimpleFunction =
|
||||
addFunction {
|
||||
this.startOffset = startOffset
|
||||
this.endOffset = endOffset
|
||||
this.name = Name.identifier(name)
|
||||
this.returnType = returnType
|
||||
this.modality = modality
|
||||
this.visibility = visibility
|
||||
this.isSuspend = isSuspend
|
||||
this.isFakeOverride = isFakeOverride
|
||||
this.origin = origin
|
||||
}.apply {
|
||||
if (!isStatic) {
|
||||
val thisReceiver = parentAsClass.thisReceiver!!
|
||||
dispatchReceiverParameter = thisReceiver.copyTo(this, type = thisReceiver.type)
|
||||
}
|
||||
}
|
||||
|
||||
inline fun IrFactory.buildConstructor(builder: IrFunctionBuilder.() -> Unit): IrConstructor =
|
||||
IrFunctionBuilder().run {
|
||||
builder()
|
||||
buildConstructor(this)
|
||||
}
|
||||
|
||||
inline fun IrClass.addConstructor(builder: IrFunctionBuilder.() -> Unit = {}): IrConstructor =
|
||||
factory.buildConstructor {
|
||||
builder()
|
||||
returnType = defaultType
|
||||
}.also { constructor ->
|
||||
declarations.add(constructor)
|
||||
constructor.parent = this@addConstructor
|
||||
}
|
||||
|
||||
fun <D> buildReceiverParameter(
|
||||
parent: D,
|
||||
origin: IrDeclarationOrigin,
|
||||
type: IrType,
|
||||
startOffset: Int = parent.startOffset,
|
||||
endOffset: Int = parent.endOffset
|
||||
): IrValueParameter
|
||||
where D : IrDeclaration, D : IrDeclarationParent =
|
||||
parent.factory.createValueParameter(
|
||||
startOffset, endOffset, origin,
|
||||
IrValueParameterSymbolImpl(),
|
||||
SpecialNames.THIS, -1, type, null, isCrossinline = false, isNoinline = false,
|
||||
isHidden = false, isAssignable = false
|
||||
).also {
|
||||
it.parent = parent
|
||||
}
|
||||
|
||||
fun IrFactory.buildValueParameter(builder: IrValueParameterBuilder, parent: IrDeclarationParent): IrValueParameter =
|
||||
with(builder) {
|
||||
return createValueParameter(
|
||||
startOffset, endOffset, origin,
|
||||
IrValueParameterSymbolImpl(),
|
||||
name, index, type, varargElementType, isCrossInline, isNoinline, isHidden, isAssignable
|
||||
).also {
|
||||
it.parent = parent
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline fun <D> buildValueParameter(declaration: D, builder: IrValueParameterBuilder.() -> Unit): IrValueParameter
|
||||
where D : IrDeclaration, D : IrDeclarationParent =
|
||||
IrValueParameterBuilder().run {
|
||||
builder()
|
||||
declaration.factory.buildValueParameter(this, declaration)
|
||||
}
|
||||
|
||||
inline fun IrFunction.addValueParameter(builder: IrValueParameterBuilder.() -> Unit): IrValueParameter =
|
||||
IrValueParameterBuilder().run {
|
||||
builder()
|
||||
if (index == UNDEFINED_PARAMETER_INDEX) {
|
||||
index = valueParameters.size
|
||||
}
|
||||
factory.buildValueParameter(this, this@addValueParameter).also { valueParameter ->
|
||||
valueParameters = valueParameters + valueParameter
|
||||
}
|
||||
}
|
||||
|
||||
fun IrFunction.addValueParameter(name: String, type: IrType, origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED): IrValueParameter =
|
||||
addValueParameter(Name.identifier(name), type, origin)
|
||||
|
||||
fun IrFunction.addValueParameter(name: Name, type: IrType, origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED): IrValueParameter =
|
||||
addValueParameter {
|
||||
this.name = name
|
||||
this.type = type
|
||||
this.origin = origin
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal fun IrFactory.buildTypeParameter(builder: IrTypeParameterBuilder, parent: IrDeclarationParent): IrTypeParameter =
|
||||
with(builder) {
|
||||
createTypeParameter(
|
||||
startOffset, endOffset, origin,
|
||||
IrTypeParameterSymbolImpl(),
|
||||
name, index, isReified, variance
|
||||
).also {
|
||||
it.superTypes = superTypes
|
||||
it.parent = parent
|
||||
}
|
||||
}
|
||||
|
||||
inline fun buildTypeParameter(parent: IrTypeParametersContainer, builder: IrTypeParameterBuilder.() -> Unit): IrTypeParameter =
|
||||
IrTypeParameterBuilder().run {
|
||||
builder()
|
||||
parent.factory.buildTypeParameter(this, parent)
|
||||
}
|
||||
|
||||
inline fun IrTypeParametersContainer.addTypeParameter(builder: IrTypeParameterBuilder.() -> Unit): IrTypeParameter =
|
||||
IrTypeParameterBuilder().run {
|
||||
builder()
|
||||
if (index == UNDEFINED_PARAMETER_INDEX) {
|
||||
index = typeParameters.size
|
||||
}
|
||||
factory.buildTypeParameter(this, this@addTypeParameter).also { typeParameter ->
|
||||
typeParameters = typeParameters + typeParameter
|
||||
}
|
||||
}
|
||||
|
||||
fun IrTypeParametersContainer.addTypeParameter(name: String, upperBound: IrType, variance: Variance = Variance.INVARIANT): IrTypeParameter =
|
||||
addTypeParameter {
|
||||
this.name = Name.identifier(name)
|
||||
this.variance = variance
|
||||
this.superTypes.add(upperBound)
|
||||
}
|
||||
|
||||
fun buildVariable(
|
||||
parent: IrDeclarationParent?,
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
origin: IrDeclarationOrigin,
|
||||
name: Name,
|
||||
type: IrType,
|
||||
isVar: Boolean = false,
|
||||
isConst: Boolean = false,
|
||||
isLateinit: Boolean = false,
|
||||
): IrVariable {
|
||||
return IrVariableImpl(
|
||||
startOffset, endOffset, origin,
|
||||
IrVariableSymbolImpl(),
|
||||
name, type, isVar, isConst, isLateinit
|
||||
).also {
|
||||
if (parent != null) {
|
||||
it.parent = parent
|
||||
}
|
||||
}
|
||||
}
|
||||
-589
@@ -1,589 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.ir.descriptors
|
||||
|
||||
import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.BuiltInOperatorNames
|
||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeBuilder
|
||||
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
class IrBuiltInsOverDescriptors(
|
||||
val builtIns: KotlinBuiltIns,
|
||||
private val typeTranslator: TypeTranslator,
|
||||
val symbolTable: SymbolTable
|
||||
) : IrBuiltIns() {
|
||||
override val languageVersionSettings = typeTranslator.languageVersionSettings
|
||||
|
||||
private var _functionFactory: IrAbstractDescriptorBasedFunctionFactory? = null
|
||||
var functionFactory: IrAbstractDescriptorBasedFunctionFactory
|
||||
get() =
|
||||
synchronized(this) {
|
||||
if (_functionFactory == null) {
|
||||
_functionFactory = IrDescriptorBasedFunctionFactory(this, symbolTable, typeTranslator)
|
||||
}
|
||||
_functionFactory!!
|
||||
}
|
||||
set(value) {
|
||||
synchronized(this) {
|
||||
if (_functionFactory != null) {
|
||||
error("functionFactory already set")
|
||||
} else {
|
||||
_functionFactory = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val irFactory: IrFactory = symbolTable.irFactory
|
||||
|
||||
private val builtInsModule = builtIns.builtInsModule
|
||||
|
||||
private val packageFragmentDescriptor = IrBuiltinsPackageFragmentDescriptorImpl(builtInsModule, KOTLIN_INTERNAL_IR_FQN)
|
||||
override val operatorsPackageFragment: IrExternalPackageFragment =
|
||||
IrExternalPackageFragmentImpl(symbolTable.referenceExternalPackageFragment(packageFragmentDescriptor), KOTLIN_INTERNAL_IR_FQN)
|
||||
|
||||
private fun ClassDescriptor.toIrSymbol() = symbolTable.referenceClass(this)
|
||||
private fun KotlinType.toIrType() = typeTranslator.translateType(this)
|
||||
|
||||
private fun defineOperator(
|
||||
name: String, returnType: IrType, valueParameterTypes: List<IrType>, isIntrinsicConst: Boolean = false
|
||||
): IrSimpleFunctionSymbol {
|
||||
val operatorDescriptor =
|
||||
IrSimpleBuiltinOperatorDescriptorImpl(packageFragmentDescriptor, Name.identifier(name), returnType.originalKotlinType!!)
|
||||
|
||||
for ((i, valueParameterType) in valueParameterTypes.withIndex()) {
|
||||
operatorDescriptor.addValueParameter(
|
||||
IrBuiltinValueParameterDescriptorImpl(
|
||||
operatorDescriptor, Name.identifier("arg$i"), i, valueParameterType.originalKotlinType!!
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val symbol = symbolTable.declareSimpleFunctionIfNotExists(operatorDescriptor) {
|
||||
val operator = irFactory.createFunction(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
BUILTIN_OPERATOR,
|
||||
it,
|
||||
Name.identifier(name),
|
||||
DescriptorVisibilities.PUBLIC,
|
||||
Modality.FINAL,
|
||||
returnType,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isTailrec = false,
|
||||
isSuspend = false,
|
||||
isOperator = false,
|
||||
isInfix = false,
|
||||
isExpect = false,
|
||||
isFakeOverride = false
|
||||
)
|
||||
operator.parent = operatorsPackageFragment
|
||||
operatorsPackageFragment.declarations += operator
|
||||
|
||||
operator.valueParameters = valueParameterTypes.withIndex().map { (i, valueParameterType) ->
|
||||
val valueParameterDescriptor = operatorDescriptor.valueParameters[i]
|
||||
val valueParameterSymbol = IrValueParameterSymbolImpl(valueParameterDescriptor)
|
||||
irFactory.createValueParameter(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, valueParameterSymbol, Name.identifier("arg$i"), i,
|
||||
valueParameterType, null, isCrossinline = false, isNoinline = false, isHidden = false, isAssignable = false
|
||||
).apply {
|
||||
parent = operator
|
||||
}
|
||||
}
|
||||
|
||||
if (isIntrinsicConst) {
|
||||
operator.annotations += IrConstructorCallImpl.fromSymbolDescriptor(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, intrinsicConstType, intrinsicConstConstructor
|
||||
)
|
||||
}
|
||||
|
||||
operator
|
||||
}
|
||||
|
||||
return symbol.symbol
|
||||
}
|
||||
|
||||
private fun defineCheckNotNullOperator(): IrSimpleFunctionSymbol {
|
||||
val name = Name.identifier("CHECK_NOT_NULL")
|
||||
val typeParameterDescriptor: TypeParameterDescriptor
|
||||
val valueParameterDescriptor: ValueParameterDescriptor
|
||||
|
||||
val returnKotlinType: SimpleType
|
||||
val valueKotlinType: SimpleType
|
||||
|
||||
// Note: We still need a complete function descriptor here because `CHECK_NOT_NULL` is being substituted by psi2ir
|
||||
val operatorDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
packageFragmentDescriptor,
|
||||
Annotations.EMPTY,
|
||||
name,
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
SourceElement.NO_SOURCE
|
||||
).apply {
|
||||
typeParameterDescriptor = TypeParameterDescriptorImpl.createForFurtherModification(
|
||||
this, Annotations.EMPTY, false, Variance.INVARIANT, Name.identifier("T0"),
|
||||
0, SourceElement.NO_SOURCE, LockBasedStorageManager.NO_LOCKS
|
||||
).apply {
|
||||
addUpperBound(any)
|
||||
setInitialized()
|
||||
}
|
||||
|
||||
valueKotlinType = typeParameterDescriptor.typeConstructor.makeNullableType()
|
||||
|
||||
valueParameterDescriptor = ValueParameterDescriptorImpl(
|
||||
this, null, 0, Annotations.EMPTY, Name.identifier("arg0"), valueKotlinType,
|
||||
declaresDefaultValue = false, isCrossinline = false, isNoinline = false, varargElementType = null,
|
||||
source = SourceElement.NO_SOURCE
|
||||
)
|
||||
|
||||
returnKotlinType = typeParameterDescriptor.typeConstructor.makeNonNullType()
|
||||
|
||||
initialize(
|
||||
null, null, listOf(), listOf(typeParameterDescriptor), listOf(valueParameterDescriptor), returnKotlinType,
|
||||
Modality.FINAL, DescriptorVisibilities.PUBLIC
|
||||
)
|
||||
}
|
||||
|
||||
return symbolTable.declareSimpleFunctionIfNotExists(operatorDescriptor) { operatorSymbol ->
|
||||
val typeParameter = symbolTable.declareGlobalTypeParameter(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
BUILTIN_OPERATOR,
|
||||
typeParameterDescriptor
|
||||
).apply {
|
||||
superTypes += anyType
|
||||
}
|
||||
val typeParameterSymbol = typeParameter.symbol
|
||||
|
||||
val returnIrType = IrSimpleTypeBuilder().run {
|
||||
classifier = typeParameterSymbol
|
||||
kotlinType = returnKotlinType
|
||||
nullability = SimpleTypeNullability.DEFINITELY_NOT_NULL
|
||||
buildSimpleType()
|
||||
}
|
||||
|
||||
val valueIrType = IrSimpleTypeBuilder().run {
|
||||
classifier = typeParameterSymbol
|
||||
kotlinType = valueKotlinType
|
||||
nullability = SimpleTypeNullability.MARKED_NULLABLE
|
||||
buildSimpleType()
|
||||
}
|
||||
|
||||
irFactory.createFunction(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR,
|
||||
operatorSymbol, name,
|
||||
DescriptorVisibilities.PUBLIC, Modality.FINAL,
|
||||
returnIrType,
|
||||
isInline = false, isExternal = false, isTailrec = false, isSuspend = false, isOperator = false, isInfix = false,
|
||||
isExpect = false, isFakeOverride = false
|
||||
).also { operator ->
|
||||
operator.parent = operatorsPackageFragment
|
||||
operatorsPackageFragment.declarations += operator
|
||||
|
||||
val valueParameterSymbol = IrValueParameterSymbolImpl(valueParameterDescriptor)
|
||||
val valueParameter = irFactory.createValueParameter(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, valueParameterSymbol, Name.identifier("arg0"), 0,
|
||||
valueIrType, null, isCrossinline = false, isNoinline = false, isHidden = false, isAssignable = false
|
||||
)
|
||||
|
||||
valueParameter.parent = operator
|
||||
typeParameter.parent = operator
|
||||
|
||||
operator.valueParameters += valueParameter
|
||||
operator.typeParameters += typeParameter
|
||||
}
|
||||
}.symbol
|
||||
}
|
||||
|
||||
private fun defineComparisonOperator(name: String, operandType: IrType) =
|
||||
defineOperator(name, booleanType, listOf(operandType, operandType), isIntrinsicConst = true)
|
||||
|
||||
private fun List<IrType>.defineComparisonOperatorForEachIrType(name: String) =
|
||||
associate { it.classifierOrFail to defineComparisonOperator(name, it) }
|
||||
|
||||
val any = builtIns.anyType
|
||||
override val anyType = any.toIrType()
|
||||
override val anyClass = builtIns.any.toIrSymbol()
|
||||
override val anyNType = anyType.makeNullable()
|
||||
|
||||
val intrinsicConst = builtIns.intrinsicConstEvaluationType
|
||||
private val intrinsicConstType = intrinsicConst.toIrType()
|
||||
private val intrinsicConstConstructor = symbolTable.referenceConstructor(builtIns.intrinsicConstEvaluation.constructors.single())
|
||||
|
||||
val bool = builtIns.booleanType
|
||||
override val booleanType = bool.toIrType()
|
||||
override val booleanClass = builtIns.boolean.toIrSymbol()
|
||||
|
||||
val char = builtIns.charType
|
||||
override val charType = char.toIrType()
|
||||
override val charClass = builtIns.char.toIrSymbol()
|
||||
|
||||
val number = builtIns.number.defaultType
|
||||
override val numberType = number.toIrType()
|
||||
override val numberClass = builtIns.number.toIrSymbol()
|
||||
|
||||
val byte = builtIns.byteType
|
||||
override val byteType = byte.toIrType()
|
||||
override val byteClass = builtIns.byte.toIrSymbol()
|
||||
|
||||
val short = builtIns.shortType
|
||||
override val shortType = short.toIrType()
|
||||
override val shortClass = builtIns.short.toIrSymbol()
|
||||
|
||||
val int = builtIns.intType
|
||||
override val intType = int.toIrType()
|
||||
override val intClass = builtIns.int.toIrSymbol()
|
||||
|
||||
val long = builtIns.longType
|
||||
override val longType = long.toIrType()
|
||||
override val longClass = builtIns.long.toIrSymbol()
|
||||
|
||||
val float = builtIns.floatType
|
||||
override val floatType = float.toIrType()
|
||||
override val floatClass = builtIns.float.toIrSymbol()
|
||||
|
||||
val double = builtIns.doubleType
|
||||
override val doubleType = double.toIrType()
|
||||
override val doubleClass = builtIns.double.toIrSymbol()
|
||||
|
||||
val nothing = builtIns.nothingType
|
||||
override val nothingType = nothing.toIrType()
|
||||
override val nothingClass = builtIns.nothing.toIrSymbol()
|
||||
override val nothingNType = nothingType.makeNullable()
|
||||
|
||||
val unit = builtIns.unitType
|
||||
override val unitType = unit.toIrType()
|
||||
override val unitClass = builtIns.unit.toIrSymbol()
|
||||
|
||||
val string = builtIns.stringType
|
||||
override val stringType = string.toIrType()
|
||||
override val stringClass = builtIns.string.toIrSymbol()
|
||||
|
||||
// TODO: check if correct
|
||||
override val charSequenceClass = findClass(Name.identifier("CharSequence"), "kotlin")!!
|
||||
|
||||
override val collectionClass = builtIns.collection.toIrSymbol()
|
||||
override val setClass = builtIns.set.toIrSymbol()
|
||||
override val listClass = builtIns.list.toIrSymbol()
|
||||
override val mapClass = builtIns.map.toIrSymbol()
|
||||
override val mapEntryClass = builtIns.mapEntry.toIrSymbol()
|
||||
override val iterableClass = builtIns.iterable.toIrSymbol()
|
||||
override val iteratorClass = builtIns.iterator.toIrSymbol()
|
||||
override val listIteratorClass = builtIns.listIterator.toIrSymbol()
|
||||
override val mutableCollectionClass = builtIns.mutableCollection.toIrSymbol()
|
||||
override val mutableSetClass = builtIns.mutableSet.toIrSymbol()
|
||||
override val mutableListClass = builtIns.mutableList.toIrSymbol()
|
||||
override val mutableMapClass = builtIns.mutableMap.toIrSymbol()
|
||||
override val mutableMapEntryClass = builtIns.mutableMapEntry.toIrSymbol()
|
||||
override val mutableIterableClass = builtIns.mutableIterable.toIrSymbol()
|
||||
override val mutableIteratorClass = builtIns.mutableIterator.toIrSymbol()
|
||||
override val mutableListIteratorClass = builtIns.mutableListIterator.toIrSymbol()
|
||||
override val comparableClass = builtIns.comparable.toIrSymbol()
|
||||
|
||||
override val arrayClass = builtIns.array.toIrSymbol()
|
||||
|
||||
override val throwableType = builtIns.throwable.defaultType.toIrType()
|
||||
override val throwableClass = builtIns.throwable.toIrSymbol()
|
||||
|
||||
override val kCallableClass = builtIns.kCallable.toIrSymbol()
|
||||
override val kPropertyClass = builtIns.kProperty.toIrSymbol()
|
||||
override val kClassClass = builtIns.kClass.toIrSymbol()
|
||||
|
||||
override val kProperty0Class = builtIns.kProperty0.toIrSymbol()
|
||||
override val kProperty1Class = builtIns.kProperty1.toIrSymbol()
|
||||
override val kProperty2Class = builtIns.kProperty2.toIrSymbol()
|
||||
override val kMutableProperty0Class = builtIns.kMutableProperty0.toIrSymbol()
|
||||
override val kMutableProperty1Class = builtIns.kMutableProperty1.toIrSymbol()
|
||||
override val kMutableProperty2Class = builtIns.kMutableProperty2.toIrSymbol()
|
||||
|
||||
override val functionClass = builtIns.getBuiltInClassByFqName(FqName("kotlin.Function")).toIrSymbol()
|
||||
override val kFunctionClass = builtIns.getBuiltInClassByFqName(FqName("kotlin.reflect.KFunction")).toIrSymbol()
|
||||
|
||||
override val annotationClass: IrClassSymbol = builtIns.annotation.toIrSymbol()
|
||||
override val annotationType: IrType = builtIns.annotationType.toIrType()
|
||||
|
||||
override fun getKPropertyClass(mutable: Boolean, n: Int): IrClassSymbol = when (n) {
|
||||
0 -> if (mutable) kMutableProperty0Class else kProperty0Class
|
||||
1 -> if (mutable) kMutableProperty1Class else kProperty1Class
|
||||
2 -> if (mutable) kMutableProperty2Class else kProperty2Class
|
||||
else -> error("No KProperty for n=$n mutable=$mutable")
|
||||
}
|
||||
|
||||
override val primitiveTypeToIrType = mapOf(
|
||||
PrimitiveType.BOOLEAN to booleanType,
|
||||
PrimitiveType.CHAR to charType,
|
||||
PrimitiveType.BYTE to byteType,
|
||||
PrimitiveType.SHORT to shortType,
|
||||
PrimitiveType.INT to intType,
|
||||
PrimitiveType.FLOAT to floatType,
|
||||
PrimitiveType.LONG to longType,
|
||||
PrimitiveType.DOUBLE to doubleType
|
||||
)
|
||||
|
||||
// TODO switch to IrType
|
||||
val primitiveTypes = listOf(bool, char, byte, short, int, float, long, double)
|
||||
override val primitiveIrTypes = listOf(booleanType, charType, byteType, shortType, intType, floatType, longType, doubleType)
|
||||
override val primitiveIrTypesWithComparisons = listOf(charType, byteType, shortType, intType, floatType, longType, doubleType)
|
||||
override val primitiveFloatingPointIrTypes = listOf(floatType, doubleType)
|
||||
|
||||
override val byteArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.BYTE).toIrSymbol()
|
||||
override val charArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.CHAR).toIrSymbol()
|
||||
override val shortArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.SHORT).toIrSymbol()
|
||||
override val intArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.INT).toIrSymbol()
|
||||
override val longArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.LONG).toIrSymbol()
|
||||
override val floatArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.FLOAT).toIrSymbol()
|
||||
override val doubleArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.DOUBLE).toIrSymbol()
|
||||
override val booleanArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.BOOLEAN).toIrSymbol()
|
||||
|
||||
override val primitiveArraysToPrimitiveTypes =
|
||||
PrimitiveType.values().associate { builtIns.getPrimitiveArrayClassDescriptor(it).toIrSymbol() to it }
|
||||
override val primitiveTypesToPrimitiveArrays = primitiveArraysToPrimitiveTypes.map { (k, v) -> v to k }.toMap()
|
||||
override val primitiveArrayElementTypes = primitiveArraysToPrimitiveTypes.mapValues { primitiveTypeToIrType[it.value] }
|
||||
override val primitiveArrayForType = primitiveArrayElementTypes.asSequence().associate { it.value to it.key }
|
||||
|
||||
override val unsignedTypesToUnsignedArrays: Map<UnsignedType, IrClassSymbol> =
|
||||
UnsignedType.values().mapNotNull { unsignedType ->
|
||||
val array = builtIns.builtInsModule.findClassAcrossModuleDependencies(unsignedType.arrayClassId)?.toIrSymbol()
|
||||
if (array == null) null else unsignedType to array
|
||||
}.toMap()
|
||||
|
||||
override val lessFunByOperandType = primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.LESS)
|
||||
override val lessOrEqualFunByOperandType =
|
||||
primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.LESS_OR_EQUAL)
|
||||
override val greaterOrEqualFunByOperandType =
|
||||
primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.GREATER_OR_EQUAL)
|
||||
override val greaterFunByOperandType =
|
||||
primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.GREATER)
|
||||
|
||||
override val ieee754equalsFunByOperandType =
|
||||
primitiveFloatingPointIrTypes.map {
|
||||
it.classifierOrFail to defineOperator(
|
||||
BuiltInOperatorNames.IEEE754_EQUALS,
|
||||
booleanType,
|
||||
listOf(it.makeNullable(), it.makeNullable()),
|
||||
isIntrinsicConst = true
|
||||
)
|
||||
}.toMap()
|
||||
|
||||
val booleanNot =
|
||||
builtIns.boolean.unsubstitutedMemberScope.getContributedFunctions(Name.identifier("not"), NoLookupLocation.FROM_BACKEND).single()
|
||||
override val booleanNotSymbol = symbolTable.referenceSimpleFunction(booleanNot)
|
||||
|
||||
override val eqeqeqSymbol = defineOperator(BuiltInOperatorNames.EQEQEQ, booleanType, listOf(anyNType, anyNType))
|
||||
override val eqeqSymbol = defineOperator(BuiltInOperatorNames.EQEQ, booleanType, listOf(anyNType, anyNType), isIntrinsicConst = true)
|
||||
override val throwCceSymbol = defineOperator(BuiltInOperatorNames.THROW_CCE, nothingType, listOf())
|
||||
override val throwIseSymbol = defineOperator(BuiltInOperatorNames.THROW_ISE, nothingType, listOf())
|
||||
override val andandSymbol = defineOperator(BuiltInOperatorNames.ANDAND, booleanType, listOf(booleanType, booleanType), isIntrinsicConst = true)
|
||||
override val ororSymbol = defineOperator(BuiltInOperatorNames.OROR, booleanType, listOf(booleanType, booleanType), isIntrinsicConst = true)
|
||||
override val noWhenBranchMatchedExceptionSymbol =
|
||||
defineOperator(BuiltInOperatorNames.NO_WHEN_BRANCH_MATCHED_EXCEPTION, nothingType, listOf())
|
||||
override val illegalArgumentExceptionSymbol =
|
||||
defineOperator(BuiltInOperatorNames.ILLEGAL_ARGUMENT_EXCEPTION, nothingType, listOf(stringType))
|
||||
|
||||
override val checkNotNullSymbol = defineCheckNotNullOperator()
|
||||
|
||||
private fun TypeConstructor.makeNonNullType() = KotlinTypeFactory.simpleType(TypeAttributes.Empty, this, listOf(), false)
|
||||
private fun TypeConstructor.makeNullableType() = KotlinTypeFactory.simpleType(TypeAttributes.Empty, this, listOf(), true)
|
||||
|
||||
override val dataClassArrayMemberHashCodeSymbol = defineOperator("dataClassArrayMemberHashCode", intType, listOf(anyType))
|
||||
|
||||
override val dataClassArrayMemberToStringSymbol = defineOperator("dataClassArrayMemberToString", stringType, listOf(anyNType))
|
||||
|
||||
override val intTimesSymbol: IrSimpleFunctionSymbol =
|
||||
builtIns.int.unsubstitutedMemberScope.findFirstFunction("times") {
|
||||
KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, int)
|
||||
}.let { symbolTable.referenceSimpleFunction(it) }
|
||||
|
||||
override val intXorSymbol: IrSimpleFunctionSymbol =
|
||||
builtIns.int.unsubstitutedMemberScope.findFirstFunction("xor") {
|
||||
KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, int)
|
||||
}.let { symbolTable.referenceSimpleFunction(it) }
|
||||
|
||||
override val intPlusSymbol: IrSimpleFunctionSymbol =
|
||||
builtIns.int.unsubstitutedMemberScope.findFirstFunction("plus") {
|
||||
KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, int)
|
||||
}.let { symbolTable.referenceSimpleFunction(it) }
|
||||
|
||||
override val arrayOf = findFunctions(Name.identifier("arrayOf")).first {
|
||||
it.descriptor.extensionReceiverParameter == null && it.descriptor.dispatchReceiverParameter == null &&
|
||||
it.descriptor.valueParameters.size == 1 && it.descriptor.valueParameters[0].varargElementType != null
|
||||
}
|
||||
|
||||
override val arrayOfNulls = findFunctions(Name.identifier("arrayOfNulls")).first {
|
||||
it.descriptor.extensionReceiverParameter == null && it.descriptor.dispatchReceiverParameter == null &&
|
||||
it.descriptor.valueParameters.size == 1 && KotlinBuiltIns.isInt(it.descriptor.valueParameters[0].type)
|
||||
}
|
||||
|
||||
override val linkageErrorSymbol: IrSimpleFunctionSymbol = defineOperator("linkageError", nothingType, listOf(stringType))
|
||||
|
||||
override val enumClass = builtIns.enum.toIrSymbol()
|
||||
|
||||
private fun builtInsPackage(vararg packageNameSegments: String) =
|
||||
builtIns.builtInsModule.getPackage(FqName.fromSegments(listOf(*packageNameSegments))).memberScope
|
||||
|
||||
override fun findFunctions(name: Name, vararg packageNameSegments: String): Iterable<IrSimpleFunctionSymbol> =
|
||||
builtInsPackage(*packageNameSegments).getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).map {
|
||||
symbolTable.referenceSimpleFunction(it)
|
||||
}
|
||||
|
||||
override fun findFunctions(name: Name, packageFqName: FqName): Iterable<IrSimpleFunctionSymbol> =
|
||||
builtIns.builtInsModule.getPackage(packageFqName).memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).map {
|
||||
symbolTable.referenceSimpleFunction(it)
|
||||
}
|
||||
|
||||
override fun findClass(name: Name, vararg packageNameSegments: String): IrClassSymbol? =
|
||||
(builtInsPackage(*packageNameSegments).getContributedClassifier(
|
||||
name,
|
||||
NoLookupLocation.FROM_BACKEND
|
||||
) as? ClassDescriptor)?.let { symbolTable.referenceClass(it) }
|
||||
|
||||
override fun findClass(name: Name, packageFqName: FqName): IrClassSymbol? =
|
||||
(builtIns.builtInsModule.getPackage(packageFqName).memberScope.getContributedClassifier(
|
||||
name,
|
||||
NoLookupLocation.FROM_BACKEND
|
||||
) as? ClassDescriptor)?.let { symbolTable.referenceClass(it) }
|
||||
|
||||
override fun findBuiltInClassMemberFunctions(builtInClass: IrClassSymbol, name: Name): Iterable<IrSimpleFunctionSymbol> =
|
||||
builtInClass.descriptor.unsubstitutedMemberScope
|
||||
.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND)
|
||||
.map { symbolTable.referenceSimpleFunction(it) }
|
||||
|
||||
private val binaryOperatorCache = mutableMapOf<Triple<Name, IrType, IrType>, IrSimpleFunctionSymbol>()
|
||||
|
||||
override fun getBinaryOperator(name: Name, lhsType: IrType, rhsType: IrType): IrSimpleFunctionSymbol {
|
||||
require(lhsType is IrSimpleType) { "Expected IrSimpleType in getBinaryOperator, got $lhsType" }
|
||||
val classifier = lhsType.classifier
|
||||
require(classifier is IrClassSymbol && classifier.isBound) {
|
||||
"Expected a bound IrClassSymbol for lhsType in getBinaryOperator, got $classifier"
|
||||
}
|
||||
val key = Triple(name, lhsType, rhsType)
|
||||
return binaryOperatorCache.getOrPut(key) {
|
||||
classifier.functions.single {
|
||||
val function = it.owner
|
||||
function.name == name && function.valueParameters.size == 1 && function.valueParameters[0].type == rhsType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val unaryOperatorCache = mutableMapOf<Pair<Name, IrType>, IrSimpleFunctionSymbol>()
|
||||
|
||||
override fun getUnaryOperator(name: Name, receiverType: IrType): IrSimpleFunctionSymbol {
|
||||
require(receiverType is IrSimpleType) { "Expected IrSimpleType in getBinaryOperator, got $receiverType" }
|
||||
val classifier = receiverType.classifier
|
||||
require(classifier is IrClassSymbol && classifier.isBound) {
|
||||
"Expected a bound IrClassSymbol for receiverType in getBinaryOperator, got $classifier"
|
||||
}
|
||||
val key = Pair(name, receiverType)
|
||||
return unaryOperatorCache.getOrPut(key) {
|
||||
classifier.functions.single {
|
||||
val function = it.owner
|
||||
function.name == name && function.valueParameters.isEmpty()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T : Any> getFunctionsByKey(
|
||||
name: Name,
|
||||
vararg packageNameSegments: String,
|
||||
makeKey: (SimpleFunctionDescriptor) -> T?
|
||||
): Map<T, IrSimpleFunctionSymbol> {
|
||||
val result = mutableMapOf<T, IrSimpleFunctionSymbol>()
|
||||
for (d in builtInsPackage(*packageNameSegments).getContributedFunctions(name, NoLookupLocation.FROM_BACKEND)) {
|
||||
makeKey(d)?.let { key ->
|
||||
result[key] = symbolTable.referenceSimpleFunction(d)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
override fun getNonBuiltInFunctionsByExtensionReceiver(
|
||||
name: Name, vararg packageNameSegments: String
|
||||
): Map<IrClassifierSymbol, IrSimpleFunctionSymbol> =
|
||||
getFunctionsByKey(name, *packageNameSegments) {
|
||||
if (it.containingDeclaration !is BuiltInsPackageFragment && it.extensionReceiverParameter != null) {
|
||||
symbolTable.referenceClassifier(it.extensionReceiverParameter!!.type.constructor.declarationDescriptor!!)
|
||||
} else null
|
||||
}
|
||||
|
||||
override fun getNonBuiltinFunctionsByReturnType(
|
||||
name: Name, vararg packageNameSegments: String
|
||||
): Map<IrClassifierSymbol, IrSimpleFunctionSymbol> =
|
||||
getFunctionsByKey(Name.identifier("getProgressionLastElement"), *packageNameSegments) { d ->
|
||||
if (d.containingDeclaration !is BuiltInsPackageFragment) {
|
||||
d.returnType?.constructor?.declarationDescriptor?.let { symbolTable.referenceClassifier(it) }
|
||||
} else null
|
||||
}
|
||||
|
||||
override val extensionToString: IrSimpleFunctionSymbol = findFunctions(OperatorNameConventions.TO_STRING, "kotlin").first {
|
||||
val descriptor = it.descriptor
|
||||
descriptor is SimpleFunctionDescriptor && descriptor.dispatchReceiverParameter == null &&
|
||||
descriptor.extensionReceiverParameter != null &&
|
||||
KotlinBuiltIns.isNullableAny(descriptor.extensionReceiverParameter!!.type) && descriptor.valueParameters.isEmpty()
|
||||
}
|
||||
|
||||
override val memberToString: IrSimpleFunctionSymbol = findBuiltInClassMemberFunctions(
|
||||
anyClass,
|
||||
OperatorNameConventions.TO_STRING
|
||||
).single {
|
||||
val descriptor = it.descriptor
|
||||
descriptor is SimpleFunctionDescriptor && descriptor.valueParameters.isEmpty()
|
||||
}
|
||||
|
||||
override val extensionStringPlus: IrSimpleFunctionSymbol = findFunctions(OperatorNameConventions.PLUS, "kotlin").first {
|
||||
val descriptor = it.descriptor
|
||||
descriptor is SimpleFunctionDescriptor && descriptor.dispatchReceiverParameter == null &&
|
||||
descriptor.extensionReceiverParameter != null &&
|
||||
KotlinBuiltIns.isStringOrNullableString(descriptor.extensionReceiverParameter!!.type) &&
|
||||
descriptor.valueParameters.size == 1 &&
|
||||
KotlinBuiltIns.isNullableAny(descriptor.valueParameters.first().type)
|
||||
}
|
||||
|
||||
override val memberStringPlus: IrSimpleFunctionSymbol = findBuiltInClassMemberFunctions(
|
||||
stringClass,
|
||||
OperatorNameConventions.PLUS
|
||||
).single {
|
||||
val descriptor = it.descriptor
|
||||
descriptor is SimpleFunctionDescriptor &&
|
||||
descriptor.valueParameters.size == 1 &&
|
||||
KotlinBuiltIns.isNullableAny(descriptor.valueParameters.first().type)
|
||||
}
|
||||
|
||||
override fun functionN(arity: Int): IrClass = functionFactory.functionN(arity)
|
||||
override fun kFunctionN(arity: Int): IrClass = functionFactory.kFunctionN(arity)
|
||||
override fun suspendFunctionN(arity: Int): IrClass = functionFactory.suspendFunctionN(arity)
|
||||
override fun kSuspendFunctionN(arity: Int): IrClass = functionFactory.kSuspendFunctionN(arity)
|
||||
}
|
||||
|
||||
private inline fun MemberScope.findFirstFunction(name: String, predicate: (CallableMemberDescriptor) -> Boolean) =
|
||||
getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).first(predicate)
|
||||
-479
@@ -1,479 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.ir.descriptors
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.StandardNames.KOTLIN_REFLECT_FQ_NAME
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.SimpleTypeNullability
|
||||
import org.jetbrains.kotlin.ir.types.impl.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
abstract class IrAbstractDescriptorBasedFunctionFactory {
|
||||
|
||||
abstract fun functionClassDescriptor(arity: Int): FunctionClassDescriptor
|
||||
abstract fun kFunctionClassDescriptor(arity: Int): FunctionClassDescriptor
|
||||
abstract fun suspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor
|
||||
abstract fun kSuspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor
|
||||
|
||||
abstract fun functionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass
|
||||
abstract fun kFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass
|
||||
abstract fun suspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass
|
||||
abstract fun kSuspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass
|
||||
|
||||
fun functionN(n: Int) = functionN(n) { callback ->
|
||||
val descriptor = functionClassDescriptor(n)
|
||||
declareClass(descriptor) { symbol ->
|
||||
callback(symbol)
|
||||
}
|
||||
}
|
||||
|
||||
fun kFunctionN(n: Int): IrClass {
|
||||
return kFunctionN(n) { callback ->
|
||||
val descriptor = kFunctionClassDescriptor(n)
|
||||
declareClass(descriptor) { symbol ->
|
||||
callback(symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun suspendFunctionN(n: Int): IrClass = suspendFunctionN(n) { callback ->
|
||||
val descriptor = suspendFunctionClassDescriptor(n)
|
||||
declareClass(descriptor) { symbol ->
|
||||
callback(symbol)
|
||||
}
|
||||
}
|
||||
|
||||
fun kSuspendFunctionN(n: Int): IrClass = kSuspendFunctionN(n) { callback ->
|
||||
val descriptor = kSuspendFunctionClassDescriptor(n)
|
||||
declareClass(descriptor) { symbol ->
|
||||
callback(symbol)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val classOrigin = object : IrDeclarationOriginImpl("FUNCTION_INTERFACE_CLASS") {}
|
||||
val memberOrigin = object : IrDeclarationOriginImpl("FUNCTION_INTERFACE_MEMBER") {}
|
||||
const val offset = SYNTHETIC_OFFSET
|
||||
|
||||
internal fun functionClassName(isK: Boolean, isSuspend: Boolean, arity: Int): String =
|
||||
"${if (isK) "K" else ""}${if (isSuspend) "Suspend" else ""}Function$arity"
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
class IrDescriptorBasedFunctionFactory(
|
||||
private val irBuiltIns: IrBuiltInsOverDescriptors,
|
||||
private val symbolTable: SymbolTable,
|
||||
private val typeTranslator: TypeTranslator,
|
||||
getPackageFragment: ((PackageFragmentDescriptor) -> IrPackageFragment)? = null,
|
||||
// Needed for JS and Wasm backends to "preload" interfaces that can referenced during lowerings
|
||||
private val referenceFunctionsWhenKFunctionAreReferenced: Boolean = false,
|
||||
) : IrAbstractDescriptorBasedFunctionFactory() {
|
||||
val getPackageFragment =
|
||||
getPackageFragment ?: symbolTable::declareExternalPackageFragmentIfNotExists
|
||||
|
||||
// TODO: Lazieness
|
||||
|
||||
private val functionNMap = mutableMapOf<Int, IrClass>()
|
||||
private val kFunctionNMap = mutableMapOf<Int, IrClass>()
|
||||
private val suspendFunctionNMap = mutableMapOf<Int, IrClass>()
|
||||
private val kSuspendFunctionNMap = mutableMapOf<Int, IrClass>()
|
||||
|
||||
private val irFactory: IrFactory get() = symbolTable.irFactory
|
||||
|
||||
val functionClass = symbolTable.referenceClass(irBuiltIns.builtIns.getBuiltInClassByFqName(FqName("kotlin.Function")))
|
||||
val kFunctionClass = symbolTable.referenceClass(irBuiltIns.builtIns.getBuiltInClassByFqName(FqName("kotlin.reflect.KFunction")))
|
||||
|
||||
override fun functionClassDescriptor(arity: Int): FunctionClassDescriptor =
|
||||
irBuiltIns.builtIns.getFunction(arity) as FunctionClassDescriptor
|
||||
|
||||
override fun suspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor =
|
||||
irBuiltIns.builtIns.getSuspendFunction(arity) as FunctionClassDescriptor
|
||||
|
||||
override fun kFunctionClassDescriptor(arity: Int): FunctionClassDescriptor {
|
||||
val kFunctionFqn = reflectFunctionClassFqn(reflectionFunctionClassName(false, arity))
|
||||
return irBuiltIns.builtIns.getBuiltInClassByFqName(kFunctionFqn) as FunctionClassDescriptor
|
||||
}
|
||||
|
||||
override fun kSuspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor {
|
||||
val kFunctionFqn = reflectFunctionClassFqn(reflectionFunctionClassName(true, arity))
|
||||
return irBuiltIns.builtIns.getBuiltInClassByFqName(kFunctionFqn) as FunctionClassDescriptor
|
||||
}
|
||||
|
||||
override fun functionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass {
|
||||
return functionNMap.getOrPut(arity) {
|
||||
symbolTable.declarator { symbol ->
|
||||
val descriptor = symbol.descriptor
|
||||
val descriptorFactory = FunctionDescriptorFactory.RealDescriptorFactory(descriptor, symbolTable)
|
||||
createFunctionClass(symbol, false, false, arity, irBuiltIns.functionClass, kotlinPackageFragment, descriptorFactory)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun suspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass {
|
||||
return suspendFunctionNMap.getOrPut(arity) {
|
||||
symbolTable.declarator { symbol ->
|
||||
val descriptor = symbol.descriptor as FunctionClassDescriptor
|
||||
val descriptorFactory = FunctionDescriptorFactory.RealDescriptorFactory(descriptor, symbolTable)
|
||||
createFunctionClass(symbol, false, true, arity, irBuiltIns.functionClass, kotlinCoroutinesPackageFragment, descriptorFactory)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun kFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass {
|
||||
if (referenceFunctionsWhenKFunctionAreReferenced)
|
||||
functionN(arity)
|
||||
|
||||
return kFunctionNMap.getOrPut(arity) {
|
||||
symbolTable.declarator { symbol ->
|
||||
val descriptor = symbol.descriptor as FunctionClassDescriptor
|
||||
val descriptorFactory = FunctionDescriptorFactory.RealDescriptorFactory(descriptor, symbolTable)
|
||||
createFunctionClass(symbol, true, false, arity, irBuiltIns.kFunctionClass, kotlinReflectPackageFragment, descriptorFactory)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun kSuspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass {
|
||||
if (referenceFunctionsWhenKFunctionAreReferenced)
|
||||
suspendFunctionN(arity)
|
||||
|
||||
return kSuspendFunctionNMap.getOrPut(arity) {
|
||||
symbolTable.declarator { symbol ->
|
||||
val descriptor = symbol.descriptor as FunctionClassDescriptor
|
||||
val descriptorFactory = FunctionDescriptorFactory.RealDescriptorFactory(descriptor, symbolTable)
|
||||
createFunctionClass(symbol, true, true, arity, irBuiltIns.kFunctionClass, kotlinReflectPackageFragment, descriptorFactory)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class FunctionDescriptorFactory(protected val symbolTable: SymbolTable) {
|
||||
abstract fun memberDescriptor(name: String, factory: (IrSimpleFunctionSymbol) -> IrSimpleFunction): IrSimpleFunctionSymbol
|
||||
abstract fun FunctionDescriptor.valueParameterDescriptor(index: Int): ValueParameterDescriptor
|
||||
abstract fun typeParameterDescriptor(index: Int, factory: (IrTypeParameterSymbol) -> IrTypeParameter): IrTypeParameterSymbol
|
||||
abstract fun classReceiverParameterDescriptor(): ReceiverParameterDescriptor
|
||||
|
||||
class RealDescriptorFactory(private val classDescriptor: ClassDescriptor, symbolTable: SymbolTable) :
|
||||
FunctionDescriptorFactory(symbolTable) {
|
||||
override fun memberDescriptor(name: String, factory: (IrSimpleFunctionSymbol) -> IrSimpleFunction): IrSimpleFunctionSymbol {
|
||||
val descriptor = classDescriptor.unsubstitutedMemberScope.run {
|
||||
if (name[0] == '<') {
|
||||
val propertyName = name.drop(5).dropLast(1)
|
||||
val property = getContributedVariables(Name.identifier(propertyName), NoLookupLocation.FROM_BACKEND).single()
|
||||
property.accessors.first { it.name.asString() == name }
|
||||
} else {
|
||||
getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).first()
|
||||
}
|
||||
}
|
||||
return symbolTable.declareSimpleFunction(descriptor, factory).symbol
|
||||
}
|
||||
|
||||
override fun FunctionDescriptor.valueParameterDescriptor(index: Int): ValueParameterDescriptor {
|
||||
assert(containingDeclaration === classDescriptor)
|
||||
return valueParameters[index]
|
||||
}
|
||||
|
||||
override fun typeParameterDescriptor(index: Int, factory: (IrTypeParameterSymbol) -> IrTypeParameter): IrTypeParameterSymbol {
|
||||
val descriptor = classDescriptor.declaredTypeParameters[index]
|
||||
return symbolTable.declareGlobalTypeParameter(offset, offset, classOrigin, descriptor, factory).symbol
|
||||
}
|
||||
|
||||
override fun classReceiverParameterDescriptor(): ReceiverParameterDescriptor {
|
||||
return classDescriptor.thisAsReceiverParameter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrTypeParametersContainer.createTypeParameters(n: Int, descriptorFactory: FunctionDescriptorFactory): IrTypeParameter {
|
||||
|
||||
var index = 0
|
||||
|
||||
val typeParametersArray = ArrayList<IrTypeParameter>(n + 1)
|
||||
|
||||
for (i in 1 until (n + 1)) {
|
||||
val pName = Name.identifier("P$i")
|
||||
|
||||
val pSymbol = descriptorFactory.typeParameterDescriptor(index) {
|
||||
irFactory.createTypeParameter(
|
||||
offset, offset, classOrigin, it, pName, index++, false, Variance.IN_VARIANCE
|
||||
)
|
||||
}
|
||||
val pDeclaration = pSymbol.owner
|
||||
|
||||
pDeclaration.superTypes += irBuiltIns.anyNType
|
||||
pDeclaration.parent = this
|
||||
typeParametersArray.add(pDeclaration)
|
||||
}
|
||||
|
||||
val rSymbol = descriptorFactory.typeParameterDescriptor(index) {
|
||||
irFactory.createTypeParameter(
|
||||
offset, offset, classOrigin, it, Name.identifier("R"), index, false, Variance.OUT_VARIANCE
|
||||
)
|
||||
}
|
||||
val rDeclaration = rSymbol.owner
|
||||
|
||||
rDeclaration.superTypes += irBuiltIns.anyNType
|
||||
rDeclaration.parent = this
|
||||
typeParametersArray.add(rDeclaration)
|
||||
|
||||
typeParameters = typeParametersArray
|
||||
|
||||
return rDeclaration
|
||||
}
|
||||
|
||||
private val kotlinPackageFragment: IrPackageFragment by lazy {
|
||||
irBuiltIns.builtIns.getFunction(0).let {
|
||||
getPackageFragment(it.containingDeclaration as PackageFragmentDescriptor)
|
||||
}
|
||||
}
|
||||
private val kotlinCoroutinesPackageFragment: IrPackageFragment by lazy {
|
||||
irBuiltIns.builtIns.getSuspendFunction(0).let {
|
||||
getPackageFragment(it.containingDeclaration as PackageFragmentDescriptor)
|
||||
}
|
||||
}
|
||||
|
||||
private val kotlinReflectPackageFragment: IrPackageFragment by lazy {
|
||||
irBuiltIns.kPropertyClass.descriptor.let {
|
||||
getPackageFragment(it.containingDeclaration as PackageFragmentDescriptor)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createThisReceiver(descriptorFactory: FunctionDescriptorFactory): IrValueParameter {
|
||||
val descriptor = descriptorFactory.classReceiverParameterDescriptor()
|
||||
return irFactory.createValueParameter(
|
||||
offset, offset, classOrigin, IrValueParameterSymbolImpl(descriptor), SpecialNames.THIS, -1,
|
||||
typeTranslator.translateType(descriptor.type), null,
|
||||
isCrossinline = false,
|
||||
isNoinline = false,
|
||||
isHidden = false,
|
||||
isAssignable = false
|
||||
)
|
||||
}
|
||||
|
||||
private fun IrClass.createMembers(isK: Boolean, isSuspend: Boolean, descriptorFactory: FunctionDescriptorFactory) {
|
||||
if (!isK) {
|
||||
val invokeSymbol = descriptorFactory.memberDescriptor("invoke") {
|
||||
val returnType = with(IrSimpleTypeBuilder()) {
|
||||
classifier = typeParameters.last().symbol
|
||||
buildSimpleType()
|
||||
}
|
||||
|
||||
irFactory.createFunction(
|
||||
offset, offset, memberOrigin, it, Name.identifier("invoke"), DescriptorVisibilities.PUBLIC, Modality.ABSTRACT,
|
||||
returnType,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isTailrec = false,
|
||||
isSuspend = isSuspend,
|
||||
isOperator = true,
|
||||
isInfix = false,
|
||||
isExpect = false,
|
||||
isFakeOverride = false
|
||||
)
|
||||
}
|
||||
|
||||
val fDeclaration = invokeSymbol.owner
|
||||
|
||||
fDeclaration.dispatchReceiverParameter = createThisReceiver(descriptorFactory).also { it.parent = fDeclaration }
|
||||
|
||||
val typeBuilder = IrSimpleTypeBuilder()
|
||||
for (i in 1 until typeParameters.size) {
|
||||
val vTypeParam = typeParameters[i - 1]
|
||||
val vDescriptor = with(descriptorFactory) { invokeSymbol.descriptor.valueParameterDescriptor(i - 1) }
|
||||
val vSymbol = IrValueParameterSymbolImpl(vDescriptor)
|
||||
val vType = with(typeBuilder) {
|
||||
classifier = vTypeParam.symbol
|
||||
buildSimpleType()
|
||||
}
|
||||
val vDeclaration = irFactory.createValueParameter(
|
||||
offset, offset, memberOrigin, vSymbol, Name.identifier("p$i"), i - 1, vType, null,
|
||||
isCrossinline = false,
|
||||
isNoinline = false,
|
||||
isHidden = false,
|
||||
isAssignable = false
|
||||
)
|
||||
vDeclaration.parent = fDeclaration
|
||||
fDeclaration.valueParameters += vDeclaration
|
||||
}
|
||||
|
||||
fDeclaration.parent = this
|
||||
declarations += fDeclaration
|
||||
}
|
||||
|
||||
// TODO: eventualy delegate it to fakeOverrideBuilder
|
||||
addFakeOverrides()
|
||||
}
|
||||
|
||||
private fun toIrType(wrapped: KotlinType): IrType {
|
||||
val kotlinType = wrapped.unwrap()
|
||||
return with(IrSimpleTypeBuilder()) {
|
||||
classifier =
|
||||
symbolTable.referenceClassifier(kotlinType.constructor.declarationDescriptor ?: error("No classifier for type $kotlinType"))
|
||||
nullability = SimpleTypeNullability.fromHasQuestionMark(kotlinType.isMarkedNullable)
|
||||
arguments = kotlinType.arguments.map {
|
||||
if (it.isStarProjection) IrStarProjectionImpl
|
||||
else makeTypeProjection(toIrType(it.type), it.projectionKind)
|
||||
}
|
||||
buildSimpleType()
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrFunction.createValueParameter(descriptor: ParameterDescriptor): IrValueParameter = with(descriptor) {
|
||||
irFactory.createValueParameter(
|
||||
offset, offset, memberOrigin, IrValueParameterSymbolImpl(this), name, indexOrMinusOne, toIrType(type),
|
||||
(this as? ValueParameterDescriptor)?.varargElementType?.let(::toIrType), isCrossinline, isNoinline, false, false
|
||||
).also {
|
||||
it.parent = this@createValueParameter
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrClass.addFakeOverrides() {
|
||||
|
||||
val fakeOverrideDescriptors = descriptor.unsubstitutedMemberScope.getContributedDescriptors(DescriptorKindFilter.CALLABLES)
|
||||
.filterIsInstance<CallableMemberDescriptor>().filter { it.kind === CallableMemberDescriptor.Kind.FAKE_OVERRIDE }
|
||||
|
||||
fun createFakeOverrideFunction(descriptor: FunctionDescriptor, property: IrPropertySymbol?): IrSimpleFunction {
|
||||
val returnType = descriptor.returnType?.let { toIrType(it) } ?: error("No return type for $descriptor")
|
||||
val newFunction = symbolTable.declareSimpleFunction(descriptor) {
|
||||
descriptor.run {
|
||||
irFactory.createFunction(
|
||||
offset, offset, memberOrigin, it, name, visibility, modality, returnType,
|
||||
isInline, isEffectivelyExternal(), isTailrec, isSuspend, isOperator, isInfix, isExpect, true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
newFunction.parent = this
|
||||
newFunction.overriddenSymbols = descriptor.overriddenDescriptors.map { symbolTable.referenceSimpleFunction(it.original) }
|
||||
newFunction.dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.let { newFunction.createValueParameter(it) }
|
||||
newFunction.extensionReceiverParameter = descriptor.extensionReceiverParameter?.let { newFunction.createValueParameter(it) }
|
||||
newFunction.contextReceiverParametersCount = descriptor.contextReceiverParameters.size
|
||||
newFunction.valueParameters = descriptor.valueParameters.map { newFunction.createValueParameter(it) }
|
||||
newFunction.correspondingPropertySymbol = property
|
||||
newFunction.annotations = descriptor.annotations.mapNotNull(
|
||||
typeTranslator.constantValueGenerator::generateAnnotationConstructorCall
|
||||
)
|
||||
|
||||
return newFunction
|
||||
}
|
||||
|
||||
fun createFakeOverrideProperty(descriptor: PropertyDescriptor): IrProperty {
|
||||
return symbolTable.declareProperty(offset, offset, memberOrigin, descriptor) {
|
||||
irFactory.createProperty(
|
||||
offset, offset, memberOrigin, it,
|
||||
name = descriptor.name,
|
||||
visibility = descriptor.visibility,
|
||||
modality = descriptor.modality,
|
||||
isVar = descriptor.isVar,
|
||||
isConst = descriptor.isConst,
|
||||
isLateinit = descriptor.isLateInit,
|
||||
isDelegated = descriptor.isDelegated,
|
||||
isExternal = descriptor.isEffectivelyExternal(),
|
||||
isExpect = descriptor.isExpect
|
||||
).apply {
|
||||
parent = this@addFakeOverrides
|
||||
getter = descriptor.getter?.let { g -> createFakeOverrideFunction(g, symbol) }
|
||||
setter = descriptor.setter?.let { s -> createFakeOverrideFunction(s, symbol) }
|
||||
annotations = descriptor.annotations.mapNotNull(
|
||||
typeTranslator.constantValueGenerator::generateAnnotationConstructorCall
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun createFakeOverride(descriptor: CallableMemberDescriptor): IrDeclaration {
|
||||
return when (descriptor) {
|
||||
is FunctionDescriptor -> createFakeOverrideFunction(descriptor, null)
|
||||
is PropertyDescriptor -> createFakeOverrideProperty(descriptor)
|
||||
else -> error("Unexpected member $descriptor")
|
||||
}
|
||||
}
|
||||
|
||||
declarations += fakeOverrideDescriptors.map { createFakeOverride(it) }
|
||||
}
|
||||
|
||||
private fun createFunctionClass(
|
||||
symbol: IrClassSymbol,
|
||||
isK: Boolean,
|
||||
isSuspend: Boolean,
|
||||
n: Int,
|
||||
baseClass: IrClassSymbol,
|
||||
packageFragment: IrPackageFragment,
|
||||
descriptorFactory: FunctionDescriptorFactory
|
||||
): IrClass {
|
||||
val name = functionClassName(isK, isSuspend, n)
|
||||
if (symbol.isBound) return symbol.owner
|
||||
val klass = irFactory.createClass(
|
||||
offset, offset, classOrigin, symbol, Name.identifier(name), ClassKind.INTERFACE, DescriptorVisibilities.PUBLIC, Modality.ABSTRACT
|
||||
)
|
||||
|
||||
val r = klass.createTypeParameters(n, descriptorFactory)
|
||||
|
||||
klass.thisReceiver = createThisReceiver(descriptorFactory).also { it.parent = klass }
|
||||
|
||||
klass.superTypes = listOf(with(IrSimpleTypeBuilder()) {
|
||||
classifier = baseClass
|
||||
arguments = listOf(
|
||||
with(IrSimpleTypeBuilder()) {
|
||||
classifier = r.symbol
|
||||
buildTypeProjection()
|
||||
},
|
||||
)
|
||||
buildSimpleType()
|
||||
})
|
||||
|
||||
klass.parent = packageFragment
|
||||
packageFragment.declarations += klass
|
||||
|
||||
klass.createMembers(isK, isSuspend, descriptorFactory)
|
||||
|
||||
return klass
|
||||
}
|
||||
}
|
||||
|
||||
private fun reflectFunctionClassFqn(shortName: Name): FqName = KOTLIN_REFLECT_FQ_NAME.child(shortName)
|
||||
private fun reflectionFunctionClassName(isSuspend: Boolean, arity: Int): Name =
|
||||
Name.identifier("K${if (isSuspend) "Suspend" else ""}Function$arity")
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun KotlinBuiltIns.functionClassDescriptor(arity: Int): FunctionClassDescriptor =
|
||||
getFunction(arity) as FunctionClassDescriptor
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun KotlinBuiltIns.suspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor =
|
||||
getSuspendFunction(arity) as FunctionClassDescriptor
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun KotlinBuiltIns.kFunctionClassDescriptor(arity: Int): FunctionClassDescriptor {
|
||||
val kFunctionFqn = reflectFunctionClassFqn(reflectionFunctionClassName(false, arity))
|
||||
return getBuiltInClassByFqName(kFunctionFqn) as FunctionClassDescriptor
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun KotlinBuiltIns.kSuspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor {
|
||||
val kFunctionFqn =
|
||||
reflectFunctionClassFqn(reflectionFunctionClassName(true, arity))
|
||||
return getBuiltInClassByFqName(kFunctionFqn) as FunctionClassDescriptor
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.ir.util
|
||||
|
||||
import org.jetbrains.kotlin.builtins.StandardNames.FqNames
|
||||
import org.jetbrains.kotlin.builtins.UnsignedTypes
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
|
||||
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
|
||||
val kotlinPackageFqn = FqName.fromSegments(listOf("kotlin"))
|
||||
private val kotlinReflectionPackageFqn = kotlinPackageFqn.child(Name.identifier("reflect"))
|
||||
private val kotlinCoroutinesPackageFqn = kotlinPackageFqn.child(Name.identifier("coroutines"))
|
||||
|
||||
fun IrType.isFunctionMarker(): Boolean = classifierOrNull?.isClassWithName("Function", kotlinPackageFqn) == true
|
||||
fun IrType.isFunction(): Boolean = classifierOrNull?.isClassWithNamePrefix("Function", kotlinPackageFqn) == true
|
||||
fun IrType.isKFunction(): Boolean = classifierOrNull?.isClassWithNamePrefix("KFunction", kotlinReflectionPackageFqn) == true
|
||||
fun IrType.isSuspendFunction(): Boolean = classifierOrNull?.isClassWithNamePrefix("SuspendFunction", kotlinCoroutinesPackageFqn) == true
|
||||
fun IrType.isKSuspendFunction(): Boolean = classifierOrNull?.isClassWithNamePrefix("KSuspendFunction", kotlinReflectionPackageFqn) == true
|
||||
|
||||
fun IrClassifierSymbol.isFunctionMarker(): Boolean = this.isClassWithName("Function", kotlinPackageFqn)
|
||||
fun IrClassifierSymbol.isFunction(): Boolean = this.isClassWithNamePrefix("Function", kotlinPackageFqn)
|
||||
fun IrClassifierSymbol.isKFunction(): Boolean = this.isClassWithNamePrefix("KFunction", kotlinReflectionPackageFqn)
|
||||
fun IrClassifierSymbol.isSuspendFunction(): Boolean = this.isClassWithNamePrefix("SuspendFunction", kotlinCoroutinesPackageFqn)
|
||||
fun IrClassifierSymbol.isKSuspendFunction(): Boolean = this.isClassWithNamePrefix("KSuspendFunction", kotlinReflectionPackageFqn)
|
||||
|
||||
private fun IrClassifierSymbol.isClassWithName(name: String, packageFqName: FqName): Boolean {
|
||||
val declaration = owner as IrDeclarationWithName
|
||||
return name == declaration.name.asString() && (declaration.parent as? IrPackageFragment)?.fqName == packageFqName
|
||||
}
|
||||
|
||||
private fun IrClassifierSymbol.isClassWithNamePrefix(prefix: String, packageFqName: FqName): Boolean {
|
||||
val declaration = owner as IrDeclarationWithName
|
||||
return declaration.name.asString().startsWith(prefix) && (declaration.parent as? IrPackageFragment)?.fqName == packageFqName
|
||||
}
|
||||
|
||||
fun IrType.superTypes(): List<IrType> = classifierOrNull?.superTypes() ?: emptyList()
|
||||
|
||||
fun IrType.isFunctionTypeOrSubtype(): Boolean = DFS.ifAny(listOf(this), IrType::superTypes, IrType::isFunction)
|
||||
fun IrType.isSuspendFunctionTypeOrSubtype(): Boolean = DFS.ifAny(listOf(this), IrType::superTypes, IrType::isSuspendFunction)
|
||||
|
||||
fun IrType.isTypeParameter() = classifierOrNull is IrTypeParameterSymbol
|
||||
|
||||
fun IrType.isInterface() = classOrNull?.owner?.kind == ClassKind.INTERFACE
|
||||
|
||||
fun IrType.isAnnotation() = classOrNull?.owner?.kind == ClassKind.ANNOTATION_CLASS
|
||||
|
||||
fun IrType.isFunctionOrKFunction() = isFunction() || isKFunction()
|
||||
|
||||
fun IrType.isSuspendFunctionOrKFunction() = isSuspendFunction() || isKSuspendFunction()
|
||||
|
||||
fun IrType.isThrowable(): Boolean = isTypeFromKotlinPackage { name -> name.asString() == "Throwable" }
|
||||
|
||||
fun IrType.isUnsigned(): Boolean = isTypeFromKotlinPackage { name -> UnsignedTypes.isShortNameOfUnsignedType(name) }
|
||||
|
||||
fun IrType.isUnsignedArray(): Boolean = isTypeFromKotlinPackage { name -> UnsignedTypes.isShortNameOfUnsignedArray(name) }
|
||||
|
||||
private inline fun IrType.isTypeFromKotlinPackage(namePredicate: (Name) -> Boolean): Boolean {
|
||||
if (this is IrSimpleType) {
|
||||
val classClassifier = classifier as? IrClassSymbol ?: return false
|
||||
if (!namePredicate(classClassifier.owner.name)) return false
|
||||
val parent = classClassifier.owner.parent as? IrPackageFragment ?: return false
|
||||
return parent.fqName == kotlinPackageFqn
|
||||
} else return false
|
||||
}
|
||||
|
||||
fun IrType.isPrimitiveArray() = isTypeFromKotlinPackage { it in FqNames.primitiveArrayTypeShortNames }
|
||||
|
||||
fun IrType.getPrimitiveArrayElementType() = (this as? IrSimpleType)?.let {
|
||||
(it.classifier.owner as? IrClass)?.fqNameWhenAvailable?.toUnsafe()?.let { fqn -> FqNames.arrayClassFqNameToPrimitiveType[fqn] }
|
||||
}
|
||||
|
||||
fun IrType.substitute(params: List<IrTypeParameter>, arguments: List<IrType>): IrType =
|
||||
substitute(params.map { it.symbol }.zip(arguments).toMap())
|
||||
|
||||
fun IrType.substitute(substitutionMap: Map<IrTypeParameterSymbol, IrType>): IrType {
|
||||
if (this !is IrSimpleType || substitutionMap.isEmpty()) return this
|
||||
|
||||
val newAnnotations = annotations.map { it.deepCopyWithSymbols() }
|
||||
|
||||
substitutionMap[classifier]?.let { substitutedType ->
|
||||
// Add nullability and annotations from original type
|
||||
return substitutedType
|
||||
.mergeNullability(this)
|
||||
.addAnnotations(newAnnotations)
|
||||
}
|
||||
|
||||
val newArguments = arguments.map {
|
||||
if (it is IrTypeProjection) {
|
||||
makeTypeProjection(it.type.substitute(substitutionMap), it.variance)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
|
||||
return IrSimpleTypeImpl(
|
||||
classifier,
|
||||
nullability,
|
||||
newArguments,
|
||||
newAnnotations
|
||||
)
|
||||
}
|
||||
|
||||
private fun getImmediateSupertypes(irType: IrSimpleType): List<IrSimpleType> {
|
||||
val irClass = irType.getClass()
|
||||
?: throw AssertionError("Not a class type: ${irType.render()}")
|
||||
val originalSupertypes = irClass.superTypes
|
||||
val arguments =
|
||||
irType.arguments.map {
|
||||
it.typeOrNull
|
||||
?: throw AssertionError("*-projection in supertype arguments: ${irType.render()}")
|
||||
}
|
||||
return originalSupertypes
|
||||
.filter { it.classOrNull != null }
|
||||
.map { superType ->
|
||||
superType.substitute(irClass.typeParameters, arguments) as IrSimpleType
|
||||
}
|
||||
}
|
||||
|
||||
private fun collectAllSupertypes(irType: IrSimpleType, result: MutableSet<IrSimpleType>) {
|
||||
val immediateSupertypes = getImmediateSupertypes(irType)
|
||||
result.addAll(immediateSupertypes)
|
||||
for (supertype in immediateSupertypes) {
|
||||
collectAllSupertypes(supertype, result)
|
||||
}
|
||||
}
|
||||
|
||||
// Given the following classes:
|
||||
// open class A<X>
|
||||
// open class B<Y> : A<List<Y>>
|
||||
// class C<Z> : B<List<Z>>
|
||||
// for the class C, this function constructs:
|
||||
// { B<List<Z>>, A<List<List<Z>>, Any }
|
||||
// where Z is a type parameter of class C.
|
||||
fun getAllSubstitutedSupertypes(irClass: IrClass): Set<IrSimpleType> {
|
||||
val result = HashSet<IrSimpleType>()
|
||||
collectAllSupertypes(irClass.defaultType, result)
|
||||
return result
|
||||
}
|
||||
|
||||
private fun collectAllSuperclasses(irClass: IrClass, set: MutableSet<IrClass>) {
|
||||
for (superType in irClass.superTypes) {
|
||||
val classifier = superType.classifierOrNull as? IrClassSymbol ?: continue
|
||||
val superClass = classifier.owner
|
||||
if (set.add(superClass)) {
|
||||
collectAllSuperclasses(superClass, set)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun IrClass.getAllSuperclasses(): Set<IrClass> {
|
||||
val result = HashSet<IrClass>()
|
||||
collectAllSuperclasses(this, result)
|
||||
return result
|
||||
}
|
||||
@@ -7,16 +7,30 @@ package org.jetbrains.kotlin.ir.util
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.*
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addConstructor
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildReceiverParameter
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildTypeParameter
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.overrides.FakeOverrideBuilderStrategy
|
||||
import org.jetbrains.kotlin.ir.overrides.IrOverridingUtil
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrPropertySymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import java.io.StringWriter
|
||||
|
||||
/**
|
||||
* Binds the arguments explicitly represented in the IR to the parameters of the accessed function.
|
||||
@@ -623,3 +637,609 @@ val IrDeclarationParent.isFacadeClass: Boolean
|
||||
(origin == IrDeclarationOrigin.JVM_MULTIFILE_CLASS ||
|
||||
origin == IrDeclarationOrigin.FILE_CLASS ||
|
||||
origin == IrDeclarationOrigin.SYNTHETIC_FILE_CLASS)
|
||||
|
||||
fun ir2string(ir: IrElement?): String = ir?.render() ?: ""
|
||||
|
||||
@Suppress("unused") // Used in kotlin-native
|
||||
fun ir2stringWhole(ir: IrElement?): String {
|
||||
val strWriter = StringWriter()
|
||||
ir?.accept(DumpIrTreeVisitor(strWriter), "")
|
||||
return strWriter.toString()
|
||||
}
|
||||
|
||||
fun IrClass.addSimpleDelegatingConstructor(
|
||||
superConstructor: IrConstructor,
|
||||
irBuiltIns: IrBuiltIns,
|
||||
isPrimary: Boolean = false,
|
||||
origin: IrDeclarationOrigin? = null
|
||||
): IrConstructor =
|
||||
addConstructor {
|
||||
val klass = this@addSimpleDelegatingConstructor
|
||||
this.startOffset = klass.startOffset
|
||||
this.endOffset = klass.endOffset
|
||||
this.origin = origin ?: klass.origin
|
||||
this.visibility = superConstructor.visibility
|
||||
this.isPrimary = isPrimary
|
||||
}.also { constructor ->
|
||||
constructor.valueParameters = superConstructor.valueParameters.mapIndexed { index, parameter ->
|
||||
parameter.copyTo(constructor, index = index)
|
||||
}
|
||||
|
||||
constructor.body = factory.createBlockBody(
|
||||
startOffset, endOffset,
|
||||
listOf(
|
||||
IrDelegatingConstructorCallImpl(
|
||||
startOffset, endOffset, irBuiltIns.unitType,
|
||||
superConstructor.symbol, 0,
|
||||
superConstructor.valueParameters.size
|
||||
).apply {
|
||||
constructor.valueParameters.forEachIndexed { idx, parameter ->
|
||||
putValueArgument(idx, IrGetValueImpl(startOffset, endOffset, parameter.type, parameter.symbol))
|
||||
}
|
||||
},
|
||||
IrInstanceInitializerCallImpl(startOffset, endOffset, this.symbol, irBuiltIns.unitType)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val IrCall.isSuspend get() = (symbol.owner as? IrSimpleFunction)?.isSuspend == true
|
||||
val IrFunctionReference.isSuspend get() = (symbol.owner as? IrSimpleFunction)?.isSuspend == true
|
||||
|
||||
val IrFunction.isOverridable get() = this is IrSimpleFunction && this.isOverridable
|
||||
|
||||
val IrSimpleFunction.isOverridable: Boolean
|
||||
get() = visibility != DescriptorVisibilities.PRIVATE && modality != Modality.FINAL && (parent as? IrClass)?.isFinalClass != true
|
||||
|
||||
val IrFunction.isOverridableOrOverrides: Boolean get() = this is IrSimpleFunction && (isOverridable || overriddenSymbols.isNotEmpty())
|
||||
|
||||
val IrDeclaration.isMemberOfOpenClass: Boolean
|
||||
get() {
|
||||
val parentClass = this.parent as? IrClass ?: return false
|
||||
return !parentClass.isFinalClass
|
||||
}
|
||||
|
||||
val IrClass.isFinalClass: Boolean
|
||||
get() = modality == Modality.FINAL && kind != ClassKind.ENUM_CLASS
|
||||
|
||||
val IrTypeParametersContainer.classIfConstructor get() = if (this is IrConstructor) parentAsClass else this
|
||||
|
||||
fun IrValueParameter.copyTo(
|
||||
irFunction: IrFunction,
|
||||
origin: IrDeclarationOrigin = this.origin,
|
||||
index: Int = this.index,
|
||||
startOffset: Int = this.startOffset,
|
||||
endOffset: Int = this.endOffset,
|
||||
name: Name = this.name,
|
||||
remapTypeMap: Map<IrTypeParameter, IrTypeParameter> = mapOf(),
|
||||
type: IrType = this.type.remapTypeParameters(
|
||||
(parent as IrTypeParametersContainer).classIfConstructor,
|
||||
irFunction.classIfConstructor,
|
||||
remapTypeMap
|
||||
),
|
||||
varargElementType: IrType? = this.varargElementType, // TODO: remapTypeParameters here as well
|
||||
defaultValue: IrExpressionBody? = this.defaultValue,
|
||||
isCrossinline: Boolean = this.isCrossinline,
|
||||
isNoinline: Boolean = this.isNoinline,
|
||||
isAssignable: Boolean = this.isAssignable
|
||||
): IrValueParameter {
|
||||
val symbol = IrValueParameterSymbolImpl()
|
||||
val defaultValueCopy = defaultValue?.let { originalDefault ->
|
||||
factory.createExpressionBody(originalDefault.startOffset, originalDefault.endOffset) {
|
||||
expression = originalDefault.expression.deepCopyWithVariables().also {
|
||||
it.patchDeclarationParents(irFunction)
|
||||
}
|
||||
}
|
||||
}
|
||||
return factory.createValueParameter(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
name, index, type, varargElementType, isCrossinline = isCrossinline,
|
||||
isNoinline = isNoinline, isHidden = false, isAssignable = isAssignable
|
||||
).also {
|
||||
it.parent = irFunction
|
||||
it.defaultValue = defaultValueCopy
|
||||
it.copyAnnotationsFrom(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun IrTypeParameter.copyToWithoutSuperTypes(
|
||||
target: IrTypeParametersContainer,
|
||||
index: Int = this.index,
|
||||
origin: IrDeclarationOrigin = this.origin
|
||||
): IrTypeParameter = buildTypeParameter(target) {
|
||||
updateFrom(this@copyToWithoutSuperTypes)
|
||||
this.name = this@copyToWithoutSuperTypes.name
|
||||
this.origin = origin
|
||||
this.index = index
|
||||
}
|
||||
|
||||
fun IrFunction.copyReceiverParametersFrom(from: IrFunction, substitutionMap: Map<IrTypeParameterSymbol, IrType>) {
|
||||
dispatchReceiverParameter = from.dispatchReceiverParameter?.run {
|
||||
factory.createValueParameter(
|
||||
startOffset, endOffset, origin,
|
||||
IrValueParameterSymbolImpl(),
|
||||
name, index,
|
||||
type.substitute(substitutionMap),
|
||||
varargElementType?.substitute(substitutionMap),
|
||||
isCrossinline, isNoinline,
|
||||
isHidden, isAssignable
|
||||
).also { parameter ->
|
||||
parameter.parent = this@copyReceiverParametersFrom
|
||||
}
|
||||
}
|
||||
extensionReceiverParameter = from.extensionReceiverParameter?.copyTo(this)
|
||||
}
|
||||
|
||||
fun IrFunction.copyValueParametersFrom(from: IrFunction, substitutionMap: Map<IrTypeParameterSymbol, IrType>) {
|
||||
copyReceiverParametersFrom(from, substitutionMap)
|
||||
val shift = valueParameters.size
|
||||
valueParameters += from.valueParameters.map {
|
||||
it.copyTo(this, index = it.index + shift, type = it.type.substitute(substitutionMap))
|
||||
}
|
||||
}
|
||||
|
||||
fun IrFunction.copyParameterDeclarationsFrom(from: IrFunction) {
|
||||
assert(typeParameters.isEmpty())
|
||||
copyTypeParametersFrom(from)
|
||||
val substitutionMap = makeTypeParameterSubstitutionMap(from, this)
|
||||
copyValueParametersFrom(from, substitutionMap)
|
||||
}
|
||||
|
||||
fun IrTypeParametersContainer.copyTypeParameters(
|
||||
srcTypeParameters: List<IrTypeParameter>,
|
||||
origin: IrDeclarationOrigin? = null,
|
||||
parameterMap: Map<IrTypeParameter, IrTypeParameter>? = null
|
||||
): List<IrTypeParameter> {
|
||||
val shift = typeParameters.size
|
||||
val oldToNewParameterMap = parameterMap.orEmpty().toMutableMap()
|
||||
// Any type parameter can figure in a boundary type for any other parameter.
|
||||
// Therefore, we first copy the parameters themselves, then set up their supertypes.
|
||||
val newTypeParameters = srcTypeParameters.mapIndexed { i, sourceParameter ->
|
||||
sourceParameter.copyToWithoutSuperTypes(this, index = i + shift, origin = origin ?: sourceParameter.origin).also {
|
||||
oldToNewParameterMap[sourceParameter] = it
|
||||
}
|
||||
}
|
||||
typeParameters += newTypeParameters
|
||||
srcTypeParameters.zip(newTypeParameters).forEach { (srcParameter, dstParameter) ->
|
||||
dstParameter.copySuperTypesFrom(srcParameter, oldToNewParameterMap)
|
||||
}
|
||||
return newTypeParameters
|
||||
}
|
||||
|
||||
fun IrTypeParametersContainer.copyTypeParametersFrom(
|
||||
source: IrTypeParametersContainer,
|
||||
origin: IrDeclarationOrigin? = null,
|
||||
parameterMap: Map<IrTypeParameter, IrTypeParameter>? = null
|
||||
) = copyTypeParameters(source.typeParameters, origin, parameterMap)
|
||||
|
||||
private fun IrTypeParameter.copySuperTypesFrom(source: IrTypeParameter, srcToDstParameterMap: Map<IrTypeParameter, IrTypeParameter>) {
|
||||
val target = this
|
||||
val sourceParent = source.parent as IrTypeParametersContainer
|
||||
val targetParent = target.parent as IrTypeParametersContainer
|
||||
target.superTypes = source.superTypes.map {
|
||||
it.remapTypeParameters(sourceParent, targetParent, srcToDstParameterMap)
|
||||
}
|
||||
}
|
||||
|
||||
fun IrAnnotationContainer.copyAnnotations(): List<IrConstructorCall> {
|
||||
return annotations.map { it.deepCopyWithSymbols(this as? IrDeclarationParent) }
|
||||
}
|
||||
|
||||
fun IrAnnotationContainer.copyAnnotationsWhen(filter: IrConstructorCall.() -> Boolean): List<IrConstructorCall> {
|
||||
return annotations.mapNotNull { if (it.filter()) it.deepCopyWithSymbols(this as? IrDeclarationParent) else null }
|
||||
}
|
||||
|
||||
fun IrMutableAnnotationContainer.copyAnnotationsFrom(source: IrAnnotationContainer) {
|
||||
annotations += source.copyAnnotations()
|
||||
}
|
||||
|
||||
fun makeTypeParameterSubstitutionMap(
|
||||
original: IrTypeParametersContainer,
|
||||
transformed: IrTypeParametersContainer
|
||||
): Map<IrTypeParameterSymbol, IrType> =
|
||||
original.typeParameters
|
||||
.map { it.symbol }
|
||||
.zip(transformed.typeParameters.map { it.defaultType })
|
||||
.toMap()
|
||||
|
||||
|
||||
// Copy value parameters, dispatch receiver, and extension receiver from source to value parameters of this function.
|
||||
// Type of dispatch receiver defaults to source's dispatch receiver. It is overridable in case the new function and the old one are used in
|
||||
// different contexts and expect different type of dispatch receivers. The overriding type should be assign compatible to the old type.
|
||||
fun IrFunction.copyValueParametersToStatic(
|
||||
source: IrFunction,
|
||||
origin: IrDeclarationOrigin,
|
||||
dispatchReceiverType: IrType? = source.dispatchReceiverParameter?.type,
|
||||
numValueParametersToCopy: Int = source.valueParameters.size
|
||||
) {
|
||||
val target = this
|
||||
assert(target.valueParameters.isEmpty())
|
||||
|
||||
var shift = 0
|
||||
source.dispatchReceiverParameter?.let { originalDispatchReceiver ->
|
||||
assert(dispatchReceiverType!!.isSubtypeOfClass(originalDispatchReceiver.type.classOrNull!!))
|
||||
val type = dispatchReceiverType.remapTypeParameters(
|
||||
(originalDispatchReceiver.parent as IrTypeParametersContainer).classIfConstructor,
|
||||
target.classIfConstructor
|
||||
)
|
||||
|
||||
target.valueParameters += originalDispatchReceiver.copyTo(
|
||||
target,
|
||||
origin = originalDispatchReceiver.origin,
|
||||
index = shift++,
|
||||
type = type,
|
||||
name = Name.identifier("\$this")
|
||||
)
|
||||
}
|
||||
source.extensionReceiverParameter?.let { originalExtensionReceiver ->
|
||||
target.valueParameters += originalExtensionReceiver.copyTo(
|
||||
target,
|
||||
origin = originalExtensionReceiver.origin,
|
||||
index = shift++,
|
||||
name = Name.identifier("\$receiver")
|
||||
)
|
||||
}
|
||||
|
||||
for (oldValueParameter in source.valueParameters) {
|
||||
if (oldValueParameter.index >= numValueParametersToCopy) break
|
||||
target.valueParameters += oldValueParameter.copyTo(
|
||||
target,
|
||||
origin = origin,
|
||||
index = oldValueParameter.index + shift
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun IrFunctionAccessExpression.passTypeArgumentsFrom(irFunction: IrTypeParametersContainer, offset: Int = 0) {
|
||||
irFunction.typeParameters.forEachIndexed { i, param ->
|
||||
putTypeArgument(i + offset, param.defaultType)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a substitution of type parameters occuring in [this]. In order of
|
||||
* precedence, parameter `P` is substituted with...
|
||||
*
|
||||
* 1) `T`, if `srcToDstParameterMap.get(P) == T`
|
||||
* 2) `T`, if `source.typeParameters[i] == P` and
|
||||
* `target.typeParameters[i] == T`
|
||||
* 3) `P`
|
||||
*
|
||||
* If [srcToDstParameterMap] is total on the domain of type parameters in
|
||||
* [this], this effectively performs a substitution according to that map.
|
||||
*/
|
||||
fun IrType.remapTypeParameters(
|
||||
source: IrTypeParametersContainer,
|
||||
target: IrTypeParametersContainer,
|
||||
srcToDstParameterMap: Map<IrTypeParameter, IrTypeParameter>? = null
|
||||
): IrType =
|
||||
when (this) {
|
||||
is IrSimpleType -> {
|
||||
val classifier = classifier.owner
|
||||
when {
|
||||
classifier is IrTypeParameter -> {
|
||||
val newClassifier =
|
||||
srcToDstParameterMap?.get(classifier) ?: if (classifier.parent == source)
|
||||
target.typeParameters[classifier.index]
|
||||
else
|
||||
classifier
|
||||
IrSimpleTypeImpl(newClassifier.symbol, nullability, arguments, annotations)
|
||||
}
|
||||
|
||||
classifier is IrClass ->
|
||||
IrSimpleTypeImpl(
|
||||
classifier.symbol,
|
||||
nullability,
|
||||
arguments.map {
|
||||
when (it) {
|
||||
is IrTypeProjection -> makeTypeProjection(
|
||||
it.type.remapTypeParameters(source, target, srcToDstParameterMap),
|
||||
it.variance
|
||||
)
|
||||
else -> it
|
||||
}
|
||||
},
|
||||
annotations
|
||||
)
|
||||
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
else -> this
|
||||
}
|
||||
|
||||
/* Copied from K/N */
|
||||
fun IrDeclarationContainer.addChild(declaration: IrDeclaration) {
|
||||
this.declarations += declaration
|
||||
declaration.setDeclarationsParent(this)
|
||||
}
|
||||
|
||||
fun <T : IrElement> T.setDeclarationsParent(parent: IrDeclarationParent): T {
|
||||
accept(SetDeclarationsParentVisitor, parent)
|
||||
return this
|
||||
}
|
||||
|
||||
object SetDeclarationsParentVisitor : IrElementVisitor<Unit, IrDeclarationParent> {
|
||||
override fun visitElement(element: IrElement, data: IrDeclarationParent) {
|
||||
if (element !is IrDeclarationParent) {
|
||||
element.acceptChildren(this, data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitDeclaration(declaration: IrDeclarationBase, data: IrDeclarationParent) {
|
||||
declaration.parent = data
|
||||
super.visitDeclaration(declaration, data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val IrFunction.isStatic: Boolean
|
||||
get() = parent is IrClass && dispatchReceiverParameter == null
|
||||
|
||||
val IrDeclaration.isTopLevel: Boolean
|
||||
get() {
|
||||
if (parent is IrPackageFragment) return true
|
||||
val parentClass = parent as? IrClass
|
||||
return parentClass?.isFileClass == true && parentClass.parent is IrPackageFragment
|
||||
}
|
||||
|
||||
fun IrClass.createImplicitParameterDeclarationWithWrappedDescriptor() {
|
||||
thisReceiver = buildReceiverParameter(this, IrDeclarationOrigin.INSTANCE_RECEIVER, symbol.typeWithParameters(typeParameters))
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun isElseBranch(branch: IrBranch) = branch is IrElseBranch || ((branch.condition as? IrConst<Boolean>)?.value == true)
|
||||
|
||||
fun IrFunction.isMethodOfAny(): Boolean =
|
||||
extensionReceiverParameter == null && dispatchReceiverParameter != null &&
|
||||
when (name) {
|
||||
OperatorNameConventions.HASH_CODE, OperatorNameConventions.TO_STRING -> valueParameters.isEmpty()
|
||||
OperatorNameConventions.EQUALS -> valueParameters.singleOrNull()?.type?.isNullableAny() == true
|
||||
else -> false
|
||||
}
|
||||
|
||||
fun IrDeclarationContainer.simpleFunctions() = declarations.flatMap {
|
||||
when (it) {
|
||||
is IrSimpleFunction -> listOf(it)
|
||||
is IrProperty -> listOfNotNull(it.getter, it.setter)
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun IrClass.createParameterDeclarations() {
|
||||
assert(thisReceiver == null)
|
||||
thisReceiver = buildReceiverParameter(this, IrDeclarationOrigin.INSTANCE_RECEIVER, symbol.typeWithParameters(typeParameters))
|
||||
}
|
||||
|
||||
fun IrFunction.createDispatchReceiverParameter(origin: IrDeclarationOrigin? = null) {
|
||||
assert(dispatchReceiverParameter == null)
|
||||
|
||||
dispatchReceiverParameter = factory.createValueParameter(
|
||||
startOffset, endOffset,
|
||||
origin ?: parentAsClass.origin,
|
||||
IrValueParameterSymbolImpl(),
|
||||
SpecialNames.THIS,
|
||||
-1,
|
||||
parentAsClass.defaultType,
|
||||
null,
|
||||
isCrossinline = false,
|
||||
isNoinline = false,
|
||||
isHidden = false,
|
||||
isAssignable = false
|
||||
).apply {
|
||||
parent = this@createDispatchReceiverParameter
|
||||
}
|
||||
}
|
||||
|
||||
val IrFunction.allParameters: List<IrValueParameter>
|
||||
get() = if (this is IrConstructor) {
|
||||
ArrayList<IrValueParameter>(allParametersCount).also {
|
||||
it.add(
|
||||
this.constructedClass.thisReceiver
|
||||
?: error(this.render())
|
||||
)
|
||||
addExplicitParametersTo(it)
|
||||
}
|
||||
} else {
|
||||
explicitParameters
|
||||
}
|
||||
|
||||
val IrFunction.allParametersCount: Int
|
||||
get() = if (this is IrConstructor) explicitParametersCount + 1 else explicitParametersCount
|
||||
|
||||
// This is essentially the same as FakeOverrideBuilder,
|
||||
// but it bypasses SymbolTable.
|
||||
// TODO: merge it with FakeOverrideBuilder.
|
||||
private class FakeOverrideBuilderForLowerings : FakeOverrideBuilderStrategy(emptyMap()) {
|
||||
|
||||
override fun linkFunctionFakeOverride(declaration: IrFakeOverrideFunction, compatibilityMode: Boolean) {
|
||||
declaration.acquireSymbol(IrSimpleFunctionSymbolImpl())
|
||||
}
|
||||
|
||||
override fun linkPropertyFakeOverride(declaration: IrFakeOverrideProperty, compatibilityMode: Boolean) {
|
||||
val propertySymbol = IrPropertySymbolImpl()
|
||||
declaration.getter?.let { it.correspondingPropertySymbol = propertySymbol }
|
||||
declaration.setter?.let { it.correspondingPropertySymbol = propertySymbol }
|
||||
|
||||
declaration.acquireSymbol(propertySymbol)
|
||||
|
||||
declaration.getter?.let {
|
||||
it.correspondingPropertySymbol = declaration.symbol
|
||||
linkFunctionFakeOverride(it as? IrFakeOverrideFunction ?: error("Unexpected fake override getter: $it"), compatibilityMode)
|
||||
}
|
||||
declaration.setter?.let {
|
||||
it.correspondingPropertySymbol = declaration.symbol
|
||||
linkFunctionFakeOverride(it as? IrFakeOverrideFunction ?: error("Unexpected fake override setter: $it"), compatibilityMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun IrClass.addFakeOverrides(typeSystem: IrTypeSystemContext, implementedMembers: List<IrOverridableMember> = emptyList()) {
|
||||
IrOverridingUtil(typeSystem, FakeOverrideBuilderForLowerings())
|
||||
.buildFakeOverridesForClassUsingOverriddenSymbols(this, implementedMembers, compatibilityMode = false)
|
||||
.forEach { addChild(it) }
|
||||
}
|
||||
|
||||
fun IrFactory.createStaticFunctionWithReceivers(
|
||||
irParent: IrDeclarationParent,
|
||||
name: Name,
|
||||
oldFunction: IrFunction,
|
||||
dispatchReceiverType: IrType? = oldFunction.dispatchReceiverParameter?.type,
|
||||
origin: IrDeclarationOrigin = oldFunction.origin,
|
||||
modality: Modality = Modality.FINAL,
|
||||
visibility: DescriptorVisibility = oldFunction.visibility,
|
||||
isFakeOverride: Boolean = oldFunction.isFakeOverride,
|
||||
copyMetadata: Boolean = true,
|
||||
typeParametersFromContext: List<IrTypeParameter> = listOf()
|
||||
): IrSimpleFunction {
|
||||
return createFunction(
|
||||
oldFunction.startOffset, oldFunction.endOffset,
|
||||
origin,
|
||||
IrSimpleFunctionSymbolImpl(),
|
||||
name,
|
||||
visibility,
|
||||
modality,
|
||||
oldFunction.returnType,
|
||||
isInline = oldFunction.isInline,
|
||||
isExternal = false,
|
||||
isTailrec = false,
|
||||
isSuspend = oldFunction.isSuspend,
|
||||
isExpect = oldFunction.isExpect,
|
||||
isFakeOverride = isFakeOverride,
|
||||
isOperator = oldFunction is IrSimpleFunction && oldFunction.isOperator,
|
||||
isInfix = oldFunction is IrSimpleFunction && oldFunction.isInfix,
|
||||
containerSource = oldFunction.containerSource,
|
||||
).apply {
|
||||
parent = irParent
|
||||
|
||||
val newTypeParametersFromContext = copyAndRenameConflictingTypeParametersFrom(
|
||||
typeParametersFromContext,
|
||||
oldFunction.typeParameters
|
||||
)
|
||||
val newTypeParametersFromFunction = copyTypeParametersFrom(oldFunction)
|
||||
val typeParameterMap =
|
||||
(typeParametersFromContext + oldFunction.typeParameters)
|
||||
.zip(newTypeParametersFromContext + newTypeParametersFromFunction).toMap()
|
||||
|
||||
fun remap(type: IrType): IrType =
|
||||
type.remapTypeParameters(oldFunction, this, typeParameterMap)
|
||||
|
||||
typeParameters.forEach { it.superTypes = it.superTypes.map(::remap) }
|
||||
|
||||
annotations = oldFunction.annotations
|
||||
|
||||
var offset = 0
|
||||
val dispatchReceiver = oldFunction.dispatchReceiverParameter?.copyTo(
|
||||
this,
|
||||
name = Name.identifier("\$this"),
|
||||
index = offset++,
|
||||
type = remap(dispatchReceiverType!!),
|
||||
origin = IrDeclarationOrigin.MOVED_DISPATCH_RECEIVER
|
||||
)
|
||||
val extensionReceiver = oldFunction.extensionReceiverParameter?.copyTo(
|
||||
this,
|
||||
name = Name.identifier("\$receiver"),
|
||||
index = offset++,
|
||||
origin = IrDeclarationOrigin.MOVED_EXTENSION_RECEIVER,
|
||||
remapTypeMap = typeParameterMap
|
||||
)
|
||||
valueParameters = listOfNotNull(dispatchReceiver, extensionReceiver) +
|
||||
oldFunction.valueParameters.map {
|
||||
it.copyTo(
|
||||
this,
|
||||
index = it.index + offset,
|
||||
remapTypeMap = typeParameterMap
|
||||
)
|
||||
}
|
||||
|
||||
if (copyMetadata) metadata = oldFunction.metadata
|
||||
|
||||
copyAttributes(oldFunction as? IrAttributeContainer)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the parameters in [contextParameters] to the type parameters of
|
||||
* [this] function, renaming those that may clash with a provided collection of
|
||||
* [existingParameters] (e.g. type parameters of the function itself, when
|
||||
* creating DefaultImpls).
|
||||
*
|
||||
* @returns List of newly created, possibly renamed, copies of type parameters
|
||||
* in order of the corresponding parameters in [context].
|
||||
*/
|
||||
private fun IrSimpleFunction.copyAndRenameConflictingTypeParametersFrom(
|
||||
contextParameters: List<IrTypeParameter>,
|
||||
existingParameters: Collection<IrTypeParameter>
|
||||
): List<IrTypeParameter> {
|
||||
val newParameters = mutableListOf<IrTypeParameter>()
|
||||
|
||||
val existingNames =
|
||||
(contextParameters.map { it.name.asString() } + existingParameters.map { it.name.asString() }).toMutableSet()
|
||||
|
||||
contextParameters.forEach { contextType ->
|
||||
val newName = if (existingParameters.any { it.name.asString() == contextType.name.asString() }) {
|
||||
val newNamePrefix = contextType.name.asString() + "_I"
|
||||
val newName = newNamePrefix + generateSequence(1) { x -> x + 1 }.first { n ->
|
||||
(newNamePrefix + n) !in existingNames
|
||||
}
|
||||
existingNames.add(newName)
|
||||
newName
|
||||
} else {
|
||||
contextType.name.asString()
|
||||
}
|
||||
|
||||
newParameters.add(buildTypeParameter(this) {
|
||||
updateFrom(contextType)
|
||||
name = Name.identifier(newName)
|
||||
})
|
||||
}
|
||||
|
||||
val zipped = contextParameters.zip(newParameters)
|
||||
val parameterMap = zipped.toMap()
|
||||
for ((oldParameter, newParameter) in zipped) {
|
||||
newParameter.copySuperTypesFrom(oldParameter, parameterMap)
|
||||
}
|
||||
|
||||
typeParameters = typeParameters + newParameters
|
||||
|
||||
return newParameters
|
||||
}
|
||||
|
||||
val IrSymbol.isSuspend: Boolean
|
||||
get() = this is IrSimpleFunctionSymbol && owner.isSuspend
|
||||
|
||||
fun IrSimpleFunction.allOverridden(includeSelf: Boolean = false): List<IrSimpleFunction> {
|
||||
val result = mutableListOf<IrSimpleFunction>()
|
||||
if (includeSelf) {
|
||||
result.add(this)
|
||||
}
|
||||
|
||||
var current = this
|
||||
while (true) {
|
||||
val overridden = current.overriddenSymbols
|
||||
when (overridden.size) {
|
||||
0 -> return result
|
||||
1 -> {
|
||||
current = overridden[0].owner
|
||||
result.add(current)
|
||||
}
|
||||
else -> {
|
||||
val resultSet = result.toMutableSet()
|
||||
computeAllOverridden(current, resultSet)
|
||||
return resultSet.toList()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun computeAllOverridden(function: IrSimpleFunction, result: MutableSet<IrSimpleFunction>) {
|
||||
for (overriddenSymbol in function.overriddenSymbols) {
|
||||
val override = overriddenSymbol.owner
|
||||
if (result.add(override)) {
|
||||
computeAllOverridden(override, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun IrBuiltIns.getKFunctionType(returnType: IrType, parameterTypes: List<IrType>) =
|
||||
kFunctionN(parameterTypes.size).typeWith(parameterTypes + returnType)
|
||||
Reference in New Issue
Block a user