null-safe == for objects
This commit is contained in:
@@ -507,6 +507,9 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
else if (opToken == JetTokens.OROR) {
|
else if (opToken == JetTokens.OROR) {
|
||||||
generateBooleanOr(expression);
|
generateBooleanOr(expression);
|
||||||
}
|
}
|
||||||
|
else if (opToken == JetTokens.EQEQ || opToken == JetTokens.EXCLEQ) {
|
||||||
|
generateEquals(expression, opToken);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationReference());
|
DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationReference());
|
||||||
if (op instanceof FunctionDescriptor) {
|
if (op instanceof FunctionDescriptor) {
|
||||||
@@ -523,19 +526,6 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
}
|
}
|
||||||
return;
|
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);
|
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));
|
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) {
|
private static boolean isNumberPrimitive(DeclarationDescriptor descriptor) {
|
||||||
if (!(descriptor instanceof ClassDescriptor)) {
|
if (!(descriptor instanceof ClassDescriptor)) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -492,6 +492,36 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
|
|||||||
main.invoke(null); // ensure no exception
|
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 {
|
private void binOpTest(final String text, final Object arg1, final Object arg2, final Object expected) throws Exception {
|
||||||
loadText(text);
|
loadText(text);
|
||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
|
|||||||
Reference in New Issue
Block a user