Constructors represented "as in Java".

TODO: extract nested initializers somehow.
This commit is contained in:
Dmitry Petrov
2016-08-29 16:41:10 +03:00
committed by Dmitry Petrov
parent 57c1b3e0e2
commit 8528c23194
51 changed files with 1068 additions and 408 deletions
@@ -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
}
@@ -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)
}
}
@@ -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)
}
@@ -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)
@@ -72,7 +72,8 @@ class CallGenerator(
IrGetterCallImpl(startOffset, endOffset, descriptor.getter!!,
dispatchReceiverValue?.load(),
extensionReceiverValue?.load(),
IrOperator.GET_PROPERTY)
IrOperator.GET_PROPERTY,
call.superQualifier)
}
}
@@ -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)
}
@@ -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)
}
@@ -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
@@ -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)
@@ -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,
@@ -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)
}
}
@@ -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
}
@@ -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) {
}
@@ -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)
@@ -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)
}
@@ -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()) {
@@ -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<PropertyDescriptor>(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 <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
return visitor.visitGetBackingField(this, data)
}
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, 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 <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
return visitor.visitSetBackingField(this, data)
}
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
value.accept(visitor, data)
}
}
@@ -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 <R, D> accept(visitor: IrElementVisitor<R, D>, 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
}
}
@@ -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")
@@ -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 <R, D> accept(visitor: IrElementVisitor<R, D>, 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
}
}
@@ -91,15 +91,24 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
"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()}"
@@ -56,6 +56,8 @@ interface IrElementVisitor<out R, in D> {
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<out R, in D> {
fun visitDummyDeclaration(declaration: IrDummyDeclaration, data: D) = visitDeclaration(declaration, data)
fun visitDummyExpression(expression: IrDummyExpression, data: D) = visitExpression(expression, data)
}
+10 -3
View File
@@ -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
@@ -0,0 +1,7 @@
open class Base
class Test : Base {
constructor()
constructor(xx: Int): super()
constructor(xx: Short): this()
}
@@ -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 .<init> type=Base operator=DELEGATING_CONSTRUCTOR_CALL
FUN public constructor Test(/*0*/ xx: kotlin.Int)
BLOCK_BODY
CALL .<init> type=Base operator=DELEGATING_CONSTRUCTOR_CALL
FUN public constructor Test(/*0*/ xx: kotlin.Short)
BLOCK_BODY
CALL .<init> type=Test operator=DELEGATING_CONSTRUCTOR_CALL
+13
View File
@@ -0,0 +1,13 @@
class TestInitValFromParameter(val x: Int)
class TestInitValInClass {
val x = 0
}
class TestInitValInInitBlock {
val x: Int
init {
x = 0
}
}
+24
View File
@@ -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
+38
View File
@@ -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
}
}
+62
View File
@@ -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 .<set-x> type=kotlin.Unit operator=EQ
$this: THIS public final class TestInitVarInInitBlock type=TestInitVarInInitBlock
<set-?>: 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=<set-x>
EXPRESSION_BODY
CONST Int type=kotlin.Int value='0'
PROPERTY_SETTER public final fun <set-x>(/*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=<set-x>
PROPERTY_SETTER public final fun <set-x>(/*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 .<init> type=kotlin.Any operator=DELEGATING_CONSTRUCTOR_CALL
BLOCK type=kotlin.Unit operator=null
CALL .<set-x> 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=<set-x>
PROPERTY_SETTER public final fun <set-x>(/*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 .<init> type=kotlin.Any operator=DELEGATING_CONSTRUCTOR_CALL
CALL .<set-x> type=kotlin.Unit operator=EQ
$this: THIS public final class TestInitVarWithCustomSetterInCtor type=TestInitVarWithCustomSetterInCtor
value: CONST Int type=kotlin.Int value='42'
+11 -6
View File
@@ -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
@@ -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)
}
@@ -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 .<init> type=Base operator=SUPER_CONSTRUCTOR_CALL
CLASS CLASS TestExplicitPrimaryConstructor
FUN public constructor TestExplicitPrimaryConstructor()
BLOCK_BODY
CALL .<init> type=Base operator=SUPER_CONSTRUCTOR_CALL
CLASS CLASS TestWithDelegatingConstructor
FUN public constructor TestWithDelegatingConstructor(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int)
BLOCK_BODY
CALL .<init> 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 .<init> type=TestWithDelegatingConstructor operator=DELEGATING_CONSTRUCTOR_CALL
x: GET_VAR x type=kotlin.Int operator=null
y: CONST Int type=kotlin.Int value='0'
@@ -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<ILeft>.foo()
super<IRight>.foo()
}
override val bar: Int
get() = super<ILeft>.bar + super<IRight>.bar
}
@@ -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=<get-bar> setter=null
PROPERTY_GETTER public open fun <get-bar>(): kotlin.Int property=bar
BLOCK_BODY
RETURN type=kotlin.Nothing from=<get-bar>
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=<get-bar> setter=null
PROPERTY_GETTER public open fun <get-bar>(): kotlin.Int property=bar
BLOCK_BODY
RETURN type=kotlin.Nothing from=<get-bar>
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=<get-bar> setter=null
PROPERTY_GETTER public open override /*2*/ fun <get-bar>(): kotlin.Int property=bar
BLOCK_BODY
RETURN type=kotlin.Nothing from=<get-bar>
CALL .plus type=kotlin.Int operator=PLUS
$this: CALL .<get-bar> superQualifier=ILeft type=kotlin.Int operator=GET_PROPERTY
$this: THIS public final class CBoth : ILeft, IRight type=ILeft
other: CALL .<get-bar> superQualifier=IRight type=kotlin.Int operator=GET_PROPERTY
$this: THIS public final class CBoth : ILeft, IRight type=IRight
@@ -0,0 +1,14 @@
open class Base
class TestProperty : Base {
val x = 0
constructor()
}
class TestInitBlock : Base {
val x: Int
init {
x = 0
}
constructor()
}
@@ -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 .<init> 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 .<init> 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'
+14
View File
@@ -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
}
+25
View File
@@ -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 .<init> 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=<get-bar> setter=null
PROPERTY_GETTER public open override /*1*/ fun <get-bar>(): kotlin.String property=bar
BLOCK_BODY
RETURN type=kotlin.Nothing from=<get-bar>
CALL .<get-bar> superQualifier=Base type=kotlin.String operator=GET_PROPERTY
$this: THIS public final class Derived : Base type=Base
@@ -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
+2 -1
View File
@@ -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
@@ -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
@@ -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
+9
View File
@@ -0,0 +1,9 @@
var testSimple: Int = 0
set(value) {
field = value
}
var testAugmented: Int = 0
set(value) {
field += value
}
+17
View File
@@ -0,0 +1,17 @@
FILE /field.kt
PROPERTY public var testSimple: kotlin.Int getter=null setter=<set-testSimple>
EXPRESSION_BODY
CONST Int type=kotlin.Int value='0'
PROPERTY_SETTER public fun <set-testSimple>(/*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=<set-testAugmented>
EXPRESSION_BODY
CONST Int type=kotlin.Int value='0'
PROPERTY_SETTER public fun <set-testAugmented>(/*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
@@ -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
@@ -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=<get-p> setter=<set-p>
PROPERTY_GETTER public fun test.C?.<get-p>(): kotlin.Int property=p
BLOCK_BODY
+2 -1
View File
@@ -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
+10
View File
@@ -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
+2
View File
@@ -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
@@ -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=<get-foo> setter=null
PROPERTY_GETTER public open fun A.<get-foo>(): B property=foo
@@ -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");