JS: fix translation of augmented assignment when RHS changes value of LHS

This commit is contained in:
Alexey Andreev
2016-11-21 18:47:09 +03:00
parent be196789d2
commit 40e00a62f5
7 changed files with 77 additions and 13 deletions
@@ -1,9 +1,6 @@
// WITH_RUNTIME
// NO_INTERCEPT_RESUME_TESTS
// TODO: fix bug in JVM backend and remove this directive
// TARGET_BACKEND: JS
class Controller {
var result = ""
@@ -29,7 +26,7 @@ fun box(): String {
}
}
}
if (value != "A;[B][C]!") return "fail: suspend as if condition: $value"
if (value != "A;B]C]!") return "fail: suspend as if condition: $value"
return "OK"
}
@@ -0,0 +1,23 @@
// WITH_RUNTIME
import kotlin.test.*
var log = ""
var result = 20
fun <T> id(value: T) = value
fun box(): String {
result += if (id("true") == "true") {
result += 10
log += "true chosen"
3
}
else {
4
}
assertEquals(23, result)
assertEquals("true chosen", log)
return "OK"
}
@@ -4768,6 +4768,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName);
}
@TestMetadata("switchLikeWhen.kt")
public void testSwitchLikeWhen() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/controlFlow/switchLikeWhen.kt");
doTest(fileName);
}
@TestMetadata("throwFromCatch.kt")
public void testThrowFromCatch() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/controlFlow/throwFromCatch.kt");
@@ -7679,6 +7685,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName);
}
@TestMetadata("augmentedAssignmentWithComplexRhs.kt")
public void testAugmentedAssignmentWithComplexRhs() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/augmentedAssignmentWithComplexRhs.kt");
doTest(fileName);
}
@TestMetadata("classNaryGetSet.kt")
public void testClassNaryGetSet() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/classNaryGetSet.kt");
@@ -4768,6 +4768,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("switchLikeWhen.kt")
public void testSwitchLikeWhen() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/controlFlow/switchLikeWhen.kt");
doTest(fileName);
}
@TestMetadata("throwFromCatch.kt")
public void testThrowFromCatch() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/controlFlow/throwFromCatch.kt");
@@ -7679,6 +7685,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("augmentedAssignmentWithComplexRhs.kt")
public void testAugmentedAssignmentWithComplexRhs() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/augmentedAssignmentWithComplexRhs.kt");
doTest(fileName);
}
@TestMetadata("classNaryGetSet.kt")
public void testClassNaryGetSet() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/classNaryGetSet.kt");
@@ -8838,6 +8838,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName);
}
@TestMetadata("augmentedAssignmentWithComplexRhs.kt")
public void testAugmentedAssignmentWithComplexRhs() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/augmentedAssignmentWithComplexRhs.kt");
doTest(fileName);
}
@TestMetadata("classNaryGetSet.kt")
public void testClassNaryGetSet() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/increment/classNaryGetSet.kt");
@@ -91,7 +91,11 @@ object DefaultVariableAccessCase : VariableAccessCase() {
getCapturedVarAccessor(functionRef)
}
else {
functionRef
functionRef.apply {
if (isGetAccess()) {
sideEffects = SideEffectKind.DEPENDS_ON_STATE
}
}
}
val localVariableDescriptor = resolvedCall.resultingDescriptor as? LocalVariableDescriptor
@@ -23,6 +23,7 @@ import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.reference.AccessTranslator;
import org.jetbrains.kotlin.lexer.KtSingleValueToken;
import org.jetbrains.kotlin.lexer.KtToken;
import org.jetbrains.kotlin.psi.KtBinaryExpression;
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
@@ -33,8 +34,10 @@ import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.isSimpleN
import static org.jetbrains.kotlin.js.translate.utils.TranslationUtils.translateRightExpression;
public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
private JsExpression right;
private AccessTranslator accessTranslator;
private final JsExpression right;
private final AccessTranslator accessTranslator;
private final boolean rightExpressionTrivial;
private final JsBlock rightBlock = new JsBlock();
@NotNull
public static JsExpression doTranslate(@NotNull KtBinaryExpression expression,
@@ -46,10 +49,9 @@ public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
@NotNull TranslationContext context) {
super(expression, context);
JsBlock rightBlock = new JsBlock();
right = translateRightExpression(context, expression, rightBlock);
accessTranslator = createAccessTranslator(expression.getLeft(), !rightBlock.isEmpty());
context.addStatementsToCurrentBlockFrom(rightBlock);
rightExpressionTrivial = rightBlock.isEmpty();
accessTranslator = createAccessTranslator(expression.getLeft(), !rightExpressionTrivial);
}
@NotNull
@@ -62,7 +64,7 @@ public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
@NotNull
private JsExpression translateAsAssignmentOperation() {
if (isSimpleNameExpressionNotDelegatedLocalVar(expression.getLeft(), context())) {
if (isSimpleNameExpressionNotDelegatedLocalVar(expression.getLeft(), context()) && rightExpressionTrivial) {
return translateAsPlainAssignmentOperation();
}
return translateAsAssignToCounterpart();
@@ -71,14 +73,19 @@ public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
@NotNull
private JsExpression translateAsAssignToCounterpart() {
JsBinaryOperator operator = getCounterpartOperator();
JsBinaryOperation counterpartOperation =
new JsBinaryOperation(operator, accessTranslator.translateAsGet(), right);
JsExpression oldValue = accessTranslator.translateAsGet();
if (!rightExpressionTrivial) {
oldValue = context().defineTemporary(oldValue);
}
JsBinaryOperation counterpartOperation = new JsBinaryOperation(operator, oldValue, right);
context().addStatementsToCurrentBlockFrom(rightBlock);
return accessTranslator.translateAsSet(counterpartOperation);
}
@NotNull
private JsBinaryOperator getCounterpartOperator() {
KtToken assignmentOperationToken = getOperationToken(expression);
assert assignmentOperationToken instanceof KtSingleValueToken;
assert OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(assignmentOperationToken);
KtToken counterpartToken = OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(assignmentOperationToken);
assert OperatorTable.hasCorrespondingBinaryOperator(counterpartToken) :
@@ -88,6 +95,7 @@ public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
@NotNull
private JsExpression translateAsPlainAssignmentOperation() {
context().addStatementsToCurrentBlockFrom(rightBlock);
JsBinaryOperator operator = getAssignmentOperator();
return new JsBinaryOperation(operator, accessTranslator.translateAsGet(), right);
}
@@ -95,6 +103,7 @@ public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
@NotNull
private JsBinaryOperator getAssignmentOperator() {
KtToken token = getOperationToken(expression);
assert token instanceof KtSingleValueToken;
assert OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(token);
assert OperatorTable.hasCorrespondingBinaryOperator(token) :
"Unsupported token encountered: " + token.toString();
@@ -103,6 +112,7 @@ public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
@NotNull
private JsExpression translateAsPlainAssignment() {
context().addStatementsToCurrentBlockFrom(rightBlock);
return accessTranslator.translateAsSet(right);
}
}