postfix part of KT-471

This commit is contained in:
Alex Tkachman
2012-01-27 23:11:14 +03:00
parent 8d39594b91
commit 686d4cae3c
4 changed files with 211 additions and 17 deletions
@@ -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");
}
}