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);