Add possibility to interpret and fold IrStringConcatenation expression
This commit is contained in:
+4
-1
@@ -398,7 +398,10 @@ private fun unfoldStringConcatenation(expression: IrStringConcatenation, environ
|
||||
is Primitive<*> -> {
|
||||
// This block is not really needed, but this way it is easier to handle `toString` with `treatFloatInSpecialWay` enabled.
|
||||
callStack.popState()
|
||||
val toStringCall = IrCallImpl.fromSymbolOwner(UNDEFINED_OFFSET, UNDEFINED_OFFSET, environment.irBuiltIns.memberToString)
|
||||
val toStringCall = IrCallImpl.fromSymbolOwner(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
if (state.isNull()) environment.irBuiltIns.extensionToString else environment.irBuiltIns.memberToString
|
||||
)
|
||||
callStack.pushSimpleInstruction(toStringCall)
|
||||
callStack.pushState(state)
|
||||
}
|
||||
|
||||
+53
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.ir.declarations.IrField
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrStringConcatenationImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreter
|
||||
import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration
|
||||
@@ -21,6 +22,8 @@ import org.jetbrains.kotlin.ir.interpreter.toIrConst
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
class IrConstTransformer(
|
||||
private val interpreter: IrInterpreter,
|
||||
@@ -100,6 +103,56 @@ class IrConstTransformer(
|
||||
return super.visitField(declaration)
|
||||
}
|
||||
|
||||
override fun visitStringConcatenation(expression: IrStringConcatenation): IrExpression {
|
||||
fun IrExpression.wrapInStringConcat(): IrExpression = IrStringConcatenationImpl(
|
||||
this.startOffset, this.endOffset, expression.type, listOf(this@wrapInStringConcat)
|
||||
)
|
||||
|
||||
fun IrExpression.wrapInToStringConcatAndInterpret(): IrExpression = wrapInStringConcat().interpret(failAsError = false)
|
||||
|
||||
// here `StringBuilder`'s list is used to optimize memory, everything works without it
|
||||
val folded = mutableListOf<IrExpression>()
|
||||
val buildersList = mutableListOf<StringBuilder>()
|
||||
for (next in expression.arguments) {
|
||||
val last = folded.lastOrNull()
|
||||
when {
|
||||
!next.wrapInStringConcat().canBeInterpreted() -> {
|
||||
folded += next
|
||||
buildersList.add(StringBuilder())
|
||||
}
|
||||
last == null || !last.wrapInStringConcat().canBeInterpreted() -> {
|
||||
val result = next.wrapInToStringConcatAndInterpret()
|
||||
folded += result
|
||||
buildersList.add(StringBuilder((result as? IrConst<*>)?.value?.toString() ?: ""))
|
||||
}
|
||||
else -> {
|
||||
val nextAsConst = next.wrapInToStringConcatAndInterpret()
|
||||
if (nextAsConst !is IrConst<*>) {
|
||||
folded += next
|
||||
buildersList.add(StringBuilder())
|
||||
} else {
|
||||
folded[folded.size - 1] = IrConstImpl.string(
|
||||
// Inlined strings may have `last.startOffset > next.endOffset`
|
||||
min(last.startOffset, next.startOffset), max(last.endOffset, next.endOffset), expression.type, ""
|
||||
)
|
||||
buildersList.last().append(nextAsConst.value.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val foldedConst = folded.singleOrNull() as? IrConst<*>
|
||||
if (foldedConst != null) {
|
||||
return IrConstImpl.string(expression.startOffset, expression.endOffset, expression.type, buildersList.single().toString())
|
||||
}
|
||||
|
||||
folded.zip(buildersList).forEach {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
(it.first as? IrConst<String>)?.value = it.second.toString()
|
||||
}
|
||||
return IrStringConcatenationImpl(expression.startOffset, expression.endOffset, expression.type, folded)
|
||||
}
|
||||
|
||||
override fun visitDeclaration(declaration: IrDeclarationBase): IrStatement {
|
||||
transformAnnotations(declaration)
|
||||
return super.visitDeclaration(declaration)
|
||||
|
||||
Reference in New Issue
Block a user