generate post-increment and post-decrement
This commit is contained in:
@@ -409,6 +409,11 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
return typeMapper.mapType(bindingContext.getExpressionType(expr));
|
||||
}
|
||||
|
||||
private int indexOfLocal(JetReferenceExpression lhs) {
|
||||
final DeclarationDescriptor declarationDescriptor = bindingContext.resolveReferenceExpression(lhs);
|
||||
return myMap.getIndex(declarationDescriptor);
|
||||
}
|
||||
|
||||
private static Type psiTypeToAsm(PsiType type) {
|
||||
if (type instanceof PsiPrimitiveType) {
|
||||
if (type == PsiType.VOID) {
|
||||
@@ -595,8 +600,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
private void generateAssignmentExpression(JetBinaryExpression expression) {
|
||||
if (expression.getLeft() instanceof JetReferenceExpression) {
|
||||
final JetReferenceExpression lhs = (JetReferenceExpression) expression.getLeft();
|
||||
final DeclarationDescriptor declarationDescriptor = bindingContext.resolveReferenceExpression(lhs);
|
||||
final int index = myMap.getIndex(declarationDescriptor);
|
||||
final int index = indexOfLocal(lhs);
|
||||
final Type type = typeMapper.mapType(bindingContext.getExpressionType(lhs));
|
||||
gen(expression.getRight(), type);
|
||||
v.store(index, type);
|
||||
@@ -613,8 +617,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
final JetType leftType = bindingContext.getExpressionType(lhs);
|
||||
final Type asmType = typeMapper.mapType(leftType);
|
||||
if (isNumberPrimitive(asmType)) {
|
||||
final DeclarationDescriptor declarationDescriptor = bindingContext.resolveReferenceExpression((JetReferenceExpression) lhs);
|
||||
final int index = myMap.getIndex(declarationDescriptor);
|
||||
final int index = indexOfLocal((JetReferenceExpression) lhs);
|
||||
assert index >= 0;
|
||||
v.load(index, asmType);
|
||||
gen(expression.getRight(), asmType);
|
||||
@@ -635,18 +638,34 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
public void visitPrefixExpression(JetPrefixExpression expression) {
|
||||
DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationSign());
|
||||
if (op instanceof FunctionDescriptor) {
|
||||
JetType returnType = bindingContext.getExpressionType(expression);
|
||||
final Type asmType = typeMapper.mapType(returnType);
|
||||
final Type asmType = expressionType(expression);
|
||||
DeclarationDescriptor cls = op.getContainingDeclaration();
|
||||
if (isNumberPrimitive(cls)) {
|
||||
if (generateUnaryOp(expression, op, asmType)) return;
|
||||
if (generateUnaryOp(op, asmType, expression.getBaseExpression())) return;
|
||||
}
|
||||
}
|
||||
throw new UnsupportedOperationException("Don't know how to generate this prefix expression");
|
||||
}
|
||||
|
||||
private boolean generateUnaryOp(JetPrefixExpression expression, DeclarationDescriptor op, Type asmType) {
|
||||
final JetExpression operand = expression.getBaseExpression();
|
||||
@Override
|
||||
public void visitPostfixExpression(JetPostfixExpression expression) {
|
||||
DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationSign());
|
||||
if (op instanceof FunctionDescriptor) {
|
||||
final Type asmType = expressionType(expression);
|
||||
DeclarationDescriptor cls = op.getContainingDeclaration();
|
||||
if (isNumberPrimitive(cls) && (op.getName().equals("inc") || op.getName().equals("dec"))) {
|
||||
int oldStackSize = myStack.size();
|
||||
gen(expression.getBaseExpression(), asmType);
|
||||
generateIncrement(op, asmType, expression.getBaseExpression());
|
||||
myStack.push(StackValue.onStack(asmType));
|
||||
assert myStack.size() == oldStackSize+1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new UnsupportedOperationException("Don't know how to generate this prefix expression");
|
||||
}
|
||||
|
||||
private boolean generateUnaryOp(DeclarationDescriptor op, Type asmType, final JetExpression operand) {
|
||||
if (op.getName().equals("minus")) {
|
||||
gen(operand, asmType);
|
||||
v.neg(asmType);
|
||||
@@ -654,41 +673,45 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
return true;
|
||||
}
|
||||
else if (op.getName().equals("inc") || op.getName().equals("dec")) {
|
||||
if (!(operand instanceof JetReferenceExpression)) {
|
||||
throw new UnsupportedOperationException("cannot increment or decrement a non-lvalue");
|
||||
}
|
||||
int increment = op.getName().equals("inc") ? 1 : -1;
|
||||
final DeclarationDescriptor descriptor = bindingContext.resolveReferenceExpression((JetReferenceExpression) operand);
|
||||
final int index = myMap.getIndex(descriptor);
|
||||
if (index >= 0) {
|
||||
if (isIntPrimitive(asmType)) {
|
||||
v.iinc(index, increment);
|
||||
}
|
||||
else {
|
||||
gen(operand, asmType);
|
||||
if (asmType == Type.LONG_TYPE) {
|
||||
v.aconst(Long.valueOf(increment));
|
||||
}
|
||||
else if (asmType == Type.FLOAT_TYPE) {
|
||||
v.aconst(Float.valueOf(increment));
|
||||
}
|
||||
else if (asmType == Type.DOUBLE_TYPE) {
|
||||
v.aconst(Double.valueOf(increment));
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
v.add(asmType);
|
||||
v.store(index, asmType);
|
||||
}
|
||||
myStack.push(StackValue.local(index, asmType));
|
||||
return true;
|
||||
}
|
||||
|
||||
final int index = generateIncrement(op, asmType, operand);
|
||||
myStack.push(StackValue.local(index, asmType));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int generateIncrement(DeclarationDescriptor op, Type asmType, JetExpression operand) {
|
||||
if (!(operand instanceof JetReferenceExpression)) {
|
||||
throw new UnsupportedOperationException("cannot increment or decrement a non-lvalue");
|
||||
}
|
||||
int increment = op.getName().equals("inc") ? 1 : -1;
|
||||
final int index = indexOfLocal((JetReferenceExpression) operand);
|
||||
if (index < 0) {
|
||||
throw new UnsupportedOperationException("don't know how to increment or decrement something which is not a local var");
|
||||
}
|
||||
if (isIntPrimitive(asmType)) {
|
||||
v.iinc(index, increment);
|
||||
}
|
||||
else {
|
||||
gen(operand, asmType);
|
||||
if (asmType == Type.LONG_TYPE) {
|
||||
v.aconst(Long.valueOf(increment));
|
||||
}
|
||||
else if (asmType == Type.FLOAT_TYPE) {
|
||||
v.aconst(Float.valueOf(increment));
|
||||
}
|
||||
else if (asmType == Type.DOUBLE_TYPE) {
|
||||
v.aconst(Double.valueOf(increment));
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("unknown type in increment: " + asmType);
|
||||
}
|
||||
v.add(asmType);
|
||||
v.store(index, asmType);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
private void generateInv(Type asmType) {
|
||||
v.aconst(-1);
|
||||
v.xor(asmType);
|
||||
|
||||
@@ -419,6 +419,24 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
|
||||
assertEquals(10, main.invoke(null, 5));
|
||||
}
|
||||
|
||||
public void testPostIncrementTypeInferenceFail() throws Exception {
|
||||
loadText("fun foo(a: Int): Int { var x = a; var y = x++; if (y+1 != x) return -1; return x; }");
|
||||
final Method main = generateFunction();
|
||||
assertEquals(6, main.invoke(null, 5));
|
||||
}
|
||||
|
||||
public void testPostIncrement() throws Exception {
|
||||
loadText("fun foo(a: Int): Int { var x = a; var y = x++; return x*y; }");
|
||||
final Method main = generateFunction();
|
||||
assertEquals(6, main.invoke(null, 2));
|
||||
}
|
||||
|
||||
public void testPostIncrementLong() throws Exception {
|
||||
loadText("fun foo(a: Long): Long { var x = a; var y = x++; return x*y; }");
|
||||
final Method main = generateFunction();
|
||||
assertEquals(6L, main.invoke(null, 2L));
|
||||
}
|
||||
|
||||
private void binOpTest(final String text, final Object arg1, final Object arg2, final Object expected) throws Exception {
|
||||
loadText(text);
|
||||
System.out.println(generateToText());
|
||||
|
||||
Reference in New Issue
Block a user