diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt index aa7a1024ef3..d2c9bfd25e1 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt @@ -16,12 +16,15 @@ package org.jetbrains.kotlin.psi2ir.generators +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi2ir.intermediate.* +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getSuperCallExpression import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.scopes.receivers.* @@ -39,10 +42,9 @@ fun StatementGenerator.generateReceiver(ktDefaultElement: KtElement, receiver: R is ImplicitClassReceiver -> IrThisReferenceImpl(ktDefaultElement.startOffset, ktDefaultElement.startOffset, receiver.type, receiver.classDescriptor) is ThisClassReceiver -> - (receiver as? ExpressionReceiver)?.expression?.let { receiverExpression -> - IrThisReferenceImpl(receiverExpression.startOffset, receiverExpression.endOffset, receiver.type, - receiver.classDescriptor) - } ?: TODO("Non-implicit ThisClassReceiver should be an expression receiver") + generateThisOrSuperReceiver(receiver, receiver.classDescriptor) + is SuperCallReceiverValue -> + generateThisOrSuperReceiver(receiver, receiver.thisType.constructor.declarationDescriptor as ClassDescriptor) is ExpressionReceiver -> generateExpression(receiver.expression) is ClassValueReceiver -> @@ -61,6 +63,13 @@ fun StatementGenerator.generateReceiver(ktDefaultElement: KtElement, receiver: R OnceExpressionValue(receiverExpression) } +private fun generateThisOrSuperReceiver(receiver: ReceiverValue, classDescriptor: ClassDescriptor): IrExpression { + val expressionReceiver = receiver as? ExpressionReceiver ?: + throw AssertionError("'this' or 'super' receiver should be an expression receiver") + val ktReceiver = expressionReceiver.expression + return IrThisReferenceImpl(ktReceiver.startOffset, ktReceiver.endOffset, receiver.type, classDescriptor) +} + fun StatementGenerator.generateCallReceiver( ktDefaultElement: KtElement, dispatchReceiver: ReceiverValue?, @@ -129,18 +138,25 @@ fun StatementGenerator.generateValueArgument(valueArgument: ResolvedValueArgumen TODO("Unexpected valueArgument: ${valueArgument.javaClass.simpleName}") } -fun StatementGenerator.pregenerateCall(resolvedCall: ResolvedCall<*>): CallBuilder { - val call = pregenerateCallReceivers(resolvedCall) +fun Generator.getSuperQualifier(resolvedCall: ResolvedCall<*>): ClassDescriptor? { + val superCallExpression = getSuperCallExpression(resolvedCall.call) ?: return null + return getOrFail(BindingContext.REFERENCE_TARGET, superCallExpression.instanceReference) as ClassDescriptor +} +fun StatementGenerator.pregenerateCall(resolvedCall: ResolvedCall<*>): CallBuilder { + val call = pregenerateCallWithReceivers(resolvedCall) + pregenerateValueArguments(call, resolvedCall) + return call +} + +private fun StatementGenerator.pregenerateValueArguments(call: CallBuilder, resolvedCall: ResolvedCall<*>) { resolvedCall.valueArgumentsByIndex!!.forEachIndexed { index, valueArgument -> val valueParameter = call.descriptor.valueParameters[index] call.irValueArgumentsByIndex[index] = generateValueArgument(valueArgument, valueParameter) } - - return call } -fun StatementGenerator.pregenerateCallReceivers(resolvedCall: ResolvedCall<*>): CallBuilder { +fun StatementGenerator.pregenerateCallWithReceivers(resolvedCall: ResolvedCall<*>): CallBuilder { val call = CallBuilder(resolvedCall) call.callReceiver = generateCallReceiver(resolvedCall.call.callElement, @@ -148,5 +164,7 @@ fun StatementGenerator.pregenerateCallReceivers(resolvedCall: ResolvedCall<*>): resolvedCall.extensionReceiver, resolvedCall.call.isSafeCall()) + call.superQualifier = getSuperQualifier(resolvedCall) + return call } \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt new file mode 100644 index 00000000000..35460d17c98 --- /dev/null +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt @@ -0,0 +1,179 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.psi2ir.generators + +import org.jetbrains.kotlin.descriptors.ConstructorDescriptor +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor +import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor +import org.jetbrains.kotlin.ir.expressions.IrBlockImpl +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrOperator +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.endOffset +import org.jetbrains.kotlin.psi.psiUtil.startOffset +import org.jetbrains.kotlin.psi2ir.defaultLoad +import org.jetbrains.kotlin.psi2ir.intermediate.* +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.scopes.receivers.ThisClassReceiver + +class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) { + fun generateAssignment(expression: KtBinaryExpression): IrExpression { + val ktLeft = expression.left!! + val irRhs = statementGenerator.generateExpression(expression.right!!) + val irAssignmentReceiver = generateAssignmentReceiver(ktLeft, IrOperator.EQ) + return irAssignmentReceiver.assign(irRhs) + } + + fun generateAugmentedAssignment(expression: KtBinaryExpression, irOperator: IrOperator): IrExpression { + val opResolvedCall = getResolvedCall(expression)!! + val isSimpleAssignment = get(BindingContext.VARIABLE_REASSIGNMENT, expression) ?: false + val ktLeft = expression.left!! + val ktRight = expression.right!! + val irAssignmentReceiver = generateAssignmentReceiver(ktLeft, irOperator) + + return irAssignmentReceiver.assign { irLValue -> + val opCall = statementGenerator.pregenerateCall(opResolvedCall) + opCall.setExplicitReceiverValue(irLValue) + opCall.irValueArgumentsByIndex[0] = statementGenerator.generateExpression(ktRight) + val irOpCall = CallGenerator(this).generateCall(expression, opCall, irOperator) + + if (isSimpleAssignment) { + // Set( Op( Get(), RHS ) ) + irLValue.store(irOpCall) + } + else { + // Op( Get(), RHS ) + irOpCall + } + } + } + + fun generatePrefixIncrementDecrement(expression: KtPrefixExpression, irOperator: IrOperator): IrExpression { + val opResolvedCall = getResolvedCall(expression)!! + val ktBaseExpression = expression.baseExpression!! + val irAssignmentReceiver = generateAssignmentReceiver(ktBaseExpression, irOperator) + + return irAssignmentReceiver.assign { irLValue -> + val irBlock = IrBlockImpl(expression.startOffset, expression.endOffset, irLValue.type, irOperator) + + // VAR tmp = [lhs].inc() + val opCall = statementGenerator.pregenerateCall(opResolvedCall) + opCall.setExplicitReceiverValue(irLValue) + val irOpCall = CallGenerator(this).generateCall(expression, opCall, irOperator) + val irTmp = statementGenerator.scope.createTemporaryVariable(irOpCall) + irBlock.addStatement(irTmp) + + // [lhs] = tmp + irBlock.addStatement(irLValue.store(irTmp.defaultLoad())) + + // ^ tmp + irBlock.addStatement(irTmp.defaultLoad()) + + irBlock + } + } + + fun generatePostfixIncrementDecrement(expression: KtPostfixExpression, irOperator: IrOperator): IrExpression { + val opResolvedCall = getResolvedCall(expression)!! + val ktBaseExpression = expression.baseExpression!! + val irAssignmentReceiver = generateAssignmentReceiver(ktBaseExpression, irOperator) + + return irAssignmentReceiver.assign { irLValue -> + val irBlock = IrBlockImpl(expression.startOffset, expression.endOffset, irLValue.type, irOperator) + + // VAR tmp = [lhs] + val irTmp = scope.createTemporaryVariable(irLValue.load()) + irBlock.addStatement(irTmp) + + // [lhs] = tmp.inc() + val opCall = statementGenerator.pregenerateCall(opResolvedCall) + opCall.setExplicitReceiverValue(VariableLValue(irTmp)) + val irOpCall = CallGenerator(this).generateCall(expression, opCall, irOperator) + irBlock.addStatement(irLValue.store(irOpCall)) + + // ^ tmp + irBlock.addStatement(irTmp.defaultLoad()) + + irBlock + } + } + + fun generateAssignmentReceiver(ktLeft: KtExpression, operator: IrOperator): AssignmentReceiver { + if (ktLeft is KtArrayAccessExpression) { + return generateArrayAccessAssignmentReceiver(ktLeft, operator) + } + + val resolvedCall = getResolvedCall(ktLeft) ?: TODO("no resolved call for LHS") + val descriptor = resolvedCall.candidateDescriptor + + return when (descriptor) { + is SyntheticFieldDescriptor -> + BackingFieldLValue(ktLeft.startOffset, ktLeft.endOffset, descriptor.propertyDescriptor, operator) + is LocalVariableDescriptor -> + if (descriptor.isDelegated) + TODO("Delegated local variable") + else + VariableLValue(ktLeft.startOffset, ktLeft.endOffset, descriptor, operator) + is PropertyDescriptor -> + generateAssignmentReceiverForProperty(descriptor, operator, ktLeft, resolvedCall) + else -> + TODO("Other cases of LHS") + } + } + + private fun generateAssignmentReceiverForProperty( + descriptor: PropertyDescriptor, + irOperator: IrOperator, + ktLeft: KtExpression, + resolvedCall: ResolvedCall<*> + ): AssignmentReceiver { + if (isValInitializationInConstructor(descriptor, resolvedCall)) { + return BackingFieldLValue(ktLeft.startOffset, ktLeft.endOffset, descriptor, null) + } + + val propertyReceiver = statementGenerator.generateCallReceiver( + ktLeft, resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver, resolvedCall.call.isSafeCall()) + + val superQualifier = getSuperQualifier(resolvedCall) + + return SimplePropertyLValue(scope, ktLeft.startOffset, ktLeft.endOffset, irOperator, descriptor, propertyReceiver, superQualifier) + } + + private fun isValInitializationInConstructor(descriptor: PropertyDescriptor, resolvedCall: ResolvedCall<*>): Boolean = + !descriptor.isVar && + statementGenerator.scopeOwner is ConstructorDescriptor && + resolvedCall.dispatchReceiver is ThisClassReceiver + + private fun generateArrayAccessAssignmentReceiver(ktLeft: KtArrayAccessExpression, irOperator: IrOperator): ArrayAccessAssignmentReceiver { + val irArray = statementGenerator.generateExpression(ktLeft.arrayExpression!!) + val irIndexExpressions = ktLeft.indexExpressions.map { statementGenerator.generateExpression(it) } + + val indexedGetResolvedCall = get(BindingContext.INDEXED_LVALUE_GET, ktLeft) + val indexedGetCall = indexedGetResolvedCall?.let { statementGenerator.pregenerateCallWithReceivers(it) } + + val indexedSetResolvedCall = get(BindingContext.INDEXED_LVALUE_SET, ktLeft) + val indexedSetCall = indexedSetResolvedCall?.let { statementGenerator.pregenerateCallWithReceivers(it) } + + return ArrayAccessAssignmentReceiver(irArray, irIndexExpressions, indexedGetCall, indexedSetCall, + CallGenerator(statementGenerator), + ktLeft.startOffset, ktLeft.endOffset, irOperator) + } + +} diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt index c87911db5cf..3171b674a71 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt @@ -18,11 +18,13 @@ package org.jetbrains.kotlin.psi2ir.generators import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset +import org.jetbrains.kotlin.resolve.BindingContext import java.util.* class BodyGenerator(val scopeOwner: CallableDescriptor, override val context: GeneratorContext): GeneratorWithScope { @@ -82,26 +84,24 @@ class BodyGenerator(val scopeOwner: CallableDescriptor, override val context: Ge fun generateSecondaryConstructorBody(ktConstructor: KtSecondaryConstructor): IrBody { - val statementGenerator = createStatementGenerator() - val irBlockBody = IrBlockBodyImpl(ktConstructor.startOffset, ktConstructor.endOffset) - val ktDelegatingConstructorCall = ktConstructor.getDelegationCall() - val delegatingConstructorCall = statementGenerator.pregenerateCall(getResolvedCall(ktDelegatingConstructorCall)!!) - val irDelegatingConstructorCall = CallGenerator(statementGenerator).generateCall( - ktDelegatingConstructorCall, delegatingConstructorCall, IrOperator.DELEGATING_CONSTRUCTOR_CALL) - irBlockBody.addStatement(irDelegatingConstructorCall) + generateDelegatingConstructorCall(irBlockBody, ktConstructor) - val ktBody = ktConstructor.bodyExpression - if (ktBody != null) { - statementGenerator.generateBlockBodyStatements(irBlockBody, ktBody) + ktConstructor.bodyExpression?.let { ktBody -> + createStatementGenerator().generateBlockBodyStatements(irBlockBody, ktBody) } return irBlockBody } - fun generateAnonymousInitializer(ktInitializer: KtAnonymousInitializer): IrStatement { - return createStatementGenerator().generateStatement(ktInitializer.body!!) + private fun generateDelegatingConstructorCall(irBlockBody: IrBlockBodyImpl, ktConstructor: KtSecondaryConstructor) { + val statementGenerator = createStatementGenerator() + val ktDelegatingConstructorCall = ktConstructor.getDelegationCall() + val delegatingConstructorCall = statementGenerator.pregenerateCall(getResolvedCall(ktDelegatingConstructorCall)!!) + val irDelegatingConstructorCall = CallGenerator(statementGenerator).generateCall( + ktDelegatingConstructorCall, delegatingConstructorCall, IrOperator.DELEGATING_CONSTRUCTOR_CALL) + irBlockBody.addStatement(irDelegatingConstructorCall) } private fun createStatementGenerator() = @@ -114,6 +114,90 @@ class BodyGenerator(val scopeOwner: CallableDescriptor, override val context: Ge fun getLoop(expression: KtExpression): IrLoop? = loopTable[expression] + fun generatePrimaryConstructorBody(ktClassOrObject: KtClassOrObject): IrBody { + val irBlockBody = IrBlockBodyImpl(ktClassOrObject.startOffset, ktClassOrObject.endOffset) + generateSuperConstructorCall(irBlockBody, ktClassOrObject) + generateInitializersForPropertiesDefinedInPrimaryConstructor(irBlockBody, ktClassOrObject) + generateInitializersForClassBody(irBlockBody, ktClassOrObject) + + return irBlockBody + } + + fun generateSecondaryConstructorBodyWithClassInitializers(ktConstructor: KtSecondaryConstructor, ktClassOrObject: KtClassOrObject): IrBody { + val irBlockBody = IrBlockBodyImpl(ktClassOrObject.startOffset, ktClassOrObject.endOffset) + + generateDelegatingConstructorCall(irBlockBody, ktConstructor) + generateInitializersForClassBody(irBlockBody, ktClassOrObject) + + ktConstructor.bodyExpression?.let { ktBody -> + createStatementGenerator().generateBlockBodyStatements(irBlockBody, ktBody) + } + + return irBlockBody + } + + private fun generateSuperConstructorCall(irBlockBody: IrBlockBodyImpl, ktClassOrObject: KtClassOrObject) { + val ktSuperTypeList = ktClassOrObject.getSuperTypeList() ?: return + for (ktSuperTypeListEntry in ktSuperTypeList.entries) { + if (ktSuperTypeListEntry is KtSuperTypeCallEntry) { + val statementGenerator = createStatementGenerator() + val superConstructorCall = statementGenerator.pregenerateCall(getResolvedCall(ktSuperTypeListEntry)!!) + val irSuperConstructorCall = CallGenerator(statementGenerator).generateCall( + ktSuperTypeListEntry, superConstructorCall, IrOperator.SUPER_CONSTRUCTOR_CALL) + irBlockBody.addStatement(irSuperConstructorCall) + } + } + } + + private fun generateInitializersForClassBody(irBlockBody: IrBlockBodyImpl, ktClassOrObject: KtClassOrObject) { + ktClassOrObject.getBody()?.let { ktClassBody -> + for (ktDeclaration in ktClassBody.declarations) { + when (ktDeclaration) { + is KtProperty -> generateInitializerForPropertyDefinedInClassBody(irBlockBody, ktDeclaration) + is KtClassInitializer -> generateAnonymousInitializer(irBlockBody, ktDeclaration) + } + } + } + } + + private fun generateAnonymousInitializer(irBlockBody: IrBlockBodyImpl, ktClassInitializer: KtClassInitializer) { + if (ktClassInitializer.body == null) return + val irInitializer = generateAnonymousInitializer(ktClassInitializer) + irBlockBody.addStatement(irInitializer) + } + + fun generateAnonymousInitializer(ktInitializer: KtAnonymousInitializer): IrStatement { + return createStatementGenerator().generateStatement(ktInitializer.body!!) + } + + private fun generateInitializerForPropertyDefinedInClassBody(irBlockBody: IrBlockBodyImpl, ktProperty: KtProperty) { + val propertyDescriptor = getOrFail(BindingContext.VARIABLE, ktProperty) as PropertyDescriptor + ktProperty.initializer?.let { ktInitializer -> + irBlockBody.addStatement(createPropertyInitializationExpression( + ktProperty, propertyDescriptor, createStatementGenerator().generateExpression(ktInitializer))) + } + } + + private fun generateInitializersForPropertiesDefinedInPrimaryConstructor(irBlockBody: IrBlockBodyImpl, ktClassOrObject: KtClassOrObject) { + ktClassOrObject.getPrimaryConstructor()?.let { ktPrimaryConstructor -> + for (ktParameter in ktPrimaryConstructor.valueParameters) { + if (ktParameter.hasValOrVar()) { + val propertyDescriptor = getOrFail(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, ktParameter) + val valueParameterDescriptor = getOrFail(BindingContext.VALUE_PARAMETER, ktParameter) + + irBlockBody.addStatement( + createPropertyInitializationExpression( + ktParameter, propertyDescriptor, + IrGetVariableImpl(ktParameter.startOffset, ktParameter.endOffset, + valueParameterDescriptor, IrOperator.INITIALIZE_PROPERTY_FROM_PARAMETER) + )) + } + } + } + } + + private fun createPropertyInitializationExpression(ktElement: KtElement, propertyDescriptor: PropertyDescriptor, value: IrExpression) = + IrSetBackingFieldImpl(ktElement.startOffset, ktElement.endOffset, propertyDescriptor, value) } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt index b99abcb639d..ee66928981a 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BranchingExpressionGenerator.kt @@ -26,10 +26,7 @@ import org.jetbrains.kotlin.psi2ir.deparenthesize import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.utils.SmartList -class BranchingExpressionGenerator(val statementGenerator: StatementGenerator) : GeneratorWithScope { - override val scope: Scope get() = statementGenerator.scope - override val context: GeneratorContext get() = statementGenerator.context - +class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) { fun generateIfExpression(expression: KtIfExpression): IrExpression { val resultType = getInferredTypeWithImplicitCastsOrFail(expression) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt index b5da8de4e2c..179816bbfd5 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt @@ -72,7 +72,8 @@ class CallGenerator( IrGetterCallImpl(startOffset, endOffset, descriptor.getter!!, dispatchReceiverValue?.load(), extensionReceiverValue?.load(), - IrOperator.GET_PROPERTY) + IrOperator.GET_PROPERTY, + call.superQualifier) } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt index fd98054249e..719b30e1f91 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt @@ -16,11 +16,15 @@ package org.jetbrains.kotlin.psi2ir.generators -import org.jetbrains.kotlin.descriptors.ConstructorDescriptor -import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.ir.expressions.IrExpressionBodyImpl +import org.jetbrains.kotlin.ir.expressions.IrGetVariableImpl +import org.jetbrains.kotlin.ir.expressions.IrOperator +import org.jetbrains.kotlin.psi.KtAnonymousInitializer +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtParameter +import org.jetbrains.kotlin.psi.KtSecondaryConstructor import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.resolve.BindingContext @@ -40,13 +44,12 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator } private fun generatePrimaryConstructor(irClass: IrClassImpl, ktClassOrObject: KtClassOrObject) { - val ktPrimaryConstructor = ktClassOrObject.getPrimaryConstructor() ?: return + val primaryConstructorDescriptor = irClass.descriptor.unsubstitutedPrimaryConstructor ?: return - val primaryConstructorDescriptor = getOrFail(BindingContext.CONSTRUCTOR, ktPrimaryConstructor) val irPrimaryConstructor = IrFunctionImpl(ktClassOrObject.startOffset, ktClassOrObject.endOffset, IrDeclarationOrigin.DEFINED, primaryConstructorDescriptor) - irPrimaryConstructor.body = generatePrimaryConstructorBodyFromClass(ktClassOrObject, primaryConstructorDescriptor) + irPrimaryConstructor.body = BodyGenerator(primaryConstructorDescriptor, context).generatePrimaryConstructorBody(ktClassOrObject) irClass.addMember(irPrimaryConstructor) } @@ -66,7 +69,12 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator for (ktDeclaration in ktClassBody.declarations) { if (ktDeclaration is KtAnonymousInitializer) continue - val irMember = declarationGenerator.generateMemberDeclaration(ktDeclaration) + val irMember = + if (ktDeclaration is KtSecondaryConstructor && isConstructorDelegatingToSuper(ktDeclaration, irClass.descriptor)) + declarationGenerator.generateSecondaryConstructorWithClassInitializers(ktDeclaration, ktClassOrObject) + else + declarationGenerator.generateMemberDeclaration(ktDeclaration) + irClass.addMember(irMember) if (irMember is IrProperty) { irMember.getter?.let { irClass.addMember(it) } @@ -76,6 +84,12 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator } } + private fun isConstructorDelegatingToSuper(ktConstructor: KtSecondaryConstructor, classOwner: ClassDescriptor): Boolean { + val delegatingResolvedCall = getResolvedCall(ktConstructor.getDelegationCall())!! + val calleeOwner = delegatingResolvedCall.resultingDescriptor.containingDeclaration as ClassDescriptor + return calleeOwner != classOwner + } + private fun generatePropertyForPrimaryConstructorParameter(ktParameter: KtParameter): IrDeclaration { val valueParameterDescriptor = getOrFail(BindingContext.VALUE_PARAMETER, ktParameter) val propertyDescriptor = getOrFail(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, ktParameter) @@ -86,52 +100,6 @@ class ClassGenerator(val declarationGenerator: DeclarationGenerator) : Generator return irProperty } - private fun generatePrimaryConstructorBodyFromClass(ktClassOrObject: KtClassOrObject, primaryConstructorDescriptor: ConstructorDescriptor): IrBody { - val irBlockBody = IrBlockBodyImpl(ktClassOrObject.startOffset, ktClassOrObject.endOffset) - - generateInitializersForPropertiesDefinedInPrimaryConstructor(irBlockBody, ktClassOrObject) - generateInitializersForClassBody(irBlockBody, ktClassOrObject, primaryConstructorDescriptor) - - return irBlockBody - } - - private fun generateInitializersForClassBody(irBlockBody: IrBlockBodyImpl, ktClassOrObject: KtClassOrObject, primaryConstructorDescriptor: ConstructorDescriptor) { - ktClassOrObject.getBody()?.let { ktClassBody -> - for (ktDeclaration in ktClassBody.declarations) { - when (ktDeclaration) { - is KtProperty -> generateInitializerForPropertyDefinedInClassBody(irBlockBody, ktDeclaration) - is KtClassInitializer -> generateAnonymousInitializer(irBlockBody, ktDeclaration, primaryConstructorDescriptor) - } - } - } - } - - private fun generateAnonymousInitializer(irBlockBody: IrBlockBodyImpl, ktClassInitializer: KtClassInitializer, primaryConstructorDescriptor: ConstructorDescriptor) { - if (ktClassInitializer.body == null) return - val irInitializer = BodyGenerator(primaryConstructorDescriptor, context).generateAnonymousInitializer(ktClassInitializer) - irBlockBody.addStatement(irInitializer) - } - - private fun generateInitializerForPropertyDefinedInClassBody(irBlockBody: IrBlockBodyImpl, ktProperty: KtProperty) { - val propertyDescriptor = getOrFail(BindingContext.VARIABLE, ktProperty) as PropertyDescriptor - if (ktProperty.initializer != null) { - irBlockBody.addStatement(createInitializeProperty(ktProperty, propertyDescriptor)) - } - } - - private fun generateInitializersForPropertiesDefinedInPrimaryConstructor(irBlockBody: IrBlockBodyImpl, ktClassOrObject: KtClassOrObject) { - ktClassOrObject.getPrimaryConstructor()?.let { ktPrimaryConstructor -> - for (ktParameter in ktPrimaryConstructor.valueParameters) { - if (ktParameter.hasValOrVar()) { - val propertyDescriptor = getOrFail(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, ktParameter) - irBlockBody.addStatement(createInitializeProperty(ktParameter, propertyDescriptor)) - } - } - } - } - - private fun createInitializeProperty(ktElement: KtElement, propertyDescriptor: PropertyDescriptor) = - IrInitializePropertyImpl(ktElement.startOffset, ktElement.endOffset, context.builtIns.unitType, propertyDescriptor) } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt index 386ef7a4824..6e7fa02a308 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt @@ -60,7 +60,15 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator { fun generateSecondaryConstructor(ktConstructor: KtSecondaryConstructor) : IrFunction { val constructorDescriptor = getOrFail(BindingContext.CONSTRUCTOR, ktConstructor) - val body = BodyGenerator(constructorDescriptor, context).generateSecondaryConstructorBody(ktConstructor) + val body = createBodyGenerator(constructorDescriptor).generateSecondaryConstructorBody(ktConstructor) + return IrFunctionImpl(ktConstructor.startOffset, ktConstructor.endOffset, IrDeclarationOrigin.DEFINED, + constructorDescriptor, body) + } + + + fun generateSecondaryConstructorWithClassInitializers(ktConstructor: KtSecondaryConstructor, ktClassOrObject: KtClassOrObject): IrDeclaration { + val constructorDescriptor = getOrFail(BindingContext.CONSTRUCTOR, ktConstructor) + val body = createBodyGenerator(constructorDescriptor).generateSecondaryConstructorBodyWithClassInitializers(ktConstructor, ktClassOrObject) return IrFunctionImpl(ktConstructor.startOffset, ktConstructor.endOffset, IrDeclarationOrigin.DEFINED, constructorDescriptor, body) } @@ -101,8 +109,12 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator { } private fun generateFunctionBody(scopeOwner: CallableDescriptor, ktBody: KtExpression): IrBody = - BodyGenerator(scopeOwner, context).generateFunctionBody(ktBody) + createBodyGenerator(scopeOwner).generateFunctionBody(ktBody) private fun generateInitializerBody(scopeOwner: CallableDescriptor, ktBody: KtExpression): IrBody = - BodyGenerator(scopeOwner, context).generatePropertyInitializerBody(ktBody) + createBodyGenerator(scopeOwner).generatePropertyInitializerBody(ktBody) + + private fun createBodyGenerator(descriptor: CallableDescriptor) = + BodyGenerator(descriptor, context) + } \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/Generator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/Generator.kt index dd81342d25b..93fb810eaf1 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/Generator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/Generator.kt @@ -17,17 +17,14 @@ package org.jetbrains.kotlin.psi2ir.generators import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.ir.expressions.IrDummyExpression -import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall -import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.typeUtil.makeNullable import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice import java.lang.AssertionError import java.lang.RuntimeException diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/LocalFunctionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/LocalFunctionGenerator.kt index a3235cc7f24..7985744f9cf 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/LocalFunctionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/LocalFunctionGenerator.kt @@ -29,10 +29,7 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.resolve.BindingContext -class LocalFunctionGenerator(val statementGenerator: StatementGenerator) : GeneratorWithScope { - override val scope: Scope get() = statementGenerator.scope - override val context: GeneratorContext get() = statementGenerator.context - +class LocalFunctionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) { fun generateLambda(ktLambda: KtLambdaExpression): IrStatement { val ktFun = ktLambda.functionLiteral val lambdaExpressionType = getInferredTypeWithImplicitCastsOrFail(ktLambda) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/LoopExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/LoopExpressionGenerator.kt index 20ccabd530e..56a15b4e891 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/LoopExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/LoopExpressionGenerator.kt @@ -27,10 +27,7 @@ import org.jetbrains.kotlin.psi2ir.intermediate.VariableLValue import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue import org.jetbrains.kotlin.resolve.BindingContext -class LoopExpressionGenerator(val statementGenerator: StatementGenerator) : GeneratorWithScope { - override val scope: Scope get() = statementGenerator.scope - override val context: GeneratorContext get() = statementGenerator.context - +class LoopExpressionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator){ fun generateWhileLoop(ktWhile: KtWhileExpression): IrExpression = generateConditionalLoop(ktWhile, IrWhileLoopImpl(ktWhile.startOffset, ktWhile.endOffset, diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt index fca32f724c4..bdd25dd8ef1 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt @@ -16,31 +16,20 @@ package org.jetbrains.kotlin.psi2ir.generators -import org.jetbrains.kotlin.descriptors.ConstructorDescriptor -import org.jetbrains.kotlin.descriptors.PropertyDescriptor -import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset -import org.jetbrains.kotlin.psi2ir.defaultLoad -import org.jetbrains.kotlin.psi2ir.intermediate.* +import org.jetbrains.kotlin.psi2ir.intermediate.createRematerializableOrTemporary import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall -import org.jetbrains.kotlin.resolve.scopes.receivers.ThisClassReceiver import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.types.typeUtil.makeNullable import java.lang.AssertionError -class OperatorExpressionGenerator( - val statementGenerator: StatementGenerator -) : GeneratorWithScope { - override val scope: Scope get() = statementGenerator.scope - override val context: GeneratorContext get() = statementGenerator.context +class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) { fun generatePrefixExpression(expression: KtPrefixExpression): IrExpression { val ktOperator = expression.operationReference.getReferencedNameElementType() @@ -48,7 +37,7 @@ class OperatorExpressionGenerator( return when (irOperator) { null -> throw AssertionError("Unexpected prefix operator: $ktOperator") - in INCREMENT_DECREMENT_OPERATORS -> generatePrefixIncrementDecrementOperator(expression, irOperator) + in INCREMENT_DECREMENT_OPERATORS -> AssignmentGenerator(statementGenerator).generatePrefixIncrementDecrement(expression, irOperator) in OPERATORS_DESUGARED_TO_CALLS -> generatePrefixOperatorAsCall(expression, irOperator) else -> createDummyExpression(expression, ktOperator.toString()) } @@ -60,7 +49,7 @@ class OperatorExpressionGenerator( return when (irOperator) { null -> throw AssertionError("Unexpected postfix operator: $ktOperator") - in INCREMENT_DECREMENT_OPERATORS -> generatePostfixIncrementDecrementOperator(expression, irOperator) + in INCREMENT_DECREMENT_OPERATORS -> AssignmentGenerator(statementGenerator).generatePostfixIncrementDecrement(expression, irOperator) IrOperator.EXCLEXCL -> generateExclExclOperator(expression, irOperator) else -> createDummyExpression(expression, ktOperator.toString()) } @@ -103,9 +92,9 @@ class OperatorExpressionGenerator( return when (irOperator) { null -> throw AssertionError("Unexpected infix operator: $ktOperator") - IrOperator.EQ -> generateAssignment(expression) + IrOperator.EQ -> AssignmentGenerator(statementGenerator).generateAssignment(expression) + in AUGMENTED_ASSIGNMENTS -> AssignmentGenerator(statementGenerator).generateAugmentedAssignment(expression, irOperator) IrOperator.ELVIS -> generateElvis(expression) - in AUGMENTED_ASSIGNMENTS -> generateAugmentedAssignment(expression, irOperator) in OPERATORS_DESUGARED_TO_CALLS -> generateBinaryOperatorAsCall(expression, irOperator) in COMPARISON_OPERATORS -> generateComparisonOperator(expression, irOperator) in EQUALITY_OPERATORS -> generateEqualityOperator(expression, irOperator) @@ -224,55 +213,7 @@ class OperatorExpressionGenerator( return CallGenerator(this).generateCall(expression, statementGenerator.pregenerateCall(operatorCall), irOperator) } - private fun generatePrefixIncrementDecrementOperator(expression: KtPrefixExpression, irOperator: IrOperator): IrExpression { - val opResolvedCall = getResolvedCall(expression)!! - val ktBaseExpression = expression.baseExpression!! - val irAssignmentReceiver = generateAssignmentReceiver(ktBaseExpression, irOperator) - return irAssignmentReceiver.assign { irLValue -> - val irBlock = IrBlockImpl(expression.startOffset, expression.endOffset, irLValue.type, irOperator) - - // VAR tmp = [lhs].inc() - val opCall = statementGenerator.pregenerateCall(opResolvedCall) - opCall.setExplicitReceiverValue(irLValue) - val irOpCall = CallGenerator(this).generateCall(expression, opCall, irOperator) - val irTmp = statementGenerator.scope.createTemporaryVariable(irOpCall) - irBlock.addStatement(irTmp) - - // [lhs] = tmp - irBlock.addStatement(irLValue.store(irTmp.defaultLoad())) - - // ^ tmp - irBlock.addStatement(irTmp.defaultLoad()) - - irBlock - } - } - - private fun generatePostfixIncrementDecrementOperator(expression: KtPostfixExpression, irOperator: IrOperator): IrExpression { - val opResolvedCall = getResolvedCall(expression)!! - val ktBaseExpression = expression.baseExpression!! - val irAssignmentReceiver = generateAssignmentReceiver(ktBaseExpression, irOperator) - - return irAssignmentReceiver.assign { irLValue -> - val irBlock = IrBlockImpl(expression.startOffset, expression.endOffset, irLValue.type, irOperator) - - // VAR tmp = [lhs] - val irTmp = scope.createTemporaryVariable(irLValue.load()) - irBlock.addStatement(irTmp) - - // [lhs] = tmp.inc() - val opCall = statementGenerator.pregenerateCall(opResolvedCall) - opCall.setExplicitReceiverValue(VariableLValue(irTmp)) - val irOpCall = CallGenerator(this).generateCall(expression, opCall, irOperator) - irBlock.addStatement(irLValue.store(irOpCall)) - - // ^ tmp - irBlock.addStatement(irTmp.defaultLoad()) - - irBlock - } - } private fun generateExclExclOperator(expression: KtPostfixExpression, irOperator: IrOperator): IrExpression { val ktArgument = expression.baseExpression!! @@ -301,95 +242,5 @@ class OperatorExpressionGenerator( return CallGenerator(statementGenerator).generateCall(expression, statementGenerator.pregenerateCall(resolvedCall), irOperator) } - private fun generateAugmentedAssignment(expression: KtBinaryExpression, irOperator: IrOperator): IrExpression { - val opResolvedCall = getResolvedCall(expression)!! - val isSimpleAssignment = get(BindingContext.VARIABLE_REASSIGNMENT, expression) ?: false - val ktLeft = expression.left!! - val ktRight = expression.right!! - val irAssignmentReceiver = generateAssignmentReceiver(ktLeft, irOperator) - - return irAssignmentReceiver.assign { irLValue -> - val opCall = statementGenerator.pregenerateCall(opResolvedCall) - opCall.setExplicitReceiverValue(irLValue) - opCall.irValueArgumentsByIndex[0] = statementGenerator.generateExpression(ktRight) - val irOpCall = CallGenerator(this).generateCall(expression, opCall, irOperator) - - if (isSimpleAssignment) { - // Set( Op( Get(), RHS ) ) - irLValue.store(irOpCall) - } - else { - // Op( Get(), RHS ) - irOpCall - } - } - } - - private fun generateAssignment(expression: KtBinaryExpression): IrExpression { - val ktLeft = expression.left!! - val irRhs = statementGenerator.generateExpression(expression.right!!) - val irAssignmentReceiver = generateAssignmentReceiver(ktLeft, IrOperator.EQ) - return irAssignmentReceiver.assign(irRhs) - } - - private fun generateAssignmentReceiver(ktLeft: KtExpression, irOperator: IrOperator): AssignmentReceiver { - if (ktLeft is KtArrayAccessExpression) { - return generateArrayAccessAssignmentReceiver(ktLeft, irOperator) - } - - val resolvedCall = getResolvedCall(ktLeft) ?: TODO("no resolved call for LHS") - val descriptor = resolvedCall.candidateDescriptor - - return when (descriptor) { - is LocalVariableDescriptor -> - if (descriptor.isDelegated) - TODO("Delegated local variable") - else - VariableLValue(ktLeft.startOffset, ktLeft.endOffset, descriptor, irOperator) - is PropertyDescriptor -> - generateAssignmentReceiverForProperty(descriptor, irOperator, ktLeft, resolvedCall) - else -> - TODO("Other cases of LHS") - } - } - - private fun generateAssignmentReceiverForProperty( - descriptor: PropertyDescriptor, - irOperator: IrOperator, - ktLeft: KtExpression, - resolvedCall: ResolvedCall<*> - ): AssignmentReceiver { - if (isPropertyInitializationWithinPrimaryConstructor(descriptor, resolvedCall)) { - return PropertyInitializerLValue(ktLeft.startOffset, ktLeft.endOffset, descriptor) - } - - val propertyReceiver = statementGenerator.generateCallReceiver( - ktLeft, resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver, resolvedCall.call.isSafeCall()) - - return SimplePropertyLValue(scope, ktLeft.startOffset, ktLeft.endOffset, irOperator, descriptor, propertyReceiver) - } - - private fun isPropertyInitializationWithinPrimaryConstructor(descriptor: PropertyDescriptor, resolvedCall: ResolvedCall<*>): Boolean { - val scopeOwner = statementGenerator.scopeOwner - - return scopeOwner is ConstructorDescriptor && scopeOwner.isPrimary && - descriptor.containingDeclaration == scopeOwner.containingDeclaration && - resolvedCall.extensionReceiver == null && resolvedCall.dispatchReceiver is ThisClassReceiver - } - - private fun generateArrayAccessAssignmentReceiver(ktLeft: KtArrayAccessExpression, irOperator: IrOperator): ArrayAccessAssignmentReceiver { - val irArray = statementGenerator.generateExpression(ktLeft.arrayExpression!!) - val irIndexExpressions = ktLeft.indexExpressions.map { statementGenerator.generateExpression(it) } - - val indexedGetResolvedCall = get(BindingContext.INDEXED_LVALUE_GET, ktLeft) - val indexedGetCall = indexedGetResolvedCall?.let { statementGenerator.pregenerateCallReceivers(it) } - - val indexedSetResolvedCall = get(BindingContext.INDEXED_LVALUE_SET, ktLeft) - val indexedSetCall = indexedSetResolvedCall?.let { statementGenerator.pregenerateCallReceivers(it) } - - return ArrayAccessAssignmentReceiver(irArray, irIndexExpressions, indexedGetCall, indexedSetCall, - CallGenerator(statementGenerator), - ktLeft.startOffset, ktLeft.endOffset, irOperator) - } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt index 141679946ad..9c2219000be 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt @@ -326,3 +326,7 @@ class StatementGenerator( LocalFunctionGenerator(this).generateFunction(function) } +abstract class StatementGeneratorExtension(val statementGenerator: StatementGenerator) : GeneratorWithScope { + override val scope: Scope get() = statementGenerator.scope + override val context: GeneratorContext get() = statementGenerator.context +} \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TemporaryVariableFactory.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TemporaryVariableFactory.kt deleted file mode 100644 index af851e68684..00000000000 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TemporaryVariableFactory.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.psi2ir.generators - -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin -import org.jetbrains.kotlin.ir.declarations.IrVariable -import org.jetbrains.kotlin.ir.declarations.IrVariableImpl -import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptor -import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.types.KotlinType - -class TemporaryVariableFactory(val scopeOwner: DeclarationDescriptor) { - - -} diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TryCatchExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TryCatchExpressionGenerator.kt index 53410a0a1ef..00b72e9813d 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TryCatchExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TryCatchExpressionGenerator.kt @@ -23,10 +23,7 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.resolve.BindingContext -class TryCatchExpressionGenerator(val statementGenerator: StatementGenerator) : GeneratorWithScope { - override val scope: Scope get() = statementGenerator.scope - override val context: GeneratorContext get() = statementGenerator.context - +class TryCatchExpressionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) { fun generateTryCatch(ktTry: KtTryExpression): IrExpression { val resultType = getInferredTypeWithImplicitCastsOrFail(ktTry) val irTryCatch = IrTryCatchImpl(ktTry.startOffset, ktTry.endOffset, resultType) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/PropertyInitializerLValue.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/BackingFieldLValue.kt similarity index 56% rename from compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/PropertyInitializerLValue.kt rename to compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/BackingFieldLValue.kt index 440bf4be8dd..e5e092a0e91 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/PropertyInitializerLValue.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/BackingFieldLValue.kt @@ -17,29 +17,23 @@ package org.jetbrains.kotlin.psi2ir.intermediate import org.jetbrains.kotlin.descriptors.PropertyDescriptor -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrInitializePropertyImpl +import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.typeUtil.builtIns -class PropertyInitializerLValue( +class BackingFieldLValue( val startOffset: Int, val endOffset: Int, - val propertyDescriptor: PropertyDescriptor + val descriptor: PropertyDescriptor, + val operator: IrOperator? ) : LValue, AssignmentReceiver { - override val type: KotlinType get() = propertyDescriptor.type + override val type: KotlinType get() = descriptor.type - override fun store(irExpression: IrExpression): IrExpression { - val irInitProperty = IrInitializePropertyImpl(startOffset, endOffset, type.builtIns.unitType, propertyDescriptor) - irInitProperty.initBlockExpression = irExpression - return irInitProperty - } + override fun store(irExpression: IrExpression): IrExpression = + IrSetBackingFieldImpl(startOffset, endOffset, descriptor, irExpression, operator) - override fun load(): IrExpression { - throw AssertionError("Property initializer LValue for $propertyDescriptor should not be used in compound assignment.") - } + override fun load(): IrExpression = + IrGetBackingFieldImpl(startOffset, endOffset, descriptor, operator) - override fun assign(withLValue: (LValue) -> IrExpression): IrExpression { - return withLValue(this) - } + override fun assign(withLValue: (LValue) -> IrExpression): IrExpression = + withLValue(this) } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SimplePropertyLValue.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SimplePropertyLValue.kt index 976bc25d6d6..8d732de10bb 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SimplePropertyLValue.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/SimplePropertyLValue.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.psi2ir.intermediate +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.* @@ -29,7 +30,8 @@ class SimplePropertyLValue( val endOffset: Int, val irOperator: IrOperator?, val descriptor: PropertyDescriptor, - val callReceiver: CallReceiver + val callReceiver: CallReceiver, + val superQualifier: ClassDescriptor? ) : LValue, AssignmentReceiver { override val type: KotlinType get() = descriptor.type @@ -39,7 +41,8 @@ class SimplePropertyLValue( IrGetterCallImpl(startOffset, endOffset, getter, dispatchReceiverValue?.load(), extensionReceiverValue?.load(), - irOperator) + irOperator, + superQualifier) } } @@ -49,7 +52,9 @@ class SimplePropertyLValue( IrSetterCallImpl(startOffset, endOffset, setter, dispatchReceiverValue?.load(), extensionReceiverValue?.load(), - irExpression, irOperator) + irExpression, + irOperator, + superQualifier) } } @@ -71,7 +76,8 @@ class SimplePropertyLValue( val irResultExpression = withLValue( SimplePropertyLValue(scope, startOffset, endOffset, irOperator, descriptor, - SimpleCallReceiver(tmpDispatchReceiverValue, tmpExtensionReceiverValue)) + SimpleCallReceiver(tmpDispatchReceiverValue, tmpExtensionReceiverValue), + superQualifier) ) if (variablesForReceivers.isEmpty()) { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBackingFieldExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBackingFieldExpression.kt new file mode 100644 index 00000000000..e0d56029e3f --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBackingFieldExpression.kt @@ -0,0 +1,111 @@ +/* + * 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.expressions + +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.ir.* +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.typeUtil.builtIns + +interface IrBackingFieldExpression : IrDeclarationReference { + override val descriptor: PropertyDescriptor + val operator: IrOperator? +} + +interface IrGetBackingField : IrBackingFieldExpression + +interface IrSetBackingField : IrBackingFieldExpression { + var value: IrExpression +} + +abstract class IrBackingFieldExpressionBase( + startOffset: Int, + endOffset: Int, + descriptor: PropertyDescriptor, + type: KotlinType, + override val operator: IrOperator? = null +) : IrDeclarationReferenceBase(startOffset, endOffset, type, descriptor), IrBackingFieldExpression + +class IrGetBackingFieldImpl( + startOffset: Int, + endOffset: Int, + descriptor: PropertyDescriptor, + operator: IrOperator? = null +) : IrBackingFieldExpressionBase(startOffset, endOffset, descriptor, descriptor.type, operator), IrGetBackingField { + override fun getChild(slot: Int): IrElement? = + null + + override fun replaceChild(slot: Int, newChild: IrElement) { + throwNoSuchSlot(slot) + } + + override fun accept(visitor: IrElementVisitor, data: D): R { + return visitor.visitGetBackingField(this, data) + } + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + // no children + } +} + +class IrSetBackingFieldImpl( + startOffset: Int, + endOffset: Int, + descriptor: PropertyDescriptor, + operator: IrOperator? = null +) : IrBackingFieldExpressionBase(startOffset, endOffset, descriptor, descriptor.type.builtIns.unitType, operator), IrSetBackingField { + constructor( + startOffset: Int, + endOffset: Int, + descriptor: PropertyDescriptor, + value: IrExpression, + operator: IrOperator? = null + ) : this(startOffset, endOffset, descriptor, operator) { + this.value = value + } + + private var valueImpl: IrExpression? = null + override var value: IrExpression + get() = valueImpl!! + set(value) { + value.assertDetached() + valueImpl?.detach() + valueImpl = value + value.setTreeLocation(this, CHILD_EXPRESSION_SLOT) + } + + override fun getChild(slot: Int): IrElement? = + when (slot) { + CHILD_EXPRESSION_SLOT -> value + else -> null + } + + override fun replaceChild(slot: Int, newChild: IrElement) { + when (slot) { + CHILD_EXPRESSION_SLOT -> value = newChild.assertCast() + } + } + + override fun accept(visitor: IrElementVisitor, data: D): R { + return visitor.visitSetBackingField(this, data) + } + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + value.accept(visitor, data) + } +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCall.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCall.kt index 535c443bf3d..7ba1989d4e9 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCall.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCall.kt @@ -18,10 +18,11 @@ package org.jetbrains.kotlin.ir.expressions import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType +import java.lang.AssertionError +import java.lang.UnsupportedOperationException interface IrCall : IrMemberAccessExpression { val superQualifier: ClassDescriptor? @@ -83,88 +84,3 @@ class IrCallImpl( argumentsByParameterIndex.forEach { it?.accept(visitor, data) } } } - -abstract class IrPropertyAccessorCallBase( - startOffset: Int, - endOffset: Int, - override val descriptor: CallableDescriptor, - override val operator: IrOperator? = null, - override val superQualifier: ClassDescriptor? = null -) : IrMemberAccessExpressionBase(startOffset, endOffset, descriptor.returnType!!), IrCall { - override fun accept(visitor: IrElementVisitor, data: D): R { - return visitor.visitCall(this, data) - } -} - -class IrGetterCallImpl( - startOffset: Int, - endOffset: Int, - descriptor: CallableDescriptor, - operator: IrOperator? = null, - superQualifier: ClassDescriptor? = null -) : IrPropertyAccessorCallBase(startOffset, endOffset, descriptor, operator, superQualifier), IrCall { - constructor( - startOffset: Int, - endOffset: Int, - descriptor: CallableDescriptor, - dispatchReceiver: IrExpression?, - extensionReceiver: IrExpression?, - operator: IrOperator? = null, - superQualifier: ClassDescriptor? = null - ) : this(startOffset, endOffset, descriptor, operator, superQualifier) { - this.dispatchReceiver = dispatchReceiver - this.extensionReceiver = extensionReceiver - } - - override fun getArgument(index: Int): IrExpression? = null - - override fun putArgument(index: Int, valueArgument: IrExpression?) { - throw UnsupportedOperationException("Property setter call has no arguments") - } - - override fun removeArgument(index: Int) { - throw UnsupportedOperationException("Property getter call has no arguments") - } -} - -class IrSetterCallImpl( - startOffset: Int, - endOffset: Int, - descriptor: CallableDescriptor, - operator: IrOperator? = null, - superQualifier: ClassDescriptor? = null -) : IrPropertyAccessorCallBase(startOffset, endOffset, descriptor, operator, superQualifier), IrCall { - constructor( - startOffset: Int, - endOffset: Int, - descriptor: CallableDescriptor, - dispatchReceiver: IrExpression?, - extensionReceiver: IrExpression?, - argument: IrExpression, - operator: IrOperator? = null, - superQualifier: ClassDescriptor? = null - ) : this(startOffset, endOffset, descriptor, operator, superQualifier) { - this.dispatchReceiver = dispatchReceiver - this.extensionReceiver = extensionReceiver - putArgument(SETTER_ARGUMENT_INDEX, argument) - } - - private var argumentImpl: IrExpression? = null - - override fun getArgument(index: Int): IrExpression? = - if (index == SETTER_ARGUMENT_INDEX) argumentImpl!! else null - - override fun putArgument(index: Int, valueArgument: IrExpression?) { - if (index != SETTER_ARGUMENT_INDEX) return - argumentImpl?.detach() - valueArgument?.assertDetached() - argumentImpl = valueArgument - valueArgument?.setTreeLocation(this, SETTER_ARGUMENT_INDEX) - } - - override fun removeArgument(index: Int) { - if (index != SETTER_ARGUMENT_INDEX) return - argumentImpl?.detach() - argumentImpl = null - } -} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperator.kt index 2af955740f2..8975cf7e29d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperator.kt @@ -87,6 +87,7 @@ interface IrOperator { object LAMBDA : IrOperatorImpl("LAMBDA") object ANONYMOUS_FUNCTION : IrOperatorImpl("ANONYMOUS_FUNCTION") + object SUPER_CONSTRUCTOR_CALL : IrOperatorImpl("SUPER_CONSTRUCTOR_CALL") object DELEGATING_CONSTRUCTOR_CALL : IrOperatorImpl("DELEGATING_CONSTRUCTOR_CALL") object INITIALIZE_PROPERTY_FROM_PARAMETER : IrOperatorImpl("INITIALIZE_PROPERTY_FROM_PARAMETER") object ANONYMOUS_INITIALIZER : IrOperatorImpl("ANONYMOUS_INITIALIZER") diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrPropertyAccessorCall.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrPropertyAccessorCall.kt new file mode 100644 index 00000000000..146c454d6fe --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrPropertyAccessorCall.kt @@ -0,0 +1,109 @@ +/* + * 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.expressions + +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.ir.SETTER_ARGUMENT_INDEX +import org.jetbrains.kotlin.ir.assertDetached +import org.jetbrains.kotlin.ir.detach +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor + +abstract class IrPropertyAccessorCallBase( + startOffset: Int, + endOffset: Int, + override val descriptor: CallableDescriptor, + override val operator: IrOperator? = null, + override val superQualifier: ClassDescriptor? = null +) : IrMemberAccessExpressionBase(startOffset, endOffset, descriptor.returnType!!), IrCall { + override fun accept(visitor: IrElementVisitor, data: D): R { + return visitor.visitCall(this, data) + } +} + +class IrGetterCallImpl( + startOffset: Int, + endOffset: Int, + descriptor: CallableDescriptor, + operator: IrOperator? = null, + superQualifier: ClassDescriptor? = null +) : IrPropertyAccessorCallBase(startOffset, endOffset, descriptor, operator, superQualifier), IrCall { + constructor( + startOffset: Int, + endOffset: Int, + descriptor: CallableDescriptor, + dispatchReceiver: IrExpression?, + extensionReceiver: IrExpression?, + operator: IrOperator? = null, + superQualifier: ClassDescriptor? = null + ) : this(startOffset, endOffset, descriptor, operator, superQualifier) { + this.dispatchReceiver = dispatchReceiver + this.extensionReceiver = extensionReceiver + } + + override fun getArgument(index: Int): IrExpression? = null + + override fun putArgument(index: Int, valueArgument: IrExpression?) { + throw UnsupportedOperationException("Property setter call has no arguments") + } + + override fun removeArgument(index: Int) { + throw UnsupportedOperationException("Property getter call has no arguments") + } +} + +class IrSetterCallImpl( + startOffset: Int, + endOffset: Int, + descriptor: CallableDescriptor, + operator: IrOperator? = null, + superQualifier: ClassDescriptor? = null +) : IrPropertyAccessorCallBase(startOffset, endOffset, descriptor, operator, superQualifier), IrCall { + constructor( + startOffset: Int, + endOffset: Int, + descriptor: CallableDescriptor, + dispatchReceiver: IrExpression?, + extensionReceiver: IrExpression?, + argument: IrExpression, + operator: IrOperator? = null, + superQualifier: ClassDescriptor? = null + ) : this(startOffset, endOffset, descriptor, operator, superQualifier) { + this.dispatchReceiver = dispatchReceiver + this.extensionReceiver = extensionReceiver + putArgument(SETTER_ARGUMENT_INDEX, argument) + } + + private var argumentImpl: IrExpression? = null + + override fun getArgument(index: Int): IrExpression? = + if (index == SETTER_ARGUMENT_INDEX) argumentImpl!! else null + + override fun putArgument(index: Int, valueArgument: IrExpression?) { + if (index != SETTER_ARGUMENT_INDEX) return + argumentImpl?.detach() + valueArgument?.assertDetached() + argumentImpl = valueArgument + valueArgument?.setTreeLocation(this, SETTER_ARGUMENT_INDEX) + } + + override fun removeArgument(index: Int) { + if (index != SETTER_ARGUMENT_INDEX) return + argumentImpl?.detach() + argumentImpl = null + } +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt index c545b7d9498..958b87b07a1 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt @@ -91,15 +91,24 @@ class RenderIrElementVisitor : IrElementVisitor { "THIS ${expression.classDescriptor.render()} type=${expression.type.render()}" override fun visitCall(expression: IrCall, data: Nothing?): String = - "CALL .${expression.descriptor.name} " + + "CALL .${expression.descriptor.name} ${expression.renderSuperQualifier()}" + "type=${expression.type.render()} operator=${expression.operator}" + private fun IrCall.renderSuperQualifier(): String = + superQualifier?.let { "superQualifier=${it.name} " } ?: "" + override fun visitGetVariable(expression: IrGetVariable, data: Nothing?): String = "GET_VAR ${expression.descriptor.name} type=${expression.type.render()} operator=${expression.operator}" override fun visitSetVariable(expression: IrSetVariable, data: Nothing?): String = "SET_VAR ${expression.descriptor.name} type=${expression.type.render()} operator=${expression.operator}" + override fun visitGetBackingField(expression: IrGetBackingField, data: Nothing?): String = + "GET_BACKING_FIELD ${expression.descriptor.name} type=${expression.type.render()} operator=${expression.operator}" + + override fun visitSetBackingField(expression: IrSetBackingField, data: Nothing?): String = + "SET_BACKING_FIELD ${expression.descriptor.name} type=${expression.type.render()} operator=${expression.operator}" + override fun visitGetObjectValue(expression: IrGetObjectValue, data: Nothing?): String = "GET_OBJECT ${expression.descriptor.name} type=${expression.type.render()}" diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt index 612ca9bc996..e622309c4ac 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt @@ -56,6 +56,8 @@ interface IrElementVisitor { fun visitGetEnumValue(expression: IrGetEnumValue, data: D) = visitSingletonReference(expression, data) fun visitGetVariable(expression: IrGetVariable, data: D) = visitDeclarationReference(expression, data) fun visitSetVariable(expression: IrSetVariable, data: D) = visitDeclarationReference(expression, data) + fun visitGetBackingField(expression: IrGetBackingField, data: D) = visitDeclarationReference(expression, data) + fun visitSetBackingField(expression: IrSetBackingField, data: D) = visitDeclarationReference(expression, data) fun visitGetExtensionReceiver(expression: IrGetExtensionReceiver, data: D) = visitDeclarationReference(expression, data) fun visitInitializeProperty(expression: IrInitializeProperty, data: D): R = visitDeclarationReference(expression, data) fun visitCall(expression: IrCall, data: D) = visitDeclarationReference(expression, data) @@ -80,4 +82,5 @@ interface IrElementVisitor { fun visitDummyDeclaration(declaration: IrDummyDeclaration, data: D) = visitDeclaration(declaration, data) fun visitDummyExpression(expression: IrDummyExpression, data: D) = visitExpression(expression, data) + } diff --git a/compiler/testData/ir/irText/classes/classMembers.txt b/compiler/testData/ir/irText/classes/classMembers.txt index ac6ec38837f..6a876635468 100644 --- a/compiler/testData/ir/irText/classes/classMembers.txt +++ b/compiler/testData/ir/irText/classes/classMembers.txt @@ -2,9 +2,12 @@ FILE /classMembers.kt CLASS CLASS C FUN public constructor C(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int, /*2*/ z: kotlin.Int = ...) BLOCK_BODY - INITIALIZE_PROPERTY y - INITIALIZE_PROPERTY z - INITIALIZE_PROPERTY property + SET_BACKING_FIELD y type=kotlin.Unit operator=null + GET_VAR y type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER + SET_BACKING_FIELD z type=kotlin.Unit operator=null + GET_VAR z type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER + SET_BACKING_FIELD property type=kotlin.Unit operator=null + CONST Int type=kotlin.Int value='0' PROPERTY public final val y: kotlin.Int getter=null setter=null EXPRESSION_BODY GET_VAR y type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER @@ -45,6 +48,8 @@ FILE /classMembers.kt CALL .println type=kotlin.Unit operator=null message: CONST String type=kotlin.String value='2' CLASS CLASS NestedClass + FUN public constructor NestedClass() + BLOCK_BODY FUN public final fun function(): kotlin.Unit BLOCK_BODY CALL .println type=kotlin.Unit operator=null @@ -61,3 +66,5 @@ FILE /classMembers.kt CALL .foo type=kotlin.Unit operator=null $this: THIS public interface NestedInterface type=C.NestedInterface CLASS OBJECT Companion + FUN private constructor Companion() + BLOCK_BODY diff --git a/compiler/testData/ir/irText/classes/delegatingConstructorCallsInSecondaryConstructors.kt b/compiler/testData/ir/irText/classes/delegatingConstructorCallsInSecondaryConstructors.kt new file mode 100644 index 00000000000..3ac39d297bd --- /dev/null +++ b/compiler/testData/ir/irText/classes/delegatingConstructorCallsInSecondaryConstructors.kt @@ -0,0 +1,7 @@ +open class Base + +class Test : Base { + constructor() + constructor(xx: Int): super() + constructor(xx: Short): this() +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/classes/delegatingConstructorCallsInSecondaryConstructors.txt b/compiler/testData/ir/irText/classes/delegatingConstructorCallsInSecondaryConstructors.txt new file mode 100644 index 00000000000..090da00cb44 --- /dev/null +++ b/compiler/testData/ir/irText/classes/delegatingConstructorCallsInSecondaryConstructors.txt @@ -0,0 +1,14 @@ +FILE /delegatingConstructorCallsInSecondaryConstructors.kt + CLASS CLASS Base + FUN public constructor Base() + BLOCK_BODY + CLASS CLASS Test + FUN public constructor Test() + BLOCK_BODY + CALL . type=Base operator=DELEGATING_CONSTRUCTOR_CALL + FUN public constructor Test(/*0*/ xx: kotlin.Int) + BLOCK_BODY + CALL . type=Base operator=DELEGATING_CONSTRUCTOR_CALL + FUN public constructor Test(/*0*/ xx: kotlin.Short) + BLOCK_BODY + CALL . type=Test operator=DELEGATING_CONSTRUCTOR_CALL diff --git a/compiler/testData/ir/irText/classes/initVal.kt b/compiler/testData/ir/irText/classes/initVal.kt new file mode 100644 index 00000000000..fe2fff8274a --- /dev/null +++ b/compiler/testData/ir/irText/classes/initVal.kt @@ -0,0 +1,13 @@ +class TestInitValFromParameter(val x: Int) + +class TestInitValInClass { + val x = 0 +} + +class TestInitValInInitBlock { + val x: Int + init { + x = 0 + } +} + diff --git a/compiler/testData/ir/irText/classes/initVal.txt b/compiler/testData/ir/irText/classes/initVal.txt new file mode 100644 index 00000000000..162bd2f2915 --- /dev/null +++ b/compiler/testData/ir/irText/classes/initVal.txt @@ -0,0 +1,24 @@ +FILE /initVal.kt + CLASS CLASS TestInitValFromParameter + FUN public constructor TestInitValFromParameter(/*0*/ x: kotlin.Int) + BLOCK_BODY + SET_BACKING_FIELD x type=kotlin.Unit operator=null + GET_VAR x type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER + PROPERTY public final val x: kotlin.Int getter=null setter=null + EXPRESSION_BODY + GET_VAR x type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER + CLASS CLASS TestInitValInClass + FUN public constructor TestInitValInClass() + BLOCK_BODY + SET_BACKING_FIELD x type=kotlin.Unit operator=null + CONST Int type=kotlin.Int value='0' + PROPERTY public final val x: kotlin.Int = 0 getter=null setter=null + EXPRESSION_BODY + CONST Int type=kotlin.Int value='0' + CLASS CLASS TestInitValInInitBlock + FUN public constructor TestInitValInInitBlock() + BLOCK_BODY + BLOCK type=kotlin.Unit operator=null + SET_BACKING_FIELD x type=kotlin.Unit operator=null + CONST Int type=kotlin.Int value='0' + PROPERTY public final val x: kotlin.Int getter=null setter=null diff --git a/compiler/testData/ir/irText/classes/initVar.kt b/compiler/testData/ir/irText/classes/initVar.kt new file mode 100644 index 00000000000..c0fb46476ac --- /dev/null +++ b/compiler/testData/ir/irText/classes/initVar.kt @@ -0,0 +1,38 @@ +class TestInitVarFromParameter(var x: Int) + +class TestInitVarInClass { + var x = 0 +} + +class TestInitVarInInitBlock { + var x: Int + init { + x = 0 + } +} + +class TestInitVarWithCustomSetter { + var x = 0 + set(value) { field = value } +} + +class TestInitVarWithCustomSetterWithExplicitCtor { + var x: Int + set(value) { field = value } + + init { + x = 0 + } + + constructor() +} + +class TestInitVarWithCustomSetterInCtor { + var x: Int set(value) { + field = value + } + + constructor() { + x = 42 + } +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/classes/initVar.txt b/compiler/testData/ir/irText/classes/initVar.txt new file mode 100644 index 00000000000..f433a7fd8af --- /dev/null +++ b/compiler/testData/ir/irText/classes/initVar.txt @@ -0,0 +1,62 @@ +FILE /initVar.kt + CLASS CLASS TestInitVarFromParameter + FUN public constructor TestInitVarFromParameter(/*0*/ x: kotlin.Int) + BLOCK_BODY + SET_BACKING_FIELD x type=kotlin.Unit operator=null + GET_VAR x type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER + PROPERTY public final var x: kotlin.Int getter=null setter=null + EXPRESSION_BODY + GET_VAR x type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER + CLASS CLASS TestInitVarInClass + FUN public constructor TestInitVarInClass() + BLOCK_BODY + SET_BACKING_FIELD x type=kotlin.Unit operator=null + CONST Int type=kotlin.Int value='0' + PROPERTY public final var x: kotlin.Int getter=null setter=null + EXPRESSION_BODY + CONST Int type=kotlin.Int value='0' + CLASS CLASS TestInitVarInInitBlock + FUN public constructor TestInitVarInInitBlock() + BLOCK_BODY + BLOCK type=kotlin.Unit operator=null + CALL . type=kotlin.Unit operator=EQ + $this: THIS public final class TestInitVarInInitBlock type=TestInitVarInInitBlock + : CONST Int type=kotlin.Int value='0' + PROPERTY public final var x: kotlin.Int getter=null setter=null + CLASS CLASS TestInitVarWithCustomSetter + FUN public constructor TestInitVarWithCustomSetter() + BLOCK_BODY + SET_BACKING_FIELD x type=kotlin.Unit operator=null + CONST Int type=kotlin.Int value='0' + PROPERTY public final var x: kotlin.Int getter=null setter= + EXPRESSION_BODY + CONST Int type=kotlin.Int value='0' + PROPERTY_SETTER public final fun (/*0*/ value: kotlin.Int): kotlin.Unit property=x + BLOCK_BODY + SET_BACKING_FIELD x type=kotlin.Unit operator=EQ + GET_VAR value type=kotlin.Int operator=null + CLASS CLASS TestInitVarWithCustomSetterWithExplicitCtor + PROPERTY public final var x: kotlin.Int getter=null setter= + PROPERTY_SETTER public final fun (/*0*/ value: kotlin.Int): kotlin.Unit property=x + BLOCK_BODY + SET_BACKING_FIELD x type=kotlin.Unit operator=EQ + GET_VAR value type=kotlin.Int operator=null + FUN public constructor TestInitVarWithCustomSetterWithExplicitCtor() + BLOCK_BODY + CALL . type=kotlin.Any operator=DELEGATING_CONSTRUCTOR_CALL + BLOCK type=kotlin.Unit operator=null + CALL . type=kotlin.Unit operator=EQ + $this: THIS public final class TestInitVarWithCustomSetterWithExplicitCtor type=TestInitVarWithCustomSetterWithExplicitCtor + value: CONST Int type=kotlin.Int value='0' + CLASS CLASS TestInitVarWithCustomSetterInCtor + PROPERTY public final var x: kotlin.Int getter=null setter= + PROPERTY_SETTER public final fun (/*0*/ value: kotlin.Int): kotlin.Unit property=x + BLOCK_BODY + SET_BACKING_FIELD x type=kotlin.Unit operator=EQ + GET_VAR value type=kotlin.Int operator=null + FUN public constructor TestInitVarWithCustomSetterInCtor() + BLOCK_BODY + CALL . type=kotlin.Any operator=DELEGATING_CONSTRUCTOR_CALL + CALL . type=kotlin.Unit operator=EQ + $this: THIS public final class TestInitVarWithCustomSetterInCtor type=TestInitVarWithCustomSetterInCtor + value: CONST Int type=kotlin.Int value='42' diff --git a/compiler/testData/ir/irText/classes/primaryConstructor.txt b/compiler/testData/ir/irText/classes/primaryConstructor.txt index ac1198f7dd5..53e7322d3bb 100644 --- a/compiler/testData/ir/irText/classes/primaryConstructor.txt +++ b/compiler/testData/ir/irText/classes/primaryConstructor.txt @@ -2,8 +2,10 @@ FILE /primaryConstructor.kt CLASS CLASS Test1 FUN public constructor Test1(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int) BLOCK_BODY - INITIALIZE_PROPERTY x - INITIALIZE_PROPERTY y + SET_BACKING_FIELD x type=kotlin.Unit operator=null + GET_VAR x type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER + SET_BACKING_FIELD y type=kotlin.Unit operator=null + GET_VAR y type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER PROPERTY public final val x: kotlin.Int getter=null setter=null EXPRESSION_BODY GET_VAR x type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER @@ -13,8 +15,10 @@ FILE /primaryConstructor.kt CLASS CLASS Test2 FUN public constructor Test2(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int) BLOCK_BODY - INITIALIZE_PROPERTY y - INITIALIZE_PROPERTY x + SET_BACKING_FIELD y type=kotlin.Unit operator=null + GET_VAR y type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER + SET_BACKING_FIELD x type=kotlin.Unit operator=null + GET_VAR x type=kotlin.Int operator=null PROPERTY public final val y: kotlin.Int getter=null setter=null EXPRESSION_BODY GET_VAR y type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER @@ -24,9 +28,10 @@ FILE /primaryConstructor.kt CLASS CLASS Test3 FUN public constructor Test3(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int) BLOCK_BODY - INITIALIZE_PROPERTY y + SET_BACKING_FIELD y type=kotlin.Unit operator=null + GET_VAR y type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER BLOCK type=kotlin.Unit operator=null - INITIALIZE_PROPERTY x + SET_BACKING_FIELD x type=kotlin.Unit operator=null GET_VAR x type=kotlin.Int operator=null PROPERTY public final val y: kotlin.Int getter=null setter=null EXPRESSION_BODY diff --git a/compiler/testData/ir/irText/classes/primaryConstructorWithSuperConstructorCall.kt b/compiler/testData/ir/irText/classes/primaryConstructorWithSuperConstructorCall.kt new file mode 100644 index 00000000000..4c1b4a019fc --- /dev/null +++ b/compiler/testData/ir/irText/classes/primaryConstructorWithSuperConstructorCall.kt @@ -0,0 +1,10 @@ +open class Base + +class TestImplicitPrimaryConstructor : Base() + +class TestExplicitPrimaryConstructor() : Base() + +class TestWithDelegatingConstructor(val x: Int, val y: Int) : Base() { + constructor(x: Int) : this(x, 0) +} + diff --git a/compiler/testData/ir/irText/classes/primaryConstructorWithSuperConstructorCall.txt b/compiler/testData/ir/irText/classes/primaryConstructorWithSuperConstructorCall.txt new file mode 100644 index 00000000000..ef28791e964 --- /dev/null +++ b/compiler/testData/ir/irText/classes/primaryConstructorWithSuperConstructorCall.txt @@ -0,0 +1,31 @@ +FILE /primaryConstructorWithSuperConstructorCall.kt + CLASS CLASS Base + FUN public constructor Base() + BLOCK_BODY + CLASS CLASS TestImplicitPrimaryConstructor + FUN public constructor TestImplicitPrimaryConstructor() + BLOCK_BODY + CALL . type=Base operator=SUPER_CONSTRUCTOR_CALL + CLASS CLASS TestExplicitPrimaryConstructor + FUN public constructor TestExplicitPrimaryConstructor() + BLOCK_BODY + CALL . type=Base operator=SUPER_CONSTRUCTOR_CALL + CLASS CLASS TestWithDelegatingConstructor + FUN public constructor TestWithDelegatingConstructor(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int) + BLOCK_BODY + CALL . type=Base operator=SUPER_CONSTRUCTOR_CALL + SET_BACKING_FIELD x type=kotlin.Unit operator=null + GET_VAR x type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER + SET_BACKING_FIELD y type=kotlin.Unit operator=null + GET_VAR y type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER + PROPERTY public final val x: kotlin.Int getter=null setter=null + EXPRESSION_BODY + GET_VAR x type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER + PROPERTY public final val y: kotlin.Int getter=null setter=null + EXPRESSION_BODY + GET_VAR y type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN public constructor TestWithDelegatingConstructor(/*0*/ x: kotlin.Int) + BLOCK_BODY + CALL . type=TestWithDelegatingConstructor operator=DELEGATING_CONSTRUCTOR_CALL + x: GET_VAR x type=kotlin.Int operator=null + y: CONST Int type=kotlin.Int value='0' diff --git a/compiler/testData/ir/irText/classes/qualifiedSuperCalls.kt b/compiler/testData/ir/irText/classes/qualifiedSuperCalls.kt new file mode 100644 index 00000000000..bb9196a6dde --- /dev/null +++ b/compiler/testData/ir/irText/classes/qualifiedSuperCalls.kt @@ -0,0 +1,19 @@ +interface ILeft { + fun foo() {} + val bar: Int get() = 1 +} + +interface IRight { + fun foo() {} + val bar: Int get() = 2 +} + +class CBoth : ILeft, IRight { + override fun foo() { + super.foo() + super.foo() + } + + override val bar: Int + get() = super.bar + super.bar +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/classes/qualifiedSuperCalls.txt b/compiler/testData/ir/irText/classes/qualifiedSuperCalls.txt new file mode 100644 index 00000000000..b822a97519d --- /dev/null +++ b/compiler/testData/ir/irText/classes/qualifiedSuperCalls.txt @@ -0,0 +1,35 @@ +FILE /qualifiedSuperCalls.kt + CLASS INTERFACE ILeft + FUN public open fun foo(): kotlin.Unit + BLOCK_BODY + PROPERTY public open val bar: kotlin.Int getter= setter=null + PROPERTY_GETTER public open fun (): kotlin.Int property=bar + BLOCK_BODY + RETURN type=kotlin.Nothing from= + CONST Int type=kotlin.Int value='1' + CLASS INTERFACE IRight + FUN public open fun foo(): kotlin.Unit + BLOCK_BODY + PROPERTY public open val bar: kotlin.Int getter= setter=null + PROPERTY_GETTER public open fun (): kotlin.Int property=bar + BLOCK_BODY + RETURN type=kotlin.Nothing from= + CONST Int type=kotlin.Int value='2' + CLASS CLASS CBoth + FUN public constructor CBoth() + BLOCK_BODY + FUN public open override /*2*/ fun foo(): kotlin.Unit + BLOCK_BODY + CALL .foo superQualifier=ILeft type=kotlin.Unit operator=null + $this: THIS public final class CBoth : ILeft, IRight type=ILeft + CALL .foo superQualifier=IRight type=kotlin.Unit operator=null + $this: THIS public final class CBoth : ILeft, IRight type=IRight + PROPERTY public open override /*2*/ val bar: kotlin.Int getter= setter=null + PROPERTY_GETTER public open override /*2*/ fun (): kotlin.Int property=bar + BLOCK_BODY + RETURN type=kotlin.Nothing from= + CALL .plus type=kotlin.Int operator=PLUS + $this: CALL . superQualifier=ILeft type=kotlin.Int operator=GET_PROPERTY + $this: THIS public final class CBoth : ILeft, IRight type=ILeft + other: CALL . superQualifier=IRight type=kotlin.Int operator=GET_PROPERTY + $this: THIS public final class CBoth : ILeft, IRight type=IRight diff --git a/compiler/testData/ir/irText/classes/secondaryConstructorWithInitializersFromClassBody.kt b/compiler/testData/ir/irText/classes/secondaryConstructorWithInitializersFromClassBody.kt new file mode 100644 index 00000000000..ed5da8be7e4 --- /dev/null +++ b/compiler/testData/ir/irText/classes/secondaryConstructorWithInitializersFromClassBody.kt @@ -0,0 +1,14 @@ +open class Base + +class TestProperty : Base { + val x = 0 + constructor() +} + +class TestInitBlock : Base { + val x: Int + init { + x = 0 + } + constructor() +} diff --git a/compiler/testData/ir/irText/classes/secondaryConstructorWithInitializersFromClassBody.txt b/compiler/testData/ir/irText/classes/secondaryConstructorWithInitializersFromClassBody.txt new file mode 100644 index 00000000000..44f078b0f75 --- /dev/null +++ b/compiler/testData/ir/irText/classes/secondaryConstructorWithInitializersFromClassBody.txt @@ -0,0 +1,21 @@ +FILE /secondaryConstructorWithInitializersFromClassBody.kt + CLASS CLASS Base + FUN public constructor Base() + BLOCK_BODY + CLASS CLASS TestProperty + PROPERTY public final val x: kotlin.Int = 0 getter=null setter=null + EXPRESSION_BODY + CONST Int type=kotlin.Int value='0' + FUN public constructor TestProperty() + BLOCK_BODY + CALL . type=Base operator=DELEGATING_CONSTRUCTOR_CALL + SET_BACKING_FIELD x type=kotlin.Unit operator=null + CONST Int type=kotlin.Int value='0' + CLASS CLASS TestInitBlock + PROPERTY public final val x: kotlin.Int getter=null setter=null + FUN public constructor TestInitBlock() + BLOCK_BODY + CALL . type=Base operator=DELEGATING_CONSTRUCTOR_CALL + BLOCK type=kotlin.Unit operator=null + SET_BACKING_FIELD x type=kotlin.Unit operator=null + CONST Int type=kotlin.Int value='0' diff --git a/compiler/testData/ir/irText/classes/superCalls.kt b/compiler/testData/ir/irText/classes/superCalls.kt new file mode 100644 index 00000000000..69039a1bd16 --- /dev/null +++ b/compiler/testData/ir/irText/classes/superCalls.kt @@ -0,0 +1,14 @@ +open class Base { + open fun foo() {} + + open val bar: String = "" +} + +class Derived : Base() { + override fun foo() { + super.foo() + } + + override val bar: String + get() = super.bar +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/classes/superCalls.txt b/compiler/testData/ir/irText/classes/superCalls.txt new file mode 100644 index 00000000000..f97be629e10 --- /dev/null +++ b/compiler/testData/ir/irText/classes/superCalls.txt @@ -0,0 +1,25 @@ +FILE /superCalls.kt + CLASS CLASS Base + FUN public constructor Base() + BLOCK_BODY + SET_BACKING_FIELD bar type=kotlin.Unit operator=null + CONST String type=kotlin.String value='' + FUN public open fun foo(): kotlin.Unit + BLOCK_BODY + PROPERTY public open val bar: kotlin.String = "" getter=null setter=null + EXPRESSION_BODY + CONST String type=kotlin.String value='' + CLASS CLASS Derived + FUN public constructor Derived() + BLOCK_BODY + CALL . type=Base operator=SUPER_CONSTRUCTOR_CALL + FUN public open override /*1*/ fun foo(): kotlin.Unit + BLOCK_BODY + CALL .foo superQualifier=Base type=kotlin.Unit operator=null + $this: THIS public final class Derived : Base type=Base + PROPERTY public open override /*1*/ val bar: kotlin.String getter= setter=null + PROPERTY_GETTER public open override /*1*/ fun (): kotlin.String property=bar + BLOCK_BODY + RETURN type=kotlin.Nothing from= + CALL . superQualifier=Base type=kotlin.String operator=GET_PROPERTY + $this: THIS public final class Derived : Base type=Base diff --git a/compiler/testData/ir/irText/expressions/arrayAugmentedAssignment1.txt b/compiler/testData/ir/irText/expressions/arrayAugmentedAssignment1.txt index 127e1fe51fc..a8845de09ed 100644 --- a/compiler/testData/ir/irText/expressions/arrayAugmentedAssignment1.txt +++ b/compiler/testData/ir/irText/expressions/arrayAugmentedAssignment1.txt @@ -14,7 +14,8 @@ FILE /arrayAugmentedAssignment1.kt CLASS CLASS C FUN public constructor C(/*0*/ x: kotlin.IntArray) BLOCK_BODY - INITIALIZE_PROPERTY x + SET_BACKING_FIELD x type=kotlin.Unit operator=null + GET_VAR x type=kotlin.IntArray operator=INITIALIZE_PROPERTY_FROM_PARAMETER PROPERTY public final val x: kotlin.IntArray getter=null setter=null EXPRESSION_BODY GET_VAR x type=kotlin.IntArray operator=INITIALIZE_PROPERTY_FROM_PARAMETER diff --git a/compiler/testData/ir/irText/expressions/assignments.txt b/compiler/testData/ir/irText/expressions/assignments.txt index 1b22571f0d6..c3f9e2d7ba1 100644 --- a/compiler/testData/ir/irText/expressions/assignments.txt +++ b/compiler/testData/ir/irText/expressions/assignments.txt @@ -2,7 +2,8 @@ FILE /assignments.kt CLASS CLASS Ref FUN public constructor Ref(/*0*/ x: kotlin.Int) BLOCK_BODY - INITIALIZE_PROPERTY x + SET_BACKING_FIELD x type=kotlin.Unit operator=null + GET_VAR x type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER PROPERTY public final var x: kotlin.Int getter=null setter=null EXPRESSION_BODY GET_VAR x type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER diff --git a/compiler/testData/ir/irText/expressions/augmentedAssignment2.txt b/compiler/testData/ir/irText/expressions/augmentedAssignment2.txt index c65902d86be..9da6092aa97 100644 --- a/compiler/testData/ir/irText/expressions/augmentedAssignment2.txt +++ b/compiler/testData/ir/irText/expressions/augmentedAssignment2.txt @@ -1,5 +1,7 @@ FILE /augmentedAssignment2.kt CLASS CLASS A + FUN public constructor A() + BLOCK_BODY FUN public operator fun A.plusAssign(/*0*/ s: kotlin.String): kotlin.Unit BLOCK_BODY FUN public operator fun A.minusAssign(/*0*/ s: kotlin.String): kotlin.Unit diff --git a/compiler/testData/ir/irText/expressions/chainOfSafeCalls.txt b/compiler/testData/ir/irText/expressions/chainOfSafeCalls.txt index 6d8132a35b4..f5ae42ea77e 100644 --- a/compiler/testData/ir/irText/expressions/chainOfSafeCalls.txt +++ b/compiler/testData/ir/irText/expressions/chainOfSafeCalls.txt @@ -1,5 +1,7 @@ FILE /chainOfSafeCalls.kt CLASS CLASS C + FUN public constructor C() + BLOCK_BODY FUN public final fun foo(): C BLOCK_BODY RETURN type=kotlin.Nothing from=foo diff --git a/compiler/testData/ir/irText/expressions/field.kt b/compiler/testData/ir/irText/expressions/field.kt new file mode 100644 index 00000000000..fb8018aba5b --- /dev/null +++ b/compiler/testData/ir/irText/expressions/field.kt @@ -0,0 +1,9 @@ +var testSimple: Int = 0 + set(value) { + field = value + } + +var testAugmented: Int = 0 + set(value) { + field += value + } \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/field.txt b/compiler/testData/ir/irText/expressions/field.txt new file mode 100644 index 00000000000..64db032ca5e --- /dev/null +++ b/compiler/testData/ir/irText/expressions/field.txt @@ -0,0 +1,17 @@ +FILE /field.kt + PROPERTY public var testSimple: kotlin.Int getter=null setter= + EXPRESSION_BODY + CONST Int type=kotlin.Int value='0' + PROPERTY_SETTER public fun (/*0*/ value: kotlin.Int): kotlin.Unit property=testSimple + BLOCK_BODY + SET_BACKING_FIELD testSimple type=kotlin.Unit operator=EQ + GET_VAR value type=kotlin.Int operator=null + PROPERTY public var testAugmented: kotlin.Int getter=null setter= + EXPRESSION_BODY + CONST Int type=kotlin.Int value='0' + PROPERTY_SETTER public fun (/*0*/ value: kotlin.Int): kotlin.Unit property=testAugmented + BLOCK_BODY + SET_BACKING_FIELD testAugmented type=kotlin.Unit operator=PLUSEQ + CALL .plus type=kotlin.Int operator=PLUSEQ + $this: GET_BACKING_FIELD testAugmented type=kotlin.Int operator=PLUSEQ + other: GET_VAR value type=kotlin.Int operator=null diff --git a/compiler/testData/ir/irText/expressions/forWithImplicitReceivers.txt b/compiler/testData/ir/irText/expressions/forWithImplicitReceivers.txt index 5e40b56dcd3..59784e0c9fc 100644 --- a/compiler/testData/ir/irText/expressions/forWithImplicitReceivers.txt +++ b/compiler/testData/ir/irText/expressions/forWithImplicitReceivers.txt @@ -1,9 +1,12 @@ FILE /forWithImplicitReceivers.kt CLASS OBJECT FiveTimes + FUN private constructor FiveTimes() + BLOCK_BODY CLASS CLASS IntCell FUN public constructor IntCell(/*0*/ value: kotlin.Int) BLOCK_BODY - INITIALIZE_PROPERTY value + SET_BACKING_FIELD value type=kotlin.Unit operator=null + GET_VAR value type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER PROPERTY public final var value: kotlin.Int getter=null setter=null EXPRESSION_BODY GET_VAR value type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER diff --git a/compiler/testData/ir/irText/expressions/safeCallWithIncrementDecrement.txt b/compiler/testData/ir/irText/expressions/safeCallWithIncrementDecrement.txt index 1b17cf7b31d..ccd740ddb31 100644 --- a/compiler/testData/ir/irText/expressions/safeCallWithIncrementDecrement.txt +++ b/compiler/testData/ir/irText/expressions/safeCallWithIncrementDecrement.txt @@ -1,5 +1,7 @@ FILE /safeCallWithIncrementDecrement.kt CLASS CLASS C + FUN public constructor C() + BLOCK_BODY PROPERTY public var test.C?.p: kotlin.Int getter= setter= PROPERTY_GETTER public fun test.C?.(): kotlin.Int property=p BLOCK_BODY diff --git a/compiler/testData/ir/irText/expressions/safeCalls.txt b/compiler/testData/ir/irText/expressions/safeCalls.txt index 73a51bc7ae8..31ecde092c4 100644 --- a/compiler/testData/ir/irText/expressions/safeCalls.txt +++ b/compiler/testData/ir/irText/expressions/safeCalls.txt @@ -2,7 +2,8 @@ FILE /safeCalls.kt CLASS CLASS Ref FUN public constructor Ref(/*0*/ value: kotlin.Int) BLOCK_BODY - INITIALIZE_PROPERTY value + SET_BACKING_FIELD value type=kotlin.Unit operator=null + GET_VAR value type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER PROPERTY public final var value: kotlin.Int getter=null setter=null EXPRESSION_BODY GET_VAR value type=kotlin.Int operator=INITIALIZE_PROPERTY_FROM_PARAMETER diff --git a/compiler/testData/ir/irText/expressions/values.txt b/compiler/testData/ir/irText/expressions/values.txt index 05c0beff567..31c2ea1e6ef 100644 --- a/compiler/testData/ir/irText/expressions/values.txt +++ b/compiler/testData/ir/irText/expressions/values.txt @@ -1,12 +1,22 @@ FILE /values.kt CLASS ENUM_CLASS Enum + FUN private constructor Enum() + BLOCK_BODY CLASS ENUM_ENTRY A + FUN private constructor A() + BLOCK_BODY CLASS OBJECT A + FUN private constructor A() + BLOCK_BODY PROPERTY public val a: kotlin.Int = 0 getter=null setter=null EXPRESSION_BODY CONST Int type=kotlin.Int value='0' CLASS CLASS Z + FUN public constructor Z() + BLOCK_BODY CLASS OBJECT Companion + FUN private constructor Companion() + BLOCK_BODY FUN public fun test1(): Enum BLOCK_BODY RETURN type=kotlin.Nothing from=test1 diff --git a/compiler/testData/ir/irText/expressions/when.txt b/compiler/testData/ir/irText/expressions/when.txt index 08622c451ad..951a05cde86 100644 --- a/compiler/testData/ir/irText/expressions/when.txt +++ b/compiler/testData/ir/irText/expressions/when.txt @@ -1,5 +1,7 @@ FILE /when.kt CLASS OBJECT A + FUN private constructor A() + BLOCK_BODY FUN public fun testWithSubject(/*0*/ x: kotlin.Any?): kotlin.String BLOCK_BODY RETURN type=kotlin.Nothing from=testWithSubject diff --git a/compiler/testData/ir/irText/lambdas/multipleImplicitReceivers.txt b/compiler/testData/ir/irText/lambdas/multipleImplicitReceivers.txt index 795c6a90e96..6f430e2fb93 100644 --- a/compiler/testData/ir/irText/lambdas/multipleImplicitReceivers.txt +++ b/compiler/testData/ir/irText/lambdas/multipleImplicitReceivers.txt @@ -1,6 +1,10 @@ FILE /multipleImplicitReceivers.kt CLASS OBJECT A + FUN private constructor A() + BLOCK_BODY CLASS OBJECT B + FUN private constructor B() + BLOCK_BODY CLASS INTERFACE IFoo PROPERTY public open val A.foo: B getter= setter=null PROPERTY_GETTER public open fun A.(): B property=foo diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index f939438f2dd..a8f5d7088a5 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -49,17 +49,59 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { doTest(fileName); } + @TestMetadata("delegatingConstructorCallsInSecondaryConstructors.kt") + public void testDelegatingConstructorCallsInSecondaryConstructors() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/delegatingConstructorCallsInSecondaryConstructors.kt"); + doTest(fileName); + } + + @TestMetadata("initVal.kt") + public void testInitVal() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/initVal.kt"); + doTest(fileName); + } + + @TestMetadata("initVar.kt") + public void testInitVar() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/initVar.kt"); + doTest(fileName); + } + @TestMetadata("primaryConstructor.kt") public void testPrimaryConstructor() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/primaryConstructor.kt"); doTest(fileName); } + @TestMetadata("primaryConstructorWithSuperConstructorCall.kt") + public void testPrimaryConstructorWithSuperConstructorCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/primaryConstructorWithSuperConstructorCall.kt"); + doTest(fileName); + } + + @TestMetadata("qualifiedSuperCalls.kt") + public void testQualifiedSuperCalls() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/qualifiedSuperCalls.kt"); + doTest(fileName); + } + + @TestMetadata("secondaryConstructorWithInitializersFromClassBody.kt") + public void testSecondaryConstructorWithInitializersFromClassBody() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/secondaryConstructorWithInitializersFromClassBody.kt"); + doTest(fileName); + } + @TestMetadata("secondaryConstructors.kt") public void testSecondaryConstructors() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/secondaryConstructors.kt"); doTest(fileName); } + + @TestMetadata("superCalls.kt") + public void testSuperCalls() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/superCalls.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/ir/irText/expressions") @@ -190,6 +232,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { doTest(fileName); } + @TestMetadata("field.kt") + public void testField() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/field.kt"); + doTest(fileName); + } + @TestMetadata("for.kt") public void testFor() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/for.kt");