Initial lazy ir implementation

This commit is contained in:
Mikhael Bogdanov
2018-07-04 15:00:08 +02:00
parent 2884d728fd
commit c19d45a2fc
14 changed files with 827 additions and 107 deletions
@@ -0,0 +1,117 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. 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.declarations.lazy
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.ir.util.transform
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
class IrLazyClass(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
override val symbol: IrClassSymbol,
override val name: Name,
override val kind: ClassKind,
override val visibility: Visibility,
override val modality: Modality,
override val isCompanion: Boolean,
override val isInner: Boolean,
override val isData: Boolean,
override val isExternal: Boolean,
stubGenerator: DeclarationStubGenerator,
typeTranslator: TypeTranslator
) :
IrLazyDeclarationBase(startOffset, endOffset, origin, stubGenerator, typeTranslator),
IrClass {
constructor(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
symbol: IrClassSymbol,
stubGenerator: DeclarationStubGenerator,
TypeTranslator: TypeTranslator
) :
this(
startOffset, endOffset, origin, symbol,
symbol.descriptor.name, symbol.descriptor.kind,
symbol.descriptor.visibility, symbol.descriptor.modality,
isCompanion = symbol.descriptor.isCompanionObject,
isInner = symbol.descriptor.isInner,
isData = symbol.descriptor.isData,
isExternal = symbol.descriptor.isEffectivelyExternal(),
stubGenerator = stubGenerator,
typeTranslator = TypeTranslator
)
init {
symbol.bind(this)
}
override val annotations: MutableList<IrCall> = arrayListOf()
override val descriptor: ClassDescriptor get() = symbol.descriptor
override var thisReceiver: IrValueParameter? by lazyVar {
typeTranslator.buildWithScope(this) {
descriptor.thisAsReceiverParameter.generateReceiverParameterStub()
}
}
override val declarations: MutableList<IrDeclaration> by lazyVar {
ArrayList<IrDeclaration>().also {
typeTranslator.buildWithScope(this) {
generateChildStubs(descriptor.constructors, it)
generateMemberStubs(descriptor.defaultType.memberScope, it)
generateMemberStubs(descriptor.staticScope, it)
}
}
}
override val typeParameters: MutableList<IrTypeParameter> by lazy {
descriptor.declaredTypeParameters.mapTo(arrayListOf()) {
stubGenerator.generateOrGetTypeParameterStub(it)
}
}
override val superTypes: MutableList<IrType> by lazy {
typeTranslator.buildWithScope(this) {
// TODO get rid of code duplication, see ClassGenerator#generateClass
descriptor.typeConstructor.supertypes.mapNotNullTo(arrayListOf()) {
it.toIrType()
}
}
}
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitClass(this, data)
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
thisReceiver?.accept(visitor, data)
typeParameters.forEach { it.accept(visitor, data) }
declarations.forEach { it.accept(visitor, data) }
}
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
thisReceiver = thisReceiver?.transform(transformer, data)
typeParameters.transform { it.transform(transformer, data) }
declarations.transform { it.transform(transformer, data) }
}
}
@@ -0,0 +1,68 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. 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.declarations.lazy
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
class IrLazyConstructor(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
override val symbol: IrConstructorSymbol,
name: Name,
visibility: Visibility,
isInline: Boolean,
isExternal: Boolean,
override val isPrimary: Boolean,
stubGenerator: DeclarationStubGenerator,
typeTranslator: TypeTranslator
) :
IrLazyFunctionBase(
startOffset, endOffset, origin, name,
visibility, isInline, isExternal,
stubGenerator, typeTranslator
),
IrConstructor {
constructor(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
symbol: IrConstructorSymbol,
stubGenerator: DeclarationStubGenerator,
TypeTranslator: TypeTranslator
) : this(
startOffset, endOffset, origin, symbol,
symbol.descriptor.name,
symbol.descriptor.visibility,
symbol.descriptor.isInline,
symbol.descriptor.isEffectivelyExternal(),
symbol.descriptor.isPrimary,
stubGenerator,
TypeTranslator
)
override val typeParameters: MutableList<IrTypeParameter> = arrayListOf()
init {
symbol.bind(this)
}
override val descriptor: ClassConstructorDescriptor get() = symbol.descriptor
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitConstructor(this, data)
}
@@ -0,0 +1,98 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. 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.declarations.lazy
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrElementBase
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinType
import kotlin.reflect.KProperty
abstract class IrLazyDeclarationBase(
startOffset: Int,
endOffset: Int,
override val origin: IrDeclarationOrigin,
private val stubGenerator: DeclarationStubGenerator,
protected val typeTranslator: TypeTranslator
) : IrElementBase(startOffset, endOffset), IrDeclaration {
protected fun KotlinType.toIrType() = typeTranslator.translateType(this)
protected fun ReceiverParameterDescriptor.generateReceiverParameterStub(): IrValueParameter =
IrValueParameterImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, this,
type.toIrType(), null
)
protected fun generateMemberStubs(memberScope: MemberScope, container: MutableList<IrDeclaration>) {
generateChildStubs(memberScope.getContributedDescriptors(), container)
}
protected fun generateChildStubs(descriptors: Collection<DeclarationDescriptor>, declarations: MutableList<IrDeclaration>) {
descriptors.mapTo(declarations) { generateMemberStub(it) }
}
private fun generateMemberStub(descriptor: DeclarationDescriptor): IrDeclaration =
stubGenerator.generateMemberStub(descriptor)
override var parent: IrDeclarationParent by lazyVar {
createLazyParent()!!
}
override val annotations: MutableList<IrCall> = arrayListOf()
private fun createLazyParent(): IrDeclarationParent? {
val currentDescriptor = descriptor
val containingDeclaration = currentDescriptor.containingDeclaration
return when (containingDeclaration) {
is PackageFragmentDescriptor -> stubGenerator.generateOrGetEmptyExternalPackageFragmentStub(containingDeclaration).also {
it.declarations.add(this)
}
is ClassDescriptor -> stubGenerator.generateClassStub(containingDeclaration)
is FunctionDescriptor -> stubGenerator.generateFunctionStub(containingDeclaration)
else -> throw AssertionError("Package or class expected: $containingDeclaration; for $currentDescriptor")
}
}
}
internal fun <T> lazyVar(initializer: () -> T): UnsafeLazyVar<T> = UnsafeLazyVar(initializer)
internal class UnsafeLazyVar<T>(initializer: () -> T) {
private var isInitialized = false;
private var initializer: (() -> T)? = initializer
private var _value: Any? = null
private val value: T
get() {
if (!isInitialized) {
_value = initializer!!()
isInitialized = true
initializer = null
}
@Suppress("UNCHECKED_CAST")
return _value as T
}
override fun toString(): String = if (isInitialized) value.toString() else "Lazy value not initialized yet."
operator fun getValue(thisRef: Any?, property: KProperty<*>): T = value
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
this._value = value
isInitialized = true
}
}
@@ -0,0 +1,65 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.ir.declarations.lazy
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrEnumEntry
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.Name
class IrLazyEnumEntryImpl(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
override val symbol: IrEnumEntrySymbol,
stubGenerator: DeclarationStubGenerator,
typeTranslator: TypeTranslator
) : IrLazyDeclarationBase(startOffset, endOffset, origin, stubGenerator, typeTranslator),
IrEnumEntry {
init {
symbol.bind(this)
}
override val descriptor: ClassDescriptor get() = symbol.descriptor
override val name: Name = symbol.descriptor.name
override var correspondingClass: IrClass? = null
override var initializerExpression: IrExpression? = null
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
return visitor.visitEnumEntry(this, data)
}
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
initializerExpression?.accept(visitor, data)
correspondingClass?.accept(visitor, data)
}
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
initializerExpression = initializerExpression?.transform(transformer, data)
correspondingClass = correspondingClass?.transform(transformer, data) as? IrClass
}
}
@@ -0,0 +1,93 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. 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.declarations.lazy
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor
class IrLazyFunction(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
override val symbol: IrSimpleFunctionSymbol,
name: Name,
visibility: Visibility,
override val modality: Modality,
isInline: Boolean,
isExternal: Boolean,
override val isTailrec: Boolean,
override val isSuspend: Boolean,
stubGenerator: DeclarationStubGenerator,
typeTranslator: TypeTranslator
) :
IrLazyFunctionBase(startOffset, endOffset, origin, name, visibility, isInline, isExternal, stubGenerator, typeTranslator),
IrSimpleFunction {
constructor(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
symbol: IrSimpleFunctionSymbol,
stubGenerator: DeclarationStubGenerator,
TypeTranslator: TypeTranslator
) : this(
startOffset, endOffset, origin, symbol,
symbol.descriptor.name,
symbol.descriptor.visibility,
symbol.descriptor.modality,
symbol.descriptor.isInline,
symbol.descriptor.isExternal,
symbol.descriptor.isTailrec,
symbol.descriptor.isSuspend,
stubGenerator,
TypeTranslator
)
override val descriptor: FunctionDescriptor = symbol.descriptor
override val typeParameters: MutableList<IrTypeParameter> by lazy {
typeTranslator.buildWithScope(this) {
stubGenerator.symbolTable.enterScope(descriptor)
val propertyIfAccessor = descriptor.propertyIfAccessor
propertyIfAccessor.typeParameters.mapTo(arrayListOf()) {
if (descriptor != propertyIfAccessor) {
stubGenerator.generateOrGetScopedTypeParameterStub(it).also {
it.parent = this@IrLazyFunction
}
} else {
stubGenerator.generateOrGetTypeParameterStub(it)
}
}.also {
stubGenerator.symbolTable.leaveScope(descriptor)
}
}
}
override val overriddenSymbols: MutableList<IrSimpleFunctionSymbol> by lazy {
descriptor.overriddenDescriptors.mapTo(arrayListOf()) {
stubGenerator.generateFunctionStub(it.original).symbol
}
}
override var correspondingProperty: IrProperty? = null
init {
symbol.bind(this)
}
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitSimpleFunction(this, data)
}
@@ -0,0 +1,81 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. 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.declarations.lazy
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.ir.util.transform
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor
abstract class IrLazyFunctionBase(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
override val name: Name,
override val visibility: Visibility,
override val isInline: Boolean,
override val isExternal: Boolean,
stubGenerator: DeclarationStubGenerator,
typeTranslator: TypeTranslator
) :
IrLazyDeclarationBase(startOffset, endOffset, origin, stubGenerator, typeTranslator),
IrFunction {
override var dispatchReceiverParameter: IrValueParameter? by lazyVar {
typeTranslator.buildWithScope(this) {
descriptor.dispatchReceiverParameter?.generateReceiverParameterStub()
}
}
override var extensionReceiverParameter: IrValueParameter? by lazyVar {
typeTranslator.buildWithScope(this) {
descriptor.extensionReceiverParameter?.generateReceiverParameterStub()
}
}
override val valueParameters: MutableList<IrValueParameter> by lazy {
typeTranslator.buildWithScope(this) {
descriptor.valueParameters.mapTo(arrayListOf()) { stubGenerator.generateValueParameterStub(it) }
}
}
final override var body: IrBody? = null
final override var returnType: IrType by lazyVar {
typeTranslator.buildWithScope(this) {
descriptor.returnType!!.toIrType()
}
}
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
typeParameters.forEach { it.accept(visitor, data) }
dispatchReceiverParameter?.accept(visitor, data)
extensionReceiverParameter?.accept(visitor, data)
valueParameters.forEach { it.accept(visitor, data) }
body?.accept(visitor, data)
}
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
typeParameters.transform { it.transform(transformer, data) }
dispatchReceiverParameter = dispatchReceiverParameter?.transform(transformer, data)
extensionReceiverParameter = extensionReceiverParameter?.transform(transformer, data)
valueParameters.transform { it.transform(transformer, data) }
body = body?.transform(transformer, data)
}
}
@@ -0,0 +1,61 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. 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.declarations.lazy
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.util.SymbolTable
class IrLazySymbolTable(private val stubGenerator: DeclarationStubGenerator, val originalTable: SymbolTable) : SymbolTable() {
/*Don't force builtins class linking before unbound symbols linking: otherwise stdlib compilation will failed*/
internal var unboundSymbolGeneration = false
override fun referenceClass(descriptor: ClassDescriptor): IrClassSymbol {
return originalTable.referenceClass(descriptor).also {
if (unboundSymbolGeneration && !it.isBound) {
stubGenerator.generateClassStub(descriptor).symbol
}
}
}
override fun referenceConstructor(descriptor: ClassConstructorDescriptor): IrConstructorSymbol {
return originalTable.referenceConstructor(descriptor).also {
if (!it.isBound && unboundSymbolGeneration) {
stubGenerator.generateConstructorStub(descriptor).symbol
}
}
}
override fun referenceEnumEntry(descriptor: ClassDescriptor): IrEnumEntrySymbol {
return originalTable.referenceEnumEntry(descriptor).also {
if (!it.isBound && unboundSymbolGeneration) {
stubGenerator.generateEnumEntryStub(descriptor).symbol
}
}
}
override fun referenceSimpleFunction(descriptor: FunctionDescriptor): IrSimpleFunctionSymbol {
return originalTable.referenceSimpleFunction(descriptor).also {
if (!it.isBound && unboundSymbolGeneration) {
stubGenerator.generateFunctionStub(descriptor).symbol
}
}
}
override fun referenceTypeParameter(classifier: TypeParameterDescriptor): IrTypeParameterSymbol {
return originalTable.referenceTypeParameter(classifier).also {
if (!it.isBound && unboundSymbolGeneration) {
stubGenerator.generateOrGetTypeParameterStub(classifier).symbol
}
}
}
}
@@ -0,0 +1,77 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. 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.declarations.lazy
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance
class IrLazyTypeParameter(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
override val symbol: IrTypeParameterSymbol,
override val name: Name,
override val index: Int,
override val variance: Variance,
stubGenerator: DeclarationStubGenerator,
typeTranslator: TypeTranslator
) :
IrLazyDeclarationBase(startOffset, endOffset, origin, stubGenerator, typeTranslator),
IrTypeParameter {
constructor(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
symbol: IrTypeParameterSymbol,
stubGenerator: DeclarationStubGenerator,
TypeTranslator: TypeTranslator
) :
this(
startOffset, endOffset, origin, symbol,
symbol.descriptor.name,
symbol.descriptor.index,
symbol.descriptor.variance,
stubGenerator, TypeTranslator
)
override val descriptor: TypeParameterDescriptor get() = symbol.descriptor
init {
symbol.bind(this)
}
override val superTypes: MutableList<IrType> by lazy {
typeTranslator.buildWithScope(this.parent as IrTypeParametersContainer) {
val descriptor = symbol.descriptor
descriptor.upperBounds.mapTo(arrayListOf()) { it.toIrType() }
}
}
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitTypeParameter(this, data)
override fun <D> transform(transformer: IrElementTransformer<D>, data: D): IrTypeParameter =
transformer.visitTypeParameter(this, data) as IrTypeParameter
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
// no children
}
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
// no children
}
}
@@ -0,0 +1,51 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. 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.declarations.lazy
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.util.*
import java.util.*
class LazyScopedTypeParametersResolver() : TypeParametersResolver {
private val typeParameterScopes = ArrayDeque<IrTypeParametersContainer>()
override fun enterTypeParameterScope(typeParametersContainer: IrTypeParametersContainer) {
typeParameterScopes.addFirst(
typeParametersContainer
)
}
override fun leaveTypeParameterScope() {
typeParameterScopes.removeFirst()
}
//TODO optimize
override fun resolveScopedTypeParameter(typeParameterDescriptor: TypeParameterDescriptor): IrTypeParameterSymbol? {
var parent = typeParameterScopes.first()
while (parent != null) {
val declaration = parent
val symbol = declaration.typeParameters.firstOrNull {
it.descriptor == typeParameterDescriptor
}?.symbol
if (symbol != null) return symbol
parent = calcParent(parent)
}
return null
}
private fun calcParent(container: IrTypeParametersContainer): IrTypeParametersContainer? {
return when(container) {
is IrClass -> if (container.isObject || !container.isInner) null else container.parent
else -> (container as? IrDeclaration)?.parent
} as? IrTypeParametersContainer
}
}
@@ -22,14 +22,13 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.declarations.lazy.*
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinType
class DeclarationStubGenerator(
@@ -38,8 +37,15 @@ class DeclarationStubGenerator(
val origin: IrDeclarationOrigin,
val languageVersionSettings: LanguageVersionSettings
) {
private val typeTranslator = TypeTranslator(symbolTable, languageVersionSettings)
private val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable)
private val lazyTable = IrLazySymbolTable(this, symbolTable)
internal var unboundSymbolGeneration: Boolean
get() = lazyTable.unboundSymbolGeneration
set(value) { lazyTable.unboundSymbolGeneration = value }
private val typeTranslator = TypeTranslator(lazyTable, languageVersionSettings, LazyScopedTypeParametersResolver())
private val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, lazyTable)
init {
typeTranslator.constantValueGenerator = constantValueGenerator
@@ -49,8 +55,9 @@ class DeclarationStubGenerator(
fun generateEmptyModuleFragmentStub(descriptor: ModuleDescriptor, irBuiltIns: IrBuiltIns): IrModuleFragment =
IrModuleFragmentImpl(descriptor, irBuiltIns)
fun generateEmptyExternalPackageFragmentStub(descriptor: PackageFragmentDescriptor): IrExternalPackageFragment =
symbolTable.declareExternalPackageFragment(descriptor)
fun generateOrGetEmptyExternalPackageFragmentStub(descriptor: PackageFragmentDescriptor): IrExternalPackageFragment {
return symbolTable.declareExternalPackageFragment(descriptor)
}
fun generateMemberStub(descriptor: DeclarationDescriptor): IrDeclaration =
when (descriptor) {
@@ -69,7 +76,7 @@ class DeclarationStubGenerator(
throw AssertionError("Unexpected member descriptor: $descriptor")
}
private fun generatePropertyStub(descriptor: PropertyDescriptor): IrProperty =
internal fun generatePropertyStub(descriptor: PropertyDescriptor): IrProperty =
IrPropertyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor).also { irProperty ->
val getterDescriptor = descriptor.getter
if (getterDescriptor == null) {
@@ -88,8 +95,13 @@ class DeclarationStubGenerator(
irProperty.setter = descriptor.setter?.let { generateFunctionStub(it) }
}
fun generateFunctionStub(descriptor: FunctionDescriptor): IrSimpleFunction =
symbolTable.declareSimpleFunctionWithOverrides(
fun generateFunctionStub(descriptor: FunctionDescriptor): IrSimpleFunction {
val referenced = symbolTable.referenceSimpleFunction(descriptor)
if (referenced.isBound) {
return referenced.owner
}
return symbolTable.declareSimpleFunction(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
if (descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
IrDeclarationOrigin.FAKE_OVERRIDE
@@ -97,41 +109,24 @@ class DeclarationStubGenerator(
origin
},
descriptor.original
).also { irFunction ->
generateTypeParameterStubs(descriptor.propertyIfAccessor.typeParameters, irFunction)
) { IrLazyFunction(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator) }
}
typeTranslator.buildWithScope(irFunction) {
irFunction.returnType = descriptor.returnType!!.toIrType()
generateValueParametersStubs(irFunction)
}
internal fun generateConstructorStub(descriptor: ClassConstructorDescriptor): IrConstructor {
val referenced = symbolTable.referenceConstructor(descriptor)
if (referenced.isBound) {
return referenced.owner
}
private fun generateConstructorStub(descriptor: ClassConstructorDescriptor): IrConstructor =
symbolTable.declareConstructor(
return symbolTable.declareConstructor(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor.original
).also { irConstructor ->
// So far, constructors in Kotlin can't have type parameters of their own.
irConstructor.returnType = descriptor.returnType.toIrType()
generateValueParametersStubs(irConstructor)
}
private fun generateValueParametersStubs(function: IrFunction) {
val descriptor = function.descriptor
function.dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.generateReceiverParameterStub()
function.extensionReceiverParameter = descriptor.extensionReceiverParameter?.generateReceiverParameterStub()
descriptor.valueParameters.mapTo(function.valueParameters) { generateValueParameterStub(it) }
) { IrLazyConstructor(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator) }
}
private fun KotlinType.toIrType() = typeTranslator.translateType(this)
private fun ReceiverParameterDescriptor.generateReceiverParameterStub(): IrValueParameter =
IrValueParameterImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, this,
type.toIrType(), null
)
private fun generateValueParameterStub(descriptor: ValueParameterDescriptor): IrValueParameter =
IrValueParameterImpl(
internal fun generateValueParameterStub(descriptor: ValueParameterDescriptor): IrValueParameter {
return IrValueParameterImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin,
descriptor, descriptor.type.toIrType(), descriptor.varargElementType?.toIrType()
).also { irValueParameter ->
@@ -145,49 +140,32 @@ class DeclarationStubGenerator(
)
}
}
}
private fun generateClassStub(descriptor: ClassDescriptor): IrClass =
symbolTable.declareClass(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor).also { irClass ->
generateTypeParameterStubs(descriptor.declaredTypeParameters, irClass)
typeTranslator.buildWithScope(irClass) {
// TODO get rid of code duplication, see ClassGenerator#generateClass
descriptor.typeConstructor.supertypes.mapNotNullTo(irClass.superTypes) {
it.toIrType()
}
irClass.thisReceiver = descriptor.thisAsReceiverParameter.generateReceiverParameterStub()
generateChildStubs(descriptor.constructors, irClass)
generateMemberStubs(descriptor.defaultType.memberScope, irClass)
generateMemberStubs(descriptor.staticScope, irClass)
}
internal fun generateClassStub(descriptor: ClassDescriptor): IrClass {
val referenceClass = symbolTable.referenceClass(descriptor)
if (referenceClass.isBound) {
return referenceClass.owner
}
return symbolTable.declareClass(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor
) { IrLazyClass(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator) }
}
private fun generateEnumEntryStub(descriptor: ClassDescriptor): IrEnumEntry =
symbolTable.declareEnumEntry(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor)
private fun generateTypeParameterStubs(typeParameters: List<TypeParameterDescriptor>, container: IrTypeParametersContainer) {
typeParameters.mapTo(container.typeParameters) { generateTypeParameterStub(it) }
typeTranslator.buildWithScope(container) {
for (typeParameter in container.typeParameters) {
val descriptor = typeParameter.descriptor
descriptor.upperBounds.mapTo(typeParameter.superTypes) { it.toIrType() }
}
internal fun generateEnumEntryStub(descriptor: ClassDescriptor): IrEnumEntry {
val referenced = symbolTable.referenceEnumEntry(descriptor)
if (referenced.isBound) {
return referenced.owner
}
return symbolTable.declareEnumEntry(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor) {
IrLazyEnumEntryImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator)
}
}
private fun generateTypeParameterStub(descriptor: TypeParameterDescriptor): IrTypeParameter =
IrTypeParameterImpl(
internal fun generateTypeParameterStub(descriptor: TypeParameterDescriptor): IrTypeParameter {
return IrLazyTypeParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin,
descriptor
IrTypeParameterSymbolImpl(descriptor), this, typeTranslator
)
private fun generateMemberStubs(memberScope: MemberScope, container: IrDeclarationContainer) {
generateChildStubs(memberScope.getContributedDescriptors(), container)
}
private fun generateChildStubs(descriptors: Collection<DeclarationDescriptor>, container: IrDeclarationContainer) {
descriptors.mapTo(container.declarations) { generateMemberStub(it) }
}
}
@@ -43,15 +43,32 @@ class ExternalDependenciesGenerator(
private val packageFragments = HashMap<PackageFragmentDescriptor, IrExternalPackageFragment>()
fun run() {
while (true) {
val collector = DependenciesCollector()
collector.collectTopLevelDescriptorsForUnboundSymbols(symbolTable)
if (collector.isEmpty) break
collector.dependencyModules.mapTo(irModule.dependencyModules) { moduleDescriptor ->
generateModuleStub(collector, moduleDescriptor)
}
stubGenerator.unboundSymbolGeneration = true
ArrayList(symbolTable.unboundClasses).forEach {
stubGenerator.generateClassStub(it.descriptor)
}
ArrayList(symbolTable.unboundConstructors).forEach {
stubGenerator.generateConstructorStub(it.descriptor)
}
ArrayList(symbolTable.unboundEnumEntries).forEach {
stubGenerator.generateEnumEntryStub(it.descriptor)
}
ArrayList(symbolTable.unboundFields).forEach {
stubGenerator.generatePropertyStub(it.descriptor)
}
ArrayList(symbolTable.unboundSimpleFunctions).forEach {
stubGenerator.generateFunctionStub(it.descriptor)
}
ArrayList(symbolTable.unboundTypeParameters).forEach {
stubGenerator.generateOrGetTypeParameterStub(it.descriptor)
}
assert(symbolTable.unboundClasses.isEmpty())
assert(symbolTable.unboundConstructors.isEmpty())
assert(symbolTable.unboundEnumEntries.isEmpty())
assert(symbolTable.unboundFields.isEmpty())
assert(symbolTable.unboundSimpleFunctions.isEmpty())
assert(symbolTable.unboundTypeParameters.isEmpty())
}
private fun generateModuleStub(collector: DependenciesCollector, moduleDescriptor: ModuleDescriptor): IrModuleFragment =
@@ -80,7 +97,7 @@ class ExternalDependenciesGenerator(
private fun getOrCreatePackageFragment(packageFragmentDescriptor: PackageFragmentDescriptor) =
packageFragments.getOrPut(packageFragmentDescriptor) {
stubGenerator.generateEmptyExternalPackageFragmentStub(packageFragmentDescriptor)
stubGenerator.generateOrGetEmptyExternalPackageFragmentStub(packageFragmentDescriptor)
}
}
@@ -10,11 +10,18 @@ import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import java.util.*
class ScopedTypeParametersResolver {
interface TypeParametersResolver {
fun enterTypeParameterScope(typeParametersContainer: IrTypeParametersContainer)
fun leaveTypeParameterScope()
fun resolveScopedTypeParameter(typeParameterDescriptor: TypeParameterDescriptor): IrTypeParameterSymbol?
}
class ScopedTypeParametersResolver : TypeParametersResolver {
private val typeParameterScopes = ArrayDeque<Map<TypeParameterDescriptor, IrTypeParameterSymbol>>()
fun enterTypeParameterScope(typeParametersContainer: IrTypeParametersContainer) {
override fun enterTypeParameterScope(typeParametersContainer: IrTypeParametersContainer) {
typeParameterScopes.addFirst(
typeParametersContainer.typeParameters.associate {
it.descriptor to it.symbol
@@ -22,11 +29,11 @@ class ScopedTypeParametersResolver {
)
}
fun leaveTypeParameterScope() {
override fun leaveTypeParameterScope() {
typeParameterScopes.removeFirst()
}
fun resolveScopedTypeParameter(typeParameterDescriptor: TypeParameterDescriptor): IrTypeParameterSymbol? {
override fun resolveScopedTypeParameter(typeParameterDescriptor: TypeParameterDescriptor): IrTypeParameterSymbol? {
for (scope in typeParameterScopes) {
val local = scope[typeParameterDescriptor]
if (local != null) return local
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.*
import org.jetbrains.kotlin.ir.types.IrType
class SymbolTable {
open class SymbolTable {
private abstract class SymbolTableBase<D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>> {
val unboundSymbols = linkedSetOf<S>()
@@ -174,14 +174,17 @@ class SymbolTable {
IrAnonymousInitializerSymbolImpl(descriptor)
)
fun declareClass(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassDescriptor): IrClass =
fun declareClass(
startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassDescriptor,
classFactory: (IrClassSymbol) -> IrClass = { IrClassImpl(startOffset, endOffset, origin, it) }
): IrClass =
classSymbolTable.declare(
descriptor,
{ IrClassSymbolImpl(descriptor) },
{ IrClassImpl(startOffset, endOffset, origin, it) }
classFactory
)
fun referenceClass(descriptor: ClassDescriptor) =
open fun referenceClass(descriptor: ClassDescriptor) =
classSymbolTable.referenced(descriptor) { IrClassSymbolImpl(descriptor) }
val unboundClasses: Set<IrClassSymbol> get() = classSymbolTable.unboundSymbols
@@ -190,27 +193,29 @@ class SymbolTable {
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
descriptor: ClassConstructorDescriptor
descriptor: ClassConstructorDescriptor,
constructorFactory: (IrConstructorSymbol) -> IrConstructor = { IrConstructorImpl(startOffset, endOffset, origin, it) }
): IrConstructor =
constructorSymbolTable.declare(
descriptor,
{ IrConstructorSymbolImpl(descriptor) },
{ IrConstructorImpl(startOffset, endOffset, origin, it) }
constructorFactory
)
fun referenceConstructor(descriptor: ClassConstructorDescriptor) =
open fun referenceConstructor(descriptor: ClassConstructorDescriptor) =
constructorSymbolTable.referenced(descriptor) { IrConstructorSymbolImpl(descriptor) }
val unboundConstructors: Set<IrConstructorSymbol> get() = constructorSymbolTable.unboundSymbols
fun declareEnumEntry(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassDescriptor): IrEnumEntry =
fun declareEnumEntry(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassDescriptor,
factory: (IrEnumEntrySymbol) -> IrEnumEntry = { IrEnumEntryImpl(startOffset, endOffset, origin, it) }): IrEnumEntry =
enumEntrySymbolTable.declare(
descriptor,
{ IrEnumEntrySymbolImpl(descriptor) },
{ IrEnumEntryImpl(startOffset, endOffset, origin, it) }
factory
)
fun referenceEnumEntry(descriptor: ClassDescriptor) =
open fun referenceEnumEntry(descriptor: ClassDescriptor) =
enumEntrySymbolTable.referenced(descriptor) { IrEnumEntrySymbolImpl(descriptor) }
val unboundEnumEntries: Set<IrEnumEntrySymbol> get() = enumEntrySymbolTable.unboundSymbols
@@ -220,12 +225,13 @@ class SymbolTable {
endOffset: Int,
origin: IrDeclarationOrigin,
descriptor: PropertyDescriptor,
type: IrType
type: IrType,
fieldFactory: (IrFieldSymbol) -> IrField = { IrFieldImpl(startOffset, endOffset, origin, it, type) }
): IrField =
fieldSymbolTable.declare(
descriptor,
{ IrFieldSymbolImpl(descriptor) },
{ IrFieldImpl(startOffset, endOffset, origin, it, type) }
fieldFactory
)
fun declareField(
@@ -249,15 +255,16 @@ class SymbolTable {
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
descriptor: FunctionDescriptor
descriptor: FunctionDescriptor,
functionFactory: (IrSimpleFunctionSymbol) -> IrSimpleFunction = { IrFunctionImpl(startOffset, endOffset, origin, it) }
): IrSimpleFunction =
simpleFunctionSymbolTable.declare(
descriptor,
{ IrSimpleFunctionSymbolImpl(descriptor) },
{ IrFunctionImpl(startOffset, endOffset, origin, it) }
functionFactory
)
fun referenceSimpleFunction(descriptor: FunctionDescriptor) =
open fun referenceSimpleFunction(descriptor: FunctionDescriptor) =
simpleFunctionSymbolTable.referenced(descriptor) { IrSimpleFunctionSymbolImpl(descriptor) }
fun referenceDeclaredFunction(descriptor: FunctionDescriptor) =
@@ -314,7 +321,7 @@ class SymbolTable {
throw AssertionError("Undefined parameter referenced: $descriptor\n${valueParameterSymbolTable.dump()}")
}
fun referenceTypeParameter(classifier: TypeParameterDescriptor): IrTypeParameterSymbol =
open fun referenceTypeParameter(classifier: TypeParameterDescriptor): IrTypeParameterSymbol =
scopedTypeParameterSymbolTable.get(classifier)
?: globalTypeParameterSymbolTable.referenced(classifier) {
throw AssertionError("Undefined type parameter referenced: $classifier")
@@ -363,9 +370,9 @@ class SymbolTable {
fun referenceFunction(callable: CallableDescriptor): IrFunctionSymbol =
when (callable) {
is ClassConstructorDescriptor ->
constructorSymbolTable.referenced(callable) { IrConstructorSymbolImpl(callable) }
referenceConstructor(callable)
is FunctionDescriptor ->
simpleFunctionSymbolTable.referenced(callable) { IrSimpleFunctionSymbolImpl(callable) }
referenceSimpleFunction(callable)
else ->
throw IllegalArgumentException("Unexpected callable descriptor: $callable")
}
@@ -385,7 +392,7 @@ class SymbolTable {
is TypeParameterDescriptor ->
referenceTypeParameter(classifier)
is ClassDescriptor ->
classSymbolTable.referenced(classifier) { IrClassSymbolImpl(classifier) }
referenceClass(classifier)
else ->
throw IllegalArgumentException("Unexpected classifier descriptor: $classifier")
}
@@ -23,10 +23,10 @@ import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes
class TypeTranslator(
private val symbolTable: SymbolTable,
val languageVersionSettings: LanguageVersionSettings
val languageVersionSettings: LanguageVersionSettings,
private val typeParametersResolver: TypeParametersResolver = ScopedTypeParametersResolver()
) {
private val typeParametersResolver = ScopedTypeParametersResolver()
private val typeApproximatorForNI = TypeApproximator()
lateinit var constantValueGenerator: ConstantValueGenerator