This commit is contained in:
Dmitry Jemerov
2011-04-07 15:35:10 +02:00
parent b6a078a562
commit 5b5e8119b5
4 changed files with 53 additions and 24 deletions
@@ -468,13 +468,14 @@ public class ExpressionCodegen extends JetVisitor {
} }
DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationReference()); DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationReference());
if (op instanceof FunctionDescriptor) { if (op instanceof FunctionDescriptor) {
JetType returnType = bindingContext.getExpressionType(expression);
final Type asmType = typeMapper.mapType(returnType);
DeclarationDescriptor cls = op.getContainingDeclaration(); DeclarationDescriptor cls = op.getContainingDeclaration();
if (cls instanceof ClassDescriptor) { if (cls instanceof ClassDescriptor) {
final String className = cls.getName(); final String className = cls.getName();
if (className.equals("Int") || className.equals("Long") || className.equals("Short") || if (isNumberPrimitive(className)) {
className.equals("Byte") || className.equals("Char")) {
if (op.getName().equals("compareTo")) { if (op.getName().equals("compareTo")) {
generateCompareOp(expression, opToken); generateCompareOp(expression, opToken, asmType);
} }
else { else {
int opcode = opcodeForMethod(op.getName()); int opcode = opcodeForMethod(op.getName());
@@ -486,10 +487,8 @@ public class ExpressionCodegen extends JetVisitor {
if (op.getName().equals("equals")) { if (op.getName().equals("equals")) {
final Type leftType = typeMapper.mapType(bindingContext.getExpressionType(expression.getLeft())); final Type leftType = typeMapper.mapType(bindingContext.getExpressionType(expression.getLeft()));
final Type rightType = typeMapper.mapType(bindingContext.getExpressionType(expression.getRight())); final Type rightType = typeMapper.mapType(bindingContext.getExpressionType(expression.getRight()));
if (isIntLikePrimitive(leftType) && isIntLikePrimitive(rightType)) { if (isNumberPrimitive(leftType) && leftType == rightType) {
gen(expression.getLeft(), Type.INT_TYPE); generateCompareOp(expression, opToken, leftType);
gen(expression.getRight(), Type.INT_TYPE);
myStack.push(StackValue.icmp(opToken));
return; return;
} }
else { else {
@@ -505,8 +504,14 @@ public class ExpressionCodegen extends JetVisitor {
throw new UnsupportedOperationException("Don't know how to generate binary op " + expression); throw new UnsupportedOperationException("Don't know how to generate binary op " + expression);
} }
private static boolean isIntLikePrimitive(Type type) { private static boolean isNumberPrimitive(String className) {
return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE; 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) { 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) { private void generateBinaryOp(JetBinaryExpression expression, FunctionDescriptor op, int opcode) {
JetType returnType = op.getUnsubstitutedReturnType(); JetType returnType = op.getUnsubstitutedReturnType();
final Type asmType = typeMapper.mapType(returnType); 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.getLeft(), asmType);
gen(expression.getRight(), asmType); gen(expression.getRight(), asmType);
v.visitInsn(asmType.getOpcode(opcode)); v.visitInsn(asmType.getOpcode(opcode));
@@ -532,10 +537,10 @@ public class ExpressionCodegen extends JetVisitor {
} }
} }
private void generateCompareOp(JetBinaryExpression expression, IElementType opToken) { private void generateCompareOp(JetBinaryExpression expression, IElementType opToken, Type type) {
gen(expression.getLeft(), Type.INT_TYPE); gen(expression.getLeft(), type);
gen(expression.getRight(), Type.INT_TYPE); gen(expression.getRight(), type);
myStack.push(StackValue.icmp(opToken)); myStack.push(StackValue.cmp(opToken, type));
} }
private void generateAssignmentExpression(JetBinaryExpression expression) { private void generateAssignmentExpression(JetBinaryExpression expression) {
@@ -32,6 +32,9 @@ public class JetTypeMapper {
if (jetType.equals(standardLibrary.getCharType())) { if (jetType.equals(standardLibrary.getCharType())) {
return Type.CHAR_TYPE; return Type.CHAR_TYPE;
} }
if (jetType.equals(standardLibrary.getFloatType())) {
return Type.FLOAT_TYPE;
}
if (jetType.equals(standardLibrary.getBooleanType())) { if (jetType.equals(standardLibrary.getBooleanType())) {
return Type.BOOLEAN_TYPE; return Type.BOOLEAN_TYPE;
} }
@@ -27,8 +27,8 @@ public abstract class StackValue {
return new Constant(value); return new Constant(value);
} }
public static StackValue icmp(IElementType opToken) { public static StackValue cmp(IElementType opToken, Type type) {
return new IntCompare(opToken); return new NumberCompare(opToken, type);
} }
public abstract void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v); 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 IElementType opToken;
private final Type type;
public IntCompare(IElementType opToken) { public NumberCompare(IElementType opToken, Type type) {
this.opToken = opToken; this.opToken = opToken;
this.type = type;
} }
@Override @Override
@@ -136,26 +138,37 @@ public abstract class StackValue {
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) { public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
int opcode; int opcode;
if (opToken == JetTokens.EQEQ) { if (opToken == JetTokens.EQEQ) {
opcode = jumpIfFalse ? Opcodes.IF_ICMPNE : Opcodes.IF_ICMPEQ; opcode = jumpIfFalse ? Opcodes.IFNE : Opcodes.IFEQ;
} }
else if (opToken == JetTokens.EXCLEQ) { else if (opToken == JetTokens.EXCLEQ) {
opcode = jumpIfFalse ? Opcodes.IF_ICMPEQ : Opcodes.IF_ICMPNE; opcode = jumpIfFalse ? Opcodes.IFEQ : Opcodes.IFNE;
} }
else if (opToken == JetTokens.GT) { else if (opToken == JetTokens.GT) {
opcode = jumpIfFalse ? Opcodes.IF_ICMPLE : Opcodes.IF_ICMPGT; opcode = jumpIfFalse ? Opcodes.IFLE : Opcodes.IFGT;
} }
else if (opToken == JetTokens.GTEQ) { else if (opToken == JetTokens.GTEQ) {
opcode = jumpIfFalse ? Opcodes.IF_ICMPLT : Opcodes.IF_ICMPGE; opcode = jumpIfFalse ? Opcodes.IFLT : Opcodes.IFGE;
} }
else if (opToken == JetTokens.LT) { else if (opToken == JetTokens.LT) {
opcode = jumpIfFalse ? Opcodes.IF_ICMPGE : Opcodes.IF_ICMPLT; opcode = jumpIfFalse ? Opcodes.IFGE : Opcodes.IFLT;
} }
else if (opToken == JetTokens.LTEQ) { else if (opToken == JetTokens.LTEQ) {
opcode = jumpIfFalse ? Opcodes.IF_ICMPGT : Opcodes.IF_ICMPLE; opcode = jumpIfFalse ? Opcodes.IFGT : Opcodes.IFLE;
} }
else { else {
throw new UnsupportedOperationException("don't know how to generate this condjump"); 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); v.visitJumpInsn(opcode, label);
} }
} }
@@ -279,6 +279,14 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
binOpTest("fun foo(a: Char, b: Char): Int = a + b", 'A', (char) 3, (int) 'D'); 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 { 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());