From 534bde52f1fb82487c203d45ab59a3a07f26cb94 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Thu, 19 Jul 2012 16:20:06 +0400 Subject: [PATCH] Cache argument of when expression (should be evaluated only once). --- .../test/semantics/PatternMatchingTest.java | 4 +++ .../translate/expression/WhenTranslator.java | 27 ++++++++++++++----- .../cases/whenEvaluatesArgumentOnlyOnce.kt | 12 +++++++++ 3 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 js/js.translator/testFiles/patternMatching/cases/whenEvaluatesArgumentOnlyOnce.kt diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/PatternMatchingTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/PatternMatchingTest.java index 2cfd988f3f6..eca4d605d06 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/PatternMatchingTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/PatternMatchingTest.java @@ -40,6 +40,10 @@ public final class PatternMatchingTest extends SingleFileTranslationTest { fooBoxTest(); } + public void testWhenEvaluatesArgumentOnlyOnce() throws Exception { + fooBoxTest(); + } + public void testWhenValue() throws Exception { fooBoxTest(); } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/WhenTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/WhenTranslator.java index 06c016582a7..c6b94c6474e 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/WhenTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/WhenTranslator.java @@ -16,6 +16,7 @@ package org.jetbrains.k2js.translate.expression; +import closurecompiler.internal.com.google.common.collect.Lists; import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; @@ -47,7 +48,7 @@ public final class WhenTranslator extends AbstractTranslator { @NotNull private final JetWhenExpression whenExpression; @Nullable - private final JsExpression expressionToMatch; + private final TemporaryVariable expressionToMatch; @NotNull private final TemporaryVariable dummyCounter; @NotNull @@ -58,7 +59,8 @@ public final class WhenTranslator extends AbstractTranslator { private WhenTranslator(@NotNull JetWhenExpression expression, @NotNull TranslationContext context) { super(context); this.whenExpression = expression; - this.expressionToMatch = translateExpressionToMatch(whenExpression); + JsExpression expressionToMatch = translateExpressionToMatch(whenExpression); + this.expressionToMatch = expressionToMatch != null ? context.declareTemporary(expressionToMatch) : null; this.dummyCounter = context.declareTemporary(program().getNumberLiteral(0)); this.result = context.declareTemporary(program().getNullLiteral()); } @@ -66,8 +68,7 @@ public final class WhenTranslator extends AbstractTranslator { @NotNull JsNode translate() { JsFor resultingFor = generateDummyFor(); - List entries = translateEntries(); - resultingFor.setBody(newBlock(entries)); + resultingFor.setBody(newBlock(translateEntries())); context().addStatementToCurrentBlock(resultingFor); return result.reference(); } @@ -92,12 +93,21 @@ public final class WhenTranslator extends AbstractTranslator { @NotNull private JsFor generateDummyFor() { JsFor result = new JsFor(); - result.setInitExpr(dummyCounter.assignmentExpression()); + result.setInitExpr(generateInitExpressions()); result.setIncrExpr(generateIncrementStatement()); result.setCondition(generateConditionStatement()); return result; } + @NotNull + private JsExpression generateInitExpressions() { + List initExpressions = Lists.newArrayList(dummyCounter.assignmentExpression()); + if (expressionToMatch != null) { + initExpressions.add(expressionToMatch.assignmentExpression()); + } + return newSequence(initExpressions); + } + @NotNull private JsBinaryOperation generateConditionStatement() { JsNumberLiteral entriesNumber = program().getNumberLiteral(whenExpression.getEntries().size()); @@ -178,13 +188,18 @@ public final class WhenTranslator extends AbstractTranslator { @NotNull private JsExpression translatePatternCondition(@NotNull JetWhenCondition condition) { JsExpression patternMatchExpression = Translation.patternTranslator(context()). - translatePattern(getPattern(condition), expressionToMatch); + translatePattern(getPattern(condition), getExpressionToMatch()); if (isNegated(condition)) { return negated(patternMatchExpression); } return patternMatchExpression; } + @Nullable + private JsExpression getExpressionToMatch() { + return expressionToMatch != null ? expressionToMatch.reference() : null; + } + private static boolean isNegated(@NotNull JetWhenCondition condition) { if (condition instanceof JetWhenConditionIsPattern) { return ((JetWhenConditionIsPattern)condition).isNegated(); diff --git a/js/js.translator/testFiles/patternMatching/cases/whenEvaluatesArgumentOnlyOnce.kt b/js/js.translator/testFiles/patternMatching/cases/whenEvaluatesArgumentOnlyOnce.kt new file mode 100644 index 00000000000..ecc7e97c523 --- /dev/null +++ b/js/js.translator/testFiles/patternMatching/cases/whenEvaluatesArgumentOnlyOnce.kt @@ -0,0 +1,12 @@ +package foo + +fun box() : Boolean { + var a = 0 + var i = 0 + when(i++) { + -100 -> a++ + 100 -> a++ + else -> a++ + } + return (a == 1) && (i == 1) +} \ No newline at end of file