Fix secondary constructor lowering

This commit is contained in:
Roman Artemev
2018-04-23 21:05:20 +03:00
parent 8721990a7f
commit 8bc80a9829
25 changed files with 129 additions and 236 deletions
@@ -8,10 +8,11 @@ package org.jetbrains.kotlin.backend.common.descriptors
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
interface DescriptorsFactory { interface DescriptorsFactory {
fun getFieldDescriptorForEnumEntry(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor fun getFieldDescriptorForEnumEntry(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor
fun getOuterThisFieldDescriptor(classDescriptor: ClassDescriptor): PropertyDescriptor fun getOuterThisFieldDescriptor(classDescriptor: ClassDescriptor): PropertyDescriptor
fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): ClassConstructorDescriptor fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): IrConstructorSymbol
fun getFieldDescriptorForObjectInstance(objectDescriptor: ClassDescriptor): PropertyDescriptor fun getFieldDescriptorForObjectInstance(objectDescriptor: ClassDescriptor): PropertyDescriptor
} }
@@ -5,8 +5,7 @@
package org.jetbrains.kotlin.backend.common.lower package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
@@ -73,11 +72,11 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
val startOffset = irConstructor.startOffset val startOffset = irConstructor.startOffset
val endOffset = irConstructor.endOffset val endOffset = irConstructor.endOffset
val newDescriptor = context.descriptorsFactory.getInnerClassConstructorWithOuterThisParameter(oldDescriptor) val newSymbol = context.descriptorsFactory.getInnerClassConstructorWithOuterThisParameter(oldDescriptor)
val outerThisValueParameter = newDescriptor.valueParameters[0] val outerThisValueParameter = newSymbol.descriptor.valueParameters[0]
oldDescriptor.valueParameters.forEach { oldValueParameter -> oldDescriptor.valueParameters.forEach { oldValueParameter ->
oldConstructorParameterToNew[oldValueParameter] = newDescriptor.valueParameters[oldValueParameter.index + 1] oldConstructorParameterToNew[oldValueParameter] = newSymbol.descriptor.valueParameters[oldValueParameter.index + 1]
} }
val blockBody = irConstructor.body as? IrBlockBody ?: throw AssertionError("Unexpected constructor body: ${irConstructor.body}") val blockBody = irConstructor.body as? IrBlockBody ?: throw AssertionError("Unexpected constructor body: ${irConstructor.body}")
@@ -105,12 +104,12 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
} }
return IrConstructorImpl( return IrConstructorImpl(
startOffset, endOffset, startOffset, endOffset,
irConstructor.origin, // TODO special origin for lowered inner class constructors? irConstructor.origin, // TODO special origin for lowered inner class constructors?
newDescriptor, newSymbol,
blockBody blockBody
).apply { ).apply {
newDescriptor.valueParameters.forEachIndexed { i, desc -> newSymbol.descriptor.valueParameters.forEachIndexed { i, desc ->
val valueParameter = if (i == 0) { val valueParameter = if (i == 0) {
IrValueParameterImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, FIELD_FOR_OUTER_THIS, desc, null) IrValueParameterImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, FIELD_FOR_OUTER_THIS, desc, null)
} else { } else {
@@ -159,7 +158,7 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
val outerThisField = context.descriptorsFactory.getOuterThisFieldDescriptor(innerClass) val outerThisField = context.descriptorsFactory.getOuterThisFieldDescriptor(innerClass)
irThis = IrGetFieldImpl(startOffset, endOffset, outerThisField, irThis, origin) irThis = IrGetFieldImpl(startOffset, endOffset, outerThisField, irThis, origin)
val outer = classDescriptor.containingDeclaration val outer = innerClass.containingDeclaration
innerClass = outer as? ClassDescriptor ?: innerClass = outer as? ClassDescriptor ?:
throw AssertionError("Unexpected containing declaration for inner class $innerClass: $outer") throw AssertionError("Unexpected containing declaration for inner class $innerClass: $outer")
} }
@@ -193,13 +192,13 @@ class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLowe
val newCallee = context.descriptorsFactory.getInnerClassConstructorWithOuterThisParameter(callee) val newCallee = context.descriptorsFactory.getInnerClassConstructorWithOuterThisParameter(callee)
val newCall = IrCallImpl( val newCall = IrCallImpl(
expression.startOffset, expression.endOffset, newCallee, expression.startOffset, expression.endOffset, newCallee, newCallee.descriptor,
null, // TODO type arguments map null, // TODO type arguments map
expression.origin expression.origin
) )
newCall.putValueArgument(0, dispatchReceiver) newCall.putValueArgument(0, dispatchReceiver)
for (i in 1 .. newCallee.valueParameters.lastIndex) { for (i in 1 .. newCallee.descriptor.valueParameters.lastIndex) {
newCall.putValueArgument(i, expression.getValueArgument(i - 1)) newCall.putValueArgument(i, expression.getValueArgument(i - 1))
} }
@@ -215,12 +214,12 @@ class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLowe
val newCallee = context.descriptorsFactory.getInnerClassConstructorWithOuterThisParameter(callee) val newCallee = context.descriptorsFactory.getInnerClassConstructorWithOuterThisParameter(callee)
val newCall = IrDelegatingConstructorCallImpl( val newCall = IrDelegatingConstructorCallImpl(
expression.startOffset, expression.endOffset, newCallee, expression.startOffset, expression.endOffset, newCallee, newCallee.descriptor,
null // TODO type arguments map null // TODO type arguments map
) )
newCall.putValueArgument(0, dispatchReceiver) newCall.putValueArgument(0, dispatchReceiver)
for (i in 1 .. newCallee.valueParameters.lastIndex) { for (i in 1 .. newCallee.descriptor.valueParameters.lastIndex) {
newCall.putValueArgument(i, expression.getValueArgument(i - 1)) newCall.putValueArgument(i, expression.getValueArgument(i - 1))
} }
@@ -235,6 +235,8 @@ val IrClass.defaultType: KotlinType
val IrSimpleFunction.isReal: Boolean get() = descriptor.kind.isReal val IrSimpleFunction.isReal: Boolean get() = descriptor.kind.isReal
// This implementation is from kotlin-native
// TODO: use this implementation instead of any other
fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction? { fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction? {
if (isReal) return this if (isReal) return this
@@ -264,7 +266,7 @@ fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction? {
} }
visited.clear() visited.clear()
realOverrides.asSequence().forEach { excludeRepeated(it) } realOverrides.toList().forEach { excludeRepeated(it) }
return realOverrides.singleOrNull { it.modality != Modality.ABSTRACT } return realOverrides.singleOrNull { it.modality != Modality.ABSTRACT }
} }
@@ -24,21 +24,20 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import java.util.* import java.util.*
class JsSpecialDescriptorsFactory( class JsDescriptorsFactory(
private val builtIns: KotlinBuiltIns private val builtIns: KotlinBuiltIns
) : DescriptorsFactory { ) : DescriptorsFactory {
private val singletonFieldDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>() private val singletonFieldDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
private val outerThisDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>() private val outerThisDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
private val innerClassConstructors = HashMap<ClassConstructorDescriptor, ClassConstructorDescriptor>() private val innerClassConstructors = HashMap<ClassConstructorDescriptor, IrConstructorSymbol>()
override fun getFieldDescriptorForEnumEntry(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor = TODO() override fun getFieldDescriptorForEnumEntry(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor = TODO()
// singletonFieldDescriptors.getOrPut(enumEntryDescriptor) {
// createEnumEntryFieldDescriptor(enumEntryDescriptor)
// }
override fun getOuterThisFieldDescriptor(innerClassDescriptor: ClassDescriptor): PropertyDescriptor = override fun getOuterThisFieldDescriptor(innerClassDescriptor: ClassDescriptor): PropertyDescriptor =
if (!innerClassDescriptor.isInner) throw AssertionError("Class is not inner: $innerClassDescriptor") if (!innerClassDescriptor.isInner) throw AssertionError("Class is not inner: $innerClassDescriptor")
@@ -46,10 +45,6 @@ class JsSpecialDescriptorsFactory(
val outerClassDescriptor = DescriptorUtils.getContainingClass(innerClassDescriptor) val outerClassDescriptor = DescriptorUtils.getContainingClass(innerClassDescriptor)
?: throw AssertionError("No containing class for inner class $innerClassDescriptor") ?: throw AssertionError("No containing class for inner class $innerClassDescriptor")
// PropertyDescriptorImpl.create(innerClassDescriptor, Annotations.EMPTY. Mo
// Name.identifier("this$0"), outerClassDescriptor.defaultType, innerClassDescriptor,
// Annotations.EMPTY, JavaVisibilities.PACKAGE_VISIBILITY, Opcodes.ACC_SYNTHETIC, SourceElement.NO_SOURCE
// )
PropertyDescriptorImpl.create( PropertyDescriptorImpl.create(
innerClassDescriptor, innerClassDescriptor,
Annotations.EMPTY, Annotations.EMPTY,
@@ -76,7 +71,7 @@ class JsSpecialDescriptorsFactory(
} }
} }
override fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): ClassConstructorDescriptor { override fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): IrConstructorSymbol {
val innerClass = innerClassConstructor.containingDeclaration val innerClass = innerClassConstructor.containingDeclaration
assert(innerClass.isInner) { "Class is not inner: $innerClass" } assert(innerClass.isInner) { "Class is not inner: $innerClass" }
@@ -85,7 +80,7 @@ class JsSpecialDescriptorsFactory(
} }
} }
private fun createInnerClassConstructorWithOuterThisParameter(oldDescriptor: ClassConstructorDescriptor): ClassConstructorDescriptor { private fun createInnerClassConstructorWithOuterThisParameter(oldDescriptor: ClassConstructorDescriptor): IrConstructorSymbol {
val classDescriptor = oldDescriptor.containingDeclaration val classDescriptor = oldDescriptor.containingDeclaration
val outerThisType = (classDescriptor.containingDeclaration as ClassDescriptor).defaultType val outerThisType = (classDescriptor.containingDeclaration as ClassDescriptor).defaultType
@@ -93,7 +88,6 @@ class JsSpecialDescriptorsFactory(
classDescriptor, oldDescriptor.annotations, oldDescriptor.isPrimary, oldDescriptor.source classDescriptor, oldDescriptor.annotations, oldDescriptor.isPrimary, oldDescriptor.source
) )
// val outerThisValueParameter = newDescriptor.createValueParameter(0, "\$outer", outerThisType)
val outerThisValueParameter = ValueParameterDescriptorImpl( val outerThisValueParameter = ValueParameterDescriptorImpl(
newDescriptor, newDescriptor,
null, null,
@@ -113,28 +107,9 @@ class JsSpecialDescriptorsFactory(
oldDescriptor.valueParameters.map { it.copy(newDescriptor, it.name, it.index + 1) } oldDescriptor.valueParameters.map { it.copy(newDescriptor, it.name, it.index + 1) }
newDescriptor.initialize(newValueParameters, oldDescriptor.visibility) newDescriptor.initialize(newValueParameters, oldDescriptor.visibility)
newDescriptor.returnType = oldDescriptor.returnType newDescriptor.returnType = oldDescriptor.returnType
return newDescriptor return IrConstructorSymbolImpl(newDescriptor)
} }
// private fun createEnumEntryFieldDescriptor(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor {
// assert(enumEntryDescriptor.kind == ClassKind.ENUM_ENTRY) { "Should be enum entry: $enumEntryDescriptor" }
//
// val enumClassDescriptor = enumEntryDescriptor.containingDeclaration as ClassDescriptor
// assert(enumClassDescriptor.kind == ClassKind.ENUM_CLASS) { "Should be enum class: $enumClassDescriptor" }
//
// return JvmPropertyDescriptorImpl.createStaticVal(
// enumEntryDescriptor.name,
// enumClassDescriptor.defaultType,
// enumClassDescriptor,
// enumEntryDescriptor.annotations,
// Modality.FINAL,
// Visibilities.PUBLIC,
// Opcodes.ACC_ENUM,
// enumEntryDescriptor.source
// )
// }
override fun getFieldDescriptorForObjectInstance(objectDescriptor: ClassDescriptor): PropertyDescriptor = override fun getFieldDescriptorForObjectInstance(objectDescriptor: ClassDescriptor): PropertyDescriptor =
singletonFieldDescriptors.getOrPut(objectDescriptor) { singletonFieldDescriptors.getOrPut(objectDescriptor) {
createObjectInstanceFieldDescriptor(objectDescriptor) createObjectInstanceFieldDescriptor(objectDescriptor)
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.backend.common.ReflectionTypes
import org.jetbrains.kotlin.backend.common.descriptors.KnownPackageFragmentDescriptor import org.jetbrains.kotlin.backend.common.descriptors.KnownPackageFragmentDescriptor
import org.jetbrains.kotlin.backend.common.ir.Ir import org.jetbrains.kotlin.backend.common.ir.Ir
import org.jetbrains.kotlin.backend.common.ir.Symbols import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.js.JsSpecialDescriptorsFactory import org.jetbrains.kotlin.backend.js.JsDescriptorsFactory
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
@@ -40,7 +40,7 @@ class JsIrBackendContext(
override val builtIns = module.builtIns override val builtIns = module.builtIns
override val sharedVariablesManager = override val sharedVariablesManager =
JsSharedVariablesManager(builtIns, KnownPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.js.internal"))) JsSharedVariablesManager(builtIns, KnownPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.js.internal")))
override val descriptorsFactory = JsSpecialDescriptorsFactory(builtIns) override val descriptorsFactory = JsDescriptorsFactory(builtIns)
override val reflectionTypes: ReflectionTypes by lazy(LazyThreadSafetyMode.PUBLICATION) { override val reflectionTypes: ReflectionTypes by lazy(LazyThreadSafetyMode.PUBLICATION) {
// TODO // TODO
@@ -10,24 +10,33 @@ import org.jetbrains.kotlin.backend.common.descriptors.SharedVariablesManager
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.* import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.expressions.IrSetVariable
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.symbols.impl.* import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.KotlinTypeFactory
import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.Variance
class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPackage: PackageFragmentDescriptor) : SharedVariablesManager { class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPackage: PackageFragmentDescriptor) : SharedVariablesManager {
override fun createSharedVariableDescriptor(variableDescriptor: VariableDescriptor): VariableDescriptor = override fun createSharedVariableDescriptor(variableDescriptor: VariableDescriptor): VariableDescriptor =
LocalVariableDescriptor( LocalVariableDescriptor(
variableDescriptor.containingDeclaration, Annotations.EMPTY, variableDescriptor.name, variableDescriptor.containingDeclaration, variableDescriptor.annotations, variableDescriptor.name,
getSharedVariableType(variableDescriptor.type), getSharedVariableType(variableDescriptor.type),
false, false, variableDescriptor.isLateInit, variableDescriptor.source false, false, variableDescriptor.isLateInit, variableDescriptor.source
) )
@@ -35,7 +44,7 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack
override fun defineSharedValue(sharedVariableDescriptor: VariableDescriptor, originalDeclaration: IrVariable): IrStatement { override fun defineSharedValue(sharedVariableDescriptor: VariableDescriptor, originalDeclaration: IrVariable): IrStatement {
val valueType = originalDeclaration.descriptor.type val valueType = originalDeclaration.descriptor.type
val boxConstructor = closureBoxConstructorTypeDescriptor val boxConstructor = closureBoxConstructorTypeDescriptor
val boxConstructorSymbol = closureBoxConstrctorTypeSymbol val boxConstructorSymbol = closureBoxConstructorTypeSymbol
val constructorTypeParam = closureBoxConstructorTypeDescriptor.typeParameters[0] val constructorTypeParam = closureBoxConstructorTypeDescriptor.typeParameters[0]
val boxConstructorTypeArgument = mapOf(constructorTypeParam to valueType) val boxConstructorTypeArgument = mapOf(constructorTypeParam to valueType)
val initializer = originalDeclaration.initializer ?: IrConstImpl.constNull( val initializer = originalDeclaration.initializer ?: IrConstImpl.constNull(
@@ -93,8 +102,7 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack
private val closureBoxConstructorTypeDescriptor = createClosureBoxClassConstructor() private val closureBoxConstructorTypeDescriptor = createClosureBoxClassConstructor()
private val closureBoxFieldDescriptor = createClosureBoxField() private val closureBoxFieldDescriptor = createClosureBoxField()
private val closureBoxTypeSymbol = IrClassSymbolImpl(closureBoxTypeDescriptor) val closureBoxConstructorTypeSymbol = createFunctionSymbol(closureBoxConstructorTypeDescriptor)
val closureBoxConstrctorTypeSymbol = createFunctionSymbol(closureBoxConstructorTypeDescriptor)
private val closureBoxFieldSymbol = IrFieldSymbolImpl(closureBoxFieldDescriptor) private val closureBoxFieldSymbol = IrFieldSymbolImpl(closureBoxFieldDescriptor)
@@ -112,13 +120,7 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack
true, true,
SourceElement.NO_SOURCE SourceElement.NO_SOURCE
).apply { ).apply {
/// constructor<T>(v: T) : T
val typeParameter = constructedClass.declaredTypeParameters[0] val typeParameter = constructedClass.declaredTypeParameters[0]
// val typeParameter = typeParameters[0]
val typeParameterType = KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope( val typeParameterType = KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
Annotations.EMPTY, Annotations.EMPTY,
typeParameter.typeConstructor, typeParameter.typeConstructor,
@@ -180,18 +182,6 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack
return desc return desc
} }
private fun getSubstitutedRefConstructor(valueType: KotlinType): ClassConstructorDescriptor =
closureBoxConstructorTypeDescriptor.substitute(
TypeSubstitutor.create(
closureBoxConstructorTypeDescriptor.typeParameters.associate {
it.typeConstructor to TypeProjectionImpl(
Variance.INVARIANT,
valueType
)
}
)
)!!
private fun getRefType(valueType: KotlinType) = private fun getRefType(valueType: KotlinType) =
KotlinTypeFactory.simpleNotNullType( KotlinTypeFactory.simpleNotNullType(
Annotations.EMPTY, Annotations.EMPTY,
@@ -62,7 +62,7 @@ fun JsIrBackendContext.lower(file: IrFile) {
InnerClassConstructorCallsLowering(this).runOnFilePostfix(file) InnerClassConstructorCallsLowering(this).runOnFilePostfix(file)
PropertiesLowering().lower(file) PropertiesLowering().lower(file)
InitializersLowering(this, JsLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, false).runOnFilePostfix(file) InitializersLowering(this, JsLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, false).runOnFilePostfix(file)
SecondaryCtorLowering(this).lower(file) SecondaryCtorLowering(this).runOnFilePostfix(file)
IntrinsicifyCallsLowering(this).lower(file) IntrinsicifyCallsLowering(this).lower(file)
FunctionReferenceLowering(this).lower(file) FunctionReferenceLowering(this).lower(file)
} }
@@ -5,18 +5,17 @@
package org.jetbrains.kotlin.ir.backend.js.descriptors package org.jetbrains.kotlin.ir.backend.js.descriptors
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.* import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -89,10 +88,10 @@ object JsSymbolBuilder {
} }
fun <T : TypeParameterDescriptor> IrSimpleFunctionSymbol.initialize( fun IrSimpleFunctionSymbol.initialize(
receiverParameterType: KotlinType? = null, receiverParameterType: KotlinType? = null,
dispatchParameterDescriptor: ReceiverParameterDescriptor? = null, dispatchParameterDescriptor: ReceiverParameterDescriptor? = null,
typeParameters: List<T> = emptyList(), typeParameters: List<TypeParameterDescriptor> = emptyList(),
valueParameters: List<ValueParameterDescriptor> = emptyList(), valueParameters: List<ValueParameterDescriptor> = emptyList(),
type: KotlinType? = null, type: KotlinType? = null,
modality: Modality = Modality.FINAL, modality: Modality = Modality.FINAL,
@@ -5,19 +5,17 @@
package org.jetbrains.kotlin.ir.backend.js.ir package org.jetbrains.kotlin.ir.backend.js.ir
import org.jetbrains.kotlin.backend.common.ir.Ir
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
object JsIrBuilder { object JsIrBuilder {
@@ -46,7 +44,6 @@ object JsIrBuilder {
fun buildGetValue(symbol: IrValueSymbol) = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, SYNTHESIZED_STATEMENT) fun buildGetValue(symbol: IrValueSymbol) = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, SYNTHESIZED_STATEMENT)
fun buildBlockBody() = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
fun buildBlockBody(stmts: List<IrStatement>) = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, stmts) fun buildBlockBody(stmts: List<IrStatement>) = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, stmts)
fun buildFunctionReference(type: KotlinType, symbol: IrFunctionSymbol) = fun buildFunctionReference(type: KotlinType, symbol: IrFunctionSymbol) =
@@ -15,16 +15,16 @@ import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.descriptors.JsSymbolBuilder import org.jetbrains.kotlin.ir.backend.js.descriptors.JsSymbolBuilder
import org.jetbrains.kotlin.ir.backend.js.descriptors.initialize import org.jetbrains.kotlin.ir.backend.js.descriptors.initialize
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
import org.jetbrains.kotlin.ir.expressions.copyTypeArgumentsFrom import org.jetbrains.kotlin.ir.expressions.copyTypeArgumentsFrom
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol
import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -32,8 +32,8 @@ import org.jetbrains.kotlin.types.KotlinType
// TODO replace with DeclarationContainerLowerPass && do flatTransform // TODO replace with DeclarationContainerLowerPass && do flatTransform
class FunctionReferenceLowering(val context: JsIrBackendContext) : FileLoweringPass, DeclarationContainerLoweringPass { class FunctionReferenceLowering(val context: JsIrBackendContext) : FileLoweringPass, DeclarationContainerLoweringPass {
val lambdas = mutableMapOf<IrDeclaration, KotlinType>() private val lambdas = mutableMapOf<IrDeclaration, KotlinType>()
val oldToNewDeclarationMap = mutableMapOf<IrSymbolOwner, IrFunction>() private val oldToNewDeclarationMap = mutableMapOf<IrFunctionSymbol, IrFunction>()
override fun lower(irFile: IrFile) { override fun lower(irFile: IrFile) {
irFile.acceptVoid(FunctionReferenceCollector()) irFile.acceptVoid(FunctionReferenceCollector())
@@ -42,7 +42,6 @@ class FunctionReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
} }
inner class FunctionReferenceCollector : IrElementVisitorVoid { inner class FunctionReferenceCollector : IrElementVisitorVoid {
override fun visitFunctionReference(expression: IrFunctionReference) { override fun visitFunctionReference(expression: IrFunctionReference) {
lambdas[expression.symbol.owner as IrFunction] = expression.type lambdas[expression.symbol.owner as IrFunction] = expression.type
} }
@@ -50,7 +49,6 @@ class FunctionReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
override fun visitElement(element: IrElement) { override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this) element.acceptChildrenVoid(this)
} }
} }
override fun lower(irDeclarationContainer: IrDeclarationContainer) { override fun lower(irDeclarationContainer: IrDeclarationContainer) {
@@ -66,9 +64,9 @@ class FunctionReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
inner class FunctionReferenceVisitor : IrElementTransformerVoid() { inner class FunctionReferenceVisitor : IrElementTransformerVoid() {
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
val newTarget = oldToNewDeclarationMap[expression.symbol.owner] val newTarget = oldToNewDeclarationMap[expression.symbol]
return if (newTarget != null) IrCallImpl(expression.startOffset, expression.endOffset, newTarget.symbol).apply { return if (newTarget != null) IrCallImpl(expression.startOffset, expression.endOffset, newTarget.symbol, expression.origin).apply {
copyTypeArgumentsFrom(expression) copyTypeArgumentsFrom(expression)
var index = 0 var index = 0
for (i in 0 until expression.valueArgumentsCount) { for (i in 0 until expression.valueArgumentsCount) {
@@ -82,15 +80,17 @@ class FunctionReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
} }
private fun lowerKFunctionReference(declaration: IrFunction, functionType: KotlinType): List<IrFunction> { private fun lowerKFunctionReference(declaration: IrFunction, functionType: KotlinType): List<IrFunction> {
// TODO: property reference
// transform // transform
// x = Foo::bar -> // x = Foo::bar ->
// x = Foo_bar_referenceGet(c1: closure$C1, c2: closure$C2) { // x = Foo_bar_KreferenceGet(c1: closure$C1, c2: closure$C2) : KFunctionN<Foo, T2, ..., TN, TReturn> {
// return function Foo_bar_closure(p0: Foo, p1: T2, p2: T3) { // return fun Foo_bar_KreferenceClosure(p0: Foo, p1: T2, p2: T3): TReturn {
// return p0.foo(c1, c2, p1, p2) // return p0.bar(c1, c2, p1, p2)
// } // }
// } // }
// KFunctionN<T1, T2, ..., TN, TReturn>, arguments.size = N + 1 // KFunctionN<Foo, T2, ..., TN, TReturn>, arguments.size = N + 1
val closureParams = functionType.arguments.dropLast(1) // drop return type val closureParams = functionType.arguments.dropLast(1) // drop return type
var kFunctionValueParamsCount = closureParams.size var kFunctionValueParamsCount = closureParams.size
@@ -99,7 +99,8 @@ class FunctionReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
assert(kFunctionValueParamsCount >= 0) assert(kFunctionValueParamsCount >= 0)
val getterValueParameters = declaration.valueParameters.drop(kFunctionValueParamsCount) // The `getter` function takes only parameters which have to be closured
val getterValueParameters = declaration.valueParameters.dropLast(kFunctionValueParamsCount)
val getterName = "${declaration.descriptor.name}_KreferenceGet" val getterName = "${declaration.descriptor.name}_KreferenceGet"
val refGetSymbol = val refGetSymbol =
@@ -117,10 +118,11 @@ class FunctionReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
} }
val closureName = "${declaration.descriptor.name}_KreferenceClosure" val closureName = "${declaration.descriptor.name}_KreferenceClosure"
val refClosureSymbol = JsSymbolBuilder.buildSimpleFunction(declaration.descriptor.containingDeclaration, closureName) val refClosureSymbol = JsSymbolBuilder.buildSimpleFunction(refGetSymbol.descriptor, closureName)
// the params which are passed to closure // the params which are passed to closure
val closureParamSymbols = closureParams.mapIndexed { index, p -> val closureParamSymbols = closureParams.mapIndexed { index, p ->
// TODO: re-use original parameter names
JsSymbolBuilder.buildValueParameter(refClosureSymbol, index, p.type) JsSymbolBuilder.buildValueParameter(refClosureSymbol, index, p.type)
} }
@@ -161,7 +163,7 @@ class FunctionReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
body = JsIrBuilder.buildBlockBody(listOf(irGetterReturn)) body = JsIrBuilder.buildBlockBody(listOf(irGetterReturn))
} }
oldToNewDeclarationMap[declaration] = refGetFunction oldToNewDeclarationMap[declaration.symbol] = refGetFunction
return listOf(declaration, refGetFunction) return listOf(declaration, refGetFunction)
} }
@@ -118,6 +118,7 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL
return irCall(call, it.symbol) return irCall(call, it.symbol)
} }
// TODO: get rid of unbound symbols
if (symbol.isBound) { if (symbol.isBound) {
(symbol.owner as? IrFunction)?.dispatchReceiverParameter?.let { (symbol.owner as? IrFunction)?.dispatchReceiverParameter?.let {
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.impl.LazyClassReceiverParameterDescriptor import org.jetbrains.kotlin.descriptors.impl.LazyClassReceiverParameterDescriptor
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
@@ -32,23 +32,18 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransformerVoid(), FileLoweringPass { class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransformerVoid(), DeclarationContainerLoweringPass {
private val oldCtorToNewMap = mutableMapOf<IrConstructorSymbol, JsIrBackendContext.SecondaryCtorPair>() private val oldCtorToNewMap = mutableMapOf<IrConstructorSymbol, JsIrBackendContext.SecondaryCtorPair>()
override fun lower(irFile: IrFile) { override fun lower(irDeclarationContainer: IrDeclarationContainer) {
irFile.accept(this, null) irDeclarationContainer.declarations.transformFlat {
context.secondaryConstructorsMap.putAll(oldCtorToNewMap) if (it is IrClass) {
} listOf(it) + lowerClass(it)
override fun visitFile(irFile: IrFile): IrFile {
irFile.declarations.transformFlat { declaration ->
if (declaration is IrClass) {
listOf(declaration) + lowerClass(declaration)
} else null } else null
} }
return irFile context.secondaryConstructorsMap.putAll(oldCtorToNewMap)
} }
private fun lowerClass(irClass: IrClass): List<IrSimpleFunction> { private fun lowerClass(irClass: IrClass): List<IrSimpleFunction> {
@@ -142,7 +137,7 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
valueParameters += (declaration.valueParameters + thisParam) valueParameters += (declaration.valueParameters + thisParam)
typeParameters += declaration.typeParameters typeParameters += declaration.typeParameters
parent = declaration.parent // parent = declaration.parent
body = JsIrBuilder.buildBlockBody(statements + retStmt).apply { body = JsIrBuilder.buildBlockBody(statements + retStmt).apply {
transformChildrenVoid(ThisUsageReplaceTransformer(it, thisSymbol)) transformChildrenVoid(ThisUsageReplaceTransformer(it, thisSymbol))
} }
@@ -169,7 +164,7 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
valueParameters += ctorOrig.valueParameters valueParameters += ctorOrig.valueParameters
typeParameters += ctorOrig.typeParameters typeParameters += ctorOrig.typeParameters
parent = ctorOrig.parent // parent = ctorOrig.parent
val returnType = ctorOrig.returnType val returnType = ctorOrig.returnType
val createFunctionIntrinsic = context.intrinsics.jsObjectCreate val createFunctionIntrinsic = context.intrinsics.jsObjectCreate
@@ -200,6 +195,9 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
override fun visitFunction(declaration: IrFunction, data: IrFunction?): IrStatement = super.visitFunction(declaration, declaration) override fun visitFunction(declaration: IrFunction, data: IrFunction?): IrStatement = super.visitFunction(declaration, declaration)
override fun visitCall(expression: IrCall, ownerFunc: IrFunction?): IrElement { override fun visitCall(expression: IrCall, ownerFunc: IrFunction?): IrElement {
super.visitCall(expression, ownerFunc)
// TODO: figure out the reason why symbol is not bound
if (expression.symbol.isBound) { if (expression.symbol.isBound) {
val target = expression.symbol.owner as IrFunction val target = expression.symbol.owner as IrFunction
@@ -219,14 +217,16 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
} }
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, ownerFunc: IrFunction?): IrElement { override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, ownerFunc: IrFunction?): IrElement {
val target = expression.symbol.owner super.visitDelegatingConstructorCall(expression, ownerFunc)
if (target.symbol.isPrimary) {
val target = expression.symbol
if (target.isPrimary) {
// nothing to do here // nothing to do here
return expression return expression
} }
val fromPrimary = ownerFunc!! is IrConstructor val fromPrimary = ownerFunc!! is IrConstructor
val newCall = redirectCall(expression, context.secondaryConstructorsMap[target.symbol]!!.delegate) val newCall = redirectCall(expression, context.secondaryConstructorsMap[target]!!.delegate)
val readThis = if (fromPrimary) { val readThis = if (fromPrimary) {
IrGetValueImpl( IrGetValueImpl(
@@ -28,11 +28,6 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
if (left != neutralExpression) JsBinaryOperation(JsBinaryOperator.COMMA, left, right) else right if (left != neutralExpression) JsBinaryOperation(JsBinaryOperator.COMMA, left, right) else right
} }
override fun visitBlock(expression: IrBlock, data: JsGenerationContext): JsExpression = visitContainerExpression(expression, data)
override fun visitComposite(expression: IrComposite, data: JsGenerationContext): JsExpression =
visitContainerExpression(expression, data)
override fun visitExpressionBody(body: IrExpressionBody, context: JsGenerationContext): JsExpression = override fun visitExpressionBody(body: IrExpressionBody, context: JsGenerationContext): JsExpression =
body.expression.accept(this, context) body.expression.accept(this, context)
@@ -78,6 +73,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
override fun visitGetObjectValue(expression: IrGetObjectValue, context: JsGenerationContext) = when (expression.symbol.kind) { override fun visitGetObjectValue(expression: IrGetObjectValue, context: JsGenerationContext) = when (expression.symbol.kind) {
ClassKind.OBJECT -> { ClassKind.OBJECT -> {
// TODO:
if (expression.type.isUnit()) JsNullLiteral() if (expression.type.isUnit()) JsNullLiteral()
else { else {
val className = context.getNameForSymbol(expression.symbol) val className = context.getNameForSymbol(expression.symbol)
@@ -133,7 +129,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
val targetName = context.getNameForSymbol(symbol) val targetName = context.getNameForSymbol(symbol)
val qPrototype = JsNameRef(targetName, prototypeOf(qualifierName)) val qPrototype = JsNameRef(targetName, prototypeOf(qualifierName))
val callRef = JsNameRef(Namer.CALL_FUNCTION, qPrototype) val callRef = JsNameRef(Namer.CALL_FUNCTION, qPrototype)
return JsInvocation(callRef, jsDispatchReceiver?. let { listOf(it) + arguments } ?: arguments) return JsInvocation(callRef, jsDispatchReceiver?.let { listOf(it) + arguments } ?: arguments)
} }
return if (symbol is IrConstructorSymbol) { return if (symbol is IrConstructorSymbol) {
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.js.backend.ast.JsStatement
class IrFileToJsTransformer : BaseIrElementToJsNodeTransformer<JsStatement, JsGenerationContext> { class IrFileToJsTransformer : BaseIrElementToJsNodeTransformer<JsStatement, JsGenerationContext> {
override fun visitFile(declaration: IrFile, context: JsGenerationContext): JsStatement { override fun visitFile(declaration: IrFile, context: JsGenerationContext): JsStatement {
val fileContext = context.newDeclaration(JsDeclarationScope(context.currentScope, "scope for file ${declaration.name}"), null, declaration) val fileContext = context.newDeclaration(JsDeclarationScope(context.currentScope, "scope for file ${declaration.name}"))
val block = fileContext.currentBlock val block = fileContext.currentBlock
declaration.declarations.forEach { declaration.declarations.forEach {
@@ -127,9 +127,8 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
return emptyList() return emptyList()
} }
val baseName = context.getNameForSymbol(baseClass.owner.symbol)
val createCall = jsAssignment( val createCall = jsAssignment(
classPrototypeRef, JsInvocation(Namer.JS_OBJECT_CREATE_FUNCTION, prototypeOf(baseName.makeRef())) classPrototypeRef, JsInvocation(Namer.JS_OBJECT_CREATE_FUNCTION, prototypeOf(baseClassName!!.makeRef()))
).makeStmt() ).makeStmt()
val ctorAssign = jsAssignment(JsNameRef(Namer.CONSTRUCTOR_NAME, classPrototypeRef), classNameRef).makeStmt() val ctorAssign = jsAssignment(JsNameRef(Namer.CONSTRUCTOR_NAME, classPrototypeRef), classNameRef).makeStmt()
@@ -74,8 +74,7 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
val args = translateCallArguments(call, context) val args = translateCallArguments(call, context)
val initializer = args[0] val initializer = args[0]
val propertyInit = JsPropertyInitializer(JsNameRef("v"), initializer) val propertyInit = JsPropertyInitializer(JsNameRef("v"), initializer)
val objectLiteral = JsObjectLiteral() JsObjectLiteral(listOf(propertyInit))
objectLiteral.apply { propertyInitializers += propertyInit }
} }
addIfNotNull(intrinsics.jsCode) { call, context -> addIfNotNull(intrinsics.jsCode) { call, context ->
@@ -5,21 +5,18 @@
package org.jetbrains.kotlin.ir.backend.js.utils package org.jetbrains.kotlin.ir.backend.js.utils
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.js.backend.ast.* import org.jetbrains.kotlin.js.backend.ast.*
class JsGenerationContext { class JsGenerationContext {
fun newDeclaration(scope: JsScope, func: IrFunction? = null, file: IrFile? = null): JsGenerationContext { fun newDeclaration(scope: JsScope, func: IrFunction? = null): JsGenerationContext {
return JsGenerationContext(this, JsBlock(), scope, func, file) return JsGenerationContext(this, JsBlock(), scope, func)
} }
val currentBlock: JsBlock val currentBlock: JsBlock
val currentScope: JsScope val currentScope: JsScope
val currentFile: IrFile?
val currentFunction: IrFunction? val currentFunction: IrFunction?
val parent: JsGenerationContext? val parent: JsGenerationContext?
val staticContext: JsStaticContext val staticContext: JsStaticContext
@@ -33,21 +30,16 @@ class JsGenerationContext {
this.currentScope = rootScope this.currentScope = rootScope
this.currentBlock = program.globalBlock this.currentBlock = program.globalBlock
this.currentFunction = null this.currentFunction = null
this.currentFile = null
} }
constructor(parent: JsGenerationContext, block: JsBlock, scope: JsScope, func: IrFunction?, file: IrFile? = null) { constructor(parent: JsGenerationContext, block: JsBlock, scope: JsScope, func: IrFunction?) {
this.parent = parent this.parent = parent
this.program = parent.program this.program = parent.program
this.staticContext = parent.staticContext this.staticContext = parent.staticContext
this.currentBlock = block this.currentBlock = block
this.currentScope = scope this.currentScope = scope
this.currentFunction = func this.currentFunction = func
this.currentFile = file ?: parent.currentFile
} }
fun getNameForSymbol(symbol: IrSymbol): JsName = staticContext.getNameForSymbol(symbol, this) fun getNameForSymbol(symbol: IrSymbol): JsName = staticContext.getNameForSymbol(symbol, this)
val currentPackage: PackageFragmentDescriptor
get() = currentFile!!.packageFragmentDescriptor
} }
@@ -21,6 +21,7 @@ class JsStaticContext(
backendContext: JsIrBackendContext backendContext: JsIrBackendContext
) { ) {
val intrinsics = JsIntrinsicTransformers(backendContext) val intrinsics = JsIntrinsicTransformers(backendContext)
// TODO: use IrSymbol instead of JsName
val classModels = mutableMapOf<JsName, JsClassModel>() val classModels = mutableMapOf<JsName, JsClassModel>()
fun getNameForSymbol(irSymbol: IrSymbol, context: JsGenerationContext) = nameGenerator.getNameForSymbol(irSymbol, context) fun getNameForSymbol(irSymbol: IrSymbol, context: JsGenerationContext) = nameGenerator.getNameForSymbol(irSymbol, context)
@@ -20,8 +20,8 @@ import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.ReflectionTypes import org.jetbrains.kotlin.backend.common.ReflectionTypes
import org.jetbrains.kotlin.backend.common.ir.Ir import org.jetbrains.kotlin.backend.common.ir.Ir
import org.jetbrains.kotlin.backend.common.ir.Symbols import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmDescriptorsFactory
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSharedVariablesManager import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSharedVariablesManager
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSpecialDescriptorsFactory
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
@@ -45,7 +45,7 @@ class JvmBackendContext(
irModuleFragment: IrModuleFragment, symbolTable: SymbolTable irModuleFragment: IrModuleFragment, symbolTable: SymbolTable
) : CommonBackendContext { ) : CommonBackendContext {
override val builtIns = state.module.builtIns override val builtIns = state.module.builtIns
override val descriptorsFactory: JvmSpecialDescriptorsFactory = JvmSpecialDescriptorsFactory(psiSourceManager, builtIns) override val descriptorsFactory: JvmDescriptorsFactory = JvmDescriptorsFactory(psiSourceManager, builtIns)
override val sharedVariablesManager = JvmSharedVariablesManager(builtIns) override val sharedVariablesManager = JvmSharedVariablesManager(builtIns)
override val reflectionTypes: ReflectionTypes by lazy(LazyThreadSafetyMode.PUBLICATION) { override val reflectionTypes: ReflectionTypes by lazy(LazyThreadSafetyMode.PUBLICATION) {
@@ -26,6 +26,8 @@ import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.ir.SourceManager import org.jetbrains.kotlin.ir.SourceManager
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
import org.jetbrains.kotlin.load.java.JavaVisibilities import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi2ir.PsiSourceManager import org.jetbrains.kotlin.psi2ir.PsiSourceManager
@@ -34,13 +36,13 @@ import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Opcodes
import java.util.* import java.util.*
class JvmSpecialDescriptorsFactory( class JvmDescriptorsFactory(
private val psiSourceManager: PsiSourceManager, private val psiSourceManager: PsiSourceManager,
private val builtIns: KotlinBuiltIns private val builtIns: KotlinBuiltIns
) : DescriptorsFactory { ) : DescriptorsFactory {
private val singletonFieldDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>() private val singletonFieldDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
private val outerThisDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>() private val outerThisDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
private val innerClassConstructors = HashMap<ClassConstructorDescriptor, ClassConstructorDescriptor>() private val innerClassConstructors = HashMap<ClassConstructorDescriptor, IrConstructorSymbol>()
override fun getFieldDescriptorForEnumEntry(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor = override fun getFieldDescriptorForEnumEntry(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor =
singletonFieldDescriptors.getOrPut(enumEntryDescriptor) { singletonFieldDescriptors.getOrPut(enumEntryDescriptor) {
@@ -72,7 +74,7 @@ class JvmSpecialDescriptorsFactory(
) )
} }
override fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): ClassConstructorDescriptor { override fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): IrConstructorSymbol {
val innerClass = innerClassConstructor.containingDeclaration val innerClass = innerClassConstructor.containingDeclaration
assert(innerClass.isInner) { "Class is not inner: $innerClass" } assert(innerClass.isInner) { "Class is not inner: $innerClass" }
@@ -81,7 +83,7 @@ class JvmSpecialDescriptorsFactory(
} }
} }
private fun createInnerClassConstructorWithOuterThisParameter(oldDescriptor: ClassConstructorDescriptor): ClassConstructorDescriptor { private fun createInnerClassConstructorWithOuterThisParameter(oldDescriptor: ClassConstructorDescriptor): IrConstructorSymbol {
val classDescriptor = oldDescriptor.containingDeclaration val classDescriptor = oldDescriptor.containingDeclaration
val outerThisType = (classDescriptor.containingDeclaration as ClassDescriptor).defaultType val outerThisType = (classDescriptor.containingDeclaration as ClassDescriptor).defaultType
@@ -96,7 +98,7 @@ class JvmSpecialDescriptorsFactory(
oldDescriptor.valueParameters.map { it.copy(newDescriptor, it.name, it.index + 1) } oldDescriptor.valueParameters.map { it.copy(newDescriptor, it.name, it.index + 1) }
newDescriptor.initialize(newValueParameters, oldDescriptor.visibility) newDescriptor.initialize(newValueParameters, oldDescriptor.visibility)
newDescriptor.returnType = oldDescriptor.returnType newDescriptor.returnType = oldDescriptor.returnType
return newDescriptor return IrConstructorSymbolImpl(newDescriptor)
} }
@@ -18,9 +18,10 @@ package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.lower.DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER import org.jetbrains.kotlin.backend.common.lower.DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER
import org.jetbrains.kotlin.backend.common.lower.InitializersLowering.Companion.clinitName
import org.jetbrains.kotlin.backend.common.lower.VariableRemapper
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.descriptors.DefaultImplsClassDescriptorImpl import org.jetbrains.kotlin.backend.jvm.descriptors.DefaultImplsClassDescriptorImpl
import org.jetbrains.kotlin.backend.common.lower.InitializersLowering.Companion.clinitName
import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
@@ -1,39 +0,0 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ValueDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
abstract class AbstractVariableRemapper : IrElementTransformerVoid() {
protected abstract fun remapVariable(value: ValueDescriptor): ValueDescriptor?
override fun visitGetValue(expression: IrGetValue): IrExpression =
remapVariable(expression.descriptor)?.let {
IrGetValueImpl(expression.startOffset, expression.endOffset, it, expression.origin)
} ?: expression
}
class VariableRemapper(val mapping: Map<ValueDescriptor, ValueDescriptor>): AbstractVariableRemapper() {
override fun remapVariable(value: ValueDescriptor): ValueDescriptor? =
mapping[value]
}
@@ -42,13 +42,16 @@ class IrConstructorImpl(
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
origin: IrDeclarationOrigin, origin: IrDeclarationOrigin,
symbol: IrConstructorSymbol symbol: IrConstructorSymbol,
body: IrBody? = null
) : this( ) : this(
startOffset, endOffset, origin, symbol, startOffset, endOffset, origin, symbol,
symbol.descriptor.visibility, symbol.descriptor.visibility,
symbol.descriptor.returnType, symbol.descriptor.returnType,
symbol.descriptor.isInline symbol.descriptor.isInline
) ) {
this.body = body
}
constructor( constructor(
startOffset: Int, startOffset: Int,
@@ -57,6 +60,7 @@ class IrConstructorImpl(
descriptor: ClassConstructorDescriptor descriptor: ClassConstructorDescriptor
) : this(startOffset, endOffset, origin, IrConstructorSymbolImpl(descriptor)) ) : this(startOffset, endOffset, origin, IrConstructorSymbolImpl(descriptor))
@Deprecated("Let use constructor which takes symbol instead of descriptor")
constructor( constructor(
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
@@ -141,8 +141,8 @@ class IrCallImpl(
copyTypeArgumentsFrom(typeArguments) copyTypeArgumentsFrom(typeArguments)
} }
constructor(startOffset: Int, endOffset: Int, symbol: IrFunctionSymbol) : constructor(startOffset: Int, endOffset: Int, symbol: IrFunctionSymbol, origin: IrStatementOrigin? = null) :
this(startOffset, endOffset, symbol, symbol.descriptor) this(startOffset, endOffset, symbol, symbol.descriptor, origin = origin)
override val superQualifier: ClassDescriptor? = superQualifierSymbol?.descriptor override val superQualifier: ClassDescriptor? = superQualifierSymbol?.descriptor
@@ -2,42 +2,14 @@
import kotlin.test.assertEquals import kotlin.test.assertEquals
inline fun foo(x: String, block: (String) -> String) = block(x)
fun run(r: () -> Any) = r()
fun test(i: Int, j: Int, k: Int): String {
var i = 0
var j = 2
val k = 4
fun f(): String = "OK"
val funVal = {
println(k)
}
run(funVal)
val funLit = { i += 1
j += k
f() }
val ret = run(funLit) as String
if (i != 1 || j != 6 || k != 4) return "fail"
return ret
}
fun box(): String { fun box(): String {
return test(1, 2, 3) fun bar(y: String) = y + "cde"
}
//fun box(): String { val res = foo("abc") { bar(it) }
//// fun bar(y: String) = y + "cde"
// assertEquals("abccde", res)
//// val res = foo("abc") { bar(it) }
// return "OK"
//// assertEquals("abccde", res) }
//
// return "OK"
//}