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 {
|
public void testKt740() throws Exception {
|
||||||
checkFooBoxIsTrue("KT-740.kt");
|
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
|
* @author Pavel Talanov
|
||||||
* <p/>
|
* <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 {
|
public interface AccessTranslator {
|
||||||
|
|
||||||
@@ -32,6 +32,7 @@ public interface AccessTranslator {
|
|||||||
@NotNull
|
@NotNull
|
||||||
JsExpression translateAsSet(@NotNull JsExpression setTo);
|
JsExpression translateAsSet(@NotNull JsExpression setTo);
|
||||||
|
|
||||||
|
//TODO: remove that method
|
||||||
@NotNull
|
@NotNull
|
||||||
CachedAccessTranslator getCached();
|
CachedAccessTranslator getCached();
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-17
@@ -19,23 +19,18 @@ package org.jetbrains.k2js.translate.reference;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetArrayAccessExpression;
|
import org.jetbrains.jet.lang.psi.JetArrayAccessExpression;
|
||||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||||
import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
import org.jetbrains.k2js.translate.general.AbstractTranslator;
|
||||||
import org.jetbrains.k2js.translate.general.Translation;
|
import org.jetbrains.k2js.translate.general.Translation;
|
||||||
|
import org.jetbrains.k2js.translate.utils.BindingUtils;
|
||||||
import org.jetbrains.k2js.translate.utils.TranslationUtils;
|
import org.jetbrains.k2js.translate.utils.TranslationUtils;
|
||||||
|
|
||||||
import java.util.List;
|
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
|
* @author Pavel Talanov
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//TODO: inspect not clear how the class handles set and get operations differently
|
|
||||||
public class ArrayAccessTranslator extends AbstractTranslator implements AccessTranslator {
|
public class ArrayAccessTranslator extends AbstractTranslator implements AccessTranslator {
|
||||||
|
|
||||||
/*package*/
|
/*package*/
|
||||||
@@ -46,16 +41,11 @@ public class ArrayAccessTranslator extends AbstractTranslator implements AccessT
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final JetArrayAccessExpression expression;
|
private final JetArrayAccessExpression expression;
|
||||||
@NotNull
|
|
||||||
private final FunctionDescriptor methodDescriptor;
|
|
||||||
|
|
||||||
protected ArrayAccessTranslator(@NotNull JetArrayAccessExpression expression,
|
protected ArrayAccessTranslator(@NotNull JetArrayAccessExpression expression,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
super(context);
|
super(context);
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
//TODO: that is strange
|
|
||||||
this.methodDescriptor = (FunctionDescriptor)
|
|
||||||
getDescriptorForReferenceExpression(context.bindingContext(), expression);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -67,7 +57,7 @@ public class ArrayAccessTranslator extends AbstractTranslator implements AccessT
|
|||||||
@NotNull
|
@NotNull
|
||||||
protected JsExpression translateAsGet(@NotNull JsExpression arrayExpression,
|
protected JsExpression translateAsGet(@NotNull JsExpression arrayExpression,
|
||||||
@NotNull List<JsExpression> indexExpression) {
|
@NotNull List<JsExpression> indexExpression) {
|
||||||
return translateAsMethodCall(arrayExpression, indexExpression);
|
return translateAsMethodCall(arrayExpression, indexExpression, /*isGetter = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@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) {
|
protected JsExpression translateAsSet(@NotNull JsExpression arrayExpression, @NotNull List<JsExpression> indexExpressions, @NotNull JsExpression toSetTo) {
|
||||||
List<JsExpression> arguments = Lists.newArrayList(indexExpressions);
|
List<JsExpression> arguments = Lists.newArrayList(indexExpressions);
|
||||||
arguments.add(toSetTo);
|
arguments.add(toSetTo);
|
||||||
return translateAsMethodCall(arrayExpression, arguments);
|
return translateAsMethodCall(arrayExpression, arguments, /*isGetter = */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@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())
|
return CallBuilder.build(context())
|
||||||
.receiver(arrayExpression)
|
.receiver(arrayExpression)
|
||||||
.args(arguments)
|
.args(arguments)
|
||||||
.resolvedCall(getResolvedCall(bindingContext(), expression))
|
.resolvedCall(BindingUtils.getResolvedCallForArrayAccess(bindingContext(), expression, isGetter))
|
||||||
.descriptor(methodDescriptor)
|
|
||||||
.translate();
|
.translate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,6 +97,6 @@ public class ArrayAccessTranslator extends AbstractTranslator implements AccessT
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public CachedAccessTranslator getCached() {
|
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
|
@NotNull
|
||||||
private final List<TemporaryVariable> indexExpressions;
|
private final List<TemporaryVariable> indexExpressions;
|
||||||
|
|
||||||
private CachedArrayAccessTranslator(@NotNull JetArrayAccessExpression expression,
|
/*package*/ CachedArrayAccessTranslator(@NotNull JetArrayAccessExpression expression,
|
||||||
@NotNull TranslationContext context) {
|
@NotNull TranslationContext context) {
|
||||||
super(expression, context);
|
super(expression, context);
|
||||||
arrayExpression = context.declareTemporary(translateArrayExpression());
|
arrayExpression = context.declareTemporary(translateArrayExpression());
|
||||||
indexExpressions = fromExpressionList(translateIndexExpressions(), context);
|
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.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
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.JetType;
|
||||||
|
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
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.*;
|
import static org.jetbrains.k2js.translate.utils.DescriptorUtils.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -332,4 +334,16 @@ public final class BindingUtils {
|
|||||||
assert type != null;
|
assert type != null;
|
||||||
return type;
|
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 false;
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
|
||||||
|
|
||||||
fun main(args : Array<String>) {
|
|
||||||
println(box())
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user