diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 68a515a1783..0a7e35748fb 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -468,13 +468,14 @@ public class ExpressionCodegen extends JetVisitor { } DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationReference()); if (op instanceof FunctionDescriptor) { + JetType returnType = bindingContext.getExpressionType(expression); + final Type asmType = typeMapper.mapType(returnType); DeclarationDescriptor cls = op.getContainingDeclaration(); if (cls instanceof ClassDescriptor) { final String className = cls.getName(); - if (className.equals("Int") || className.equals("Long") || className.equals("Short") || - className.equals("Byte") || className.equals("Char")) { + if (isNumberPrimitive(className)) { if (op.getName().equals("compareTo")) { - generateCompareOp(expression, opToken); + generateCompareOp(expression, opToken, asmType); } else { int opcode = opcodeForMethod(op.getName()); @@ -486,10 +487,8 @@ public class ExpressionCodegen extends JetVisitor { if (op.getName().equals("equals")) { final Type leftType = typeMapper.mapType(bindingContext.getExpressionType(expression.getLeft())); final Type rightType = typeMapper.mapType(bindingContext.getExpressionType(expression.getRight())); - if (isIntLikePrimitive(leftType) && isIntLikePrimitive(rightType)) { - gen(expression.getLeft(), Type.INT_TYPE); - gen(expression.getRight(), Type.INT_TYPE); - myStack.push(StackValue.icmp(opToken)); + if (isNumberPrimitive(leftType) && leftType == rightType) { + generateCompareOp(expression, opToken, leftType); return; } else { @@ -505,8 +504,14 @@ public class ExpressionCodegen extends JetVisitor { throw new UnsupportedOperationException("Don't know how to generate binary op " + expression); } - private static boolean isIntLikePrimitive(Type type) { - return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE; + private static boolean isNumberPrimitive(String className) { + return className.equals("Int") || className.equals("Long") || className.equals("Short") || + className.equals("Byte") || className.equals("Char") || className.equals("Float"); + } + + private static boolean isNumberPrimitive(Type type) { + return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE || + type == Type.FLOAT_TYPE; } private static int opcodeForMethod(final String name) { @@ -521,7 +526,7 @@ public class ExpressionCodegen extends JetVisitor { private void generateBinaryOp(JetBinaryExpression expression, FunctionDescriptor op, int opcode) { JetType returnType = op.getUnsubstitutedReturnType(); final Type asmType = typeMapper.mapType(returnType); - if (asmType == Type.INT_TYPE || asmType == Type.LONG_TYPE) { + if (asmType == Type.INT_TYPE || asmType == Type.LONG_TYPE || asmType == Type.FLOAT_TYPE) { gen(expression.getLeft(), asmType); gen(expression.getRight(), asmType); v.visitInsn(asmType.getOpcode(opcode)); @@ -532,10 +537,10 @@ public class ExpressionCodegen extends JetVisitor { } } - private void generateCompareOp(JetBinaryExpression expression, IElementType opToken) { - gen(expression.getLeft(), Type.INT_TYPE); - gen(expression.getRight(), Type.INT_TYPE); - myStack.push(StackValue.icmp(opToken)); + private void generateCompareOp(JetBinaryExpression expression, IElementType opToken, Type type) { + gen(expression.getLeft(), type); + gen(expression.getRight(), type); + myStack.push(StackValue.cmp(opToken, type)); } private void generateAssignmentExpression(JetBinaryExpression expression) { diff --git a/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 1c30a92a603..36970231c95 100644 --- a/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -32,6 +32,9 @@ public class JetTypeMapper { if (jetType.equals(standardLibrary.getCharType())) { return Type.CHAR_TYPE; } + if (jetType.equals(standardLibrary.getFloatType())) { + return Type.FLOAT_TYPE; + } if (jetType.equals(standardLibrary.getBooleanType())) { return Type.BOOLEAN_TYPE; } diff --git a/idea/src/org/jetbrains/jet/codegen/StackValue.java b/idea/src/org/jetbrains/jet/codegen/StackValue.java index 85edf04591e..e103d16bb1e 100644 --- a/idea/src/org/jetbrains/jet/codegen/StackValue.java +++ b/idea/src/org/jetbrains/jet/codegen/StackValue.java @@ -27,8 +27,8 @@ public abstract class StackValue { return new Constant(value); } - public static StackValue icmp(IElementType opToken) { - return new IntCompare(opToken); + public static StackValue cmp(IElementType opToken, Type type) { + return new NumberCompare(opToken, type); } public abstract void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v); @@ -113,11 +113,13 @@ public abstract class StackValue { } } - private static class IntCompare extends StackValue { + private static class NumberCompare extends StackValue { private final IElementType opToken; + private final Type type; - public IntCompare(IElementType opToken) { + public NumberCompare(IElementType opToken, Type type) { this.opToken = opToken; + this.type = type; } @Override @@ -136,26 +138,37 @@ public abstract class StackValue { public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) { int opcode; if (opToken == JetTokens.EQEQ) { - opcode = jumpIfFalse ? Opcodes.IF_ICMPNE : Opcodes.IF_ICMPEQ; + opcode = jumpIfFalse ? Opcodes.IFNE : Opcodes.IFEQ; } else if (opToken == JetTokens.EXCLEQ) { - opcode = jumpIfFalse ? Opcodes.IF_ICMPEQ : Opcodes.IF_ICMPNE; + opcode = jumpIfFalse ? Opcodes.IFEQ : Opcodes.IFNE; } else if (opToken == JetTokens.GT) { - opcode = jumpIfFalse ? Opcodes.IF_ICMPLE : Opcodes.IF_ICMPGT; + opcode = jumpIfFalse ? Opcodes.IFLE : Opcodes.IFGT; } else if (opToken == JetTokens.GTEQ) { - opcode = jumpIfFalse ? Opcodes.IF_ICMPLT : Opcodes.IF_ICMPGE; + opcode = jumpIfFalse ? Opcodes.IFLT : Opcodes.IFGE; } else if (opToken == JetTokens.LT) { - opcode = jumpIfFalse ? Opcodes.IF_ICMPGE : Opcodes.IF_ICMPLT; + opcode = jumpIfFalse ? Opcodes.IFGE : Opcodes.IFLT; } else if (opToken == JetTokens.LTEQ) { - opcode = jumpIfFalse ? Opcodes.IF_ICMPGT : Opcodes.IF_ICMPLE; + opcode = jumpIfFalse ? Opcodes.IFGT : Opcodes.IFLE; } else { throw new UnsupportedOperationException("don't know how to generate this condjump"); } + if (type == Type.FLOAT_TYPE) { + if (opToken == JetTokens.GT || opToken == JetTokens.GTEQ) { + v.cmpg(type); + } + else { + v.cmpl(type); + } + } + else { + opcode += (Opcodes.IF_ICMPEQ - Opcodes.IFEQ); + } v.visitJumpInsn(opcode, label); } } diff --git a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java index e23c3c603f8..c046b82d067 100644 --- a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java @@ -279,6 +279,14 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase { binOpTest("fun foo(a: Char, b: Char): Int = a + b", 'A', (char) 3, (int) 'D'); } + public void testFloat() throws Exception { + binOpTest("fun foo(a: Float, b: Float): Float = a + b", 1.0f, 2.0f, 3.0f); + } + + public void testFloatCmp() throws Exception { + binOpTest("fun foo(a: Float, b: Float): Boolean = a == b", 1.0f, 1.0f, true); + } + private void binOpTest(final String text, final Object arg1, final Object arg2, final Object expected) throws Exception { loadText(text); System.out.println(generateToText());