KT-817 Wrong code on prefix increment operators.
This commit is contained in:
@@ -81,6 +81,10 @@ public final class MiscTest extends AbstractExpressionTest {
|
|||||||
checkFooBoxIsTrue("KT-1361-2.kt");
|
checkFooBoxIsTrue("KT-1361-2.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testKt817() throws Exception {
|
||||||
|
checkFooBoxIsTrue("KT-817.kt");
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: depends on KT-1198
|
//TODO: depends on KT-1198
|
||||||
//TODO: look into BindingContext.VARIABLE_REASSIGNMENT
|
//TODO: look into BindingContext.VARIABLE_REASSIGNMENT
|
||||||
// public void testKt740_3() throws Exception {
|
// public void testKt740_3() throws Exception {
|
||||||
|
|||||||
+18
-41
@@ -31,8 +31,6 @@ import org.jetbrains.k2js.translate.reference.CachedAccessTranslator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.k2js.translate.reference.AccessTranslationUtils.getCachedAccessTranslator;
|
import static org.jetbrains.k2js.translate.reference.AccessTranslationUtils.getCachedAccessTranslator;
|
||||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.isStatement;
|
|
||||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.isVariableReassignment;
|
|
||||||
import static org.jetbrains.k2js.translate.utils.JsAstUtils.newSequence;
|
import static org.jetbrains.k2js.translate.utils.JsAstUtils.newSequence;
|
||||||
import static org.jetbrains.k2js.translate.utils.PsiUtils.*;
|
import static org.jetbrains.k2js.translate.utils.PsiUtils.*;
|
||||||
import static org.jetbrains.k2js.translate.utils.TemporariesUtils.temporariesInitialization;
|
import static org.jetbrains.k2js.translate.utils.TemporariesUtils.temporariesInitialization;
|
||||||
@@ -54,58 +52,49 @@ public abstract class IncrementTranslator extends AbstractTranslator {
|
|||||||
if (isIntrinsicOperation(context, expression)) {
|
if (isIntrinsicOperation(context, expression)) {
|
||||||
return IntrinsicIncrementTranslator.doTranslate(expression, context);
|
return IntrinsicIncrementTranslator.doTranslate(expression, context);
|
||||||
}
|
}
|
||||||
return OverloadedIncrementTranslator.doTranslate(expression, context);
|
return (new OverloadedIncrementTranslator(expression, context)).translateIncrementExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
protected final JetUnaryExpression expression;
|
protected final JetUnaryExpression expression;
|
||||||
@NotNull
|
@NotNull
|
||||||
protected final CachedAccessTranslator accessTranslator;
|
protected final CachedAccessTranslator accessTranslator;
|
||||||
private final boolean isVariableReassignment;
|
|
||||||
|
|
||||||
protected IncrementTranslator(@NotNull JetUnaryExpression expression,
|
protected IncrementTranslator(@NotNull JetUnaryExpression expression,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
super(context);
|
super(context);
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
this.isVariableReassignment = isVariableReassignment(context.bindingContext(), expression);
|
|
||||||
JetExpression baseExpression = getBaseExpression(expression);
|
JetExpression baseExpression = getBaseExpression(expression);
|
||||||
this.accessTranslator = getCachedAccessTranslator(baseExpression, context());
|
this.accessTranslator = getCachedAccessTranslator(baseExpression, context());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
protected JsExpression translateAsMethodCall() {
|
protected JsExpression translateIncrementExpression() {
|
||||||
return withTemporariesInitialized(doTranslateAsMethodCall());
|
return withTemporariesInitialized(doTranslateIncrementExpression());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsExpression doTranslateAsMethodCall() {
|
private JsExpression doTranslateIncrementExpression() {
|
||||||
if (returnValueIgnored() || isPrefix(expression)) {
|
if (isPrefix(expression)) {
|
||||||
return asPrefix();
|
return asPrefix();
|
||||||
}
|
}
|
||||||
if (isVariableReassignment) {
|
return asPostfix();
|
||||||
return asPostfixWithReassignment();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return asPostfixWithNoReassignment();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean returnValueIgnored() {
|
|
||||||
return isStatement(bindingContext(), expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private JsExpression asPrefix() {
|
|
||||||
JsExpression getExpression = accessTranslator.translateAsGet();
|
|
||||||
if (isVariableReassignment) {
|
|
||||||
return variableReassignment(getExpression);
|
|
||||||
}
|
|
||||||
return operationExpression(getExpression);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: decide if this expression can be optimised in case of direct access (not property)
|
//TODO: decide if this expression can be optimised in case of direct access (not property)
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsExpression asPostfixWithReassignment() {
|
private JsExpression asPrefix() {
|
||||||
|
// code fragment: expr(a++)
|
||||||
|
// generate: expr(a = a.inc(), a)
|
||||||
|
JsExpression getExpression = accessTranslator.translateAsGet();
|
||||||
|
JsExpression reassignment = variableReassignment(getExpression);
|
||||||
|
JsExpression getNewValue = accessTranslator.translateAsGet();
|
||||||
|
return AstUtil.newSequence(reassignment, getNewValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: decide if this expression can be optimised in case of direct access (not property)
|
||||||
|
@NotNull
|
||||||
|
private JsExpression asPostfix() {
|
||||||
// code fragment: expr(a++)
|
// code fragment: expr(a++)
|
||||||
// generate: expr( (t1 = a, t2 = t1, a = t1.inc(), t2) )
|
// generate: expr( (t1 = a, t2 = t1, a = t1.inc(), t2) )
|
||||||
TemporaryVariable t1 = context().declareTemporary(accessTranslator.translateAsGet());
|
TemporaryVariable t1 = context().declareTemporary(accessTranslator.translateAsGet());
|
||||||
@@ -115,18 +104,6 @@ public abstract class IncrementTranslator extends AbstractTranslator {
|
|||||||
variableReassignment, t2.reference());
|
variableReassignment, t2.reference());
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: TEST
|
|
||||||
@NotNull
|
|
||||||
private JsExpression asPostfixWithNoReassignment() {
|
|
||||||
// code fragment: expr(a++)
|
|
||||||
// generate: expr( (t1 = a, t2 = t1, t2.inc(), t1) )
|
|
||||||
TemporaryVariable t1 = context().declareTemporary(accessTranslator.translateAsGet());
|
|
||||||
TemporaryVariable t2 = context().declareTemporary(t1.reference());
|
|
||||||
JsExpression methodCall = operationExpression(t2.reference());
|
|
||||||
JsExpression returnedValue = t1.reference();
|
|
||||||
return AstUtil.newSequence(t1.assignmentExpression(), t2.assignmentExpression(), methodCall, returnedValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsExpression variableReassignment(@NotNull JsExpression toCallMethodUpon) {
|
private JsExpression variableReassignment(@NotNull JsExpression toCallMethodUpon) {
|
||||||
JsExpression overloadedMethodCallOnPropertyGetter = operationExpression(toCallMethodUpon);
|
JsExpression overloadedMethodCallOnPropertyGetter = operationExpression(toCallMethodUpon);
|
||||||
|
|||||||
+5
-5
@@ -33,7 +33,6 @@ import static org.jetbrains.k2js.translate.utils.PsiUtils.isPrefix;
|
|||||||
*/
|
*/
|
||||||
public final class IntrinsicIncrementTranslator extends IncrementTranslator {
|
public final class IntrinsicIncrementTranslator extends IncrementTranslator {
|
||||||
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsExpression doTranslate(@NotNull JetUnaryExpression expression,
|
public static JsExpression doTranslate(@NotNull JetUnaryExpression expression,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
@@ -49,9 +48,9 @@ public final class IntrinsicIncrementTranslator extends IncrementTranslator {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private JsExpression translate() {
|
private JsExpression translate() {
|
||||||
if (isPrimitiveExpressionIncrement()) {
|
if (isPrimitiveExpressionIncrement()) {
|
||||||
return jsUnaryExpression();
|
return primitiveExpressionIncrement();
|
||||||
}
|
}
|
||||||
return translateAsMethodCall();
|
return translateIncrementExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPrimitiveExpressionIncrement() {
|
private boolean isPrimitiveExpressionIncrement() {
|
||||||
@@ -59,7 +58,7 @@ public final class IntrinsicIncrementTranslator extends IncrementTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private JsExpression jsUnaryExpression() {
|
private JsExpression primitiveExpressionIncrement() {
|
||||||
JsUnaryOperator operator = OperatorTable.getUnaryOperator(getOperationToken(expression));
|
JsUnaryOperator operator = OperatorTable.getUnaryOperator(getOperationToken(expression));
|
||||||
JsExpression getExpression = accessTranslator.translateAsGet();
|
JsExpression getExpression = accessTranslator.translateAsGet();
|
||||||
if (isPrefix(expression)) {
|
if (isPrefix(expression)) {
|
||||||
@@ -76,7 +75,8 @@ public final class IntrinsicIncrementTranslator extends IncrementTranslator {
|
|||||||
return unaryAsBinary(receiver);
|
return unaryAsBinary(receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JsBinaryOperation unaryAsBinary(@NotNull JsExpression leftExpression) {
|
@NotNull
|
||||||
|
private JsBinaryOperation unaryAsBinary(@NotNull JsExpression leftExpression) {
|
||||||
JsNumberLiteral oneLiteral = program().getNumberLiteral(1);
|
JsNumberLiteral oneLiteral = program().getNumberLiteral(1);
|
||||||
JetToken token = getOperationToken(expression);
|
JetToken token = getOperationToken(expression);
|
||||||
if (token.equals(JetTokens.PLUSPLUS)) {
|
if (token.equals(JetTokens.PLUSPLUS)) {
|
||||||
|
|||||||
+2
-13
@@ -31,26 +31,15 @@ import static org.jetbrains.k2js.translate.utils.TranslationUtils.getMethodRefer
|
|||||||
*/
|
*/
|
||||||
public final class OverloadedIncrementTranslator extends IncrementTranslator {
|
public final class OverloadedIncrementTranslator extends IncrementTranslator {
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static JsExpression doTranslate(@NotNull JetUnaryExpression expression,
|
|
||||||
@NotNull TranslationContext context) {
|
|
||||||
return (new OverloadedIncrementTranslator(expression, context))
|
|
||||||
.translate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final JsNameRef operationReference;
|
private final JsNameRef operationReference;
|
||||||
|
|
||||||
private OverloadedIncrementTranslator(@NotNull JetUnaryExpression expression,
|
/*package*/ OverloadedIncrementTranslator(@NotNull JetUnaryExpression expression,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
super(expression, context);
|
super(expression, context);
|
||||||
this.operationReference = getMethodReferenceForOverloadedOperation(context, expression);
|
this.operationReference = getMethodReferenceForOverloadedOperation(context, expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private JsExpression translate() {
|
|
||||||
return translateAsMethodCall();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ fun box() : String {
|
|||||||
if (c0 != 2) {
|
if (c0 != 2) {
|
||||||
return "3"
|
return "3"
|
||||||
}
|
}
|
||||||
if (c1 != 2) {
|
if (c1 != 3) {
|
||||||
return "4"
|
return "4"
|
||||||
}
|
}
|
||||||
if (c2 != 1) {
|
if (c2 != 1) {
|
||||||
@@ -46,14 +46,11 @@ fun box() : String {
|
|||||||
if (c0 != 3) {
|
if (c0 != 3) {
|
||||||
return "6"
|
return "6"
|
||||||
}
|
}
|
||||||
if (c1 != 3) {
|
if (c1 != 5) {
|
||||||
return "7"
|
return "7"
|
||||||
}
|
}
|
||||||
if (c2 != 2) {
|
if (c2 != 2) {
|
||||||
return "8"
|
return "8"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
class Range() {
|
||||||
|
|
||||||
|
val reversed = false;
|
||||||
|
val start = 0;
|
||||||
|
var count = 10;
|
||||||
|
|
||||||
|
fun next() = start + if (reversed) -(--count) else (--count);
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() : Boolean {
|
||||||
|
val r = Range()
|
||||||
|
if (r.next() != 9) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (r.next() != 8) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user