diff --git a/js/js.inliner/src/org/jetbrains/k2js/inline/Renaming.kt b/js/js.inliner/src/org/jetbrains/k2js/inline/util/namingUtils.kt similarity index 52% rename from js/js.inliner/src/org/jetbrains/k2js/inline/Renaming.kt rename to js/js.inliner/src/org/jetbrains/k2js/inline/util/namingUtils.kt index eac92190bf2..0df446b1d2f 100644 --- a/js/js.inliner/src/org/jetbrains/k2js/inline/Renaming.kt +++ b/js/js.inliner/src/org/jetbrains/k2js/inline/util/namingUtils.kt @@ -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, parameters: List ) { @@ -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.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 - } -} +} \ No newline at end of file diff --git a/js/js.inliner/src/org/jetbrains/k2js/inline/util/sideEffectUtils.kt b/js/js.inliner/src/org/jetbrains/k2js/inline/util/sideEffectUtils.kt index 1931acd9515..2e596132395 100644 --- a/js/js.inliner/src/org/jetbrains/k2js/inline/util/sideEffectUtils.kt +++ b/js/js.inliner/src/org/jetbrains/k2js/inline/util/sideEffectUtils.kt @@ -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.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) + } } \ No newline at end of file