提交 8e551399 编写于 作者: D Dmitry Jemerov

generate === and !==

上级 ae4bb5d7
......@@ -503,7 +503,8 @@ public class ExpressionCodegen extends JetVisitor {
else if (opToken == JetTokens.OROR) {
generateBooleanOr(expression);
}
else if (opToken == JetTokens.EQEQ || opToken == JetTokens.EXCLEQ) {
else if (opToken == JetTokens.EQEQ || opToken == JetTokens.EXCLEQ ||
opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) {
generateEquals(expression, opToken);
}
else {
......@@ -562,37 +563,46 @@ public class ExpressionCodegen extends JetVisitor {
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));
if (opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) {
myStack.push(StackValue.cmp(opToken, leftType));
}
else {
myStack.push(onStack);
generateNullSafeEquals(opToken);
}
}
}
private void generateNullSafeEquals(IElementType opToken) {
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;
......
......@@ -33,7 +33,7 @@ public abstract class StackValue {
}
public static StackValue cmp(IElementType opToken, Type type) {
return new NumberCompare(opToken, type);
return type.getSort() == Type.OBJECT ? new ObjectCompare(opToken, type) : new NumberCompare(opToken, type);
}
public static StackValue not(StackValue stackValue) {
......@@ -171,7 +171,7 @@ public abstract class StackValue {
}
private static class NumberCompare extends StackValue {
private final IElementType opToken;
protected final IElementType opToken;
private final Type operandType;
public NumberCompare(IElementType opToken, Type operandType) {
......@@ -230,6 +230,27 @@ public abstract class StackValue {
}
}
private static class ObjectCompare extends NumberCompare {
public ObjectCompare(IElementType opToken, Type operandType) {
super(opToken, operandType);
}
@Override
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
int opcode;
if (opToken == JetTokens.EQEQEQ) {
opcode = jumpIfFalse ? Opcodes.IF_ACMPNE : Opcodes.IF_ACMPEQ;
}
else if (opToken == JetTokens.EXCLEQEQEQ) {
opcode = jumpIfFalse ? Opcodes.IF_ACMPEQ : Opcodes.IF_ACMPNE;
}
else {
throw new UnsupportedOperationException("don't know how to generate this condjump");
}
v.visitJumpInsn(opcode, label);
}
}
private static class Invert extends StackValue {
private StackValue myOperand;
......
......@@ -537,6 +537,24 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
assertEquals(Boolean.FALSE, main.invoke(null, "jet"));
}
public void testTripleEq() throws Exception {
loadText("fun foo(s1: String?, s2: String?) = s1 === s2");
final Method main = generateFunction();
String s1 = new String("jet");
String s2 = new String("jet");
assertEquals(Boolean.TRUE, main.invoke(null, s1, s1));
assertEquals(Boolean.FALSE, main.invoke(null, s1, s2));
}
public void testTripleNotEq() throws Exception {
loadText("fun foo(s1: String?, s2: String?) = s1 !== s2");
final Method main = generateFunction();
String s1 = new String("jet");
String s2 = new String("jet");
assertEquals(Boolean.FALSE, main.invoke(null, s1, s1));
assertEquals(Boolean.TRUE, main.invoke(null, s1, s2));
}
public void testFunctionCall() throws Exception {
loadFile("functionCall.jet");
System.out.println(generateToText());
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册