diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 8a27359c016..765a2a28d4b 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1323,7 +1323,8 @@ public class ExpressionCodegen extends JetVisitor { DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationSign()); if (op instanceof FunctionDescriptor) { final Type asmType = expressionType(expression); - if (generateUnaryOp(op, asmType, expression)) return; + generateUnaryOp(op, asmType, expression); + return; } throw new UnsupportedOperationException("Don't know how to generate this prefix expression"); } @@ -1351,18 +1352,28 @@ public class ExpressionCodegen extends JetVisitor { throw new UnsupportedOperationException("Don't know how to generate this prefix expression"); } - private boolean generateUnaryOp(DeclarationDescriptor op, Type asmType, final JetUnaryExpression unaryExpression) { - final IntrinsicMethod intrinsic = intrinsics.getIntrinsic(op); + private void generateUnaryOp(DeclarationDescriptor op, Type asmType, final JetUnaryExpression unaryExpression) { final JetExpression operand = unaryExpression.getBaseExpression(); - if (intrinsic != null) { - myStack.push(intrinsic.generate(this, v, asmType, unaryExpression, Collections.singletonList(operand), false)); - return true; - } - else if (isNumberPrimitive(asmType) && (op.getName().equals("inc") || op.getName().equals("dec"))) { + if (isNumberPrimitive(asmType) && (op.getName().equals("inc") || op.getName().equals("dec"))) { myStack.push(generateIncrement(op, asmType, operand)); - return true; + return; + } + + final Callable callable = resolveToCallable((FunctionDescriptor) op); + if (callable instanceof IntrinsicMethod) { + IntrinsicMethod intrinsic = (IntrinsicMethod) callable; + myStack.push(intrinsic.generate(this, v, expressionType(unaryExpression), unaryExpression, + Arrays.asList(unaryExpression.getBaseExpression()), false)); + } + else { + CallableMethod callableMethod = (CallableMethod) callable; + genToJVMStack(unaryExpression.getBaseExpression()); + callableMethod.invoke(v); + final StackValue value = returnValueAsStackValue((FunctionDescriptor) op, callableMethod.getSignature().getReturnType()); + if (value != null) { + myStack.push(value); + } } - return false; } private StackValue generateIncrement(DeclarationDescriptor op, Type asmType, JetExpression operand) { diff --git a/idea/testData/codegen/classes/overloadUnaryOperator.jet b/idea/testData/codegen/classes/overloadUnaryOperator.jet new file mode 100644 index 00000000000..120f84a2746 --- /dev/null +++ b/idea/testData/codegen/classes/overloadUnaryOperator.jet @@ -0,0 +1,28 @@ +import java.util.* + +class ArrayWrapper() { + val contents = ArrayList() + + fun add(item: T) { + contents.add(item) + } + + fun minus(): ArrayWrapper { + val result = ArrayWrapper() + result.contents.addAll(contents) + Collections.reverse(result.contents) + return result + } + + fun get(index: Int): T { + return contents.get(index) + } +} + +fun box(): String { + val v1 = ArrayWrapper() + v1.add("foo") + v1.add("bar") + val v2 = -v1 + return if (v2[0] == "bar" && v2[1] == "foo") "OK" else "fail" +} diff --git a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java index 4c6151b78dd..aefcec68fab 100644 --- a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -136,6 +136,10 @@ public class ClassGenTest extends CodegenTestCase { blackBoxFile("classes/overloadBinaryOperator.jet"); } + public void testOverloadUnaryOperator() throws Exception { + blackBoxFile("classes/overloadUnaryOperator.jet"); + } + public void testEnumClass() throws Exception { loadText("enum class Direction { NORTH; SOUTH; EAST; WEST }"); final Class direction = loadAllClasses(generateClassesInFile()).get("Direction");