[JS IR] Fix switch transformer in case of if as an expr
- Fix KT-43374
This commit is contained in:
+7
-3
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
|
|||||||
import org.jetbrains.kotlin.ir.types.isAny
|
import org.jetbrains.kotlin.ir.types.isAny
|
||||||
import org.jetbrains.kotlin.ir.util.constructedClassType
|
import org.jetbrains.kotlin.ir.util.constructedClassType
|
||||||
import org.jetbrains.kotlin.ir.util.file
|
import org.jetbrains.kotlin.ir.util.file
|
||||||
|
import org.jetbrains.kotlin.ir.util.render
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
|
|
||||||
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
|
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
|
||||||
@@ -64,8 +65,11 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
|
|||||||
|
|
||||||
private fun IrExpression.maybeOptimizeIntoSwitch(context: JsGenerationContext, transformer: (JsExpression) -> JsStatement): JsStatement {
|
private fun IrExpression.maybeOptimizeIntoSwitch(context: JsGenerationContext, transformer: (JsExpression) -> JsStatement): JsStatement {
|
||||||
if (this is IrWhen) {
|
if (this is IrWhen) {
|
||||||
val stmtTransformer = { stmt: JsStatement -> transformer((stmt as JsExpressionStatement).expression) }
|
val stmtTransformer = { stmt: JsStatement ->
|
||||||
SwitchOptimizer(context, stmtTransformer).tryOptimize(this)?.let { return it }
|
assert(stmt is JsExpressionStatement) { "${render()} is not a statement $stmt" }
|
||||||
|
transformer((stmt as JsExpressionStatement).expression)
|
||||||
|
}
|
||||||
|
SwitchOptimizer(context, isExpression = true, stmtTransformer).tryOptimize(this)?.let { return it }
|
||||||
}
|
}
|
||||||
|
|
||||||
return transformer(accept(IrElementToJsExpressionTransformer(), context))
|
return transformer(accept(IrElementToJsExpressionTransformer(), context))
|
||||||
@@ -112,7 +116,7 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
|
|||||||
JsBinaryOperation(JsBinaryOperator.ASG, varRef, expr).makeStmt()
|
JsBinaryOperation(JsBinaryOperator.ASG, varRef, expr).makeStmt()
|
||||||
}
|
}
|
||||||
|
|
||||||
SwitchOptimizer(context, transformer).tryOptimize(value)?.let {
|
SwitchOptimizer(context, isExpression = true, transformer).tryOptimize(value)?.let {
|
||||||
return JsBlock(JsVars(JsVars.JsVar(varName)), it).withSource(declaration, context)
|
return JsBlock(JsVars(JsVars.JsVar(varName)), it).withSource(declaration, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-10
@@ -11,10 +11,10 @@ import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
|||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
|
|
||||||
class SwitchOptimizer(private val context: JsGenerationContext, private val lastStatementTransformer: (JsStatement) -> JsStatement) {
|
class SwitchOptimizer(private val context: JsGenerationContext, private val isExpression: Boolean, private val lastStatementTransformer: (JsStatement) -> JsStatement) {
|
||||||
|
|
||||||
// TODO: reimplement optimization on top of IR
|
// TODO: reimplement optimization on top of IR
|
||||||
constructor(context: JsGenerationContext) : this(context, { it })
|
constructor(context: JsGenerationContext) : this(context, isExpression = false, { it })
|
||||||
|
|
||||||
private val jsEqeqeq = context.staticContext.backendContext.intrinsics.jsEqeqeq
|
private val jsEqeqeq = context.staticContext.backendContext.intrinsics.jsEqeqeq
|
||||||
private val jsEqeq = context.staticContext.backendContext.intrinsics.jsEqeq
|
private val jsEqeq = context.staticContext.backendContext.intrinsics.jsEqeq
|
||||||
@@ -144,19 +144,27 @@ class SwitchOptimizer(private val context: JsGenerationContext, private val last
|
|||||||
JsDefault().also { jsCases += it }
|
JsDefault().also { jsCases += it }
|
||||||
}
|
}
|
||||||
|
|
||||||
val jsBody = case.body.accept(stmtTransformer, context).asBlock()
|
val lastStatement = if (isExpression) {
|
||||||
var lastStatement = jsBody.statements.lastOrNull()
|
val expression = case.body.accept(exprTransformer, context).makeStmt()
|
||||||
|
val lastStatement = lastStatementTransformer(expression)
|
||||||
|
jsCase.statements += lastStatement
|
||||||
|
lastStatement
|
||||||
|
} else {
|
||||||
|
val jsBody = case.body.accept(stmtTransformer, context).asBlock()
|
||||||
|
var lastStatement = jsBody.statements.lastOrNull()
|
||||||
|
|
||||||
if (lastStatement != null) {
|
if (lastStatement != null) {
|
||||||
lastStatement = lastStatementTransformer(lastStatement)
|
lastStatement = lastStatementTransformer(lastStatement)
|
||||||
jsBody.statements[jsBody.statements.lastIndex] = lastStatement
|
jsBody.statements[jsBody.statements.lastIndex] = lastStatement
|
||||||
|
}
|
||||||
|
|
||||||
|
jsCase.statements += jsBody.statements
|
||||||
|
lastStatement
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastStatement !is JsBreak && lastStatement !is JsContinue && lastStatement !is JsReturn && lastStatement !is JsThrow) {
|
if (lastStatement !is JsBreak && lastStatement !is JsContinue && lastStatement !is JsReturn && lastStatement !is JsThrow) {
|
||||||
jsBody.statements += JsBreak()
|
jsCase.statements += JsBreak()
|
||||||
}
|
}
|
||||||
|
|
||||||
jsCase.statements += jsBody.statements
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return JsSwitch(jsExpr, jsCases)
|
return JsSwitch(jsExpr, jsCases)
|
||||||
|
|||||||
Reference in New Issue
Block a user