IrComposite - block introducing immediate declarations to the surrounding scope.

E.g., destructuring declaration is represented as IrComposite.
This commit is contained in:
Dmitry Petrov
2016-09-09 12:15:37 +03:00
committed by Dmitry Petrov
parent aaa5fa4209
commit 838b639692
12 changed files with 132 additions and 51 deletions
@@ -93,10 +93,8 @@ class StatementGenerator(
)
override fun visitDestructuringDeclaration(multiDeclaration: KtDestructuringDeclaration, data: Nothing?): IrStatement {
// TODO use some special form that introduces multiple declarations into surrounding scope?
val irBlock = IrBlockImpl(multiDeclaration.startOffset, multiDeclaration.endOffset,
context.builtIns.unitType, IrOperator.DESTRUCTURING_DECLARATION)
val irBlock = IrCompositeImpl(multiDeclaration.startOffset, multiDeclaration.endOffset,
context.builtIns.unitType, IrOperator.DESTRUCTURING_DECLARATION)
val ktInitializer = multiDeclaration.initializer!!
val containerValue = scope.createTemporaryVariableInBlock(ktInitializer.genExpr(), irBlock, "container")
@@ -105,7 +103,7 @@ class StatementGenerator(
return irBlock
}
fun declareComponentVariablesInBlock(multiDeclaration: KtDestructuringDeclaration, irBlock: IrBlockImpl, containerValue: IntermediateValue) {
fun declareComponentVariablesInBlock(multiDeclaration: KtDestructuringDeclaration, irBlock: IrContainerExpressionBase, containerValue: IntermediateValue) {
val callGenerator = CallGenerator(this)
for ((index, ktEntry) in multiDeclaration.entries.withIndex()) {
val componentResolvedCall = getOrFail(BindingContext.COMPONENT_RESOLVED_CALL, ktEntry)
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrExpressionWithCopy
import org.jetbrains.kotlin.ir.expressions.impl.IrContainerExpressionBase
import org.jetbrains.kotlin.psi2ir.generators.Scope
import org.jetbrains.kotlin.types.KotlinType
@@ -28,7 +29,7 @@ class RematerializableValue(val irExpression: IrExpressionWithCopy) : Intermedia
override fun load(): IrExpression = irExpression.copy()
}
fun Scope.createTemporaryVariableInBlock(irExpression: IrExpression, block: IrBlockImpl, nameHint: String? = null): IntermediateValue {
fun Scope.createTemporaryVariableInBlock(irExpression: IrExpression, block: IrContainerExpressionBase, nameHint: String? = null): IntermediateValue {
val temporaryVariable = createTemporaryVariable(irExpression, nameHint)
block.addStatement(temporaryVariable)
return VariableLValue(temporaryVariable)
@@ -16,13 +16,17 @@
package org.jetbrains.kotlin.ir.expressions
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.detach
interface IrBlock : IrExpression {
interface IrContainerExpression : IrExpression, IrStatementContainer {
val operator: IrOperator?
val statements: List<IrStatement>
val isTransparentScope: Boolean
}
interface IrBlock : IrContainerExpression {
override val isTransparentScope: Boolean
get() = false
}
interface IrComposite : IrContainerExpression {
override val isTransparentScope: Boolean
get() = true
}
@@ -25,10 +25,12 @@ interface IrExpressionBody : IrBody {
var expression: IrExpression
}
interface IrBlockBody : IrBody {
interface IrStatementContainer {
val statements: List<IrStatement>
}
interface IrBlockBody : IrBody, IrStatementContainer
interface IrSyntheticBody : IrBody {
val kind: IrSyntheticBodyKind
}
@@ -16,49 +16,20 @@
package org.jetbrains.kotlin.ir.expressions.impl
import org.jetbrains.kotlin.ir.*
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.detach
import org.jetbrains.kotlin.ir.expressions.IrBlock
import org.jetbrains.kotlin.ir.expressions.IrOperator
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.types.KotlinType
import java.util.*
class IrBlockImpl(startOffset: Int, endOffset: Int, type: KotlinType, override val operator: IrOperator? = null):
IrExpressionBase(startOffset, endOffset, type), IrBlock {
class IrBlockImpl(startOffset: Int, endOffset: Int, type: KotlinType, operator: IrOperator? = null):
IrContainerExpressionBase(startOffset, endOffset, type, operator), IrBlock {
constructor(startOffset: Int, endOffset: Int, type: KotlinType, operator: IrOperator?, statements: List<IrStatement>) :
this(startOffset, endOffset, type, operator) {
addAll(statements)
}
override val statements: MutableList<IrStatement> = ArrayList(2)
fun addStatement(statement: IrStatement) {
statement.assertDetached()
statement.setTreeLocation(this, statements.size)
statements.add(statement)
}
fun addAll(newStatements: List<IrStatement>) {
newStatements.forEach { it.assertDetached() }
val originalSize = this.statements.size
this.statements.addAll(newStatements)
newStatements.forEachIndexed { i, irStatement ->
irStatement.setTreeLocation(this, originalSize + i)
}
}
override fun getChild(slot: Int): IrElement? =
statements.getOrNull(slot)
override fun replaceChild(slot: Int, newChild: IrElement) {
if (slot < 0 || slot >= statements.size) throwNoSuchSlot(slot)
newChild.assertDetached()
statements[slot].detach()
statements[slot] = newChild.assertCast()
newChild.setTreeLocation(this, slot)
}
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitBlock(this, data)
@@ -0,0 +1,39 @@
/*
* 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.impl
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.expressions.IrComposite
import org.jetbrains.kotlin.ir.expressions.IrOperator
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.types.KotlinType
class IrCompositeImpl(startOffset: Int, endOffset: Int, type: KotlinType, operator: IrOperator? = null) :
IrContainerExpressionBase(startOffset, endOffset, type, operator), IrComposite {
constructor(startOffset: Int, endOffset: Int, type: KotlinType, operator: IrOperator?, statements: List<IrStatement>) :
this(startOffset, endOffset, type, operator) {
addAll(statements)
}
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitComposite(this, data)
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
statements.forEach { it.accept(visitor, data) }
}
}
@@ -0,0 +1,55 @@
/*
* 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.impl
import org.jetbrains.kotlin.ir.*
import org.jetbrains.kotlin.ir.expressions.IrOperator
import org.jetbrains.kotlin.ir.expressions.IrContainerExpression
import org.jetbrains.kotlin.types.KotlinType
import java.util.*
abstract class IrContainerExpressionBase(startOffset: Int, endOffset: Int, type: KotlinType, override val operator: IrOperator? = null):
IrExpressionBase(startOffset, endOffset, type), IrContainerExpression {
override val statements: MutableList<IrStatement> = ArrayList(2)
fun addStatement(statement: IrStatement) {
statement.assertDetached()
statement.setTreeLocation(this, statements.size)
statements.add(statement)
}
fun addAll(newStatements: List<IrStatement>) {
newStatements.forEach { it.assertDetached() }
val originalSize = this.statements.size
this.statements.addAll(newStatements)
newStatements.forEachIndexed { i, irStatement ->
irStatement.setTreeLocation(this, originalSize + i)
}
}
override fun getChild(slot: Int): IrElement? =
statements.getOrNull(slot)
override fun replaceChild(slot: Int, newChild: IrElement) {
if (slot < 0 || slot >= statements.size) throwNoSuchSlot(slot)
newChild.assertDetached()
statements[slot].detach()
statements[slot] = newChild.assertCast()
newChild.setTreeLocation(this, slot)
}
}
@@ -102,6 +102,9 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
override fun visitBlock(expression: IrBlock, data: Nothing?): String =
"BLOCK type=${expression.type.render()} operator=${expression.operator}"
override fun visitComposite(expression: IrComposite, data: Nothing?): String =
"COMPOSITE type=${expression.type.render()} operator=${expression.operator}"
override fun visitReturn(expression: IrReturn, data: Nothing?): String =
"RETURN type=${expression.type.render()} from='${expression.returnTarget.ref()}'"
@@ -52,7 +52,9 @@ interface IrElementVisitor<out R, in D> {
fun visitVararg(expression: IrVararg, data: D) = visitExpression(expression, data)
fun visitSpreadElement(spread: IrSpreadElement, data: D) = visitElement(spread, data)
fun visitBlock(expression: IrBlock, data: D) = visitExpression(expression, data)
fun visitContainerExpression(expression: IrContainerExpression, data: D) = visitExpression(expression, data)
fun visitBlock(expression: IrBlock, data: D) = visitContainerExpression(expression, data)
fun visitComposite(expression: IrComposite, data: D) = visitContainerExpression(expression, data)
fun visitStringConcatenation(expression: IrStringConcatenation, data: D) = visitExpression(expression, data)
fun visitThisReference(expression: IrThisReference, data: D) = visitExpression(expression, data)
@@ -102,7 +102,13 @@ interface IrElementVisitorVoid : IrElementVisitor<Unit, Nothing?> {
fun visitSpreadElement(spread: IrSpreadElement) = visitElement(spread)
override fun visitSpreadElement(spread: IrSpreadElement, data: Nothing?) = visitSpreadElement(spread)
fun visitBlock(expression: IrBlock) = visitExpression(expression)
fun visitContainerExpression(expression: IrContainerExpression) = visitExpression(expression)
override fun visitContainerExpression(expression: IrContainerExpression, data: Nothing?) = visitContainerExpression(expression)
fun visitComposite(expression: IrComposite) = visitContainerExpression(expression)
override fun visitComposite(expression: IrComposite, data: Nothing?) = visitComposite(expression)
fun visitBlock(expression: IrBlock) = visitContainerExpression(expression)
override fun visitBlock(expression: IrBlock, data: Nothing?) = visitBlock(expression)
fun visitStringConcatenation(expression: IrStringConcatenation) = visitExpression(expression)
+1 -1
View File
@@ -19,7 +19,7 @@ FILE /destructuring1.kt
CONST Int type=kotlin.Int value='2'
FUN public fun B.test(): kotlin.Unit
BLOCK_BODY
BLOCK type=kotlin.Unit operator=DESTRUCTURING_DECLARATION
COMPOSITE type=kotlin.Unit operator=DESTRUCTURING_DECLARATION
VAR val tmp0_container: A
GET_OBJECT 'A' type=A
VAR val x: kotlin.Int
@@ -15,7 +15,7 @@ FILE /smartCastsWithDestructuring.kt
if: TYPE_OP operator=NOT_INSTANCEOF typeOperand=I2
GET_VAR 'value-parameter x: I1' type=I1 operator=null
then: RETURN type=kotlin.Nothing from='test(I1): Unit'
BLOCK type=kotlin.Unit operator=DESTRUCTURING_DECLARATION
COMPOSITE type=kotlin.Unit operator=DESTRUCTURING_DECLARATION
VAR val tmp0_container: I1
GET_VAR 'value-parameter x: I1' type=I1 operator=null
VAR val c1: kotlin.Int