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));
|
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) {
|
private static Type psiTypeToAsm(PsiType type) {
|
||||||
if (type instanceof PsiPrimitiveType) {
|
if (type instanceof PsiPrimitiveType) {
|
||||||
if (type == PsiType.VOID) {
|
if (type == PsiType.VOID) {
|
||||||
@@ -595,8 +600,7 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
private void generateAssignmentExpression(JetBinaryExpression expression) {
|
private void generateAssignmentExpression(JetBinaryExpression expression) {
|
||||||
if (expression.getLeft() instanceof JetReferenceExpression) {
|
if (expression.getLeft() instanceof JetReferenceExpression) {
|
||||||
final JetReferenceExpression lhs = (JetReferenceExpression) expression.getLeft();
|
final JetReferenceExpression lhs = (JetReferenceExpression) expression.getLeft();
|
||||||
final DeclarationDescriptor declarationDescriptor = bindingContext.resolveReferenceExpression(lhs);
|
final int index = indexOfLocal(lhs);
|
||||||
final int index = myMap.getIndex(declarationDescriptor);
|
|
||||||
final Type type = typeMapper.mapType(bindingContext.getExpressionType(lhs));
|
final Type type = typeMapper.mapType(bindingContext.getExpressionType(lhs));
|
||||||
gen(expression.getRight(), type);
|
gen(expression.getRight(), type);
|
||||||
v.store(index, type);
|
v.store(index, type);
|
||||||
@@ -613,8 +617,7 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
final JetType leftType = bindingContext.getExpressionType(lhs);
|
final JetType leftType = bindingContext.getExpressionType(lhs);
|
||||||
final Type asmType = typeMapper.mapType(leftType);
|
final Type asmType = typeMapper.mapType(leftType);
|
||||||
if (isNumberPrimitive(asmType)) {
|
if (isNumberPrimitive(asmType)) {
|
||||||
final DeclarationDescriptor declarationDescriptor = bindingContext.resolveReferenceExpression((JetReferenceExpression) lhs);
|
final int index = indexOfLocal((JetReferenceExpression) lhs);
|
||||||
final int index = myMap.getIndex(declarationDescriptor);
|
|
||||||
assert index >= 0;
|
assert index >= 0;
|
||||||
v.load(index, asmType);
|
v.load(index, asmType);
|
||||||
gen(expression.getRight(), asmType);
|
gen(expression.getRight(), asmType);
|
||||||
@@ -635,18 +638,34 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
public void visitPrefixExpression(JetPrefixExpression expression) {
|
public void visitPrefixExpression(JetPrefixExpression expression) {
|
||||||
DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationSign());
|
DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationSign());
|
||||||
if (op instanceof FunctionDescriptor) {
|
if (op instanceof FunctionDescriptor) {
|
||||||
JetType returnType = bindingContext.getExpressionType(expression);
|
final Type asmType = expressionType(expression);
|
||||||
final Type asmType = typeMapper.mapType(returnType);
|
|
||||||
DeclarationDescriptor cls = op.getContainingDeclaration();
|
DeclarationDescriptor cls = op.getContainingDeclaration();
|
||||||
if (isNumberPrimitive(cls)) {
|
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");
|
throw new UnsupportedOperationException("Don't know how to generate this prefix expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean generateUnaryOp(JetPrefixExpression expression, DeclarationDescriptor op, Type asmType) {
|
@Override
|
||||||
final JetExpression operand = expression.getBaseExpression();
|
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")) {
|
if (op.getName().equals("minus")) {
|
||||||
gen(operand, asmType);
|
gen(operand, asmType);
|
||||||
v.neg(asmType);
|
v.neg(asmType);
|
||||||
@@ -654,41 +673,45 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (op.getName().equals("inc") || op.getName().equals("dec")) {
|
else if (op.getName().equals("inc") || op.getName().equals("dec")) {
|
||||||
if (!(operand instanceof JetReferenceExpression)) {
|
final int index = generateIncrement(op, asmType, operand);
|
||||||
throw new UnsupportedOperationException("cannot increment or decrement a non-lvalue");
|
myStack.push(StackValue.local(index, asmType));
|
||||||
}
|
return true;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return false;
|
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) {
|
private void generateInv(Type asmType) {
|
||||||
v.aconst(-1);
|
v.aconst(-1);
|
||||||
v.xor(asmType);
|
v.xor(asmType);
|
||||||
|
|||||||
@@ -419,6 +419,24 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
|
|||||||
assertEquals(10, main.invoke(null, 5));
|
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 {
|
private void binOpTest(final String text, final Object arg1, final Object arg2, final Object expected) throws Exception {
|
||||||
loadText(text);
|
loadText(text);
|
||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
|
|||||||
Reference in New Issue
Block a user