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 1b5eb9a0317..f6b629d069b 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 @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrBodyBase import org.jetbrains.kotlin.ir.expressions.IrExpressionBodyImpl import org.jetbrains.kotlin.ir.expressions.IrReturnExpressionImpl +import org.jetbrains.kotlin.ir.expressions.returnedExpression import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext @@ -98,8 +99,9 @@ abstract class IrDeclarationGeneratorBase( if (ktBody is KtBlockExpression) irExpression else - IrReturnExpressionImpl(sourceLocation, irExpression.type, irExpression).apply { irExpression.parent = this } + IrReturnExpressionImpl(sourceLocation, irExpression.type) + .apply { returnedExpression = irExpression } - return IrExpressionBodyImpl(sourceLocation,bodyExpression) + return IrExpressionBodyImpl(sourceLocation).apply { childExpression = bodyExpression } } } \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrExpressionGenerator.kt index d16ae400bd1..153224aea99 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrExpressionGenerator.kt @@ -42,8 +42,8 @@ class IrExpressionGenerator( } override fun visitReturnExpression(expression: KtReturnExpression, data: Nothing?): IrExpressionBase = - IrReturnExpressionImpl(expression.loc(), expression.type(), - expression.returnedExpression?.irExpr()) + IrReturnExpressionImpl(expression.loc(), expression.type()) + .apply { this.childExpression = expression.returnedExpression?.irExpr() } override fun visitConstantExpression(expression: KtConstantExpression, data: Nothing?): IrExpressionBase { val compileTimeConstant = ConstantExpressionEvaluator.getConstant(expression, context.bindingContext) @@ -67,7 +67,7 @@ class IrExpressionGenerator( } val irStringTemplate = IrStringConcatenationExpressionImpl(expression.loc(), expression.type()) - expression.entries.forEach { irStringTemplate.entries.add(it.irExpr()) } + expression.entries.forEach { irStringTemplate.addChildExpression(it.irExpr()) } return irStringTemplate } 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 1adc87798e0..5d2ec5e023c 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 @@ -19,19 +19,14 @@ package org.jetbrains.kotlin.ir.expressions import org.jetbrains.kotlin.ir.SourceLocation import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType -import java.util.* -interface IrBlockExpression : IrExpression { - val childExpressions: List -} +interface IrBlockExpression : IrCompoundExpressionN class IrBlockExpressionImpl( sourceLocation: SourceLocation, type: KotlinType -) : IrExpressionBase(sourceLocation, type), IrBlockExpression { - override val childExpressions: MutableList = ArrayList() - +) : IrCompoundExpressionNBase(sourceLocation, type), IrBlockExpression { override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitBlockExpression(this, data) 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 924c528c875..0bc62b0b644 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 @@ -27,22 +27,37 @@ interface IrBody : IrElement { override val parent: IrDeclaration } -interface IrExpressionBody : IrBody { - val expression: IrExpression -} +interface IrExpressionBody : IrBody, IrExpressionOwner1 abstract class IrBodyBase(sourceLocation: SourceLocation): IrElementBase(sourceLocation), IrBody { override lateinit var parent: IrDeclaration } -class IrExpressionBodyImpl( - sourceLocation: SourceLocation, - override val expression: IrExpression -) : IrBodyBase(sourceLocation), IrExpressionBody { +// TODO IrExpressionBodyImpl vs IrCompoundExpression1Impl: extract common base class? +class IrExpressionBodyImpl(sourceLocation: SourceLocation) : IrBodyBase(sourceLocation), IrExpressionBody { + override var childExpression: IrExpression? = null + set(newExpression) { + field?.detach() + field = newExpression + newExpression?.setTreeLocation(this, IrExpressionOwner1.EXPRESSION_INDEX) + } + + override fun getChildExpression(index: Int): IrExpression? = + if (index == IrExpressionOwner1.EXPRESSION_INDEX) childExpression else null + + override fun replaceChildExpression(oldChild: IrExpression, newChild: IrExpression) { + validateChild(oldChild) + childExpression = newChild + } + override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitExpressionBody(this, data) override fun acceptChildren(visitor: IrElementVisitor, data: D) { - expression.accept(visitor, data) + acceptChildExpressions(visitor, data) + } + + override fun acceptChildExpressions(visitor: IrElementVisitor, data: D) { + childExpression?.accept(visitor, data) } } \ No newline at end of file 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 new file mode 100644 index 00000000000..63ac9bbc1b8 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCompoundExpression.kt @@ -0,0 +1,96 @@ +/* + * 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.SourceLocation +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 IrCompoundExpressionN : IrCompoundExpression, IrExpressionOwnerN + +abstract class IrCompoundExpressionNBase( + sourceLocation: SourceLocation, + override val type: KotlinType +) : IrExpressionBase(sourceLocation, 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( + sourceLocation: SourceLocation, + override val type: KotlinType +) : IrExpressionBase(sourceLocation, type), IrCompoundExpression1 { + override var childExpression: IrExpression? = null + set(newExpression) { + field?.detach() + field = newExpression + newExpression?.setTreeLocation(this, IrExpressionOwner1.EXPRESSION_INDEX) + } + + override fun getChildExpression(index: Int): IrExpression? = + if (index == IrExpressionOwner1.EXPRESSION_INDEX) childExpression else null + + override fun replaceChildExpression(oldChild: IrExpression, newChild: IrExpression) { + validateChild(oldChild) + childExpression = newChild + } + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + acceptChildExpressions(visitor, data) + } + + override fun acceptChildExpressions(visitor: IrElementVisitor, data: D) { + childExpression?.accept(visitor, data) + } +} \ No newline at end of file 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 395f66d8e87..ff06b3e56d1 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 @@ -23,12 +23,34 @@ import org.jetbrains.kotlin.types.KotlinType interface IrExpression : IrElement { + override val parent: IrExpressionOwner? + val index: Int val type: KotlinType + + fun setTreeLocation(parent: IrExpressionOwner?, index: Int) + + companion object { + const val DETACHED_INDEX = Int.MIN_VALUE + } +} + +fun IrExpression.detach() { + setTreeLocation(null, IrExpression.DETACHED_INDEX) +} + +fun IrExpressionOwner.validateChild(child: IrExpression) { + assert(child.parent == this && getChildExpression(child.index) == child) { "Inconsistent child: $child" } } abstract class IrExpressionBase( sourceLocation: SourceLocation, override val type: KotlinType ) : IrElementBase(sourceLocation), IrExpression { - override lateinit var parent: IrElement + override var parent: IrExpressionOwner? = null + override var index: Int = IrExpression.DETACHED_INDEX + + override fun setTreeLocation(parent: IrExpressionOwner?, index: Int) { + this.parent = parent + this.index = index + } } \ No newline at end of file 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 new file mode 100644 index 00000000000..04d1a6b8d63 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrExpressionOwner.kt @@ -0,0 +1,50 @@ +/* + * 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 childExpression: IrExpression? + + companion object { + const val EXPRESSION_INDEX = 0 + } +} + +interface IrExpressionOwner2 : IrExpressionOwner { + var childExpression1: IrExpression? + var childExpression2: IrExpression? + + companion object { + const val EXPRESSION1_INDEX = 1 + const val EXPRESSION2_INDEX = 2 + } +} + +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/IrReturnExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrReturnExpression.kt index 2e5ea436cc7..217cf6f15f8 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 @@ -21,19 +21,16 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType -interface IrReturnExpression : IrExpression { - val returnValueExpression: IrExpression? -} +interface IrReturnExpression : IrExpression, IrExpressionOwner1 + +var IrReturnExpression.returnedExpression: IrExpression? + get() = childExpression + set(newReturnedExpression) { childExpression = newReturnedExpression } class IrReturnExpressionImpl( sourceLocation: SourceLocation, - type: KotlinType, - override val returnValueExpression: IrExpression? -) : IrExpressionBase(sourceLocation, type), IrReturnExpression { + type: KotlinType +) : IrCompoundExpression1Base(sourceLocation, type), IrReturnExpression { override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitReturnExpression(this, data) - - override fun acceptChildren(visitor: IrElementVisitor, data: D) { - returnValueExpression?.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 5948813b6b5..c5cfeec82f9 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 @@ -22,20 +22,12 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType import java.util.* -interface IrStringConcatenationExpression : IrExpression { - val entries: List -} +interface IrStringConcatenationExpression : IrCompoundExpressionN class IrStringConcatenationExpressionImpl( sourceLocation: SourceLocation, type: KotlinType -) : IrExpressionBase(sourceLocation, type), IrStringConcatenationExpression { - override val entries: MutableList = ArrayList() - +) : IrCompoundExpressionNBase(sourceLocation, type), IrStringConcatenationExpression { override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitStringTemplate(this, data) - - override fun acceptChildren(visitor: IrElementVisitor, data: D) { - entries.forEach { it.accept(visitor, data) } - } }