Implement inlining of default parameters in JS BE

Fix KT-17910
This commit is contained in:
Alexey Andreev
2017-05-24 19:57:01 +03:00
parent 40bbf82a41
commit 0e31c14a86
24 changed files with 421 additions and 8 deletions
@@ -18,18 +18,16 @@ package org.jetbrains.kotlin.js.inline.clean
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.backend.ast.metadata.hasDefaultValue
import org.jetbrains.kotlin.js.inline.util.toIdentitySet
import org.jetbrains.kotlin.js.backend.ast.metadata.staticRef
import org.jetbrains.kotlin.js.inline.util.zipWithDefault
import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.decomposeAssignmentToVariable
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.flattenStatement
/**
* Removes initializers for default parameters with defined arguments given
* Expands initializers for default parameters with undefined arguments given
*
* @see isInitializer
*/
fun removeDefaultInitializers(arguments: List<JsExpression>, parameters: List<JsParameter>, body: JsBlock) {
val toRemove = getDefaultParamsNames(arguments, parameters, initialized = true)
@@ -45,8 +43,11 @@ fun removeDefaultInitializers(arguments: List<JsExpression>, parameters: List<Js
when {
name != null && name in toRemove ->
listOf<JsStatement>()
name != null && name in toExpand ->
flattenStatement((it as JsIf).thenStatement)
name != null && name in toExpand -> {
val thenStatement = (it as JsIf).thenStatement
markAssignmentAsStaticRef(name, thenStatement)
flattenStatement(thenStatement)
}
else ->
listOf(it)
}
@@ -56,6 +57,19 @@ fun removeDefaultInitializers(arguments: List<JsExpression>, parameters: List<Js
statements.addAll(newStatements)
}
private fun markAssignmentAsStaticRef(name: JsName, node: JsNode) {
node.accept(object : RecursiveJsVisitor() {
override fun visitBinaryExpression(x: JsBinaryOperation) {
decomposeAssignmentToVariable(x)?.let { (assignmentTarget, assignmentExpr) ->
if (assignmentTarget == name) {
assignmentTarget.staticRef = assignmentExpr
}
}
super.visitBinaryExpression(x)
}
})
}
private fun getNameFromInitializer(statement: JsStatement): JsName? {
val ifStmt = (statement as? JsIf)
val testExpr = ifStmt?.ifExpression
@@ -118,6 +132,6 @@ private fun getDefaultParamsNames(
.filter { initialized == !JsAstUtils.isUndefinedExpression(it.first) }
val names = relevantParams.map { it.second.name }
return names.toIdentitySet()
return names.toSet()
}
@@ -44,6 +44,7 @@ fun aliasArgumentsIfNeeded(
for (defaultParam in defaultParams) {
val paramName = defaultParam.name
val freshName = JsScope.declareTemporaryName(paramName.ident)
freshName.copyMetadataFrom(paramName)
context.newVar(freshName)
context.replaceName(paramName, freshName.makeRef())