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.
*/
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.JsVars.JsVar
@@ -25,9 +25,11 @@ import java.util.HashMap
import java.util.IdentityHashMap
import kotlin.test.assertTrue
import org.jetbrains.k2js.inline.context.NamingContext
import org.jetbrains.k2js.inline.util.needToAlias
fun aliasArgumentsIfNeeded(
context: RenamingContext<*>,
public fun aliasArgumentsIfNeeded(
context: NamingContext,
arguments: List<JsExpression>,
parameters: List<JsParameter>
) {
@@ -60,74 +62,12 @@ fun aliasArgumentsIfNeeded(
/**
* Makes function local names fresh in context
*/
fun renameLocalNames(
context: RenamingContext<*>,
public fun renameLocalNames(
context: NamingContext,
function: JsFunction
) {
for (name in collectLocalNames(function)) {
val freshName = context.getFreshName(name)
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
import com.google.dart.compiler.backend.js.ast.JsExpression
import com.google.dart.compiler.backend.js.ast.RecursiveJsVisitor
import com.google.dart.compiler.backend.js.ast.JsNode
import com.google.dart.compiler.backend.js.ast.JsArrayAccess
import com.google.dart.compiler.backend.js.ast.JsArrayLiteral
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.JsPrefixOperation
import com.google.dart.compiler.backend.js.ast.JsNew
import com.google.dart.compiler.backend.js.ast.JsInvocation
import com.google.dart.compiler.backend.js.ast.RecursiveJsVisitor
public fun canHaveSideEffect(expression: JsExpression): Boolean {
val visitor = SideEffectExpessionVisitor()
visitor.accept(expression)
return visitor.canHaveSideEffect
public fun canHaveSideEffect(x: JsExpression): Boolean {
return with(SideEffectVisitor()) {
accept(x)
!sideEffectFree
}
}
private class SideEffectExpessionVisitor() : RecursiveJsVisitor() {
public var canHaveSideEffect: Boolean = false
private set
public fun needToAlias(x: JsExpression): Boolean {
return with(NeedToAliasVisitor()) {
accept(x)
!sideEffectFree
}
}
private open class SideEffectVisitor() : RecursiveJsVisitor() {
public var sideEffectFree: Boolean = true
protected set
override fun visitElement(node: JsNode?) {
if (!canHaveSideEffect) {
super<RecursiveJsVisitor>.visitElement(node)
sideEffectFree = sideEffectFree && isSideEffectFree(node)
if (sideEffectFree) {
super.visitElement(node)
}
}
override fun visitBinaryExpression(x: JsBinaryOperation?) {
canHaveSideEffect = true
}
protected open fun isSideEffectFree(node: JsNode?): Boolean =
when (node) {
is JsValueLiteral,
is JsConditional,
is JsBinaryOperation,
is JsArrayAccess,
is JsArrayLiteral,
is JsNameRef -> true
else -> false
}
}
override fun visitPostfixOperation(x: JsPostfixOperation?) {
canHaveSideEffect = true
}
override fun visitPrefixOperation(x: JsPrefixOperation?) {
canHaveSideEffect = true
}
override fun visitNew(x: JsNew?) {
canHaveSideEffect = true
}
override fun visitInvocation(invocation: JsInvocation?) {
canHaveSideEffect = true
}
private class NeedToAliasVisitor() : SideEffectVisitor() {
override fun isSideEffectFree(node: JsNode?): Boolean =
when (node) {
is JsThisRef,
is JsConditional,
is JsBinaryOperation,
is JsArrayLiteral -> false
is JsInvocation -> isFunctionCreatorInvocation(node)
else -> super.isSideEffectFree(node)
}
}