IR: Collapse desugared blocks as a postprocessing pass.

This commit is contained in:
Dmitry Petrov
2016-08-15 14:26:06 +03:00
committed by Dmitry Petrov
parent aa7bf4637b
commit c4bbcadb34
14 changed files with 134 additions and 34 deletions
@@ -0,0 +1,45 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.psi2ir
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrModule
import org.jetbrains.kotlin.ir.declarations.IrModuleImpl
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.generators.IrGeneratorContext
import org.jetbrains.kotlin.psi2ir.generators.IrModuleGenerator
import org.jetbrains.kotlin.psi2ir.transformations.collapseDesugaredBlocks
import org.jetbrains.kotlin.resolve.BindingContext
class Psi2IrTranslator(val configuration: Configuration = Configuration()) {
class Configuration(
val shouldCollapseDesugaredBlocks: Boolean = true
)
fun generateModule(moduleDescriptor: ModuleDescriptor, ktFiles: List<KtFile>, bindingContext: BindingContext): IrModule {
val irModule = IrModuleImpl(moduleDescriptor)
val irGeneratorContext = IrGeneratorContext(ktFiles, irModule, bindingContext)
IrModuleGenerator(irGeneratorContext).generateModuleContent()
postprocess(irModule)
return irModule
}
private fun postprocess(irElement: IrElement) {
if (configuration.shouldCollapseDesugaredBlocks) collapseDesugaredBlocks(irElement)
}
}
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.psi2ir
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.expressions.*
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.psi2ir
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.declarations.*
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.psi2ir
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.psi2ir
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.psi2ir
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtExpression
@@ -14,12 +14,13 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.psi2ir
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.declarations.IrModuleImpl
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
import org.jetbrains.kotlin.resolve.BindingContext
class IrGeneratorContext(
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.psi2ir
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.ir.declarations.IrFileImpl
import org.jetbrains.kotlin.resolve.BindingContext
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.jetbrains.kotlin.psi2ir
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.deparenthesize
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
@@ -0,0 +1,53 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.psi2ir.transformations
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.detach
import org.jetbrains.kotlin.ir.expressions.IrBlockExpression
import org.jetbrains.kotlin.ir.expressions.IrBlockExpressionImpl
import org.jetbrains.kotlin.ir.replaceWith
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
fun collapseDesugaredBlocks(element: IrElement) {
element.accept(CollapseDesugaredBlocks(), null)
}
class CollapseDesugaredBlocks : IrElementVisitor<Unit, Nothing?> {
override fun visitElement(element: IrElement, data: Nothing?) {
element.acceptChildren(this, data)
}
override fun visitBlockExpression(expression: IrBlockExpression, data: Nothing?) {
val transformedBlock = IrBlockExpressionImpl(
expression.startOffset, expression.endOffset, expression.type,
expression.hasResult, expression.isDesugared
)
for (statement in expression.statements) {
statement.accept(this, data)
if (statement is IrBlockExpression && statement.isDesugared) {
statement.statements.forEach {
transformedBlock.addStatement(it.detach())
}
}
else {
transformedBlock.addStatement(statement.detach())
}
}
expression.replaceWith(transformedBlock)
}
}
@@ -19,8 +19,10 @@ package org.jetbrains.kotlin.ir
import org.jetbrains.kotlin.codegen.CodegenTestCase
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleImpl
import org.jetbrains.kotlin.psi2ir.IrGeneratorContext
import org.jetbrains.kotlin.psi2ir.IrModuleGenerator
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
import org.jetbrains.kotlin.psi2ir.generators.IrGeneratorContext
import org.jetbrains.kotlin.psi2ir.generators.IrModuleGenerator
import org.jetbrains.kotlin.psi2ir.transformations.collapseDesugaredBlocks
import org.jetbrains.kotlin.resolve.AnalyzingUtils
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil
import org.jetbrains.kotlin.test.ConfigurationKind
@@ -41,9 +43,8 @@ abstract class AbstractIrGeneratorTestCase : CodegenTestCase() {
val analysisResult = JvmResolveUtil.analyzeAndCheckForErrors(myFiles.psiFiles, myEnvironment)
analysisResult.throwIfError()
AnalyzingUtils.throwExceptionOnErrors(analysisResult.bindingContext)
val irModule = IrModuleImpl(analysisResult.moduleDescriptor)
val irGeneratorContext = IrGeneratorContext(myFiles.psiFiles, irModule, analysisResult.bindingContext)
IrModuleGenerator(irGeneratorContext).generateModuleContent()
val psi2ir = Psi2IrTranslator()
val irModule = psi2ir.generateModule(analysisResult.moduleDescriptor, myFiles.psiFiles, analysisResult.bindingContext)
return testFiles.filter { it.name.endsWith(".kt") }.zip(irModule.files).toMap()
}
}
@@ -44,12 +44,13 @@ abstract class IrElementBase(override val startOffset: Int, override val endOffs
}
}
fun IrElement?.detach() {
fun <T : IrElement?> T.detach(): T {
this?.setTreeLocation(null, DETACHED_SLOT)
return this
}
fun IrElement.replaceWith(otherElement: IrElement) {
parent?.replaceChild(slot, otherElement)
parent?.run { replaceChild(slot, otherElement.detach()) } ?: throw AssertionError("Can't replace a non-root element $this")
}
fun IrElement.assertChild(child: IrElement) {
+7 -8
View File
@@ -28,11 +28,10 @@ IrFile /callWithReorderedArguments.kt
CALL .foo type=kotlin.Unit operator=
a: CALL .noReorder1 type=kotlin.Int operator=
b: CALL .noReorder2 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
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
+10 -11
View File
@@ -1,14 +1,13 @@
IrFunction public fun B.test(): kotlin.Unit
IrExpressionBody
BLOCK type=kotlin.Unit hasResult=false isDesugared=false
BLOCK type=kotlin.Unit hasResult=false isDesugared=true
VAR val tmp0: A
GET_VAR A type=A
VAR val x: kotlin.Int
CALL .component1 type=kotlin.Int operator=COMPONENT_N(index=1)
$this: $RECEIVER of: test type=B
$receiver: GET_VAR tmp0 type=A
VAR val y: kotlin.Int
CALL .component2 type=kotlin.Int operator=COMPONENT_N(index=2)
$this: $RECEIVER of: test type=B
$receiver: GET_VAR tmp0 type=A
VAR val tmp0: A
GET_VAR A type=A
VAR val x: kotlin.Int
CALL .component1 type=kotlin.Int operator=COMPONENT_N(index=1)
$this: $RECEIVER of: test type=B
$receiver: GET_VAR tmp0 type=A
VAR val y: kotlin.Int
CALL .component2 type=kotlin.Int operator=COMPONENT_N(index=2)
$this: $RECEIVER of: test type=B
$receiver: GET_VAR tmp0 type=A