diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 1f05b5e079a..2f1d9f06a7b 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -815,12 +815,7 @@ public class ExpressionCodegen extends JetVisitor { invokeMethodWithArguments(callableMethod, expression, haveReceiver); final Type callReturnType = callableMethod.getSignature().getReturnType(); - if (callReturnType != Type.VOID_TYPE) { - final Type retType = typeMapper.mapType(fd.getReturnType()); - StackValue.onStack(callReturnType).upcast(retType, v); - return StackValue.onStack(retType); - } - return null; + return returnValueAsStackValue(fd, callReturnType); } else { IntrinsicMethod intrinsic = (IntrinsicMethod) callable; @@ -832,6 +827,15 @@ public class ExpressionCodegen extends JetVisitor { } } + private StackValue returnValueAsStackValue(FunctionDescriptor fd, Type callReturnType) { + if (callReturnType != Type.VOID_TYPE) { + final Type retType = typeMapper.mapType(fd.getReturnType()); + StackValue.onStack(callReturnType).upcast(retType, v); + return StackValue.onStack(retType); + } + return null; + } + private Callable resolveToCallable(FunctionDescriptor fd) { final IntrinsicMethod intrinsic = intrinsics.getIntrinsic(fd); if (intrinsic != null) { @@ -1094,14 +1098,23 @@ public class ExpressionCodegen extends JetVisitor { else { DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationReference()); if (op instanceof FunctionDescriptor) { - final IntrinsicMethod intrinsic = intrinsics.getIntrinsic(op); - if (intrinsic != null) { + final Callable callable = resolveToCallable((FunctionDescriptor) op); + if (callable instanceof IntrinsicMethod) { + IntrinsicMethod intrinsic = (IntrinsicMethod) callable; myStack.push(intrinsic.generate(this, v, expressionType(expression), expression, Arrays.asList(expression.getLeft(), expression.getRight()), false)); - return; + } + else { + CallableMethod callableMethod = (CallableMethod) callable; + genToJVMStack(expression.getLeft()); + genToJVMStack(expression.getRight()); + callableMethod.invoke(v); + final StackValue value = returnValueAsStackValue((FunctionDescriptor) op, callableMethod.getSignature().getReturnType()); + if (value != null) { + myStack.push(value); + } } } - throw new UnsupportedOperationException("Don't know how to generate binary op " + expression); } } diff --git a/idea/testData/codegen/classes/overloadBinaryOperator.jet b/idea/testData/codegen/classes/overloadBinaryOperator.jet new file mode 100644 index 00000000000..bee66062979 --- /dev/null +++ b/idea/testData/codegen/classes/overloadBinaryOperator.jet @@ -0,0 +1,25 @@ +import java.util.* + +class ArrayWrapper() { + val contents = ArrayList() + + fun add(item: T) { + contents.add(item) + } + + fun plus(b: ArrayWrapper): ArrayWrapper { + val result = ArrayWrapper() + result.contents.addAll(contents) + result.contents.addAll(b.contents) + return result + } +} + +fun box(): String { + val v1 = ArrayWrapper() + val v2 = ArrayWrapper() + v1.add("foo") + v2.add("bar") + val v3 = v1 + v2 + return if (v3.contents.size() == 2) "OK" else "fail" +} diff --git a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java index 8800d0aae20..4c6151b78dd 100644 --- a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -132,6 +132,10 @@ public class ClassGenTest extends CodegenTestCase { assertInstanceOf(result, Runnable.class); } + public void testOverloadBinaryOperator() throws Exception { + blackBoxFile("classes/overloadBinaryOperator.jet"); + } + public void testEnumClass() throws Exception { loadText("enum class Direction { NORTH; SOUTH; EAST; WEST }"); final Class direction = loadAllClasses(generateClassesInFile()).get("Direction");