generate === and !==
This commit is contained in:
@@ -503,7 +503,8 @@ 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) {
|
else if (opToken == JetTokens.EQEQ || opToken == JetTokens.EXCLEQ ||
|
||||||
|
opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) {
|
||||||
generateEquals(expression, opToken);
|
generateEquals(expression, opToken);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -562,37 +563,46 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
else {
|
else {
|
||||||
gen(expression.getLeft(), leftType);
|
gen(expression.getLeft(), leftType);
|
||||||
gen(expression.getRight(), rightType);
|
gen(expression.getRight(), rightType);
|
||||||
v.dup2(); // left right left right
|
if (opToken == JetTokens.EQEQEQ || opToken == JetTokens.EXCLEQEQEQ) {
|
||||||
Label rightNull = new Label();
|
myStack.push(StackValue.cmp(opToken, leftType));
|
||||||
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 {
|
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) {
|
private static boolean isNumberPrimitive(DeclarationDescriptor descriptor) {
|
||||||
if (!(descriptor instanceof ClassDescriptor)) {
|
if (!(descriptor instanceof ClassDescriptor)) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public abstract class StackValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static StackValue cmp(IElementType opToken, Type type) {
|
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) {
|
public static StackValue not(StackValue stackValue) {
|
||||||
@@ -171,7 +171,7 @@ public abstract class StackValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class NumberCompare extends StackValue {
|
private static class NumberCompare extends StackValue {
|
||||||
private final IElementType opToken;
|
protected final IElementType opToken;
|
||||||
private final Type operandType;
|
private final Type operandType;
|
||||||
|
|
||||||
public NumberCompare(IElementType opToken, 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 static class Invert extends StackValue {
|
||||||
private StackValue myOperand;
|
private StackValue myOperand;
|
||||||
|
|
||||||
|
|||||||
@@ -537,6 +537,24 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
|
|||||||
assertEquals(Boolean.FALSE, main.invoke(null, "jet"));
|
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 {
|
public void testFunctionCall() throws Exception {
|
||||||
loadFile("functionCall.jet");
|
loadFile("functionCall.jet");
|
||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
|
|||||||
Reference in New Issue
Block a user