From 2ce07a5ee26f33dd73d6a149ef65985d01f3bb3b Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 7 Apr 2011 18:33:32 +0200 Subject: [PATCH] pre-increment, pre-decrement --- .../jet/codegen/ExpressionCodegen.java | 58 ++++++++++++++++--- .../org/jetbrains/jet/codegen/FrameMap.java | 2 +- .../jet/codegen/NamespaceGenTest.java | 36 ++++++++++++ 3 files changed, 88 insertions(+), 8 deletions(-) diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 335ef671b99..cd4fb136c48 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -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); diff --git a/idea/src/org/jetbrains/jet/codegen/FrameMap.java b/idea/src/org/jetbrains/jet/codegen/FrameMap.java index 481d87c65a7..5060ff56b0d 100644 --- a/idea/src/org/jetbrains/jet/codegen/FrameMap.java +++ b/idea/src/org/jetbrains/jet/codegen/FrameMap.java @@ -25,7 +25,7 @@ public class FrameMap { } public int getIndex(DeclarationDescriptor descriptor) { - return myVarIndex.get(descriptor); + return myVarIndex.contains(descriptor) ? myVarIndex.get(descriptor) : -1; } } diff --git a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java index 89fb56ab5aa..957c3cc6a64 100644 --- a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java @@ -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());