Support increment and '+=' on local delegated properties

This commit is contained in:
Mikhael Bogdanov
2016-05-05 14:13:26 +03:00
parent 6ae511b253
commit ec632c37ab
5 changed files with 69 additions and 3 deletions
@@ -2813,11 +2813,14 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
}
public int indexOfLocal(KtReferenceExpression lhs) {
public int indexOfLocalNotDelegated(KtReferenceExpression lhs) {
DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, lhs);
if (isVarCapturedInClosure(bindingContext, declarationDescriptor)) {
return -1;
}
if (declarationDescriptor instanceof LocalVariableDescriptor && ((LocalVariableDescriptor) declarationDescriptor).isDelegated()) {
return -1;
}
return lookupLocalIndex(declarationDescriptor);
}
@@ -3346,7 +3349,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
// Optimization for j = i++, when j and i are Int without any smart cast: we just work with primitive int
if (operand instanceof KtReferenceExpression && asmResultType == Type.INT_TYPE &&
bindingContext.get(BindingContext.SMARTCAST, operand) == null) {
int index = indexOfLocal((KtReferenceExpression) operand);
int index = indexOfLocalNotDelegated((KtReferenceExpression) operand);
if (index >= 0) {
return StackValue.postIncrement(index, increment);
}
@@ -672,7 +672,16 @@ public abstract class StackValue {
@NotNull CallableMethod getter,
@Nullable CallableMethod setter
) {
super(type, false, false, new Receiver(OBJECT_TYPE, delegateValue, constant(null, OBJECT_TYPE), metadataValue), false);
super(type, false, false, new Receiver(OBJECT_TYPE, delegateValue, constant(null, OBJECT_TYPE), metadataValue) {
@Override
public void dup(@NotNull InstructionAdapter v, boolean withReceiver) {
//UGLY HACK
//TODO rethink Receiver/StackValue concept
//We need to make duplication of delegated var, owner (null) and property metadata: dup 3.
//As HACK Type.LONG_TYPE and Type.INT_TYPE passed to dup util to simulate dup 3.
AsmUtil.dup(v, Type.LONG_TYPE, Type.INT_TYPE);
}
}, false);
this.delegateValue = delegateValue;
this.metadataValue = metadataValue;
this.getter = getter;
@@ -0,0 +1,17 @@
import kotlin.reflect.KProperty
class Delegate {
var inner = 1
operator fun getValue(t: Any?, p: KProperty<*>): Int = inner
operator fun setValue(t: Any?, p: KProperty<*>, i: Int) {
inner = i
}
}
fun box(): String {
var prop: Int by Delegate()
var result = prop++
if (result != 1) return "fail increment result: $prop"
if (prop != 2) return "fail increment: $prop"
return "OK"
}
@@ -0,0 +1,16 @@
import kotlin.reflect.KProperty
class Delegate {
var inner = 1
operator fun getValue(t: Any?, p: KProperty<*>): Int = inner
operator fun setValue(t: Any?, p: KProperty<*>, i: Int) {
inner = i
}
}
fun box(): String {
var prop: Int by Delegate()
prop += 1
if (prop != 2) return "fail : $prop"
return "OK"
}
@@ -4974,6 +4974,27 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/varInInnerClass.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/codegen/box/delegatedProperty/local")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Local extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInLocal() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/delegatedProperty/local"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("iinc.kt")
public void testIinc() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/local/iinc.kt");
doTest(fileName);
}
@TestMetadata("plusAssign.kt")
public void testPlusAssign() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/local/plusAssign.kt");
doTest(fileName);
}
}
}
@TestMetadata("compiler/testData/codegen/box/delegation")