From 37cce98d19776e1b5fd794db87a341e7b5c9fc59 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Mon, 15 Aug 2016 11:40:42 +0300 Subject: [PATCH] Simplify IrElement hierarchy. IrDeclaration can be now hosted under IrExpression (as IrStatement). --- .../kotlin/psi2ir/IrCallGenerator.kt | 30 ++-- .../kotlin/psi2ir/IrDeclarationFactory.kt | 30 ++-- .../kotlin/psi2ir/IrDeclarationGenerator.kt | 15 +- .../kotlin/psi2ir/IrFileGenerator.kt | 9 +- .../jetbrains/kotlin/psi2ir/IrGenerator.kt | 3 + .../kotlin/psi2ir/IrModuleGenerator.kt | 4 +- ...onGenerator.kt => IrStatementGenerator.kt} | 76 +++++---- .../src/org/jetbrains/kotlin/ir/IrElement.kt | 39 ++++- .../ir/{IrChildIndices.kt => IrSlots.kt} | 17 +- .../kotlin/ir/declarations/IrClass.kt | 39 ++++- .../ir/declarations/IrCompoundDeclaration.kt | 152 ------------------ .../kotlin/ir/declarations/IrDeclaration.kt | 18 +-- .../kotlin/ir/declarations/IrFile.kt | 42 +++-- .../kotlin/ir/declarations/IrFunction.kt | 43 +++-- .../kotlin/ir/declarations/IrModule.kt | 37 +++-- .../kotlin/ir/declarations/IrProperty.kt | 57 ++++++- .../ir/declarations/IrPropertyAccessor.kt | 8 +- .../{IrLocalVariable.kt => IrVariable.kt} | 38 ++--- .../ir/expressions/IrBlockExpression.kt | 38 ++++- .../jetbrains/kotlin/ir/expressions/IrBody.kt | 57 +++---- .../kotlin/ir/expressions/IrCallExpression.kt | 75 ++++----- .../ir/expressions/IrCompoundExpression.kt | 145 ----------------- .../ir/expressions/IrDeclarationReference.kt | 25 ++- .../ir/expressions/IrDummyExpression.kt | 2 +- .../kotlin/ir/expressions/IrExpression.kt | 34 ++-- .../ir/expressions/IrExpressionOwner.kt | 41 ----- .../ir/expressions/IrGetVariableExpression.kt | 6 +- .../IrLocalDeclarationExpression.kt | 70 -------- .../expressions/IrMemberAccessExpression.kt | 32 +++- .../kotlin/ir/expressions/IrOperator.kt | 3 +- .../ir/expressions/IrOperatorExpression.kt | 105 +++++++++++- .../expressions/IrPropertyAccessExpression.kt | 88 ++++------ .../ir/expressions/IrReturnExpression.kt | 43 ++++- .../IrStringConcatenationExpression.kt | 36 ++++- .../kotlin/ir/expressions/IrThisExpression.kt | 5 +- .../expressions/IrTypeOperatorExpression.kt | 49 +++++- .../jetbrains/kotlin/ir/util/DumpIrTree.kt | 4 +- .../kotlin/ir/util/RenderIrElement.kt | 9 +- .../kotlin/ir/visitors/IrElementVisitor.kt | 14 +- .../ir/irText/callWithReorderedArguments.txt | 16 +- compiler/testData/ir/irText/destructuring1.kt | 10 ++ .../testData/ir/irText/destructuring1.txt | 4 + compiler/testData/ir/irText/references.txt | 7 +- compiler/testData/ir/irText/smoke.kt | 4 +- .../ir/irText/smoke.testSimpleVal.txt | 3 - compiler/testData/ir/irText/smoke.txt | 4 +- .../kotlin/ir/IrTextTestCaseGenerated.java | 6 + 47 files changed, 786 insertions(+), 806 deletions(-) rename compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/{IrExpressionGenerator.kt => IrStatementGenerator.kt} (76%) rename compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/{IrChildIndices.kt => IrSlots.kt} (65%) delete mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrCompoundDeclaration.kt rename compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/{IrLocalVariable.kt => IrVariable.kt} (59%) delete mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCompoundExpression.kt delete mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpressionOwner.kt delete mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLocalDeclarationExpression.kt create mode 100644 compiler/testData/ir/irText/destructuring1.kt create mode 100644 compiler/testData/ir/irText/destructuring1.txt delete mode 100644 compiler/testData/ir/irText/smoke.testSimpleVal.txt diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrCallGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrCallGenerator.kt index 391705b8824..fbb0c3ccf71 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrCallGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrCallGenerator.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.psi2ir import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.assertCast import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.psiUtil.endOffset @@ -29,7 +30,7 @@ import java.util.* class IrCallGenerator( override val context: IrGeneratorContext, - val irExpressionGenerator: IrExpressionGenerator + val irStatementGenerator: IrStatementGenerator ) : IrGenerator { fun generateCall( ktExpression: KtExpression, @@ -92,7 +93,7 @@ class IrCallGenerator( for (index in valueArguments!!.indices) { val valueArgument = valueArguments[index] val irArgument = generateValueArgument(valueArgument) ?: continue - irCall.putValueArgument(index, irArgument) + irCall.putArgument(index, irArgument) } } } @@ -105,17 +106,16 @@ class IrCallGenerator( resultType: KotlinType ): IrExpression { val valueArgumentsInEvaluationOrder = resolvedCall.valueArguments.values - val hasResult = isUsedAsExpression(ktExpression) - val irBlock = IrBlockExpressionImpl(ktExpression.startOffset, ktExpression.endOffset, resultType, hasResult) + + val irBlock = IrBlockExpressionImpl(ktExpression.startOffset, ktExpression.endOffset, resultType, + hasResult = isUsedAsExpression(ktExpression), + isDesugared = true) val temporaryVariablesForValueArguments = HashMap>() for (valueArgument in valueArgumentsInEvaluationOrder) { val irArgument = generateValueArgument(valueArgument) ?: continue - val irTemporary = irExpressionGenerator.declarationFactory.createTemporaryVariable(irArgument) - val irTemporaryDeclaration = IrLocalVariableDeclarationExpressionImpl(irArgument.startOffset, irArgument.endOffset) - irTemporaryDeclaration.childDeclaration = irTemporary - - irBlock.addChildExpression(irTemporaryDeclaration) + val irTemporary = irStatementGenerator.declarationFactory.createTemporaryVariable(irArgument) + irBlock.addStatement(irTemporary) temporaryVariablesForValueArguments[valueArgument] = Pair(irTemporary.descriptor, irArgument) } @@ -124,16 +124,16 @@ class IrCallGenerator( val (temporaryDescriptor, irArgument) = temporaryVariablesForValueArguments[valueArgument]!! val irGetTemporary = IrGetVariableExpressionImpl(irArgument.startOffset, irArgument.endOffset, irArgument.type, temporaryDescriptor) - irCall.putValueArgument(index, irGetTemporary) + irCall.putArgument(index, irGetTemporary) } - irBlock.addChildExpression(irCall) + irBlock.addStatement(irCall) return irBlock } // TODO smart casts on implicit receivers - private fun generateReceiver(ktExpression: KtExpression, receiver: ReceiverValue?): IrExpression? = + fun generateReceiver(ktExpression: KtExpression, receiver: ReceiverValue?): IrExpression? = when (receiver) { is ImplicitClassReceiver -> IrThisExpressionImpl(ktExpression.startOffset, ktExpression.startOffset, receiver.type, receiver.classDescriptor) @@ -142,7 +142,7 @@ class IrCallGenerator( IrThisExpressionImpl(receiverExpression.startOffset, receiverExpression.endOffset, receiver.type, receiver.classDescriptor) } ?: TODO("Non-implicit ThisClassReceiver should be an expression receiver") is ExpressionReceiver -> - irExpressionGenerator.generateExpression(receiver.expression) + irStatementGenerator.generateStatement(receiver.expression).assertCast() is ClassValueReceiver -> IrGetObjectValueExpressionImpl(receiver.expression.startOffset, receiver.expression.endOffset, receiver.type, receiver.classQualifier.descriptor) @@ -155,12 +155,12 @@ class IrCallGenerator( TODO("Receiver: ${receiver.javaClass.simpleName}") } - private fun generateValueArgument(valueArgument: ResolvedValueArgument): IrExpression? { + fun generateValueArgument(valueArgument: ResolvedValueArgument): IrExpression? { when (valueArgument) { is DefaultValueArgument -> return null is ExpressionValueArgument -> - return irExpressionGenerator.generateExpression(valueArgument.valueArgument!!.getArgumentExpression()!!) + return irStatementGenerator.generateStatement(valueArgument.valueArgument!!.getArgumentExpression()!!).assertCast() is VarargValueArgument -> TODO("vararg") else -> diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrDeclarationFactory.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrDeclarationFactory.kt index a935d61bc75..06e21e51895 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrDeclarationFactory.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrDeclarationFactory.kt @@ -70,20 +70,22 @@ class IrLocalDeclarationsFactory(val scopeOwner: DeclarationDescriptor) : IrDecl fun createDescriptorForTemporaryVariable(type: KotlinType): IrTemporaryVariableDescriptor = IrTemporaryVariableDescriptorImpl(scopeOwner, Name.identifier("tmp${nextTemporaryIndex()}"), type) - fun createTemporaryVariable(ktElement: KtElement, type: KotlinType): IrLocalVariable = - IrLocalVariableImpl(ktElement.startOffset, ktElement.endOffset, - IrDeclarationOriginKind.IR_TEMPORARY_VARIABLE, - createDescriptorForTemporaryVariable(type)) + fun createTemporaryVariable(ktElement: KtElement, type: KotlinType): IrVariable = + IrVariableImpl(ktElement.startOffset, ktElement.endOffset, + IrDeclarationOriginKind.IR_TEMPORARY_VARIABLE, + createDescriptorForTemporaryVariable(type)) - fun createTemporaryVariable(irExpression: IrExpression): IrLocalVariable = - IrLocalVariableImpl(irExpression.startOffset, irExpression.endOffset, - IrDeclarationOriginKind.IR_TEMPORARY_VARIABLE, - createDescriptorForTemporaryVariable(irExpression.type - ?: throw AssertionError("No type for $irExpression")) - ).apply { initializerExpression = irExpression } + fun createTemporaryVariable(irExpression: IrExpression): IrVariable = + IrVariableImpl(irExpression.startOffset, irExpression.endOffset, + IrDeclarationOriginKind.IR_TEMPORARY_VARIABLE, + createDescriptorForTemporaryVariable( + irExpression.type + ?: throw AssertionError("No type for $irExpression") + ) + ).apply { initializer = irExpression } - fun createLocalVariable(ktElement: KtElement, descriptor: VariableDescriptor): IrLocalVariable = - IrLocalVariableImpl(ktElement.startOffset, ktElement.endOffset, - IrDeclarationOriginKind.DEFINED, - descriptor) + fun createLocalVariable(ktElement: KtElement, descriptor: VariableDescriptor): IrVariable = + IrVariableImpl(ktElement.startOffset, ktElement.endOffset, + IrDeclarationOriginKind.DEFINED, + descriptor) } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrDeclarationGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrDeclarationGenerator.kt index 5ff6ea9caf1..66c679bd1f6 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrDeclarationGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrDeclarationGenerator.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor import org.jetbrains.kotlin.descriptors.PropertySetterDescriptor +import org.jetbrains.kotlin.ir.assertCast import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrBody import org.jetbrains.kotlin.ir.expressions.IrExpressionBodyImpl @@ -33,11 +34,9 @@ interface IrDeclarationGenerator : IrGenerator abstract class IrDeclarationGeneratorBase( override val context: IrGeneratorContext, - val container: IrDeclarationOwnerN, val declarationFactory: IrDeclarationFactoryBase ) : IrDeclarationGenerator { - private fun D.register(): D = - apply { container.addChildDeclaration(this) } + protected abstract fun D.register(): D fun generateAnnotationEntries(annotationEntries: List) { // TODO create IrAnnotation's for each KtAnnotationEntry @@ -50,10 +49,10 @@ abstract class IrDeclarationGeneratorBase( generateFunctionDeclaration(ktDeclaration) is KtProperty -> generatePropertyDeclaration(ktDeclaration) - is KtClassOrObject -> - TODO("classOrObject") - is KtTypeAlias -> - TODO("typealias") + is KtClassOrObject -> {} +// TODO("classOrObject") + is KtTypeAlias -> {} +// TODO("typealias") } } @@ -90,6 +89,6 @@ abstract class IrDeclarationGeneratorBase( fun generateExpressionBody(scopeOwner: DeclarationDescriptor, ktBody: KtExpression): IrBody = IrExpressionBodyImpl(ktBody.startOffset, ktBody.endOffset).apply { - argument = IrExpressionGenerator(context, IrLocalDeclarationsFactory(scopeOwner)).generateExpression(ktBody) + expression = IrStatementGenerator(context, IrLocalDeclarationsFactory(scopeOwner)).generateStatement(ktBody).assertCast() } } \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrFileGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrFileGenerator.kt index c6b8d855ec0..e1aedf8f1c4 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrFileGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrFileGenerator.kt @@ -16,17 +16,20 @@ package org.jetbrains.kotlin.psi2ir +import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFileImpl import org.jetbrains.kotlin.psi.KtFile class IrFileGenerator( private val ktFile: KtFile, + private val irFile: IrFile, context: IrGeneratorContext, - irFile: IrFile, - parent: IrModuleGenerator, declarationFactory: IrDeclarationFactory -) : IrDeclarationGeneratorBase(context, irFile, declarationFactory) { +) : IrDeclarationGeneratorBase(context, declarationFactory) { + override fun D.register(): D = + apply { irFile.addDeclaration(this) } + fun generateFileContent() { generateAnnotationEntries(ktFile.annotationEntries) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrGenerator.kt index 7eb65917fa7..648e8e4a0bf 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrGenerator.kt @@ -37,6 +37,9 @@ fun IrGenerator.getTypeOrFail(key: KtExpression): KotlinType = fun IrGenerator.get(slice: ReadOnlySlice, key: K): V? = context.bindingContext[slice, key] +fun IrGenerator.getOrFail(slice: ReadOnlySlice, key: K): V = + context.bindingContext[slice, key] ?: throw RuntimeException("No $slice for $key") + inline fun IrGenerator.getOrFail(slice: ReadOnlySlice, key: K, message: (K) -> String): V = context.bindingContext[slice, key] ?: throw RuntimeException(message(key)) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrModuleGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrModuleGenerator.kt index d54830c8ee5..a19587a602e 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrModuleGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrModuleGenerator.kt @@ -22,14 +22,14 @@ import org.jetbrains.kotlin.resolve.BindingContext class IrModuleGenerator(override val context: IrGeneratorContext) : IrDeclarationGenerator { fun generateModuleContent() { for (ktFile in context.inputFiles) { - val packageFragmentDescriptor = getOrFail(BindingContext.FILE_TO_PACKAGE_FRAGMENT, ktFile) { "no package fragment for file" } + val packageFragmentDescriptor = getOrFail(BindingContext.FILE_TO_PACKAGE_FRAGMENT, ktFile) val fileEntry = context.sourceManager.getOrCreateFileEntry(ktFile) val fileName = fileEntry.getRecognizableName() val irFile = IrFileImpl(fileEntry, fileName, packageFragmentDescriptor) context.sourceManager.putFileEntry(irFile, fileEntry) context.irModule.addFile(irFile) val irFileElementFactory = IrDeclarationFactory() - val generator = IrFileGenerator(ktFile, context, irFile, this, irFileElementFactory) + val generator = IrFileGenerator(ktFile, irFile, context, irFileElementFactory) generator.generateFileContent() } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrStatementGenerator.kt similarity index 76% rename from compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrExpressionGenerator.kt rename to compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrStatementGenerator.kt index 320e0e75587..6191f8b81b8 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrStatementGenerator.kt @@ -20,6 +20,8 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.assertCast import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.endOffset @@ -31,55 +33,59 @@ import org.jetbrains.kotlin.resolve.constants.IntValue import org.jetbrains.kotlin.resolve.constants.StringValue import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator -class IrExpressionGenerator( +class IrStatementGenerator( override val context: IrGeneratorContext, val declarationFactory: IrLocalDeclarationsFactory -) : KtVisitor(), IrGenerator { +) : KtVisitor(), IrGenerator { private val irCallGenerator = IrCallGenerator(context, this) - fun generateExpression(ktExpression: KtExpression) = ktExpression.generate() + fun generateStatement(ktExpression: KtExpression) = ktExpression.generate() - private fun KtElement.generate(): IrExpression = + private fun KtElement.generate(): IrStatement = deparenthesize() - .accept(this@IrExpressionGenerator, null) + .accept(this@IrStatementGenerator, null) .applySmartCastIfNeeded(this) - private fun IrExpression.applySmartCastIfNeeded(ktElement: KtElement): IrExpression { - if (ktElement is KtExpression) { + private fun KtElement.generateExpression(): IrExpression = + generate().assertCast() + + private fun IrStatement.applySmartCastIfNeeded(ktElement: KtElement): IrStatement { + if (this is IrExpression && ktElement is KtExpression) { val smartCastType = get(BindingContext.SMARTCAST, ktElement) if (smartCastType != null) { return IrTypeOperatorExpressionImpl( ktElement.startOffset, ktElement.endOffset, smartCastType, - IrTypeOperator.SMART_AS, smartCastType - ).apply { argument = this@applySmartCastIfNeeded } + IrTypeOperator.SMART_AS, this@applySmartCastIfNeeded, smartCastType + ) } } return this } - override fun visitExpression(expression: KtExpression, data: Nothing?): IrExpression = - IrDummyExpression(expression.startOffset, expression.endOffset, getTypeOrFail(expression), expression.javaClass.simpleName) + override fun visitExpression(expression: KtExpression, data: Nothing?): IrStatement = + IrDummyExpression(expression.startOffset, expression.endOffset, getType(expression), expression.javaClass.simpleName) - override fun visitProperty(property: KtProperty, data: Nothing?): IrExpression { + override fun visitProperty(property: KtProperty, data: Nothing?): IrStatement { if (property.delegateExpression != null) TODO("Local delegated property") - val variableDescriptor = getOrFail(BindingContext.VARIABLE, property) { "No descriptor for local variable ${property.name}" } + val variableDescriptor = getOrFail(BindingContext.VARIABLE, property) val irLocalVariable = declarationFactory.createLocalVariable(property, variableDescriptor) - irLocalVariable.initializerExpression = property.initializer?.generate() + irLocalVariable.initializer = property.initializer?.generateExpression() - return IrLocalVariableDeclarationExpressionImpl(property.startOffset, property.endOffset, irLocalVariable) + return irLocalVariable } - override fun visitBlockExpression(expression: KtBlockExpression, data: Nothing?): IrExpression { - val irBlock = IrBlockExpressionImpl(expression.startOffset, expression.endOffset, getTypeOrFail(expression), false) - expression.statements.forEach { irBlock.addChildExpression(it.generate()) } + override fun visitBlockExpression(expression: KtBlockExpression, data: Nothing?): IrStatement { + val irBlock = IrBlockExpressionImpl(expression.startOffset, expression.endOffset, getType(expression), + hasResult = isUsedAsExpression(expression), isDesugared = false) + expression.statements.forEach { irBlock.addStatement(it.generate()) } return irBlock } - override fun visitReturnExpression(expression: KtReturnExpression, data: Nothing?): IrExpression = - IrReturnExpressionImpl(expression.startOffset, expression.endOffset, getTypeOrFail(expression)) - .apply { this.argument = expression.returnedExpression?.generate() } + override fun visitReturnExpression(expression: KtReturnExpression, data: Nothing?): IrStatement = + IrReturnExpressionImpl(expression.startOffset, expression.endOffset, getType(expression), + expression.returnedExpression?.generateExpression()) override fun visitConstantExpression(expression: KtConstantExpression, data: Nothing?): IrExpression { val compileTimeConstant = ConstantExpressionEvaluator.getConstant(expression, context.bindingContext) @@ -97,17 +103,17 @@ class IrExpressionGenerator( } } - override fun visitStringTemplateExpression(expression: KtStringTemplateExpression, data: Nothing?): IrExpression { + override fun visitStringTemplateExpression(expression: KtStringTemplateExpression, data: Nothing?): IrStatement { if (expression.entries.size == 1 && expression.entries[0] is KtLiteralStringTemplateEntry) { return expression.entries[0].generate() } - val irStringTemplate = IrStringConcatenationExpressionImpl(expression.startOffset, expression.endOffset, getTypeOrFail(expression)) - expression.entries.forEach { irStringTemplate.addChildExpression(it.generate()) } + val irStringTemplate = IrStringConcatenationExpressionImpl(expression.startOffset, expression.endOffset, getType(expression)) + expression.entries.forEach { irStringTemplate.addArgument(it.generateExpression()) } return irStringTemplate } - override fun visitLiteralStringTemplateEntry(entry: KtLiteralStringTemplateEntry, data: Nothing?): IrExpression = + override fun visitLiteralStringTemplateEntry(entry: KtLiteralStringTemplateEntry, data: Nothing?): IrStatement = IrLiteralExpressionImpl.string(entry.startOffset, entry.endOffset, context.builtIns.stringType, entry.text) override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, data: Nothing?): IrExpression { @@ -122,25 +128,25 @@ class IrExpressionGenerator( return when (descriptor) { is ClassDescriptor -> if (DescriptorUtils.isObject(descriptor)) - IrGetObjectValueExpressionImpl(expression.startOffset, expression.endOffset, getTypeOrFail(expression), descriptor) + IrGetObjectValueExpressionImpl(expression.startOffset, expression.endOffset, getType(expression), descriptor) else if (DescriptorUtils.isEnumEntry(descriptor)) - IrGetEnumValueExpressionImpl(expression.startOffset, expression.endOffset, getTypeOrFail(expression), descriptor) + IrGetEnumValueExpressionImpl(expression.startOffset, expression.endOffset, getType(expression), descriptor) else - IrGetObjectValueExpressionImpl(expression.startOffset, expression.endOffset, getTypeOrFail(expression), + IrGetObjectValueExpressionImpl(expression.startOffset, expression.endOffset, getType(expression), descriptor.companionObjectDescriptor ?: error("Class value without companion object: $descriptor")) is PropertyDescriptor -> { irCallGenerator.generateCall(expression, resolvedCall) } is VariableDescriptor -> - IrGetVariableExpressionImpl(expression.startOffset, expression.endOffset, getTypeOrFail(expression), descriptor) + IrGetVariableExpressionImpl(expression.startOffset, expression.endOffset, getType(expression), descriptor) else -> - IrDummyExpression(expression.startOffset, expression.endOffset, getTypeOrFail(expression), + IrDummyExpression(expression.startOffset, expression.endOffset, getType(expression), expression.getReferencedName() + ": ${descriptor?.name} ${descriptor?.javaClass?.simpleName}") } } - override fun visitCallExpression(expression: KtCallExpression, data: Nothing?): IrExpression { + override fun visitCallExpression(expression: KtCallExpression, data: Nothing?): IrStatement { val resolvedCall = getResolvedCall(expression) ?: TODO("No resolved call for call expression") if (resolvedCall is VariableAsFunctionResolvedCall) { @@ -150,20 +156,20 @@ class IrExpressionGenerator( return irCallGenerator.generateCall(expression, resolvedCall) } - override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression, data: Nothing?): IrExpression = + override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression, data: Nothing?): IrStatement = expression.selectorExpression!!.accept(this, data) - override fun visitSafeQualifiedExpression(expression: KtSafeQualifiedExpression, data: Nothing?): IrExpression = + override fun visitSafeQualifiedExpression(expression: KtSafeQualifiedExpression, data: Nothing?): IrStatement = expression.selectorExpression!!.accept(this, data) override fun visitThisExpression(expression: KtThisExpression, data: Nothing?): IrExpression { val referenceTarget = getOrFail(BindingContext.REFERENCE_TARGET, expression.instanceReference) { "No reference target for this" } return when (referenceTarget) { is ClassDescriptor -> - IrThisExpressionImpl(expression.startOffset, expression.endOffset, getTypeOrFail(expression), referenceTarget) + IrThisExpressionImpl(expression.startOffset, expression.endOffset, getType(expression), referenceTarget) is CallableDescriptor -> IrGetExtensionReceiverExpressionImpl( - expression.startOffset, expression.endOffset, getTypeOrFail(expression), + expression.startOffset, expression.endOffset, getType(expression), referenceTarget.extensionReceiverParameter!! ) else -> diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrElement.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrElement.kt index f4a69ced2fa..a1fa5828272 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrElement.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrElement.kt @@ -21,10 +21,47 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor interface IrElement { val startOffset: Int val endOffset: Int + val parent: IrElement? + val slot: Int + fun setTreeLocation(newParent: IrElement?, newSlot: Int) + fun getChild(slot: Int): IrElement? + fun replaceChild(slot: Int, newChild: IrElement) fun accept(visitor: IrElementVisitor, data: D): R fun acceptChildren(visitor: IrElementVisitor, data: D): Unit } -abstract class IrElementBase(override val startOffset: Int, override val endOffset: Int) : IrElement +interface IrStatement : IrElement + +abstract class IrElementBase(override val startOffset: Int, override val endOffset: Int) : IrElement { + override var parent: IrElement? = null + override var slot: Int = DETACHED_SLOT + + override fun setTreeLocation(newParent: IrElement?, newSlot: Int) { + parent = newParent + slot = newSlot + } +} + +fun IrElement?.detach() { + this?.setTreeLocation(null, DETACHED_SLOT) +} + +fun IrElement.replaceWith(otherElement: IrElement) { + parent?.replaceChild(slot, otherElement) +} + +fun IrElement.assertChild(child: IrElement) { + assert(getChild(child.slot) == child) { "$this: Invalid child: $child" } +} + +fun IrElement.assertDetached() { + assert(parent == null && slot == DETACHED_SLOT) { "$this: should be detached" } +} + +fun IrElement.throwNoSuchSlot(slot: Int): Nothing = + throw AssertionError("$this: no such slot $slot") + +inline fun IrElement.assertCast(): T = + if (this is T) this else throw AssertionError("Expected ${T::class.simpleName}: $this") \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrChildIndices.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrSlots.kt similarity index 65% rename from compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrChildIndices.kt rename to compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrSlots.kt index e4f1cb8039e..0917f8d6acf 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrChildIndices.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrSlots.kt @@ -16,10 +16,13 @@ package org.jetbrains.kotlin.ir -const val CHILD_DECLARATION_INDEX = 0 -const val DETACHED_INDEX = Int.MIN_VALUE -const val CHILD_EXPRESSION_INDEX = 0 -const val ARGUMENT0_INDEX = 0 -const val ARGUMENT1_INDEX = 1 -const val DISPATCH_RECEIVER_INDEX = -1 -const val EXTENSION_RECEIVER_INDEX = -2 +const val CHILD_DECLARATION_SLOT = 0 +const val DETACHED_SLOT = Int.MIN_VALUE +const val CHILD_EXPRESSION_SLOT = 0 +const val ARGUMENT0_SLOT = 0 +const val ARGUMENT1_SLOT = 1 +const val DISPATCH_RECEIVER_SLOT = -1 +const val EXTENSION_RECEIVER_SLOT = -2 +const val FUNCTION_BODY_SLOT = 0 +const val MODULE_SLOT = 0 +const val INITIALIZER_SLOT = 0 \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrClass.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrClass.kt index 918383857f7..c39c74bdb0e 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrClass.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrClass.kt @@ -17,13 +17,21 @@ package org.jetbrains.kotlin.ir.declarations import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import java.util.* + +interface IrClassElement : IrElement + +interface IrClass : IrDeclaration { + override val declarationKind: IrDeclarationKind + get() = IrDeclarationKind.CLASS -interface IrClass : IrCompoundDeclaration, IrMemberDeclaration { override val descriptor: ClassDescriptor - override val declarationKind: IrDeclarationKind - get() = IrDeclarationKind.MODULE + val children: List + + fun addChild(child: IrClassElement) } class IrClassImpl( @@ -31,7 +39,30 @@ class IrClassImpl( endOffset: Int, originKind: IrDeclarationOriginKind, override val descriptor: ClassDescriptor -) : IrCompoundMemberDeclarationBase(startOffset, endOffset, originKind), IrClass { +) : IrDeclarationBase(startOffset, endOffset, originKind), IrClass { + override val children: MutableList = ArrayList() + + override fun addChild(child: IrClassElement) { + child.assertDetached() + child.setTreeLocation(this, children.size) + children.add(child) + } + + override fun getChild(slot: Int): IrElement? = + children.getOrNull(slot) + + override fun replaceChild(slot: Int, newChild: IrElement) { + newChild.assertDetached() + children.getOrNull(slot)?.detach() ?: throwNoSuchSlot(slot) + children[slot] = newChild.assertCast() + newChild.setTreeLocation(this, slot) + } + override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitClass(this, data) + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + children.forEach { it.accept(visitor, data) } + } + } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrCompoundDeclaration.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrCompoundDeclaration.kt deleted file mode 100644 index c54a6f4516e..00000000000 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrCompoundDeclaration.kt +++ /dev/null @@ -1,152 +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.ir.declarations - -import org.jetbrains.kotlin.ir.CHILD_DECLARATION_INDEX -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.IrElementBase -import org.jetbrains.kotlin.ir.DETACHED_INDEX -import org.jetbrains.kotlin.ir.visitors.IrElementVisitor -import java.util.* - -interface IrDeclarationOwner : IrElement { - fun getChildDeclaration(index: Int): IrMemberDeclaration? - fun replaceChildDeclaration(oldChild: IrMemberDeclaration, newChild: IrMemberDeclaration) -} - -interface IrDeclarationOwner1 : IrDeclarationOwner { - val childDeclaration: IrMemberDeclaration -} - -interface IrDeclarationOwnerN : IrDeclarationOwner { - val childrenCount: Int - fun addChildDeclaration(child: IrMemberDeclaration) - fun removeChildDeclaration(child: IrMemberDeclaration) - fun removeAllChildDeclarations() - - fun acceptChildDeclarations(visitor: IrElementVisitor, data: D) -} - -interface IrCompoundDeclaration : IrDeclaration, IrDeclarationOwnerN - -interface IrMemberDeclaration : IrDeclaration { - override var parent: IrDeclarationOwner? - - fun setTreeLocation(parent: IrDeclarationOwner?, index: Int) -} - -abstract class IrDeclarationOwnerNBase( - startOffset: Int, - endOffset: Int -) : IrElementBase(startOffset, endOffset), IrDeclarationOwnerN { - protected val childDeclarations: MutableList = ArrayList() - - override val childrenCount: Int - get() = childDeclarations.size - - override fun getChildDeclaration(index: Int): IrMemberDeclaration? = - childDeclarations.getOrNull(index) - - override fun addChildDeclaration(child: IrMemberDeclaration) { - child.setTreeLocation(this, childDeclarations.size) - childDeclarations.add(child) - } - - override fun removeChildDeclaration(child: IrMemberDeclaration) { - validateChild(child) - childDeclarations.removeAt(child.indexInParent) - for (i in child.indexInParent..childDeclarations.size - 1) { - childDeclarations[i].setTreeLocation(this, i) - } - child.detach() - } - - override fun removeAllChildDeclarations() { - childDeclarations.forEach { it.detach() } - childDeclarations.clear() - } - - override fun replaceChildDeclaration(oldChild: IrMemberDeclaration, newChild: IrMemberDeclaration) { - validateChild(oldChild) - childDeclarations[oldChild.indexInParent] = newChild - newChild.setTreeLocation(this, oldChild.indexInParent) - oldChild.detach() - } - - override fun acceptChildDeclarations(visitor: IrElementVisitor, data: D) { - childDeclarations.forEach { it.accept(visitor, data) } - } -} - -// TODO synchronization? -abstract class IrCompoundDeclarationBase( - startOffset: Int, - endOffset: Int, - override val originKind: IrDeclarationOriginKind -) : IrDeclarationOwnerNBase(startOffset, endOffset), IrCompoundDeclaration { - override var indexInParent: Int = IrDeclaration.DETACHED_INDEX - - override fun acceptChildren(visitor: IrElementVisitor, data: D) { - acceptChildDeclarations(visitor, data) - } -} - -abstract class IrCompoundMemberDeclarationBase( - startOffset: Int, - endOffset: Int, - originKind: IrDeclarationOriginKind -) : IrCompoundDeclarationBase(startOffset, endOffset, originKind), IrMemberDeclaration { - private var parentImpl: IrDeclarationOwner? = null - - override var parent: IrDeclarationOwner? - get() = parentImpl!! - set(newParent) { - parentImpl = newParent - } - - override fun setTreeLocation(parent: IrDeclarationOwner?, index: Int) { - this.parentImpl = parent - this.indexInParent = index - } -} - -abstract class IrMemberDeclarationBase( - startOffset: Int, - endOffset: Int, - originKind: IrDeclarationOriginKind -) : IrDeclarationBase(startOffset, endOffset, originKind), IrMemberDeclaration { - private var parentImpl: IrDeclarationOwner? = null - - override var parent: IrDeclarationOwner? - get() = parentImpl!! - set(newParent) { - parentImpl = newParent - } - - override fun setTreeLocation(parent: IrDeclarationOwner?, index: Int) { - this.parentImpl = parent - this.indexInParent = index - } -} - -fun IrMemberDeclaration.detach() { - setTreeLocation(null, IrDeclaration.DETACHED_INDEX) -} - -fun IrDeclarationOwner.validateChild(child: IrMemberDeclaration) { - assert(child.parent == this && getChildDeclaration(child.indexInParent) == child) { "Invalid child: $child" } -} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclaration.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclaration.kt index a0eebb65a35..1a2121cb66e 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclaration.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclaration.kt @@ -17,21 +17,13 @@ package org.jetbrains.kotlin.ir.declarations import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElementBase +import org.jetbrains.kotlin.ir.IrStatement -interface IrDeclaration : IrElement { - override val parent: IrDeclarationOwner? - val indexInParent: Int - +interface IrDeclaration : IrStatement, IrClassElement { val descriptor: DeclarationDescriptor? - val declarationKind: IrDeclarationKind val originKind: IrDeclarationOriginKind - - companion object { - const val DETACHED_INDEX = Int.MIN_VALUE - } } enum class IrDeclarationKind { @@ -41,7 +33,7 @@ enum class IrDeclarationKind { PROPERTY_GETTER, PROPERTY_SETTER, PROPERTY, - LOCAL_VARIABLE, + VARIABLE, CLASS } @@ -54,6 +46,4 @@ abstract class IrDeclarationBase( startOffset: Int, endOffset: Int, override val originKind: IrDeclarationOriginKind -) : IrElementBase(startOffset, endOffset), IrDeclaration { - override var indexInParent: Int = IrDeclaration.DETACHED_INDEX -} +) : IrElementBase(startOffset, endOffset), IrDeclaration diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrFile.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrFile.kt index d05640faa8c..26f4819c4cc 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrFile.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrFile.kt @@ -17,28 +17,48 @@ package org.jetbrains.kotlin.ir.declarations import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor -import org.jetbrains.kotlin.ir.SourceLocationManager +import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import java.util.* -interface IrFile : IrCompoundDeclaration { +interface IrFile : IrElement { val name: String val fileEntry: SourceLocationManager.FileEntry - val module: IrModule - override val descriptor: PackageFragmentDescriptor + val packageFragmentDescriptor: PackageFragmentDescriptor + val declarations: List - override val parent: Nothing? get() = null - - override val declarationKind: IrDeclarationKind - get() = IrDeclarationKind.FILE + fun addDeclaration(declaration: IrDeclaration) } class IrFileImpl( override val fileEntry: SourceLocationManager.FileEntry, override val name: String, - override val descriptor: PackageFragmentDescriptor -) : IrCompoundDeclarationBase(0, fileEntry.maxOffset, IrDeclarationOriginKind.DEFINED), IrFile { - override lateinit var module: IrModule + override val packageFragmentDescriptor: PackageFragmentDescriptor +) : IrElementBase(0, fileEntry.maxOffset), IrFile { + override val declarations: MutableList = ArrayList() + + override fun addDeclaration(declaration: IrDeclaration) { + declaration.assertDetached() + declaration.setTreeLocation(this, declarations.size) + declarations.add(declaration) + } + + override fun getChild(slot: Int): IrElement? = + declarations.getOrNull(slot) + + override fun replaceChild(slot: Int, newChild: IrElement) { + newChild.assertDetached() + declarations.getOrNull(slot)?.detach() ?: throwNoSuchSlot(slot) + declarations[slot] = newChild.assertCast() + newChild.setTreeLocation(this, slot) + } override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitFile(this, data) + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + declarations.forEach { it.accept(visitor, data) } + } + + } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrFunction.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrFunction.kt index 29062c9ae5e..b688d0e2954 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrFunction.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrFunction.kt @@ -17,10 +17,11 @@ package org.jetbrains.kotlin.ir.declarations import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.expressions.IrBody import org.jetbrains.kotlin.ir.visitors.IrElementVisitor -interface IrFunction : IrMemberDeclaration { +interface IrFunction : IrDeclaration { override val descriptor: FunctionDescriptor val body: IrBody @@ -31,8 +32,36 @@ interface IrFunction : IrMemberDeclaration { abstract class IrFunctionBase( startOffset: Int, endOffset: Int, - originKind: IrDeclarationOriginKind -) : IrMemberDeclarationBase(startOffset, endOffset, originKind), IrFunction { + originKind: IrDeclarationOriginKind, + body: IrBody? = null +) : IrDeclarationBase(startOffset, endOffset, originKind), IrFunction { + init { + body?.setTreeLocation(this, FUNCTION_BODY_SLOT) + } + + private var bodyImpl: IrBody? = body + override var body: IrBody + get() = bodyImpl!! + set(newValue) { + newValue.assertDetached() + bodyImpl?.detach() + bodyImpl = newValue + newValue.setTreeLocation(this, FUNCTION_BODY_SLOT) + } + + override fun getChild(slot: Int): IrElement? = + when (slot) { + FUNCTION_BODY_SLOT -> body + else -> null + } + + override fun replaceChild(slot: Int, newChild: IrElement) { + when (slot) { + FUNCTION_BODY_SLOT -> body = newChild.assertCast() + else -> throwNoSuchSlot(slot) + } + } + override fun acceptChildren(visitor: IrElementVisitor, data: D) { body.accept(visitor, data) } @@ -43,12 +72,8 @@ class IrFunctionImpl( endOffset: Int, originKind: IrDeclarationOriginKind, override val descriptor: FunctionDescriptor, - override val body: IrBody -) : IrFunctionBase(startOffset, endOffset, originKind) { - init { - body.parent = this - } - + body: IrBody +) : IrFunctionBase(startOffset, endOffset, originKind, body) { override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitFunction(this, data) } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrModule.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrModule.kt index f15befdcc89..e34ef4a93b3 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrModule.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrModule.kt @@ -17,41 +17,44 @@ package org.jetbrains.kotlin.ir.declarations import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import java.util.* -interface IrModule : IrDeclaration { - override val descriptor: ModuleDescriptor - +interface IrModule : IrElement { override val startOffset: Int get() = UNDEFINED_OFFSET override val endOffset: Int get() = UNDEFINED_OFFSET - override val parent: Nothing? get() = null - override val indexInParent: Int get() = MODULE_INDEX + override val parent: IrElement? get() = null + override val slot: Int get() = MODULE_SLOT + override fun setTreeLocation(newParent: IrElement?, newSlot: Int) { + throw AssertionError("IrModule can't have a parent element") + } - override val declarationKind: IrDeclarationKind - get() = IrDeclarationKind.MODULE + val descriptor: ModuleDescriptor val files: List - companion object { - const val MODULE_INDEX = -1 - } + fun addFile(file: IrFile) } class IrModuleImpl( override val descriptor: ModuleDescriptor ) : IrModule { - - override val originKind: IrDeclarationOriginKind - get() = IrDeclarationOriginKind.DEFINED - override val files: MutableList = ArrayList() - fun addFile(file: IrFileImpl) { + override fun addFile(file: IrFile) { + file.assertDetached() + file.setTreeLocation(this, files.size) files.add(file) - file.module = this + } + + override fun getChild(slot: Int): IrElement? = + files.getOrNull(slot) + + override fun replaceChild(slot: Int, newChild: IrElement) { + newChild.assertDetached() + files.getOrNull(slot)?.detach() ?: throwNoSuchSlot(slot) } override fun accept(visitor: IrElementVisitor, data: D): R = diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrProperty.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrProperty.kt index cb80eb900cb..a9ba7c09679 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrProperty.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrProperty.kt @@ -17,10 +17,11 @@ package org.jetbrains.kotlin.ir.declarations import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.expressions.IrBody import org.jetbrains.kotlin.ir.visitors.IrElementVisitor -interface IrProperty : IrMemberDeclaration { +interface IrProperty : IrDeclaration { override val descriptor: PropertyDescriptor var getter: IrPropertyGetter? var setter: IrPropertySetter? @@ -32,11 +33,11 @@ interface IrProperty : IrMemberDeclaration { } interface IrSimpleProperty : IrProperty { - val valueInitializer: IrBody? + var valueInitializer: IrBody? } interface IrDelegatedProperty : IrProperty { - val delegateInitializer: IrBody + var delegateInitializer: IrBody } // TODO synchronization? @@ -45,15 +46,17 @@ abstract class IrPropertyBase( endOffset: Int, originKind: IrDeclarationOriginKind, override val descriptor: PropertyDescriptor -) : IrMemberDeclarationBase(startOffset, endOffset, originKind), IrProperty { +) : IrDeclarationBase(startOffset, endOffset, originKind), IrProperty { override var getter: IrPropertyGetter? = null set(newGetter) { + newGetter?.run { assert(property == null) { "$newGetter: should not have a property" } } newGetter?.property = this field = newGetter } override var setter: IrPropertySetter? = null set(newSetter) { + newSetter?.run { assert(property == null) { "$newSetter: should not have a property" } } newSetter?.property = this field = newSetter } @@ -69,10 +72,27 @@ class IrSimplePropertyImpl( endOffset: Int, originKind: IrDeclarationOriginKind, descriptor: PropertyDescriptor, - override val valueInitializer: IrBody? + valueInitializer: IrBody? = null ) : IrPropertyBase(startOffset, endOffset, originKind, descriptor), IrSimpleProperty { - init { - valueInitializer?.parent = this + override var valueInitializer: IrBody? = valueInitializer + set(value) { + value?.assertDetached() + field?.detach() + field = value + value?.setTreeLocation(this, INITIALIZER_SLOT) + } + + override fun getChild(slot: Int): IrElement? = + when (slot) { + INITIALIZER_SLOT -> valueInitializer + else -> null + } + + override fun replaceChild(slot: Int, newChild: IrElement) { + when (slot) { + INITIALIZER_SLOT -> valueInitializer = newChild.assertCast() + else -> throwNoSuchSlot(slot) + } } override fun accept(visitor: IrElementVisitor, data: D): R = @@ -88,8 +108,29 @@ class IrDelegatedPropertyImpl( endOffset: Int, originKind: IrDeclarationOriginKind, descriptor: PropertyDescriptor, - override val delegateInitializer: IrBody + delegateInitializer: IrBody ) : IrPropertyBase(startOffset, endOffset, originKind, descriptor), IrDelegatedProperty { + override var delegateInitializer: IrBody = delegateInitializer + set(value) { + value.assertDetached() + field.detach() + field = value + value.setTreeLocation(this, INITIALIZER_SLOT) + } + + override fun getChild(slot: Int): IrElement? = + when (slot) { + INITIALIZER_SLOT -> delegateInitializer + else -> null + } + + override fun replaceChild(slot: Int, newChild: IrElement) { + when (slot) { + INITIALIZER_SLOT -> delegateInitializer = newChild.assertCast() + else -> throwNoSuchSlot(slot) + } + } + override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitDelegatedProperty(this, data) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrPropertyAccessor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrPropertyAccessor.kt index ac02c6dc771..9bff67ac239 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrPropertyAccessor.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrPropertyAccessor.kt @@ -45,12 +45,8 @@ abstract class IrPropertyAccessorBase( startOffset: Int, endOffset: Int, originKind: IrDeclarationOriginKind, - override val body: IrBody -) : IrFunctionBase(startOffset, endOffset, originKind), IrPropertyAccessor { - init { - body.parent = this - } - + body: IrBody +) : IrFunctionBase(startOffset, endOffset, originKind, body), IrPropertyAccessor { override var property: IrProperty? = null } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrLocalVariable.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrVariable.kt similarity index 59% rename from compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrLocalVariable.kt rename to compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrVariable.kt index 19979929b61..51e71e931d1 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrLocalVariable.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrVariable.kt @@ -17,38 +17,44 @@ package org.jetbrains.kotlin.ir.declarations import org.jetbrains.kotlin.descriptors.VariableDescriptor -import org.jetbrains.kotlin.ir.CHILD_EXPRESSION_INDEX +import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor -interface IrLocalVariable : IrMemberDeclaration, IrExpressionOwner { +interface IrVariable : IrDeclaration { override val descriptor: VariableDescriptor override val declarationKind: IrDeclarationKind - get() = IrDeclarationKind.LOCAL_VARIABLE + get() = IrDeclarationKind.VARIABLE - var initializerExpression: IrExpression? + var initializer: IrExpression? } -class IrLocalVariableImpl( +class IrVariableImpl( startOffset: Int, endOffset: Int, originKind: IrDeclarationOriginKind, override val descriptor: VariableDescriptor -) : IrMemberDeclarationBase(startOffset, endOffset, originKind), IrLocalVariable { - override var initializerExpression: IrExpression? = null +) : IrDeclarationBase(startOffset, endOffset, originKind), IrVariable { + override var initializer: IrExpression? = null set(value) { + value?.assertDetached() field?.detach() field = value - value?.setTreeLocation(this, CHILD_EXPRESSION_INDEX) + value?.setTreeLocation(this, INITIALIZER_SLOT) } - override fun getChildExpression(index: Int): IrExpression? = - if (index == CHILD_EXPRESSION_INDEX) initializerExpression else null + override fun getChild(slot: Int): IrElement? = + when (slot) { + INITIALIZER_SLOT -> initializer + else -> null + } - override fun replaceChildExpression(oldChild: IrExpression, newChild: IrExpression) { - validateChild(oldChild) - initializerExpression = newChild + override fun replaceChild(slot: Int, newChild: IrElement) { + when (slot) { + INITIALIZER_SLOT -> initializer = newChild.assertCast() + else -> throwNoSuchSlot(slot) + } } override fun accept(visitor: IrElementVisitor, data: D): R { @@ -56,10 +62,6 @@ class IrLocalVariableImpl( } override fun acceptChildren(visitor: IrElementVisitor, data: D) { - acceptChildExpressions(visitor, data) - } - - override fun acceptChildExpressions(visitor: IrElementVisitor, data: D) { - initializerExpression?.accept(visitor, data) + initializer?.accept(visitor, data) } } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBlockExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBlockExpression.kt index cbc741f7fb9..5180aa236f3 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBlockExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBlockExpression.kt @@ -16,27 +16,51 @@ package org.jetbrains.kotlin.ir.expressions +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.assertCast +import org.jetbrains.kotlin.ir.assertDetached import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType +import java.util.* -interface IrBlockExpression : IrCompoundExpressionN { +interface IrBlockExpression : IrExpression { val hasResult: Boolean -} + val isDesugared: Boolean -fun IrBlockExpression.getResultExpression() = - if (hasResult) childExpressions.lastOrNull() else null + val statements: List + fun addStatement(statement: IrStatement) +} class IrBlockExpressionImpl( startOffset: Int, endOffset: Int, type: KotlinType?, - override val hasResult: Boolean -) : IrCompoundExpressionNBase(startOffset, endOffset, type), IrBlockExpression { + override val hasResult: Boolean, + override val isDesugared: Boolean +) : IrExpressionBase(startOffset, endOffset, type), IrBlockExpression { + override val statements: MutableList = ArrayList() + + override fun addStatement(statement: IrStatement) { + statement.assertDetached() + statement.setTreeLocation(this, statements.size) + statements.add(statement) + } + + override fun getChild(slot: Int): IrElement? = + statements.getOrNull(slot) + + override fun replaceChild(slot: Int, newChild: IrElement) { + if (0 <= slot && slot < statements.size) { + statements[slot] = newChild.assertCast() + } + } + override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitBlockExpression(this, data) override fun acceptChildren(visitor: IrElementVisitor, data: D) { - childExpressions.forEach { it.accept(visitor, data) } + statements.forEach { it.accept(visitor, data) } } } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBody.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBody.kt index 5ce52b41975..d5c7ecbf679 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBody.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBody.kt @@ -16,50 +16,53 @@ package org.jetbrains.kotlin.ir.expressions -import org.jetbrains.kotlin.ir.CHILD_EXPRESSION_INDEX -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.IrElementBase -import org.jetbrains.kotlin.ir.declarations.IrDeclaration -import org.jetbrains.kotlin.ir.declarations.IrDeclarationOwner -import org.jetbrains.kotlin.ir.declarations.IrDeclarationOwnerNBase +import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor -interface IrBody : IrElement { - override var parent: IrDeclaration +interface IrBody : IrElement + +interface IrExpressionBody : IrBody { + var expression: IrExpression } -interface IrExpressionBody : IrBody, IrExpressionOwner1 - -// TODO IrExpressionBodyImpl vs IrCompoundExpression1Impl: extract common base class? class IrExpressionBodyImpl( startOffset: Int, endOffset: Int ) : IrElementBase(startOffset, endOffset), IrExpressionBody { - override lateinit var parent: IrDeclaration + constructor( + startOffset: Int, + endOffset: Int, + expression: IrExpression + ) : this(startOffset, endOffset) { + this.expression = expression + } - override var argument: IrExpression? = null - set(newExpression) { - field?.detach() - field = newExpression - newExpression?.setTreeLocation(this, CHILD_EXPRESSION_INDEX) + private var expressionImpl: IrExpression? = null + override var expression: IrExpression + get() = expressionImpl!! + set(newValue) { + newValue.assertDetached() + expressionImpl?.detach() + expressionImpl = newValue + newValue.setTreeLocation(this, CHILD_EXPRESSION_SLOT) } - override fun getChildExpression(index: Int): IrExpression? = - if (index == CHILD_EXPRESSION_INDEX) argument else null + override fun getChild(slot: Int): IrElement? = + when (slot) { + CHILD_EXPRESSION_SLOT -> expression + else -> null + } - override fun replaceChildExpression(oldChild: IrExpression, newChild: IrExpression) { - validateChild(oldChild) - argument = newChild + override fun replaceChild(slot: Int, newChild: IrElement) { + when (slot) { + CHILD_EXPRESSION_SLOT -> expression = newChild.assertCast() + } } override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitExpressionBody(this, data) override fun acceptChildren(visitor: IrElementVisitor, data: D) { - acceptChildExpressions(visitor, data) - } - - override fun acceptChildExpressions(visitor: IrElementVisitor, data: D) { - argument?.accept(visitor, data) + expression.accept(visitor, data) } } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallExpression.kt index d6aa0a07765..38f524e74a8 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallExpression.kt @@ -18,21 +18,18 @@ package org.jetbrains.kotlin.ir.expressions import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.ir.DISPATCH_RECEIVER_INDEX -import org.jetbrains.kotlin.ir.EXTENSION_RECEIVER_INDEX +import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType -interface IrCallExpression : IrMemberAccessExpression, IrCompoundExpression { +interface IrCallExpression : IrMemberAccessExpression { val superQualifier: ClassDescriptor? val operator: IrOperator? override val descriptor: CallableDescriptor - fun getValueArgument(index: Int): IrExpression? - fun putValueArgument(index: Int, valueArgument: IrExpression?) - fun removeValueArgument(index: Int) - - fun acceptValueArguments(visitor: IrElementVisitor, data: D) + fun getArgument(index: Int): IrExpression? + fun putArgument(index: Int, valueArgument: IrExpression?) + fun removeArgument(index: Int) } class IrCallExpressionImpl( @@ -42,63 +39,45 @@ class IrCallExpressionImpl( override val descriptor: CallableDescriptor, isSafe: Boolean, override val operator: IrOperator?, - override val superQualifier: ClassDescriptor? + override val superQualifier: ClassDescriptor? = null ) : IrMemberAccessExpressionBase(startOffset, endOffset, type, isSafe), IrCallExpression { private val argumentsByParameterIndex = - kotlin.arrayOfNulls(descriptor.valueParameters.size) + arrayOfNulls(descriptor.valueParameters.size) - override fun getValueArgument(index: Int): IrExpression? = + override fun getArgument(index: Int): IrExpression? = argumentsByParameterIndex[index] - override fun putValueArgument(index: Int, valueArgument: IrExpression?) { + override fun putArgument(index: Int, valueArgument: IrExpression?) { + if (index >= argumentsByParameterIndex.size) throw AssertionError("$this: No such argument slot: $index") + valueArgument?.assertDetached() argumentsByParameterIndex[index]?.detach() argumentsByParameterIndex[index] = valueArgument valueArgument?.setTreeLocation(this, index) } - override fun removeValueArgument(index: Int) { + override fun removeArgument(index: Int) { argumentsByParameterIndex[index]?.detach() argumentsByParameterIndex[index] = null } - override fun getChildExpression(index: Int): IrExpression? = - when (index) { - DISPATCH_RECEIVER_INDEX -> - dispatchReceiver - EXTENSION_RECEIVER_INDEX -> - extensionReceiver - else -> - argumentsByParameterIndex.getOrNull(index) - } + override fun getChild(slot: Int): IrElement? = + if (0 <= slot) + argumentsByParameterIndex.getOrNull(slot) + else + super.getChild(slot) - override fun replaceChildExpression(oldChild: IrExpression, newChild: IrExpression) { - validateChild(oldChild) - when (oldChild.index) { - DISPATCH_RECEIVER_INDEX -> - dispatchReceiver = newChild - EXTENSION_RECEIVER_INDEX -> - extensionReceiver = newChild - else -> - putValueArgument(oldChild.index, newChild) - } - } - - override fun acceptValueArguments(visitor: IrElementVisitor, data: D) { - for (valueArgument in argumentsByParameterIndex) { - valueArgument?.let { it.accept(visitor, data) } - } - } - - override fun acceptChildExpressions(visitor: IrElementVisitor, data: D) { - dispatchReceiver?.accept(visitor, data) - extensionReceiver?.accept(visitor, data) - acceptValueArguments(visitor, data) - } - - override fun acceptChildren(visitor: IrElementVisitor, data: D) { - acceptChildExpressions(visitor, data) + override fun replaceChild(slot: Int, newChild: IrElement) { + if (0 <= slot) + putArgument(slot, newChild.assertCast()) + else + super.replaceChild(slot, newChild) } override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitCallExpression(this, data) + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + super.acceptChildren(visitor, data) + argumentsByParameterIndex.forEach { it?.accept(visitor, data) } + } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCompoundExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCompoundExpression.kt deleted file mode 100644 index a32a16d7d1b..00000000000 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCompoundExpression.kt +++ /dev/null @@ -1,145 +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.ir.expressions - -import org.jetbrains.kotlin.ir.ARGUMENT0_INDEX -import org.jetbrains.kotlin.ir.ARGUMENT1_INDEX -import org.jetbrains.kotlin.ir.visitors.IrElementVisitor -import org.jetbrains.kotlin.types.KotlinType -import java.util.* - -interface IrCompoundExpression : IrExpression, IrExpressionOwner - -interface IrCompoundExpression1 : IrCompoundExpression, IrExpressionOwner1 - -interface IrCompoundExpression2 : IrCompoundExpression, IrExpressionOwner2 - -interface IrCompoundExpressionN : IrCompoundExpression, IrExpressionOwnerN - -abstract class IrCompoundExpressionNBase( - startOffset: Int, - endOffset: Int, - override val type: KotlinType? -) : IrExpressionBase(startOffset, endOffset, type), IrCompoundExpressionN { - override val childExpressions: MutableList = ArrayList() - - override fun acceptChildren(visitor: IrElementVisitor, data: D) { - childExpressions.forEach { it.accept(visitor, data) } - } - - override fun addChildExpression(child: IrExpression) { - child.setTreeLocation(this, childExpressions.size) - childExpressions.add(child) - } - - override fun getChildExpression(index: Int): IrExpression? = - childExpressions.getOrNull(index) - - override fun removeChildExpression(child: IrExpression) { - validateChild(child) - childExpressions.removeAt(child.index) - for (i in child.index ..childExpressions.size - 1) { - childExpressions[i].setTreeLocation(parent, i) - } - child.detach() - } - - override fun replaceChildExpression(oldChild: IrExpression, newChild: IrExpression) { - validateChild(oldChild) - childExpressions[oldChild.index] = newChild - newChild.setTreeLocation(this, oldChild.index) - oldChild.detach() - } - - override fun acceptChildExpressions(visitor: IrElementVisitor, data: D) { - childExpressions.forEach { it.accept(visitor, data) } - } -} - -// TODO IrExpressionBodyImpl vs IrCompoundExpression1Impl: extract common base class? -abstract class IrCompoundExpression1Base( - startOffset: Int, - endOffset: Int, - override val type: KotlinType? -) : IrExpressionBase(startOffset, endOffset, type), IrCompoundExpression1 { - override var argument: IrExpression? = null - set(newExpression) { - field?.detach() - field = newExpression - newExpression?.setTreeLocation(this, ARGUMENT0_INDEX) - } - - override fun getChildExpression(index: Int): IrExpression? = - if (index == ARGUMENT0_INDEX) argument else null - - override fun replaceChildExpression(oldChild: IrExpression, newChild: IrExpression) { - validateChild(oldChild) - argument = newChild - } - - override fun acceptChildren(visitor: IrElementVisitor, data: D) { - acceptChildExpressions(visitor, data) - } - - override fun acceptChildExpressions(visitor: IrElementVisitor, data: D) { - argument?.accept(visitor, data) - } -} - -abstract class IrCompoundExpression2Base( - startOffset: Int, - endOffset: Int, - override val type: KotlinType? -) : IrExpressionBase(startOffset, endOffset, type), IrCompoundExpression2 { - override var argument0: IrExpression? = null - set(newExpression) { - field?.detach() - field = newExpression - newExpression?.setTreeLocation(this, ARGUMENT0_INDEX) - } - - override var argument1: IrExpression? = null - set(newExpression) { - field?.detach() - field = newExpression - newExpression?.setTreeLocation(this, ARGUMENT1_INDEX) - } - - override fun getChildExpression(index: Int): IrExpression? = - when (index) { - ARGUMENT0_INDEX -> argument0 - ARGUMENT1_INDEX -> argument1 - else -> null - } - - override fun replaceChildExpression(oldChild: IrExpression, newChild: IrExpression) { - validateChild(oldChild) - when (oldChild.index) { - ARGUMENT0_INDEX -> argument0 = newChild - ARGUMENT1_INDEX -> argument1 = newChild - } - } - - override fun acceptChildren(visitor: IrElementVisitor, data: D) { - acceptChildExpressions(visitor, data) - } - - override fun acceptChildExpressions(visitor: IrElementVisitor, data: D) { - argument0?.accept(visitor, data) - argument1?.accept(visitor, data) - } -} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDeclarationReference.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDeclarationReference.kt index e2825cfac15..9494c838a6f 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDeclarationReference.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDeclarationReference.kt @@ -18,6 +18,8 @@ package org.jetbrains.kotlin.ir.expressions import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.throwNoSuchSlot import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType @@ -39,14 +41,31 @@ abstract class IrDeclarationReferenceBase( endOffset: Int, type: KotlinType?, override val descriptor: D -) : IrTerminalExpressionBase(startOffset, endOffset, type), IrDeclarationReference +) : IrExpressionBase(startOffset, endOffset, type), IrDeclarationReference + +abstract class IrTerminalDeclarationReferenceBase( + startOffset: Int, + endOffset: Int, + type: KotlinType?, + descriptor: D +) : IrDeclarationReferenceBase(startOffset, endOffset, type, descriptor) { + override fun getChild(slot: Int): IrElement? = null + + override fun replaceChild(slot: Int, newChild: IrElement) { + throwNoSuchSlot(slot) + } + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + // No children + } +} class IrGetObjectValueExpressionImpl( startOffset: Int, endOffset: Int, type: KotlinType?, descriptor: ClassDescriptor -) : IrDeclarationReferenceBase(startOffset, endOffset, type, descriptor), IrGetObjectValueExpression { +) : IrTerminalDeclarationReferenceBase(startOffset, endOffset, type, descriptor), IrGetObjectValueExpression { override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitGetObjectValue(this, data) } @@ -56,7 +75,7 @@ class IrGetEnumValueExpressionImpl( endOffset: Int, type: KotlinType?, descriptor: ClassDescriptor -) : IrDeclarationReferenceBase(startOffset, endOffset, type, descriptor), IrGetEnumValueExpression { +) : IrTerminalDeclarationReferenceBase(startOffset, endOffset, type, descriptor), IrGetEnumValueExpression { override fun accept(visitor: IrElementVisitor, data: D): R { return visitor.visitGetEnumValue(this, data) } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDummyExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDummyExpression.kt index e9c0d94d2de..bc860b7d18c 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDummyExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDummyExpression.kt @@ -24,7 +24,7 @@ class IrDummyExpression( endOffset: Int, type: KotlinType?, val description: String -) : IrExpressionBase(startOffset, endOffset, type) { +) : IrTerminalExpressionBase(startOffset, endOffset, type) { override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitDummyExpression(this, data) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpression.kt index 4f9615bbbf8..cde1745d3a9 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpression.kt @@ -16,48 +16,34 @@ package org.jetbrains.kotlin.ir.expressions -import org.jetbrains.kotlin.ir.DETACHED_INDEX import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElementBase +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.throwNoSuchSlot import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType - -interface IrExpression : IrElement { - override val parent: IrExpressionOwner? - val index: Int +interface IrExpression : IrStatement { val type: KotlinType? - - fun setTreeLocation(parent: IrExpressionOwner?, index: Int) -} - -fun IrExpression.detach() { - setTreeLocation(null, DETACHED_INDEX) -} - -fun IrExpressionOwner.validateChild(child: IrExpression) { - assert(child.parent == this && getChildExpression(child.index) == child) { "Inconsistent child: $child" } } abstract class IrExpressionBase( startOffset: Int, endOffset: Int, override val type: KotlinType? -) : IrElementBase(startOffset, endOffset), IrExpression { - override var parent: IrExpressionOwner? = null - override var index: Int = DETACHED_INDEX - - override fun setTreeLocation(parent: IrExpressionOwner?, index: Int) { - this.parent = parent - this.index = index - } -} +) : IrElementBase(startOffset, endOffset), IrExpression abstract class IrTerminalExpressionBase( startOffset: Int, endOffset: Int, type: KotlinType? ) : IrExpressionBase(startOffset, endOffset, type) { + override fun getChild(slot: Int): IrElement? = null + + override fun replaceChild(slot: Int, newChild: IrElement) { + throwNoSuchSlot(slot) + } + override fun acceptChildren(visitor: IrElementVisitor, data: D) { // No children } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpressionOwner.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpressionOwner.kt deleted file mode 100644 index b45b406f480..00000000000 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpressionOwner.kt +++ /dev/null @@ -1,41 +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.ir.expressions - -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.visitors.IrElementVisitor - -interface IrExpressionOwner : IrElement { - fun getChildExpression(index: Int): IrExpression? - fun replaceChildExpression(oldChild: IrExpression, newChild: IrExpression) - fun acceptChildExpressions(visitor: IrElementVisitor, data: D) -} - -interface IrExpressionOwner1 : IrExpressionOwner { - var argument: IrExpression? -} - -interface IrExpressionOwner2 : IrExpressionOwner { - var argument0: IrExpression? - var argument1: IrExpression? -} - -interface IrExpressionOwnerN : IrExpressionOwner { - val childExpressions: List - fun addChildExpression(child: IrExpression) - fun removeChildExpression(child: IrExpression) -} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrGetVariableExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrGetVariableExpression.kt index 93b967b89e6..ec8f9b10318 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrGetVariableExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrGetVariableExpression.kt @@ -34,7 +34,7 @@ class IrGetVariableExpressionImpl( endOffset: Int, type: KotlinType?, descriptor: VariableDescriptor -) : IrDeclarationReferenceBase(startOffset, endOffset, type, descriptor), IrGetVariableExpression { +) : IrTerminalDeclarationReferenceBase(startOffset, endOffset, type, descriptor), IrGetVariableExpression { override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitGetVariable(this, data) } @@ -43,8 +43,8 @@ class IrGetExtensionReceiverExpressionImpl( startOffset: Int, endOffset: Int, type: KotlinType?, - override val descriptor: CallableDescriptor -) : IrTerminalExpressionBase(startOffset, endOffset, type), IrGetExtensionReceiverExpression { + descriptor: CallableDescriptor +) : IrTerminalDeclarationReferenceBase(startOffset, endOffset, type, descriptor), IrGetExtensionReceiverExpression { override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitGetExtensionReceiver(this, data) } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLocalDeclarationExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLocalDeclarationExpression.kt deleted file mode 100644 index 2baef0d7b26..00000000000 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLocalDeclarationExpression.kt +++ /dev/null @@ -1,70 +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.ir.expressions - -import org.jetbrains.kotlin.ir.CHILD_DECLARATION_INDEX -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.visitors.IrElementVisitor -import org.jetbrains.kotlin.types.KotlinType - -interface IrLocalDeclarationExpression : IrExpression, IrDeclarationOwner1 { - override val childDeclaration: D -} - -interface IrLocalVariableDeclarationExpression : IrLocalDeclarationExpression { - override var childDeclaration: IrLocalVariable -} - -abstract class IrLocalDeclarationExpressionBase( - startOffset: Int, - endOffset: Int, - type: KotlinType? -) : IrExpressionBase(startOffset, endOffset, type), IrLocalVariableDeclarationExpression { - private var childDeclarationImpl: IrLocalVariable? = null - override var childDeclaration: IrLocalVariable - get() = childDeclarationImpl!! - set(value) { - childDeclarationImpl?.detach() - childDeclarationImpl = value - value.setTreeLocation(this, CHILD_DECLARATION_INDEX) - } - - override fun getChildDeclaration(index: Int): IrMemberDeclaration? = - if (index == CHILD_DECLARATION_INDEX) childDeclaration else null - - override fun replaceChildDeclaration(oldChild: IrMemberDeclaration, newChild: IrMemberDeclaration) { - if (newChild !is IrLocalVariable) throw AssertionError("IrLocalVariable expected: $newChild") - validateChild(oldChild) - childDeclaration = newChild - } - - override fun acceptChildren(visitor: IrElementVisitor, data: D) { - childDeclarationImpl?.accept(visitor, data) - } -} - -class IrLocalVariableDeclarationExpressionImpl( - startOffset: Int, - endOffset: Int -) : IrLocalDeclarationExpressionBase(startOffset, endOffset, null), IrLocalVariableDeclarationExpression { - constructor(startOffset: Int, endOffset: Int, childDeclaration: IrLocalVariable) : this(startOffset, endOffset) { - this.childDeclaration = childDeclaration - } - - override fun accept(visitor: IrElementVisitor, data: D): R = - visitor.visitLocalVariableDeclarationExpression(this, data) -} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrMemberAccessExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrMemberAccessExpression.kt index e8a8210ebf2..5217a06fe16 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrMemberAccessExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrMemberAccessExpression.kt @@ -16,11 +16,11 @@ package org.jetbrains.kotlin.ir.expressions -import org.jetbrains.kotlin.ir.DISPATCH_RECEIVER_INDEX -import org.jetbrains.kotlin.ir.EXTENSION_RECEIVER_INDEX +import org.jetbrains.kotlin.ir.* +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType -interface IrMemberAccessExpression : IrDeclarationReference, IrExpressionOwner { +interface IrMemberAccessExpression : IrDeclarationReference { var dispatchReceiver: IrExpression? var extensionReceiver: IrExpression? val isSafe: Boolean @@ -34,15 +34,37 @@ abstract class IrMemberAccessExpressionBase( ) : IrExpressionBase(startOffset, endOffset, type), IrMemberAccessExpression { override var dispatchReceiver: IrExpression? = null set(newReceiver) { + newReceiver?.assertDetached() field?.detach() field = newReceiver - newReceiver?.setTreeLocation(this, DISPATCH_RECEIVER_INDEX) + newReceiver?.setTreeLocation(this, DISPATCH_RECEIVER_SLOT) } override var extensionReceiver: IrExpression? = null set(newReceiver) { + newReceiver?.assertDetached() field?.detach() field = newReceiver - newReceiver?.setTreeLocation(this, EXTENSION_RECEIVER_INDEX) + newReceiver?.setTreeLocation(this, EXTENSION_RECEIVER_SLOT) } + + override fun getChild(slot: Int): IrElement? = + when (slot) { + DISPATCH_RECEIVER_SLOT -> dispatchReceiver + EXTENSION_RECEIVER_SLOT -> extensionReceiver + else -> null + } + + override fun replaceChild(slot: Int, newChild: IrElement) { + when (slot) { + DISPATCH_RECEIVER_SLOT -> dispatchReceiver = newChild.assertCast() + EXTENSION_RECEIVER_SLOT -> extensionReceiver = newChild.assertCast() + else -> throwNoSuchSlot(slot) + } + } + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + dispatchReceiver?.accept(visitor, data) + extensionReceiver?.accept(visitor, data) + } } 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 21bc3f64eff..6eba894c757 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 @@ -30,7 +30,8 @@ enum class IrOperator { RANGE, PLUS, MINUS, MUL, DIV, MOD, EQ, - PLUSEQ, MINUSEQ, MULEQ, DIVEQ, MODEQ; + PLUSEQ, MINUSEQ, MULEQ, DIVEQ, MODEQ, + DESTRUCTURING; } private val CAO_START = IrOperator.PLUSEQ.ordinal diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperatorExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperatorExpression.kt index b90b02f1cd6..ca2ddfd927f 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperatorExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperatorExpression.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.ir.expressions import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType @@ -25,9 +26,14 @@ interface IrOperatorExpression : IrExpression { val relatedDescriptor: FunctionDescriptor? } -interface IrUnaryOperatorExpression : IrOperatorExpression, IrCompoundExpression1 +interface IrUnaryOperatorExpression : IrOperatorExpression { + var argument: IrExpression +} -interface IrBinaryOperatorExpression : IrOperatorExpression, IrCompoundExpression2 +interface IrBinaryOperatorExpression : IrOperatorExpression { + var argument0: IrExpression + var argument1: IrExpression +} class IrUnaryOperatorExpressionImpl( startOffset: Int, @@ -35,10 +41,48 @@ class IrUnaryOperatorExpressionImpl( type: KotlinType?, override val operator: IrOperator, override val relatedDescriptor: FunctionDescriptor? -) : IrCompoundExpression1Base(startOffset, endOffset, type), IrUnaryOperatorExpression { +) : IrExpressionBase(startOffset, endOffset, type), IrUnaryOperatorExpression { + constructor( + startOffset: Int, + endOffset: Int, + type: KotlinType?, + operator: IrOperator, + relatedDescriptor: FunctionDescriptor?, + argument: IrExpression + ) : this(startOffset, endOffset, type, operator, relatedDescriptor) { + this.argument = argument + } + + private var argumentImpl: IrExpression? = null + override var argument: IrExpression + get() = argumentImpl!! + set(value) { + value.assertDetached() + argumentImpl?.detach() + argumentImpl = value + value.setTreeLocation(this, ARGUMENT0_SLOT) + } + + override fun getChild(slot: Int): IrElement? = + when (slot) { + ARGUMENT0_SLOT -> argument + else -> null + } + + override fun replaceChild(slot: Int, newChild: IrElement) { + when (slot) { + ARGUMENT0_SLOT -> argument = newChild.assertCast() + else -> throwNoSuchSlot(slot) + } + } + override fun accept(visitor: IrElementVisitor, data: D): R { return visitor.visitUnaryOperator(this, data) } + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + argument.accept(visitor, data) + } } class IrBinaryOperatorExpressionImpl( @@ -47,7 +91,60 @@ class IrBinaryOperatorExpressionImpl( type: KotlinType?, override val operator: IrOperator, override val relatedDescriptor: FunctionDescriptor? -) : IrCompoundExpression2Base(startOffset, endOffset, type), IrBinaryOperatorExpression { +) : IrExpressionBase(startOffset, endOffset, type), IrBinaryOperatorExpression { + constructor( + startOffset: Int, + endOffset: Int, + type: KotlinType?, + operator: IrOperator, + relatedDescriptor: FunctionDescriptor?, + argument0: IrExpression, + argument1: IrExpression + ) : this(startOffset, endOffset, type, operator, relatedDescriptor) { + this.argument0 = argument0 + this.argument1 = argument1 + } + + private var argument0Impl: IrExpression? = null + override var argument0: IrExpression + get() = argument0Impl!! + set(value) { + value.assertDetached() + argument0Impl?.detach() + argument0Impl = value + value.setTreeLocation(this, ARGUMENT0_SLOT) + } + + private var argument1Impl: IrExpression? = null + override var argument1: IrExpression + get() = argument1Impl!! + set(value) { + value.assertDetached() + argument1Impl?.detach() + argument1Impl = value + value.setTreeLocation(this, ARGUMENT1_SLOT) + } + + override fun getChild(slot: Int): IrElement? = + when (slot) { + ARGUMENT0_SLOT -> argument0 + ARGUMENT1_SLOT -> argument1 + else -> null + } + + override fun replaceChild(slot: Int, newChild: IrElement) { + when (slot) { + ARGUMENT0_SLOT -> argument0 = newChild.assertCast() + ARGUMENT1_SLOT -> argument1 = newChild.assertCast() + else -> throwNoSuchSlot(slot) + } + } + override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitBinaryOperator(this, data) + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + argument0.acceptChildren(visitor, data) + argument1.acceptChildren(visitor, data) + } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrPropertyAccessExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrPropertyAccessExpression.kt index b7a7149bf55..b8f7a19375a 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrPropertyAccessExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrPropertyAccessExpression.kt @@ -17,9 +17,7 @@ package org.jetbrains.kotlin.ir.expressions import org.jetbrains.kotlin.descriptors.PropertyDescriptor -import org.jetbrains.kotlin.ir.ARGUMENT0_INDEX -import org.jetbrains.kotlin.ir.DISPATCH_RECEIVER_INDEX -import org.jetbrains.kotlin.ir.EXTENSION_RECEIVER_INDEX +import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType @@ -29,7 +27,9 @@ interface IrPropertyAccessExpression : IrMemberAccessExpression { interface IrGetPropertyExpression : IrPropertyAccessExpression -interface IrSetPropertyExpression : IrPropertyAccessExpression, IrCompoundExpression1 +interface IrSetPropertyExpression : IrPropertyAccessExpression { + var value: IrExpression +} class IrGetPropertyExpressionImpl( startOffset: Int, @@ -38,33 +38,8 @@ class IrGetPropertyExpressionImpl( isSafe: Boolean, override val descriptor: PropertyDescriptor ) : IrMemberAccessExpressionBase(startOffset, endOffset, type, isSafe), IrGetPropertyExpression { - override fun accept(visitor: IrElementVisitor, data: D): R { - return visitor.visitGetProperty(this, data) - } - - override fun acceptChildren(visitor: IrElementVisitor, data: D) { - acceptChildExpressions(visitor, data) - } - - override fun acceptChildExpressions(visitor: IrElementVisitor, data: D) { - dispatchReceiver?.accept(visitor, data) - extensionReceiver?.accept(visitor, data) - } - - override fun getChildExpression(index: Int): IrExpression? = - when (index) { - DISPATCH_RECEIVER_INDEX -> dispatchReceiver - EXTENSION_RECEIVER_INDEX -> extensionReceiver - else -> null - } - - override fun replaceChildExpression(oldChild: IrExpression, newChild: IrExpression) { - validateChild(oldChild) - when (oldChild.index) { - DISPATCH_RECEIVER_INDEX -> dispatchReceiver = newChild - EXTENSION_RECEIVER_INDEX -> extensionReceiver = newChild - } - } + override fun accept(visitor: IrElementVisitor, data: D): R = + visitor.visitGetProperty(this, data) } class IrSetPropertyExpressionImpl( @@ -74,11 +49,25 @@ class IrSetPropertyExpressionImpl( isSafe: Boolean, override val descriptor: PropertyDescriptor ) : IrMemberAccessExpressionBase(startOffset, endOffset, type, isSafe), IrSetPropertyExpression { - override var argument: IrExpression? = null + constructor( + startOffset: Int, + endOffset: Int, + type: KotlinType?, + isSafe: Boolean, + descriptor: PropertyDescriptor, + value: IrExpression + ) : this(startOffset, endOffset, type, isSafe, descriptor) { + this.value = value + } + + private var valueImpl: IrExpression? = null + override var value: IrExpression + get() = valueImpl!! set(value) { - field?.detach() - field = value - value?.setTreeLocation(this, ARGUMENT0_INDEX) + value.assertDetached() + valueImpl?.detach() + valueImpl = value + value.setTreeLocation(this, ARGUMENT0_SLOT) } override fun accept(visitor: IrElementVisitor, data: D): R { @@ -86,29 +75,20 @@ class IrSetPropertyExpressionImpl( } override fun acceptChildren(visitor: IrElementVisitor, data: D) { - acceptChildExpressions(visitor, data) + super.acceptChildren(visitor, data) + value.accept(visitor, data) } - override fun acceptChildExpressions(visitor: IrElementVisitor, data: D) { - dispatchReceiver?.accept(visitor, data) - extensionReceiver?.accept(visitor, data) - argument?.accept(visitor, data) - } - - override fun getChildExpression(index: Int): IrExpression? = - when (index) { - DISPATCH_RECEIVER_INDEX -> dispatchReceiver - EXTENSION_RECEIVER_INDEX -> extensionReceiver - ARGUMENT0_INDEX -> argument - else -> null + override fun getChild(slot: Int): IrElement? = + when (slot) { + ARGUMENT0_SLOT -> value + else -> super.getChild(slot) } - override fun replaceChildExpression(oldChild: IrExpression, newChild: IrExpression) { - validateChild(oldChild) - when (oldChild.index) { - DISPATCH_RECEIVER_INDEX -> dispatchReceiver = newChild - EXTENSION_RECEIVER_INDEX -> extensionReceiver = newChild - ARGUMENT0_INDEX -> argument = newChild + override fun replaceChild(slot: Int, newChild: IrElement) { + when (slot) { + ARGUMENT0_SLOT -> value = newChild.assertCast() + else -> super.replaceChild(slot, newChild) } } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrReturnExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrReturnExpression.kt index df9f46b15a1..1b5bb16e66d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrReturnExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrReturnExpression.kt @@ -16,17 +16,56 @@ package org.jetbrains.kotlin.ir.expressions +import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType -interface IrReturnExpression : IrCompoundExpression1 +interface IrReturnExpression : IrExpression { + var value: IrExpression? +} class IrReturnExpressionImpl( startOffset: Int, endOffset: Int, type: KotlinType? -) : IrCompoundExpression1Base(startOffset, endOffset, type), IrReturnExpression { +) : IrExpressionBase(startOffset, endOffset, type), IrReturnExpression { + constructor( + startOffset: Int, + endOffset: Int, + type: KotlinType?, + value: IrExpression? + ) : this(startOffset, endOffset, type) { + this.value = value + } + + override var value: IrExpression? = null + set(newValue) { + newValue?.assertDetached() + field?.detach() + field = newValue + newValue?.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() + else -> throwNoSuchSlot(slot) + } + } + override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitReturnExpression(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/IrStringConcatenationExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStringConcatenationExpression.kt index d0d2a239c81..d250542a6ee 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStringConcatenationExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStringConcatenationExpression.kt @@ -16,16 +16,48 @@ package org.jetbrains.kotlin.ir.expressions +import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType +import java.util.* -interface IrStringConcatenationExpression : IrCompoundExpressionN +interface IrStringConcatenationExpression : IrExpression { + val arguments: List + fun addArgument(argument: IrExpression) +} class IrStringConcatenationExpressionImpl( startOffset: Int, endOffset: Int, type: KotlinType? -) : IrCompoundExpressionNBase(startOffset, endOffset, type), IrStringConcatenationExpression { +) : IrExpressionBase(startOffset, endOffset, type), IrStringConcatenationExpression { + override val arguments: MutableList = ArrayList() + + override fun addArgument(argument: IrExpression) { + argument.assertDetached() + argument.setTreeLocation(this, arguments.size) + arguments.add(argument) + } + + override fun getChild(slot: Int): IrElement? = + arguments.getOrNull(slot) + + override fun replaceChild(slot: Int, newChild: IrElement) { + newChild.assertDetached() + if (0 <= slot && slot < arguments.size) { + arguments[slot].detach() + arguments[slot] = newChild.assertCast() + newChild.setTreeLocation(this, slot) + } + else { + throwNoSuchSlot(slot) + } + } + override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitStringTemplate(this, data) + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + arguments.forEach { it.accept(visitor, data) } + } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrThisExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrThisExpression.kt index 2a20b2fe557..33ea0dd30dc 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrThisExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrThisExpression.kt @@ -30,7 +30,6 @@ class IrThisExpressionImpl( type: KotlinType?, override val classDescriptor: ClassDescriptor ) : IrTerminalExpressionBase(startOffset, endOffset, type), IrThisExpression { - override fun accept(visitor: IrElementVisitor, data: D): R { - return visitor.visitThisExpression(this, data) - } + override fun accept(visitor: IrElementVisitor, data: D): R = + visitor.visitThisExpression(this, data) } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorExpression.kt index f74e6b7bdfe..d4769816298 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorExpression.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.ir.expressions +import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType @@ -27,8 +28,9 @@ enum class IrTypeOperator { NOT_IS; } -interface IrTypeOperatorExpression : IrExpression, IrCompoundExpression1 { +interface IrTypeOperatorExpression : IrExpression { val operator: IrTypeOperator + var argument: IrExpression val typeOperand: KotlinType } @@ -38,8 +40,47 @@ class IrTypeOperatorExpressionImpl( type: KotlinType?, override val operator: IrTypeOperator, override val typeOperand: KotlinType -) : IrCompoundExpression1Base(startOffset, endOffset, type), IrTypeOperatorExpression { - override fun accept(visitor: IrElementVisitor, data: D): R { - return visitor.visitTypeOperatorExpression(this, data) +) : IrExpressionBase(startOffset, endOffset, type), IrTypeOperatorExpression { + constructor( + startOffset: Int, + endOffset: Int, + type: KotlinType?, + operator: IrTypeOperator, + argument: IrExpression, + typeOperand: KotlinType + ) : this(startOffset, endOffset, type, operator, typeOperand) { + this.argument = argument } + + private var argumentImpl: IrExpression? = null + override var argument: IrExpression + get() = argumentImpl!! + set(value) { + value.assertDetached() + argumentImpl?.detach() + argumentImpl = value + value.setTreeLocation(this, ARGUMENT0_SLOT) + } + + override fun getChild(slot: Int): IrElement? = + when (slot) { + ARGUMENT0_SLOT -> argument + else -> null + } + + override fun replaceChild(slot: Int, newChild: IrElement) { + when (slot) { + ARGUMENT0_SLOT -> argument = newChild.assertCast() + else -> throwNoSuchSlot(slot) + } + } + + override fun accept(visitor: IrElementVisitor, data: D): R = + visitor.visitTypeOperatorExpression(this, data) + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + argument.accept(visitor, data) + } + + } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt index 6ec5ef5b7a3..d9a6154ff4c 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt @@ -50,7 +50,7 @@ class DumpIrTreeVisitor(out: Appendable): IrElementVisitor { expression.dispatchReceiver?.accept(this, "\$this") expression.extensionReceiver?.accept(this, "\$receiver") for (valueParameter in expression.descriptor.valueParameters) { - expression.getValueArgument(valueParameter.index)?.accept(this, valueParameter.name.asString()) + expression.getArgument(valueParameter.index)?.accept(this, valueParameter.name.asString()) } } } @@ -66,7 +66,7 @@ class DumpIrTreeVisitor(out: Appendable): IrElementVisitor { expression.dumpLabeledElementWith(data) { expression.dispatchReceiver?.accept(this, "\$this") expression.extensionReceiver?.accept(this, "\$receiver") - expression.argument?.accept(this, "\$value") + expression.value.accept(this, "\$value") } } 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 c2c566ab9fd..8cfa50c4da3 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 @@ -48,8 +48,8 @@ class RenderIrElementVisitor : IrElementVisitor { override fun visitPropertySetter(declaration: IrPropertySetter, data: Nothing?): String = "IrPropertySetter ${declaration.descriptor.render()} property=${declaration.property?.name()}" - override fun visitLocalVariable(declaration: IrLocalVariable, data: Nothing?): String = - "IrLocalVariable ${declaration.descriptor.render()}" + override fun visitLocalVariable(declaration: IrVariable, data: Nothing?): String = + "VAR ${declaration.descriptor.render()}" override fun visitExpressionBody(body: IrExpressionBody, data: Nothing?): String = "IrExpressionBody" @@ -60,11 +60,8 @@ class RenderIrElementVisitor : IrElementVisitor { override fun visitLiteral(expression: IrLiteralExpression, data: Nothing?): String = "LITERAL ${expression.kind} type=${expression.renderType()} value='${expression.value}'" - override fun visitLocalVariableDeclarationExpression(expression: IrLocalVariableDeclarationExpression, data: Nothing?): String = - "LOCAL ${expression.childDeclaration.descriptor.name}" - override fun visitBlockExpression(expression: IrBlockExpression, data: Nothing?): String = - "BLOCK type=${expression.renderType()}" + "BLOCK type=${expression.renderType()} hasResult=${expression.hasResult} isDesugared=${expression.isDesugared}" override fun visitReturnExpression(expression: IrReturnExpression, data: Nothing?): String = "RETURN type=${expression.renderType()}" 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 c04df1d09c5..667eb5a6e94 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 @@ -22,19 +22,18 @@ import org.jetbrains.kotlin.ir.expressions.* interface IrElementVisitor { fun visitElement(element: IrElement, data: D): R + fun visitModule(declaration: IrModule, data: D): R = visitElement(declaration, data) + fun visitFile(declaration: IrFile, data: D): R = visitElement(declaration, data) fun visitDeclaration(declaration: IrDeclaration, data: D): R = visitElement(declaration, data) - fun visitModule(declaration: IrModule, data: D): R = visitDeclaration(declaration, data) - fun visitCompoundDeclaration(declaration: IrCompoundDeclaration, data: D): R = visitDeclaration(declaration, data) - fun visitFile(declaration: IrFile, data: D): R = visitCompoundDeclaration(declaration, data) - fun visitClass(declaration: IrClass, data: D): R = visitCompoundDeclaration(declaration, data) + fun visitClass(declaration: IrClass, data: D): R = visitDeclaration(declaration, data) fun visitFunction(declaration: IrFunction, data: D): R = visitDeclaration(declaration, data) fun visitPropertyGetter(declaration: IrPropertyGetter, data: D): R = visitFunction(declaration, data) fun visitPropertySetter(declaration: IrPropertySetter, data: D): R = visitFunction(declaration, data) fun visitProperty(declaration: IrProperty, data: D): R = visitDeclaration(declaration, data) fun visitSimpleProperty(declaration: IrSimpleProperty, data: D): R = visitProperty(declaration, data) fun visitDelegatedProperty(declaration: IrDelegatedProperty, data: D): R = visitProperty(declaration, data) - fun visitLocalVariable(declaration: IrLocalVariable, data: D) = visitDeclaration(declaration, data) + fun visitLocalVariable(declaration: IrVariable, data: D) = visitDeclaration(declaration, data) fun visitBody(body: IrBody, data: D): R = visitElement(body, data) fun visitExpressionBody(body: IrExpressionBody, data: D): R = visitBody(body, data) @@ -46,11 +45,6 @@ interface IrElementVisitor { fun visitStringTemplate(expression: IrStringConcatenationExpression, data: D) = visitExpression(expression, data) fun visitThisExpression(expression: IrThisExpression, data: D) = visitExpression(expression, data) - fun visitLocalDeclarationExpression(expression: IrLocalDeclarationExpression, data: D) = - visitExpression(expression, data) - fun visitLocalVariableDeclarationExpression(expression: IrLocalVariableDeclarationExpression, data: D) = - visitLocalDeclarationExpression(expression, data) - fun visitDeclarationReference(expression: IrDeclarationReference, data: D) = visitExpression(expression, data) fun visitGetObjectValue(expression: IrGetObjectValueExpression, data: D) = visitDeclarationReference(expression, data) fun visitGetEnumValue(expression: IrGetEnumValueExpression, data: D) = visitDeclarationReference(expression, data) diff --git a/compiler/testData/ir/irText/callWithReorderedArguments.txt b/compiler/testData/ir/irText/callWithReorderedArguments.txt index 6f69f1355b7..272e769f641 100644 --- a/compiler/testData/ir/irText/callWithReorderedArguments.txt +++ b/compiler/testData/ir/irText/callWithReorderedArguments.txt @@ -1,7 +1,7 @@ IrFile /callWithReorderedArguments.kt IrFunction public fun foo(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int): kotlin.Unit IrExpressionBody - BLOCK type=kotlin.Unit + BLOCK type=kotlin.Unit hasResult=false isDesugared=false IrFunction public fun noReorder1(): kotlin.Int IrExpressionBody LITERAL Int type=kotlin.Int value='1' @@ -16,17 +16,15 @@ IrFile /callWithReorderedArguments.kt LITERAL Int type=kotlin.Int value='2' IrFunction public fun test(): kotlin.Unit IrExpressionBody - BLOCK type=kotlin.Unit + BLOCK type=kotlin.Unit hasResult=false isDesugared=false CALL .foo type=kotlin.Unit operator= a: CALL .noReorder1 type=kotlin.Int operator= b: CALL .noReorder2 type=kotlin.Int operator= - BLOCK type=kotlin.Unit - LOCAL tmp0 - IrLocalVariable val tmp0: kotlin.Int - CALL .reordered1 type=kotlin.Int operator= - LOCAL tmp1 - IrLocalVariable val tmp1: kotlin.Int - CALL .reordered2 type=kotlin.Int operator= + BLOCK type=kotlin.Unit hasResult=false isDesugared=true + VAR val tmp0: kotlin.Int + CALL .reordered1 type=kotlin.Int operator= + VAR val tmp1: kotlin.Int + CALL .reordered2 type=kotlin.Int operator= CALL .foo type=kotlin.Unit operator= a: GET_VAR tmp1 type=kotlin.Int b: GET_VAR tmp0 type=kotlin.Int diff --git a/compiler/testData/ir/irText/destructuring1.kt b/compiler/testData/ir/irText/destructuring1.kt new file mode 100644 index 00000000000..e726afb8027 --- /dev/null +++ b/compiler/testData/ir/irText/destructuring1.kt @@ -0,0 +1,10 @@ +object A + +object B { + operator fun A.component1() = 1 + operator fun A.component2() = 2 +} + +fun B.test() { // <<< destructuring1.txt + val (x, y) = A +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/destructuring1.txt b/compiler/testData/ir/irText/destructuring1.txt new file mode 100644 index 00000000000..55fdf970106 --- /dev/null +++ b/compiler/testData/ir/irText/destructuring1.txt @@ -0,0 +1,4 @@ +IrFunction public fun B.test(): kotlin.Unit + IrExpressionBody + BLOCK type=kotlin.Unit hasResult=false isDesugared=false + DUMMY KtDestructuringDeclaration type=kotlin.Unit diff --git a/compiler/testData/ir/irText/references.txt b/compiler/testData/ir/irText/references.txt index ca4a342e64e..00e9213abed 100644 --- a/compiler/testData/ir/irText/references.txt +++ b/compiler/testData/ir/irText/references.txt @@ -17,10 +17,9 @@ IrFile /references.kt GET_VAR x type=kotlin.String IrFunction public fun test3(): kotlin.String IrExpressionBody - BLOCK type=kotlin.Nothing - LOCAL x - IrLocalVariable val x: kotlin.String = "OK" - LITERAL String type=kotlin.String value='OK' + BLOCK type=kotlin.Nothing hasResult=false isDesugared=false + VAR val x: kotlin.String = "OK" + LITERAL String type=kotlin.String value='OK' RETURN type=kotlin.Nothing GET_VAR x type=kotlin.String IrFunction public fun test4(): kotlin.String diff --git a/compiler/testData/ir/irText/smoke.kt b/compiler/testData/ir/irText/smoke.kt index bfdf6a1421a..5d57c9aeea2 100644 --- a/compiler/testData/ir/irText/smoke.kt +++ b/compiler/testData/ir/irText/smoke.kt @@ -1,6 +1,6 @@ // <<< smoke.txt fun testFun(): String { return "OK" } -val testSimpleVal = 1 // <<< smoke.testSimpleVal.txt +val testSimpleVal = 1 val testValWithGetter: Int get() = 42 var testSimpleVar = 2 var testVarWithAccessors: Int @@ -13,4 +13,4 @@ var testVarWithAccessors: Int // 2 IrPropertyGetter // 1 IrPropertySetter // 1 IrProperty public var testSimpleVar -// 1 IrProperty public var testVarWithAccessors +// 1 IrProperty public var testVarWithAccessors \ No newline at end of file diff --git a/compiler/testData/ir/irText/smoke.testSimpleVal.txt b/compiler/testData/ir/irText/smoke.testSimpleVal.txt deleted file mode 100644 index f5db130b5f3..00000000000 --- a/compiler/testData/ir/irText/smoke.testSimpleVal.txt +++ /dev/null @@ -1,3 +0,0 @@ -IrProperty public val testSimpleVal: kotlin.Int = 1 getter=null setter=null - IrExpressionBody - LITERAL Int type=kotlin.Int value='1' diff --git a/compiler/testData/ir/irText/smoke.txt b/compiler/testData/ir/irText/smoke.txt index ffe0925ca37..5457cf4937d 100644 --- a/compiler/testData/ir/irText/smoke.txt +++ b/compiler/testData/ir/irText/smoke.txt @@ -1,7 +1,7 @@ IrFile /smoke.kt IrFunction public fun testFun(): kotlin.String IrExpressionBody - BLOCK type=kotlin.Nothing + BLOCK type=kotlin.Nothing hasResult=false isDesugared=false RETURN type=kotlin.Nothing LITERAL String type=kotlin.String value='OK' IrProperty public val testSimpleVal: kotlin.Int = 1 getter=null setter=null @@ -20,4 +20,4 @@ IrFile /smoke.kt LITERAL Int type=kotlin.Int value='42' IrPropertySetter public fun (/*0*/ v: kotlin.Int): kotlin.Unit property=testVarWithAccessors IrExpressionBody - BLOCK type=kotlin.Unit + BLOCK type=kotlin.Unit hasResult=false isDesugared=false diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index 7edd4dbce8e..56700680953 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -53,6 +53,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { doTest(fileName); } + @TestMetadata("destructuring1.kt") + public void testDestructuring1() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/destructuring1.kt"); + doTest(fileName); + } + @TestMetadata("dotQualified.kt") public void testDotQualified() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/dotQualified.kt");