diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index e2a6d90cfc1..e1037b7ddf5 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -507,6 +507,9 @@ public class ExpressionCodegen extends JetVisitor { else if (opToken == JetTokens.OROR) { generateBooleanOr(expression); } + else if (opToken == JetTokens.EQEQ || opToken == JetTokens.EXCLEQ) { + generateEquals(expression, opToken); + } else { DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationReference()); if (op instanceof FunctionDescriptor) { @@ -523,19 +526,6 @@ public class ExpressionCodegen extends JetVisitor { } return; } - else if (isClass(cls, "Hashable")) { - if (op.getName().equals("equals")) { - final Type leftType = typeMapper.mapType(bindingContext.getExpressionType(expression.getLeft())); - final Type rightType = typeMapper.mapType(bindingContext.getExpressionType(expression.getRight())); - if (isNumberPrimitive(leftType) && leftType == rightType) { - generateCompareOp(expression, opToken, leftType); - return; - } - else { - throw new UnsupportedOperationException("Don't know how to generate equality for these types"); - } - } - } } throw new UnsupportedOperationException("Don't know how to generate binary op " + expression); } @@ -567,6 +557,46 @@ public class ExpressionCodegen extends JetVisitor { myStack.push(StackValue.onStack(Type.BOOLEAN_TYPE)); } + private void generateEquals(JetBinaryExpression expression, IElementType opToken) { + final Type leftType = expressionType(expression.getLeft()); + final Type rightType = expressionType(expression.getRight()); + if (isNumberPrimitive(leftType) && leftType == rightType) { + generateCompareOp(expression, opToken, leftType); + } + else { + gen(expression.getLeft(), leftType); + gen(expression.getRight(), rightType); + v.dup2(); // left right left right + Label rightNull = new Label(); + v.ifnull(rightNull); + Label leftNull = new Label(); + v.ifnull(leftNull); + v.invokevirtual("java/lang/Object", "equals", "(Ljava/lang/Object;)Z"); + Label end = new Label(); + v.goTo(end); + v.mark(rightNull); + // left right left + Label bothNull = new Label(); + v.ifnull(bothNull); + v.mark(leftNull); + v.pop2(); + v.aconst(Boolean.FALSE); + v.goTo(end); + v.mark(bothNull); + v.pop2(); + v.aconst(Boolean.TRUE); + v.mark(end); + + final StackValue onStack = StackValue.onStack(Type.BOOLEAN_TYPE); + if (opToken == JetTokens.EXCLEQ) { + myStack.push(StackValue.not(onStack)); + } + else { + myStack.push(onStack); + } + } + } + private static boolean isNumberPrimitive(DeclarationDescriptor descriptor) { if (!(descriptor instanceof ClassDescriptor)) { return false; diff --git a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java index 9c6980c355a..1735c150a4f 100644 --- a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java @@ -492,6 +492,36 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase { main.invoke(null); // ensure no exception } + public void testJavaConstructor() throws Exception { + loadText("fun foo(): StringBuilder = new StringBuilder()"); + final Method main = generateFunction(); + final Object result = main.invoke(null); + assertTrue(result instanceof StringBuilder); + } + + public void testJavaEquals() throws Exception { + loadText("fun foo(s1: String, s2: String) = s1 == s2"); + System.out.println(generateToText()); + final Method main = generateFunction(); + assertEquals(Boolean.TRUE, main.invoke(null, new String("jet"), new String("jet"))); + assertEquals(Boolean.FALSE, main.invoke(null, new String("jet"), new String("ceylon"))); + } + + public void testJavaNotEquals() throws Exception { + loadText("fun foo(s1: String, s2: String) = s1 != s2"); + final Method main = generateFunction(); + assertEquals(Boolean.FALSE, main.invoke(null, new String("jet"), new String("jet"))); + assertEquals(Boolean.TRUE, main.invoke(null, new String("jet"), new String("ceylon"))); + } + + public void testJavaEqualsNull() throws Exception { + loadText("fun foo(s1: String?, s2: String?) = s1 == s2"); + final Method main = generateFunction(); + assertEquals(Boolean.TRUE, main.invoke(null, null, null)); + assertEquals(Boolean.FALSE, main.invoke(null, "jet", null)); + assertEquals(Boolean.FALSE, main.invoke(null, null, "jet")); + } + private void binOpTest(final String text, final Object arg1, final Object arg2, final Object expected) throws Exception { loadText(text); System.out.println(generateToText());