pre-increment, pre-decrement

This commit is contained in:
Dmitry Jemerov
2011-04-07 18:33:32 +02:00
parent 5b2200a04e
commit 2ce07a5ee2
3 changed files with 88 additions and 8 deletions
@@ -533,8 +533,11 @@ public class ExpressionCodegen extends JetVisitor {
}
private static boolean isNumberPrimitive(Type type) {
return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE ||
type == Type.FLOAT_TYPE || type == Type.DOUBLE_TYPE || type == Type.LONG_TYPE;
return isIntPrimitive(type) || type == Type.FLOAT_TYPE || type == Type.DOUBLE_TYPE || type == Type.LONG_TYPE;
}
private static boolean isIntPrimitive(Type type) {
return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE;
}
private static int opcodeForMethod(final String name) {
@@ -588,16 +591,57 @@ public class ExpressionCodegen extends JetVisitor {
JetType returnType = bindingContext.getExpressionType(expression);
final Type asmType = typeMapper.mapType(returnType);
DeclarationDescriptor cls = op.getContainingDeclaration();
if (isNumberPrimitive(cls) && op.getName().equals("minus")) {
gen(expression.getBaseExpression(), asmType);
v.neg(asmType);
myStack.push(StackValue.onStack(asmType));
return;
if (isNumberPrimitive(cls)) {
if (generateUnaryOp(expression, op, asmType)) 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();
if (op.getName().equals("minus")) {
gen(operand, asmType);
v.neg(asmType);
myStack.push(StackValue.onStack(asmType));
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;
}
}
return false;
}
@Override
public void visitProperty(JetProperty property) {
PropertyDescriptor propertyDescriptor = bindingContext.getPropertyDescriptor(property);
@@ -25,7 +25,7 @@ public class FrameMap {
}
public int getIndex(DeclarationDescriptor descriptor) {
return myVarIndex.get(descriptor);
return myVarIndex.contains(descriptor) ? myVarIndex.get(descriptor) : -1;
}
}
@@ -342,6 +342,42 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
assertEquals(-10, main.invoke(null, 10));
}
public void testPreIncrement() throws Exception {
loadText("fun foo(a: Int): Int { var x = a; ++x; return x;");
final Method main = generateFunction();
assertEquals(11, main.invoke(null, 10));
}
public void testPreIncrementValue() throws Exception {
loadText("fun foo(a: Int): Int { var x = a; return ++x;");
final Method main = generateFunction();
assertEquals(11, main.invoke(null, 10));
}
public void testPreDecrement() throws Exception {
loadText("fun foo(a: Int): Int { return --a;");
final Method main = generateFunction();
assertEquals(9, main.invoke(null, 10));
}
public void testPreIncrementLong() throws Exception {
loadText("fun foo(a: Long): Long = ++a");
final Method main = generateFunction();
assertEquals(11L, main.invoke(null, 10L));
}
public void testPreIncrementFloat() throws Exception {
loadText("fun foo(a: Float): Float = ++a");
final Method main = generateFunction();
assertEquals(2.0f, main.invoke(null, 1.0f));
}
public void testPreIncrementDouble() throws Exception {
loadText("fun foo(a: Double): Double = ++a");
final Method main = generateFunction();
assertEquals(2.0, main.invoke(null, 1.0));
}
private void binOpTest(final String text, final Object arg1, final Object arg2, final Object expected) throws Exception {
loadText(text);
System.out.println(generateToText());