Desugar basic binary operators (+, -, *, /, %, ..).
Fold String.plus calls to IrStringConcatenationExpression.
This commit is contained in:
committed by
Dmitry Petrov
parent
287d804131
commit
1b018a6ead
@@ -22,12 +22,14 @@ import org.jetbrains.kotlin.ir.declarations.IrModule
|
||||
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.psi2ir.transformations.foldStringConcatenation
|
||||
import org.jetbrains.kotlin.psi2ir.transformations.inlineDesugaredBlocks
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
|
||||
class Psi2IrTranslator(val configuration: Configuration = Configuration()) {
|
||||
class Configuration(
|
||||
val shouldCollapseDesugaredBlocks: Boolean = true
|
||||
val shouldInlineDesugaredBlocks: Boolean = true,
|
||||
val shouldFoldStringConcatenation: Boolean = true
|
||||
)
|
||||
|
||||
fun generateModule(moduleDescriptor: ModuleDescriptor, ktFiles: List<KtFile>, bindingContext: BindingContext): IrModule {
|
||||
@@ -38,6 +40,7 @@ class Psi2IrTranslator(val configuration: Configuration = Configuration()) {
|
||||
}
|
||||
|
||||
private fun postprocess(irElement: IrElement) {
|
||||
if (configuration.shouldCollapseDesugaredBlocks) collapseDesugaredBlocks(irElement)
|
||||
if (configuration.shouldInlineDesugaredBlocks) inlineDesugaredBlocks(irElement)
|
||||
if (configuration.shouldFoldStringConcatenation) foldStringConcatenation(irElement)
|
||||
}
|
||||
}
|
||||
|
||||
+10
-1
@@ -40,7 +40,9 @@ val KT_OPERATOR_TO_IR_OPERATOR = hashMapOf(
|
||||
KtTokens.PLUS to IrOperator.PLUS,
|
||||
KtTokens.MINUS to IrOperator.MINUS,
|
||||
KtTokens.MUL to IrOperator.MUL,
|
||||
KtTokens.DIV to IrOperator.DIV
|
||||
KtTokens.DIV to IrOperator.DIV,
|
||||
KtTokens.PERC to IrOperator.PERC,
|
||||
KtTokens.RANGE to IrOperator.RANGE
|
||||
)
|
||||
|
||||
val AUGMENTED_ASSIGNMENTS = KtTokens.AUGMENTED_ASSIGNMENTS
|
||||
@@ -55,10 +57,17 @@ class IrOperatorExpressionGenerator(val irStatementGenerator: IrStatementGenerat
|
||||
return when (ktOperator) {
|
||||
KtTokens.EQ -> generateAssignment(expression)
|
||||
in AUGMENTED_ASSIGNMENTS -> generateAugmentedAssignment(expression, ktOperator)
|
||||
in BINARY_OPERATORS_WITH_CALLS -> generateBinaryOperatorWithConventionalCall(expression, ktOperator)
|
||||
else -> createDummyExpression(expression, ktOperator.toString())
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateBinaryOperatorWithConventionalCall(expression: KtBinaryExpression, ktOperator: IElementType): IrExpression {
|
||||
val irOperator = getIrOperator(ktOperator)
|
||||
val operatorCall = getResolvedCall(expression)!!
|
||||
return IrCallGenerator(irStatementGenerator).generateCall(expression, operatorCall, irOperator)
|
||||
}
|
||||
|
||||
private fun generateAugmentedAssignment(expression: KtBinaryExpression, ktOperator: IElementType): IrExpression {
|
||||
val ktLeft = expression.left!!
|
||||
|
||||
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.detach
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCallExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStringConcatenationExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStringConcatenationExpressionImpl
|
||||
import org.jetbrains.kotlin.ir.replaceWith
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import java.util.*
|
||||
|
||||
fun foldStringConcatenation(element: IrElement) {
|
||||
element.accept(FoldStringConcatenation(), null)
|
||||
}
|
||||
|
||||
class FoldStringConcatenation : IrElementVisitor<Unit, Nothing?> {
|
||||
override fun visitElement(element: IrElement, data: Nothing?) {
|
||||
element.acceptChildren(this, data)
|
||||
}
|
||||
|
||||
override fun visitCallExpression(expression: IrCallExpression, data: Nothing?) {
|
||||
if (!isStringPlus(expression.descriptor)) {
|
||||
visitElement(expression, data)
|
||||
return
|
||||
}
|
||||
|
||||
val arguments = ArrayList<IrExpression>()
|
||||
collectStringConcatenationArguments(expression, arguments)
|
||||
val irStringConcatenation = IrStringConcatenationExpressionImpl(expression.startOffset, expression.endOffset, expression.type)
|
||||
arguments.forEach { irStringConcatenation.addArgument(it) }
|
||||
|
||||
expression.replaceWith(irStringConcatenation)
|
||||
}
|
||||
|
||||
private fun collectStringConcatenationArguments(expression: IrExpression, arguments: ArrayList<IrExpression>) {
|
||||
when {
|
||||
expression is IrCallExpression && isStringPlus(expression.descriptor)-> {
|
||||
collectStringConcatenationArguments(expression.dispatchReceiver!!, arguments)
|
||||
collectStringConcatenationArguments(expression.getArgument(0)!!, arguments)
|
||||
}
|
||||
expression is IrStringConcatenationExpression -> {
|
||||
arguments.addAll(expression.arguments)
|
||||
expression.arguments.forEach { it.detach() }
|
||||
}
|
||||
else -> {
|
||||
arguments.add(expression)
|
||||
expression.detach()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isStringPlus(descriptor: CallableDescriptor): Boolean {
|
||||
if (descriptor.name != OperatorNameConventions.PLUS) return false
|
||||
val dispatchReceiverType = descriptor.dispatchReceiverParameter?.type ?: return false
|
||||
if (!KotlinBuiltIns.isString(dispatchReceiverType)) return false
|
||||
return true
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -23,11 +23,11 @@ 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)
|
||||
fun inlineDesugaredBlocks(element: IrElement) {
|
||||
element.accept(InlineDesugaredBlocks(), null)
|
||||
}
|
||||
|
||||
class CollapseDesugaredBlocks : IrElementVisitor<Unit, Nothing?> {
|
||||
class InlineDesugaredBlocks : IrElementVisitor<Unit, Nothing?> {
|
||||
override fun visitElement(element: IrElement, data: Nothing?) {
|
||||
element.acceptChildren(this, data)
|
||||
}
|
||||
@@ -48,7 +48,7 @@ sealed class IrOperator(val debugName: String) {
|
||||
object MINUS : IrOperator("MINUS")
|
||||
object MUL : IrOperator("MUL")
|
||||
object DIV : IrOperator("DIV")
|
||||
object MOD : IrOperator("MOD")
|
||||
object PERC : IrOperator("PERC")
|
||||
|
||||
object EQ : IrOperator("EQ")
|
||||
object PLUSEQ : IrOperator("PLUSEQ")
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ class IrStringConcatenationExpressionImpl(
|
||||
}
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||
visitor.visitStringTemplate(this, data)
|
||||
visitor.visitStringConcatenation(this, data)
|
||||
|
||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||
arguments.forEach { it.accept(visitor, data) }
|
||||
|
||||
@@ -99,6 +99,9 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
|
||||
"SET_PROPERTY ${if (expression.isSafe) "?." else "."}${expression.descriptor.name}" +
|
||||
"type=${expression.renderType()}"
|
||||
|
||||
override fun visitStringConcatenation(expression: IrStringConcatenationExpression, data: Nothing?): String =
|
||||
"STRING_CONCATENATION type=${expression.renderType()}"
|
||||
|
||||
override fun visitTypeOperatorExpression(expression: IrTypeOperatorExpression, data: Nothing?): String {
|
||||
return "TYPE_OP operator=${expression.operator} typeOperand=${expression.typeOperand.render()}"
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ interface IrElementVisitor<out R, in D> {
|
||||
fun <T> visitLiteral(expression: IrLiteralExpression<T>, data: D): R = visitExpression(expression, data)
|
||||
fun visitReturnExpression(expression: IrReturnExpression, data: D): R = visitExpression(expression, data)
|
||||
fun visitBlockExpression(expression: IrBlockExpression, data: D): R = visitExpression(expression, data)
|
||||
fun visitStringTemplate(expression: IrStringConcatenationExpression, data: D) = visitExpression(expression, data)
|
||||
fun visitStringConcatenation(expression: IrStringConcatenationExpression, data: D) = visitExpression(expression, data)
|
||||
fun visitThisExpression(expression: IrThisExpression, data: D) = visitExpression(expression, data)
|
||||
|
||||
fun visitDeclarationReference(expression: IrDeclarationReference, data: D) = visitExpression(expression, data)
|
||||
|
||||
Reference in New Issue
Block a user