提交 812d2a18 编写于 作者: D Dmitry Jemerov

casts for constants

上级 365c9af5
......@@ -2,6 +2,7 @@ package org.jetbrains.jet.codegen;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.*;
......@@ -186,7 +187,7 @@ public class ExpressionCodegen extends JetVisitor {
@Override
public void visitConstantExpression(JetConstantExpression expression) {
myStack.push(StackValue.constant(expression.getValue()));
myStack.push(StackValue.constant(expression.getValue(), expressionType(expression)));
}
@Override
......@@ -259,6 +260,18 @@ public class ExpressionCodegen extends JetVisitor {
@Override
public void visitSimpleNameExpression(JetSimpleNameExpression expression) {
final DeclarationDescriptor descriptor = bindingContext.resolveReferenceExpression(expression);
if (descriptor instanceof PropertyDescriptor) {
final DeclarationDescriptor container = descriptor.getContainingDeclaration();
if (isClass(container, "Number")) {
Type castType = getCastType(expression.getReferencedName());
if (castType != null) {
final StackValue value = myStack.pop();
value.put(castType, v);
myStack.push(StackValue.onStack(castType));
return;
}
}
}
PsiElement declaration = bindingContext.getDeclarationPsiElement(descriptor);
if (declaration instanceof PsiField) {
PsiField psiField = (PsiField) declaration;
......@@ -284,6 +297,32 @@ public class ExpressionCodegen extends JetVisitor {
}
}
@Nullable
private static Type getCastType(String castMethodName) {
if ("dbl".equals(castMethodName)) {
return Type.DOUBLE_TYPE;
}
if ("flt".equals(castMethodName)) {
return Type.FLOAT_TYPE;
}
if ("lng".equals(castMethodName)) {
return Type.LONG_TYPE;
}
if ("int".equals(castMethodName)) {
return Type.INT_TYPE;
}
if ("chr".equals(castMethodName)) {
return Type.CHAR_TYPE;
}
if ("sht".equals(castMethodName)) {
return Type.SHORT_TYPE;
}
if ("byt".equals(castMethodName)) {
return Type.BYTE_TYPE;
}
return null;
}
@Override
public void visitCallExpression(JetCallExpression expression) {
JetExpression callee = expression.getCalleeExpression();
......@@ -354,6 +393,10 @@ public class ExpressionCodegen extends JetVisitor {
return Type.getMethodDescriptor(returnType, parameterTypes);
}
private Type expressionType(JetExpression expr) {
return typeMapper.mapType(bindingContext.getExpressionType(expr));
}
private static Type psiTypeToAsm(PsiType type) {
if (type instanceof PsiPrimitiveType) {
if (type == PsiType.VOID) {
......@@ -444,45 +487,51 @@ public class ExpressionCodegen extends JetVisitor {
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 (isNumberPrimitive(className)) {
if (op.getName().equals("compareTo")) {
generateCompareOp(expression, opToken, asmType);
if (isNumberPrimitive(cls)) {
if (op.getName().equals("compareTo")) {
generateCompareOp(expression, opToken, asmType);
}
else {
int opcode = opcodeForMethod(op.getName());
generateBinaryOp(expression, (FunctionDescriptor) op, opcode);
}
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 {
int opcode = opcodeForMethod(op.getName());
generateBinaryOp(expression, (FunctionDescriptor) op, opcode);
}
return;
}
else if (className.equals("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 equality for these types");
}
}
else {
throw new UnsupportedOperationException("Don't know how to generate binary op for class " + className);
}
}
}
throw new UnsupportedOperationException("Don't know how to generate binary op " + expression);
}
private static boolean isNumberPrimitive(String className) {
private static boolean isNumberPrimitive(DeclarationDescriptor descriptor) {
if (!(descriptor instanceof ClassDescriptor)) {
return false;
}
String className = descriptor.getName();
return className.equals("Int") || className.equals("Long") || className.equals("Short") ||
className.equals("Byte") || className.equals("Char") || className.equals("Float") ||
className.equals("Double");
}
private static boolean isClass(DeclarationDescriptor descriptor, String name) {
if (!(descriptor instanceof ClassDescriptor)) {
return false;
}
String className = descriptor.getName();
return className.equals(name);
}
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 || type == Type.DOUBLE_TYPE || type == Type.LONG_TYPE;
......
......@@ -11,6 +11,12 @@ import org.objectweb.asm.commons.InstructionAdapter;
* @author yole
*/
public abstract class StackValue {
protected final Type type;
public StackValue(Type type) {
this.type = type;
}
public abstract void put(Type type, InstructionAdapter v);
public static StackValue local(int index, Type type) {
......@@ -22,8 +28,8 @@ public abstract class StackValue {
return new OnStack(type);
}
public static StackValue constant(Object value) {
return new Constant(value);
public static StackValue constant(Object value, Type type) {
return new Constant(value, type);
}
public static StackValue cmp(IElementType opToken, Type type) {
......@@ -32,44 +38,54 @@ public abstract class StackValue {
public abstract void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v);
private static void box(final Type type, InstructionAdapter v) {
if (type == Type.INT_TYPE) {
v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
}
else if (type == Type.BOOLEAN_TYPE) {
v.invokestatic("java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
}
else if (type == Type.CHAR_TYPE) {
v.invokestatic("java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
}
else if (type == Type.SHORT_TYPE) {
v.invokestatic("java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
}
else if (type == Type.LONG_TYPE) {
v.invokestatic("java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
}
else if (type == Type.BYTE_TYPE) {
v.invokestatic("java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
}
else if (type == Type.FLOAT_TYPE) {
v.invokestatic("java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
}
else if (type == Type.DOUBLE_TYPE) {
v.invokestatic("java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
}
}
protected void coerce(Type type, InstructionAdapter v) {
if (type.getSort() == Type.OBJECT) {
box(this.type, v);
}
else if (type != this.type) {
v.cast(this.type, type);
}
}
public static class Local extends StackValue {
private final int index;
private final Type type;
public Local(int index, Type type) {
super(type);
this.index = index;
this.type = type;
}
@Override
public void put(Type type, InstructionAdapter v) {
v.load(index, this.type);
if (type.getSort() == Type.OBJECT) {
if (this.type == Type.INT_TYPE) {
v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
}
else if (this.type == Type.BOOLEAN_TYPE) {
v.invokestatic("java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
}
else if (this.type == Type.CHAR_TYPE) {
v.invokestatic("java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
}
else if (this.type == Type.SHORT_TYPE) {
v.invokestatic("java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
}
else if (this.type == Type.LONG_TYPE) {
v.invokestatic("java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
}
else if (this.type == Type.BYTE_TYPE) {
v.invokestatic("java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
}
else if (this.type == Type.FLOAT_TYPE) {
v.invokestatic("java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
}
else if (this.type == Type.DOUBLE_TYPE) {
v.invokestatic("java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
}
}
coerce(type, v);
// TODO unbox
}
......@@ -86,10 +102,8 @@ public abstract class StackValue {
}
public static class OnStack extends StackValue {
private final Type type;
public OnStack(Type type) {
this.type = type;
super(type);
}
@Override
......@@ -98,7 +112,7 @@ public abstract class StackValue {
@Override
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
if (type == Type.BOOLEAN_TYPE) {
if (this.type == Type.BOOLEAN_TYPE) {
if (jumpIfFalse) {
v.ifeq(label);
}
......@@ -115,39 +129,15 @@ public abstract class StackValue {
public static class Constant extends StackValue {
private final Object value;
public Constant(Object value) {
public Constant(Object value, Type type) {
super(type);
this.value = value;
}
@Override
public void put(Type type, InstructionAdapter v) {
v.aconst(value);
if (type.getSort() == Type.OBJECT) {
if (value instanceof Integer) {
v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
}
else if (value instanceof Boolean) {
v.invokestatic("java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
}
else if (value instanceof Character) {
v.invokestatic("java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
}
else if (value instanceof Short) {
v.invokestatic("java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
}
else if (value instanceof Long) {
v.invokestatic("java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
}
else if (value instanceof Byte) {
v.invokestatic("java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
}
else if (value instanceof Float) {
v.invokestatic("java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
}
else if (value instanceof Double) {
v.invokestatic("java/lang/Double", "valueOf", "(D)Ljava/lang/Double;");
}
}
coerce(type, v);
}
@Override
......@@ -166,11 +156,10 @@ public abstract class StackValue {
private static class NumberCompare extends StackValue {
private final IElementType opToken;
private final Type type;
public NumberCompare(IElementType opToken, Type type) {
super(type);
this.opToken = opToken;
this.type = type;
}
@Override
......
......@@ -314,6 +314,19 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
assertEquals("1.0", main.invoke(null, 1.0));
}
public void testDoubleToInt() throws Exception {
loadText("fun foo(a: Double): Int = a.int");
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(1, main.invoke(null, 1.0));
}
public void testCastConstant() throws Exception {
loadText("fun foo(): Double = 1.dbl");
final Method main = generateFunction();
assertEquals(1.0, main.invoke(null));
}
private void binOpTest(final String text, final Object arg1, final Object arg2, final Object expected) throws Exception {
loadText(text);
System.out.println(generateToText());
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册