JS inline refactor: splitted Renaming.kt

This commit is contained in:
Alexey Tsvetkov
2014-10-02 15:40:40 +04:00
committed by Zalim Bashorov
parent 17a78dd522
commit 6018b103cc
2 changed files with 61 additions and 100 deletions
@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.k2js.inline package org.jetbrains.k2js.inline.util
import com.google.dart.compiler.backend.js.ast.* import com.google.dart.compiler.backend.js.ast.*
import com.google.dart.compiler.backend.js.ast.JsVars.JsVar import com.google.dart.compiler.backend.js.ast.JsVars.JsVar
@@ -25,9 +25,11 @@ import java.util.HashMap
import java.util.IdentityHashMap import java.util.IdentityHashMap
import kotlin.test.assertTrue import kotlin.test.assertTrue
import org.jetbrains.k2js.inline.context.NamingContext
import org.jetbrains.k2js.inline.util.needToAlias
fun aliasArgumentsIfNeeded( public fun aliasArgumentsIfNeeded(
context: RenamingContext<*>, context: NamingContext,
arguments: List<JsExpression>, arguments: List<JsExpression>,
parameters: List<JsParameter> parameters: List<JsParameter>
) { ) {
@@ -60,74 +62,12 @@ fun aliasArgumentsIfNeeded(
/** /**
* Makes function local names fresh in context * Makes function local names fresh in context
*/ */
fun renameLocalNames( public fun renameLocalNames(
context: RenamingContext<*>, context: NamingContext,
function: JsFunction function: JsFunction
) { ) {
for (name in collectLocalNames(function)) { for (name in collectLocalNames(function)) {
val freshName = context.getFreshName(name) val freshName = context.getFreshName(name)
context.replaceName(name, freshName.makeRef()) context.replaceName(name, freshName.makeRef())
} }
} }
private fun isLambdaConstructor(x: JsInvocation): Boolean {
val staticRef = (x.getQualifier() as? HasName)?.getName()?.getStaticRef()
return when (staticRef) {
is JsFunction -> isLambdaConstructor(staticRef)
else -> false
}
}
private fun isLambdaConstructor(x: JsFunction): Boolean {
return InvocationUtil.getInnerFunction(x) != null;
}
private fun needToAlias(x: JsExpression): Boolean {
val visitor = ShouldBeAliasedVisitor()
visitor.accept(x)
return visitor.shouldBeAliased
}
private class ShouldBeAliasedVisitor(): RecursiveJsVisitor() {
public var shouldBeAliased: Boolean = false
private set
override fun visitElement(node: JsNode?) {
if (!shouldBeAliased) {
super<RecursiveJsVisitor>.visitElement(node)
}
}
override fun visitBinaryExpression(x: JsBinaryOperation?) {
shouldBeAliased = true
}
override fun visitInvocation(invocation: JsInvocation?) {
if (invocation != null && !isLambdaConstructor(invocation)) {
shouldBeAliased = true
}
}
override fun visitPostfixOperation(x: JsPostfixOperation?) {
shouldBeAliased = true
}
override fun visitPrefixOperation(x: JsPrefixOperation?) {
shouldBeAliased = true
}
override fun visitObjectLiteral(x: JsObjectLiteral?) {
shouldBeAliased = true
}
override fun visitNew(x: JsNew?) {
shouldBeAliased = true
}
override fun visitThis(x: JsLiteral.JsThisRef?) {
shouldBeAliased = true
}
override fun visitArray(x: JsArrayLiteral?) {
shouldBeAliased = true
}
}
@@ -16,48 +16,69 @@
package org.jetbrains.k2js.inline.util package org.jetbrains.k2js.inline.util
import com.google.dart.compiler.backend.js.ast.JsExpression import com.google.dart.compiler.backend.js.ast.JsArrayAccess
import com.google.dart.compiler.backend.js.ast.RecursiveJsVisitor import com.google.dart.compiler.backend.js.ast.JsArrayLiteral
import com.google.dart.compiler.backend.js.ast.JsNode
import com.google.dart.compiler.backend.js.ast.JsBinaryOperation import com.google.dart.compiler.backend.js.ast.JsBinaryOperation
import com.google.dart.compiler.backend.js.ast.JsConditional
import com.google.dart.compiler.backend.js.ast.JsExpression
import com.google.dart.compiler.backend.js.ast.JsInvocation
import com.google.dart.compiler.backend.js.ast.JsLiteral
import com.google.dart.compiler.backend.js.ast.JsLiteral.JsThisRef
import com.google.dart.compiler.backend.js.ast.JsLiteral.JsValueLiteral
import com.google.dart.compiler.backend.js.ast.JsNameRef
import com.google.dart.compiler.backend.js.ast.JsNew
import com.google.dart.compiler.backend.js.ast.JsNode
import com.google.dart.compiler.backend.js.ast.JsObjectLiteral
import com.google.dart.compiler.backend.js.ast.JsPostfixOperation import com.google.dart.compiler.backend.js.ast.JsPostfixOperation
import com.google.dart.compiler.backend.js.ast.JsPrefixOperation import com.google.dart.compiler.backend.js.ast.JsPrefixOperation
import com.google.dart.compiler.backend.js.ast.JsNew import com.google.dart.compiler.backend.js.ast.RecursiveJsVisitor
import com.google.dart.compiler.backend.js.ast.JsInvocation
public fun canHaveSideEffect(expression: JsExpression): Boolean { public fun canHaveSideEffect(x: JsExpression): Boolean {
val visitor = SideEffectExpessionVisitor() return with(SideEffectVisitor()) {
visitor.accept(expression) accept(x)
return visitor.canHaveSideEffect !sideEffectFree
}
} }
private class SideEffectExpessionVisitor() : RecursiveJsVisitor() { public fun needToAlias(x: JsExpression): Boolean {
public var canHaveSideEffect: Boolean = false return with(NeedToAliasVisitor()) {
private set accept(x)
!sideEffectFree
}
}
private open class SideEffectVisitor() : RecursiveJsVisitor() {
public var sideEffectFree: Boolean = true
protected set
override fun visitElement(node: JsNode?) { override fun visitElement(node: JsNode?) {
if (!canHaveSideEffect) { sideEffectFree = sideEffectFree && isSideEffectFree(node)
super<RecursiveJsVisitor>.visitElement(node)
if (sideEffectFree) {
super.visitElement(node)
} }
} }
override fun visitBinaryExpression(x: JsBinaryOperation?) { protected open fun isSideEffectFree(node: JsNode?): Boolean =
canHaveSideEffect = true when (node) {
} is JsValueLiteral,
is JsConditional,
is JsBinaryOperation,
is JsArrayAccess,
is JsArrayLiteral,
is JsNameRef -> true
else -> false
}
}
override fun visitPostfixOperation(x: JsPostfixOperation?) { private class NeedToAliasVisitor() : SideEffectVisitor() {
canHaveSideEffect = true override fun isSideEffectFree(node: JsNode?): Boolean =
} when (node) {
is JsThisRef,
override fun visitPrefixOperation(x: JsPrefixOperation?) { is JsConditional,
canHaveSideEffect = true is JsBinaryOperation,
} is JsArrayLiteral -> false
is JsInvocation -> isFunctionCreatorInvocation(node)
override fun visitNew(x: JsNew?) { else -> super.isSideEffectFree(node)
canHaveSideEffect = true }
}
override fun visitInvocation(invocation: JsInvocation?) {
canHaveSideEffect = true
}
} }