KT-740: Make sure that assign and increment operations compute receiver only once:
- Array operations.
This commit is contained in:
@@ -64,4 +64,8 @@ public final class MiscTest extends AbstractExpressionTest {
|
||||
public void testKt740() throws Exception {
|
||||
checkFooBoxIsTrue("KT-740.kt");
|
||||
}
|
||||
|
||||
public void testKt740_2() throws Exception {
|
||||
checkFooBoxIsOk("KT-740-2.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* @author Pavel Talanov
|
||||
* <p/>
|
||||
* Abstract entity for language constructs that you can get/set. Also dispatches to the real implemntation.
|
||||
* Abstract entity for language constructs that you can get/set.
|
||||
*/
|
||||
public interface AccessTranslator {
|
||||
|
||||
@@ -32,6 +32,7 @@ public interface AccessTranslator {
|
||||
@NotNull
|
||||
JsExpression translateAsSet(@NotNull JsExpression setTo);
|
||||
|
||||
//TODO: remove that method
|
||||
@NotNull
|
||||
CachedAccessTranslator getCached();
|
||||
}
|
||||
|
||||
+8
-17
@@ -19,23 +19,18 @@ package org.jetbrains.k2js.translate.reference;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetArrayAccessExpression;
|
||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||
import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
||||
import org.jetbrains.k2js.translate.general.Translation;
|
||||
import org.jetbrains.k2js.translate.utils.BindingUtils;
|
||||
import org.jetbrains.k2js.translate.utils.TranslationUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.getDescriptorForReferenceExpression;
|
||||
import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCall;
|
||||
|
||||
/**
|
||||
* @author Pavel Talanov
|
||||
*/
|
||||
|
||||
//TODO: inspect not clear how the class handles set and get operations differently
|
||||
public class ArrayAccessTranslator extends AbstractTranslator implements AccessTranslator {
|
||||
|
||||
/*package*/
|
||||
@@ -46,16 +41,11 @@ public class ArrayAccessTranslator extends AbstractTranslator implements AccessT
|
||||
|
||||
@NotNull
|
||||
private final JetArrayAccessExpression expression;
|
||||
@NotNull
|
||||
private final FunctionDescriptor methodDescriptor;
|
||||
|
||||
protected ArrayAccessTranslator(@NotNull JetArrayAccessExpression expression,
|
||||
@NotNull TranslationContext context) {
|
||||
super(context);
|
||||
this.expression = expression;
|
||||
//TODO: that is strange
|
||||
this.methodDescriptor = (FunctionDescriptor)
|
||||
getDescriptorForReferenceExpression(context.bindingContext(), expression);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -67,7 +57,7 @@ public class ArrayAccessTranslator extends AbstractTranslator implements AccessT
|
||||
@NotNull
|
||||
protected JsExpression translateAsGet(@NotNull JsExpression arrayExpression,
|
||||
@NotNull List<JsExpression> indexExpression) {
|
||||
return translateAsMethodCall(arrayExpression, indexExpression);
|
||||
return translateAsMethodCall(arrayExpression, indexExpression, /*isGetter = */ true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -80,16 +70,17 @@ public class ArrayAccessTranslator extends AbstractTranslator implements AccessT
|
||||
protected JsExpression translateAsSet(@NotNull JsExpression arrayExpression, @NotNull List<JsExpression> indexExpressions, @NotNull JsExpression toSetTo) {
|
||||
List<JsExpression> arguments = Lists.newArrayList(indexExpressions);
|
||||
arguments.add(toSetTo);
|
||||
return translateAsMethodCall(arrayExpression, arguments);
|
||||
return translateAsMethodCall(arrayExpression, arguments, /*isGetter = */ false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsExpression translateAsMethodCall(@NotNull JsExpression arrayExpression, @NotNull List<JsExpression> arguments) {
|
||||
private JsExpression translateAsMethodCall(@NotNull JsExpression arrayExpression,
|
||||
@NotNull List<JsExpression> arguments,
|
||||
boolean isGetter) {
|
||||
return CallBuilder.build(context())
|
||||
.receiver(arrayExpression)
|
||||
.args(arguments)
|
||||
.resolvedCall(getResolvedCall(bindingContext(), expression))
|
||||
.descriptor(methodDescriptor)
|
||||
.resolvedCall(BindingUtils.getResolvedCallForArrayAccess(bindingContext(), expression, isGetter))
|
||||
.translate();
|
||||
}
|
||||
|
||||
@@ -106,6 +97,6 @@ public class ArrayAccessTranslator extends AbstractTranslator implements AccessT
|
||||
@NotNull
|
||||
@Override
|
||||
public CachedAccessTranslator getCached() {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
return new CachedArrayAccessTranslator(expression, context());
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -38,8 +38,8 @@ public final class CachedArrayAccessTranslator extends ArrayAccessTranslator imp
|
||||
@NotNull
|
||||
private final List<TemporaryVariable> indexExpressions;
|
||||
|
||||
private CachedArrayAccessTranslator(@NotNull JetArrayAccessExpression expression,
|
||||
@NotNull TranslationContext context) {
|
||||
/*package*/ CachedArrayAccessTranslator(@NotNull JetArrayAccessExpression expression,
|
||||
@NotNull TranslationContext context) {
|
||||
super(expression, context);
|
||||
arrayExpression = context.declareTemporary(translateArrayExpression());
|
||||
indexExpressions = fromExpressionList(translateIndexExpressions(), context);
|
||||
|
||||
@@ -25,13 +25,15 @@ import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.INDEXED_LVALUE_GET;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.INDEXED_LVALUE_SET;
|
||||
import static org.jetbrains.k2js.translate.utils.DescriptorUtils.*;
|
||||
|
||||
/**
|
||||
@@ -332,4 +334,16 @@ public final class BindingUtils {
|
||||
assert type != null;
|
||||
return type;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ResolvedCall<FunctionDescriptor> getResolvedCallForArrayAccess(@NotNull BindingContext context,
|
||||
@NotNull JetArrayAccessExpression arrayAccessExpression,
|
||||
boolean isGet
|
||||
) {
|
||||
ResolvedCall<FunctionDescriptor> resolvedCall = context.get(isGet
|
||||
? INDEXED_LVALUE_GET
|
||||
: INDEXED_LVALUE_SET, arrayAccessExpression);
|
||||
assert resolvedCall != null;
|
||||
return resolvedCall;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package foo
|
||||
|
||||
var c0 = 0
|
||||
var c1 = 0
|
||||
var c2 = 0
|
||||
|
||||
class A() {
|
||||
var p = 0
|
||||
fun get(i : Int) : Int {
|
||||
c1++
|
||||
return 0
|
||||
}
|
||||
|
||||
fun set(i : Int, value : Int) {
|
||||
c2++
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
val a : A = A()
|
||||
get() {
|
||||
c0++
|
||||
return $a
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
|
||||
var d = a[1]
|
||||
if (c0 != 1) {
|
||||
return "1"
|
||||
}
|
||||
if (c1 != 1) {
|
||||
return "2"
|
||||
}
|
||||
++a[1]
|
||||
if (c0 != 2) {
|
||||
return "3"
|
||||
}
|
||||
if (c1 != 2) {
|
||||
return "4"
|
||||
}
|
||||
if (c2 != 1) {
|
||||
return "5"
|
||||
}
|
||||
--a[1]
|
||||
if (c0 != 3) {
|
||||
return "6"
|
||||
}
|
||||
if (c1 != 3) {
|
||||
return "7"
|
||||
}
|
||||
if (c2 != 2) {
|
||||
return "8"
|
||||
}
|
||||
|
||||
|
||||
return "OK"
|
||||
|
||||
}
|
||||
@@ -19,8 +19,4 @@ fun box() : Boolean {
|
||||
return false;
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun main(args : Array<String>) {
|
||||
println(box())
|
||||
}
|
||||
Reference in New Issue
Block a user