diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsFor.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsFor.java index 54d3fff7579..5d6daaff112 100644 --- a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsFor.java +++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsFor.java @@ -133,7 +133,7 @@ public class JsFor extends SourceInfoAwareJsNode implements JsStatement { if (initVars != null) { result = new JsFor(initVars.deepCopy(), conditionCopy, incrementalExprCopy, bodyCopy); } else { - result = new JsFor(initExpression.deepCopy(), conditionCopy, incrementExpression, bodyCopy); + result = new JsFor(initExpression.deepCopy(), conditionCopy, incrementalExprCopy, bodyCopy); } return result.withMetadataFrom(this); diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/TemporaryAssignmentElimination.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/TemporaryAssignmentElimination.kt index 19570433fc7..b2b9957a023 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/TemporaryAssignmentElimination.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/TemporaryAssignmentElimination.kt @@ -121,6 +121,16 @@ internal class TemporaryAssignmentElimination(private val root: JsBlock) { override fun visitBreak(x: JsBreak) { } override fun visitContinue(x: JsContinue) { } + + override fun visitFor(x: JsFor) { + x.initVars?.let { it.vars.forEach { it.initExpression?.let { accept(it) } } } + x.initExpression?.let { accept(it) } + x.condition?.let { accept(it) } + x.body?.let { accept(it) } + x.incrementExpression?.let { accept(it) } + + super.visitFor(x) + } }.accept(root) usages.keys.retainAll(syntheticNames) diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/DynamicContext.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/DynamicContext.java index 99db190c06f..78623634238 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/DynamicContext.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/DynamicContext.java @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.js.translate.context; import com.google.dart.compiler.backend.js.ast.*; +import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -57,11 +58,14 @@ public final class DynamicContext { public TemporaryVariable declareTemporary(@Nullable JsExpression initExpression) { if (vars == null) { vars = new JsVars(); + MetadataProperties.setSynthetic(vars, true); currentBlock.getStatements().add(vars); } JsName temporaryName = currentScope.declareTemporary(); - vars.add(new JsVar(temporaryName, null)); + JsVar var = new JsVar(temporaryName, null); + MetadataProperties.setSynthetic(var, true); + vars.add(var); return TemporaryVariable.create(temporaryName, initExpression); } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/TemporaryVariable.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/TemporaryVariable.java index 1db67c1435b..00403d268ca 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/TemporaryVariable.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/TemporaryVariable.java @@ -16,9 +16,11 @@ package org.jetbrains.kotlin.js.translate.context; +import com.google.dart.compiler.backend.js.ast.JsBinaryOperation; import com.google.dart.compiler.backend.js.ast.JsExpression; import com.google.dart.compiler.backend.js.ast.JsName; import com.google.dart.compiler.backend.js.ast.JsNameRef; +import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.js.translate.utils.JsAstUtils; @@ -26,7 +28,12 @@ import org.jetbrains.kotlin.js.translate.utils.JsAstUtils; public class TemporaryVariable { /*package*/ static TemporaryVariable create(@NotNull JsName temporaryName, @Nullable JsExpression initExpression) { - return new TemporaryVariable(temporaryName, initExpression == null ? null : JsAstUtils.assignment(temporaryName.makeRef(), initExpression)); + JsBinaryOperation rhs = null; + if (initExpression != null) { + rhs = JsAstUtils.assignment(temporaryName.makeRef(), initExpression); + MetadataProperties.setSynthetic(rhs, true); + } + return new TemporaryVariable(temporaryName, rhs); } @Nullable diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/ExpressionVisitor.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/ExpressionVisitor.java index f4c279ad1cb..a1c5da77c3f 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/ExpressionVisitor.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/ExpressionVisitor.java @@ -29,9 +29,8 @@ import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention; import org.jetbrains.kotlin.js.translate.context.Namer; import org.jetbrains.kotlin.js.translate.context.TranslationContext; import org.jetbrains.kotlin.js.translate.declaration.ClassTranslator; -import org.jetbrains.kotlin.js.translate.declaration.PropertyTranslatorKt; -import org.jetbrains.kotlin.js.translate.expression.loopTranslator.LoopTranslator; import org.jetbrains.kotlin.js.translate.general.Translation; +import org.jetbrains.kotlin.js.translate.declaration.PropertyTranslatorKt; import org.jetbrains.kotlin.js.translate.general.TranslatorVisitor; import org.jetbrains.kotlin.js.translate.operation.BinaryOperationTranslator; import org.jetbrains.kotlin.js.translate.operation.UnaryOperationTranslator; diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/LoopTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/LoopTranslator.kt index e014f48b3c4..dbdd35c0e33 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/LoopTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/LoopTranslator.kt @@ -16,14 +16,13 @@ @file:JvmName("LoopTranslator") -package org.jetbrains.kotlin.js.translate.expression.loopTranslator +package org.jetbrains.kotlin.js.translate.expression import com.google.dart.compiler.backend.js.ast.* import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator import org.jetbrains.kotlin.js.translate.context.TemporaryVariable import org.jetbrains.kotlin.js.translate.context.TranslationContext -import org.jetbrains.kotlin.js.translate.expression.DestructuringDeclarationTranslator import org.jetbrains.kotlin.js.translate.general.Translation import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.CompositeFIF import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getHasNextCallable @@ -33,7 +32,6 @@ import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getTypeForExpression import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.* import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getLoopParameter import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getLoopRange -import org.jetbrains.kotlin.js.translate.utils.TemporariesUtils.temporariesInitialization import org.jetbrains.kotlin.js.translate.utils.TranslationUtils import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtBinaryExpression @@ -117,16 +115,16 @@ fun translateForExpression(expression: KtForExpression, context: TranslationCont val destructuringParameter: KtDestructuringDeclaration? = expression.destructuringParameter - fun declareParameter(): JsName { + fun declareParameter(): Pair { val loopParameter = getLoopParameter(expression) if (loopParameter != null) { - return context.getNameForElement(loopParameter) + return Pair(context.getNameForElement(loopParameter), false) } assert(destructuringParameter != null) { "If loopParameter is null, multi parameter must be not null ${expression.text}" } - return context.scope().declareTemporary() + return Pair(context.scope().declareTemporary(), true) } - val parameterName: JsName = declareParameter() + val (parameterName, parameterIsTemporary) = declareParameter() fun translateBody(itemValue: JsExpression?): JsStatement? { val realBody = expression.body?.let { Translation.translateAsStatementAndMergeInBlockIfNeeded(it, context) } @@ -135,10 +133,12 @@ fun translateForExpression(expression: KtForExpression, context: TranslationCont } else { val currentVarInit = - if (destructuringParameter == null) + if (destructuringParameter == null) { newVar(parameterName, itemValue) - else + } + else { DestructuringDeclarationTranslator.translate(destructuringParameter, parameterName, itemValue, context) + } if (realBody == null) return JsBlock(currentVarInit) @@ -170,12 +170,16 @@ fun translateForExpression(expression: KtForExpression, context: TranslationCont val rangeEnd = context.declareTemporary(rightExpression) val body = translateBody(null) - val initExpression = newVar(parameterName, rangeStart) val conditionExpression = lessThanEq(parameterName.makeRef(), rangeEnd.reference()) val incrementExpression = JsPostfixOperation(JsUnaryOperator.INC, parameterName.makeRef()) - context.addStatementToCurrentBlock(temporariesInitialization(rangeEnd).makeStmt()) - return JsFor(initExpression, conditionExpression, incrementExpression, body) + context.addStatementToCurrentBlock(asSyntheticStatement(rangeEnd.assignmentExpression())) + return if (parameterIsTemporary) { + JsFor(assignment(parameterName.makeRef(), rangeStart), conditionExpression, incrementExpression, body) + } + else { + JsFor(newVar(parameterName, rangeStart), conditionExpression, incrementExpression, body) + } } fun translateForOverRange(): JsStatement { @@ -188,12 +192,21 @@ fun translateForExpression(expression: KtForExpression, context: TranslationCont val increment = context.declareTemporary(getProperty("step")) val body = translateBody(null) - val initExpression = newVar(parameterName, start.reference()) - val conditionExpression = lessThanEq(parameterName.makeRef(), end.reference()) + + val conditionExpression = lessThanEq(parameterName.makeRef(), end.reference()) val incrementExpression = addAssign(parameterName.makeRef(), increment.reference()) - context.addStatementToCurrentBlock(temporariesInitialization(rangeExpression, start, end, increment).makeStmt()) - return JsFor(initExpression, conditionExpression, incrementExpression, body) + context.addStatementToCurrentBlock(asSyntheticStatement(rangeExpression.assignmentExpression())) + context.addStatementToCurrentBlock(asSyntheticStatement(start.assignmentExpression())) + context.addStatementToCurrentBlock(asSyntheticStatement(end.assignmentExpression())) + context.addStatementToCurrentBlock(asSyntheticStatement(increment.assignmentExpression())) + + return if (parameterIsTemporary) { + JsFor(assignment(parameterName.makeRef(), start.reference()), conditionExpression, incrementExpression, body) + } + else { + JsFor(newVar(parameterName, start.reference()), conditionExpression, incrementExpression, body) + } } fun translateForOverArray(): JsStatement { @@ -204,11 +217,12 @@ fun translateForExpression(expression: KtForExpression, context: TranslationCont val arrayAccess = JsArrayAccess(rangeExpression.reference(), index.reference()) val body = translateBody(arrayAccess) - val initExpression = newVar(index.name(), context.program().getNumberLiteral(0)) + val initExpression = assignment(index.name().makeRef(), context.program().getNumberLiteral(0)) val conditionExpression = inequality(index.reference(), end.reference()) val incrementExpression = JsPrefixOperation(JsUnaryOperator.INC, index.reference()) - context.addStatementToCurrentBlock(temporariesInitialization(rangeExpression, end).makeStmt()) + context.addStatementToCurrentBlock(asSyntheticStatement(rangeExpression.assignmentExpression())) + context.addStatementToCurrentBlock(asSyntheticStatement(end.assignmentExpression())) return JsFor(initExpression, conditionExpression, incrementExpression, body) } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/WhenTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/WhenTranslator.java index 5adee1c22f9..ec5cb9ef4aa 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/WhenTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/expression/WhenTranslator.java @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.js.translate.expression; import com.google.dart.compiler.backend.js.ast.*; +import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.js.translate.context.TemporaryVariable; @@ -57,9 +58,12 @@ public final class WhenTranslator extends AbstractTranslator { KtExpression subject = expression.getSubjectExpression(); if (subject != null) { JsExpression subjectExpression = Translation.translateAsExpression(subject, context); - if (TranslationUtils.isCacheNeeded(subjectExpression)) { + if (!JsAstUtils.isEmptyExpression(subjectExpression)) { TemporaryVariable subjectVar = context.declareTemporary(null); - context.addStatementToCurrentBlock(JsAstUtils.assignment(subjectVar.reference(), subjectExpression).makeStmt()); + JsExpressionStatement subjectAssignment = new JsExpressionStatement( + JsAstUtils.assignment(subjectVar.reference(), subjectExpression)); + MetadataProperties.setSynthetic(subjectAssignment, true); + context.addStatementToCurrentBlock(subjectAssignment); subjectExpression = subjectVar.reference(); } expressionToMatch = subjectExpression; diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsAstUtils.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsAstUtils.java index 7879634d7c9..9aceef42d15 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsAstUtils.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/JsAstUtils.java @@ -302,6 +302,12 @@ public final class JsAstUtils { return new JsBinaryOperation(JsBinaryOperator.ASG, left, right); } + public static JsStatement asSyntheticStatement(@NotNull JsExpression expression) { + JsExpressionStatement statement = new JsExpressionStatement(expression); + MetadataProperties.setSynthetic(statement, true); + return statement; + } + @Nullable public static Pair decomposeAssignment(@NotNull JsExpression expr) { if (!(expr instanceof JsBinaryOperation)) return null;