postfix part of KT-471
This commit is contained in:
@@ -2006,19 +2006,36 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
Arrays.asList(expression.getBaseExpression()), receiver);
|
||||
}
|
||||
else {
|
||||
return invokeOperation(expression, (FunctionDescriptor) op, (CallableMethod) callable);
|
||||
DeclarationDescriptor cls = op.getContainingDeclaration();
|
||||
if (isNumberPrimitive(cls) || !(op.getName().equals("inc") || op.getName().equals("dec")) ) {
|
||||
return invokeOperation(expression, (FunctionDescriptor) op, (CallableMethod) callable);
|
||||
}
|
||||
else {
|
||||
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference());
|
||||
assert resolvedCall != null;
|
||||
|
||||
StackValue value = gen(expression.getBaseExpression());
|
||||
value.dupReceiver(v);
|
||||
value.dupReceiver(v);
|
||||
|
||||
Type type = expressionType(expression.getBaseExpression());
|
||||
value.put(type, v);
|
||||
((CallableMethod)callable).invoke(v);
|
||||
value.store(v);
|
||||
value.put(type, v);
|
||||
return StackValue.onStack(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private StackValue invokeOperation(JetOperationExpression expression, FunctionDescriptor op, CallableMethod callable) {
|
||||
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference());
|
||||
assert resolvedCall != null;
|
||||
CallableMethod callableMethod = (CallableMethod) callable;
|
||||
genThisAndReceiverFromResolvedCall(StackValue.none(), resolvedCall, callableMethod);
|
||||
genThisAndReceiverFromResolvedCall(StackValue.none(), resolvedCall, callable);
|
||||
pushTypeArguments(resolvedCall);
|
||||
pushMethodArguments(resolvedCall, callableMethod.getValueParameterTypes());
|
||||
callableMethod.invoke(v);
|
||||
return returnValueAsStackValue((FunctionDescriptor) op, callableMethod.getSignature().getAsmMethod().getReturnType());
|
||||
pushMethodArguments(resolvedCall, callable.getValueParameterTypes());
|
||||
callable.invoke(v);
|
||||
return returnValueAsStackValue(op, callable.getSignature().getAsmMethod().getReturnType());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2027,19 +2044,63 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
if (op instanceof FunctionDescriptor) {
|
||||
final Type asmType = expressionType(expression);
|
||||
DeclarationDescriptor cls = op.getContainingDeclaration();
|
||||
if (isNumberPrimitive(cls) && (op.getName().equals("inc") || op.getName().equals("dec"))) {
|
||||
receiver.put(receiver.type, v);
|
||||
JetExpression operand = expression.getBaseExpression();
|
||||
if (operand instanceof JetReferenceExpression) {
|
||||
final int index = indexOfLocal((JetReferenceExpression) operand);
|
||||
if (index >= 0 && isIntPrimitive(asmType)) {
|
||||
int increment = op.getName().equals("inc") ? 1 : -1;
|
||||
return StackValue.postIncrement(index, increment);
|
||||
if (op.getName().equals("inc") || op.getName().equals("dec")) {
|
||||
if (isNumberPrimitive(cls)) {
|
||||
receiver.put(receiver.type, v);
|
||||
JetExpression operand = expression.getBaseExpression();
|
||||
if (operand instanceof JetReferenceExpression) {
|
||||
final int index = indexOfLocal((JetReferenceExpression) operand);
|
||||
if (index >= 0 && isIntPrimitive(asmType)) {
|
||||
int increment = op.getName().equals("inc") ? 1 : -1;
|
||||
return StackValue.postIncrement(index, increment);
|
||||
}
|
||||
}
|
||||
gen(operand, asmType); // old value
|
||||
generateIncrement(op, asmType, operand, receiver); // increment in-place
|
||||
return StackValue.onStack(asmType); // old value
|
||||
}
|
||||
else {
|
||||
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference());
|
||||
assert resolvedCall != null;
|
||||
|
||||
final Callable callable = resolveToCallable(op, false);
|
||||
|
||||
StackValue value = gen(expression.getBaseExpression());
|
||||
value.dupReceiver(v);
|
||||
|
||||
Type type = expressionType(expression.getBaseExpression());
|
||||
value.put(type, v);
|
||||
|
||||
switch(value.receiverSize()) {
|
||||
case 0:
|
||||
if(type.getSize() == 2)
|
||||
v.dup2();
|
||||
else
|
||||
v.dup();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if(type.getSize() == 2)
|
||||
v.dup2X1();
|
||||
else
|
||||
v.dupX1();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if(type.getSize() == 2)
|
||||
v.dup2X2();
|
||||
else
|
||||
v.dupX2();
|
||||
break;
|
||||
|
||||
case -1:
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
((CallableMethod)callable).invoke(v);
|
||||
value.store(v);
|
||||
return StackValue.onStack(type);
|
||||
}
|
||||
gen(operand, asmType); // old value
|
||||
generateIncrement(op, asmType, operand, receiver); // increment in-place
|
||||
return StackValue.onStack(asmType); // old value
|
||||
}
|
||||
}
|
||||
throw new UnsupportedOperationException("Don't know how to generate this prefix expression");
|
||||
|
||||
@@ -51,6 +51,10 @@ public abstract class StackValue {
|
||||
public void dupReceiver(InstructionAdapter v) {
|
||||
}
|
||||
|
||||
public int receiverSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
|
||||
if (this.type == Type.BOOLEAN_TYPE) {
|
||||
put(Type.BOOLEAN_TYPE, v);
|
||||
@@ -491,6 +495,10 @@ public abstract class StackValue {
|
||||
public void dupReceiver(InstructionAdapter v) {
|
||||
v.dup2(); // array and index
|
||||
}
|
||||
|
||||
public int receiverSize() {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
private static class CollectionElement extends StackValue {
|
||||
@@ -547,6 +555,15 @@ public abstract class StackValue {
|
||||
((IntrinsicMethod)setter).generate(codegen, v, null, null, null, null);
|
||||
}
|
||||
|
||||
public int receiverSize() {
|
||||
if(isStandardStack(resolvedGetCall) && isStandardStack(resolvedSetCall)) {
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dupReceiver(InstructionAdapter v) {
|
||||
if(isStandardStack(resolvedGetCall) && isStandardStack(resolvedSetCall)) {
|
||||
@@ -686,6 +703,9 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
private boolean isStandardStack(ResolvedCall call) {
|
||||
if(call == null)
|
||||
return true;
|
||||
|
||||
for (TypeParameterDescriptor typeParameterDescriptor : call.getResultingDescriptor().getTypeParameters()) {
|
||||
if(typeParameterDescriptor.isReified())
|
||||
return false;
|
||||
@@ -736,6 +756,10 @@ public abstract class StackValue {
|
||||
}
|
||||
}
|
||||
|
||||
public int receiverSize() {
|
||||
return isStatic ? 0 : 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(InstructionAdapter v) {
|
||||
v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner, name, this.type.getDescriptor());
|
||||
@@ -801,6 +825,10 @@ public abstract class StackValue {
|
||||
v.dup();
|
||||
}
|
||||
}
|
||||
|
||||
public int receiverSize() {
|
||||
return isStatic ? 0 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Expression extends StackValue {
|
||||
@@ -904,6 +932,10 @@ public abstract class StackValue {
|
||||
v.dup();
|
||||
}
|
||||
|
||||
public int receiverSize() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(Type type, InstructionAdapter v) {
|
||||
Type sharedType = sharedTypeForType(this.type);
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
import java.util.ArrayList
|
||||
|
||||
class MyNumber(val i: Int) {
|
||||
fun inc(): MyNumber = MyNumber(i+1)
|
||||
}
|
||||
|
||||
class MNR(var ref: MyNumber) {}
|
||||
|
||||
fun test1() : Boolean {
|
||||
var m = MyNumber(42)
|
||||
|
||||
m++
|
||||
if (m.i != 43) return false
|
||||
return true
|
||||
}
|
||||
|
||||
fun test2() : Boolean {
|
||||
var m = MyNumber(44)
|
||||
|
||||
var m2 = m++
|
||||
if (m2.i != 44) return false
|
||||
if (m.i != 45) return false
|
||||
return true
|
||||
}
|
||||
|
||||
fun test3() : Boolean {
|
||||
var mnr = MNR(MyNumber(42))
|
||||
mnr.ref++
|
||||
if (mnr.ref.i != 43) return false
|
||||
return true
|
||||
}
|
||||
|
||||
fun test4() : Boolean {
|
||||
var mnr = MNR(MyNumber(42))
|
||||
val m3 = mnr.ref++
|
||||
if (m3.i != 42) return false
|
||||
return true
|
||||
}
|
||||
|
||||
fun test5() : Boolean {
|
||||
var mnr = Array<MyNumber>(2,{MyNumber(42)})
|
||||
mnr[0]++
|
||||
if (mnr[0].i != 43) return false
|
||||
return true
|
||||
}
|
||||
|
||||
fun test6() : Boolean {
|
||||
var mnr = Array<MyNumber>(2,{it -> MyNumber(42-it)})
|
||||
mnr[1] = mnr[0]++
|
||||
if (mnr[0].i != 43) return false
|
||||
if (mnr[1].i != 42) return false
|
||||
return true
|
||||
}
|
||||
|
||||
/*
|
||||
fun test7() : Boolean {
|
||||
var mnr = ArrayList<MyNumber>()
|
||||
mnr.add(MyNumber(42))
|
||||
mnr[0]++
|
||||
if (mnr[0].i != 43) return false
|
||||
return true
|
||||
}
|
||||
|
||||
fun test8() : Boolean {
|
||||
var mnr = ArrayList<MyNumber>()
|
||||
mnr.add(MyNumber(42))
|
||||
mnr.add(MyNumber(41))
|
||||
mnr[1] = mnr[0]++
|
||||
if (mnr[0].i != 43) return false
|
||||
if (mnr[1].i != 42) return false
|
||||
return true
|
||||
}
|
||||
*/
|
||||
|
||||
fun box() : String {
|
||||
var m = MyNumber(42)
|
||||
|
||||
if (!test1()) return "fail test 1"
|
||||
if (!test2()) return "fail test 2"
|
||||
if (!test3()) return "fail test 3"
|
||||
if (!test4()) return "fail test 4"
|
||||
if (!test5()) return "fail test 5"
|
||||
if (!test6()) return "fail test 6"
|
||||
/*
|
||||
if (!test7()) return "fail test 7"
|
||||
if (!test8()) return "fail test 8"
|
||||
|
||||
|
||||
++m
|
||||
if (m.i != 44) return "fail 0"
|
||||
|
||||
var m1 = ++m
|
||||
if (m1.i != 46) return "fail 3"
|
||||
if (m.i != 46) return "fail 4"
|
||||
*/
|
||||
return "OK"
|
||||
}
|
||||
@@ -261,4 +261,8 @@ public class ClassGenTest extends CodegenTestCase {
|
||||
public void testkt1157() throws Exception {
|
||||
blackBoxFile("regressions/kt1157.kt");
|
||||
}
|
||||
|
||||
public void testkt471() throws Exception {
|
||||
blackBoxFile("regressions/kt471.kt");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user