use CallableMethod also for Java constructor calls

This commit is contained in:
Dmitry Jemerov
2011-06-30 20:46:23 +02:00
parent 4b8f40b238
commit ef30fde1c2
2 changed files with 79 additions and 68 deletions
@@ -604,7 +604,7 @@ public class ExpressionCodegen extends JetVisitor {
if (declaration instanceof PsiField) { if (declaration instanceof PsiField) {
PsiField psiField = (PsiField) declaration; PsiField psiField = (PsiField) declaration;
final String owner = JetTypeMapper.jvmName(psiField.getContainingClass()); final String owner = JetTypeMapper.jvmName(psiField.getContainingClass());
final Type fieldType = psiTypeToAsm(psiField.getType()); final Type fieldType = JetTypeMapper.psiTypeToAsm(psiField.getType());
final boolean isStatic = psiField.hasModifierProperty(PsiModifier.STATIC); final boolean isStatic = psiField.hasModifierProperty(PsiModifier.STATIC);
if (!isStatic) { if (!isStatic) {
ensureReceiverOnStack(expression, null); ensureReceiverOnStack(expression, null);
@@ -833,7 +833,7 @@ public class ExpressionCodegen extends JetVisitor {
private Method generateJavaMethodCall(JetCallExpression expression, PsiMethod psiMethod) { private Method generateJavaMethodCall(JetCallExpression expression, PsiMethod psiMethod) {
final PsiClass containingClass = psiMethod.getContainingClass(); final PsiClass containingClass = psiMethod.getContainingClass();
String owner = JetTypeMapper.jvmName(containingClass); String owner = JetTypeMapper.jvmName(containingClass);
Method methodDescriptor = getMethodDescriptor(psiMethod); Method methodDescriptor = JetTypeMapper.getMethodDescriptor(psiMethod);
final boolean isStatic = psiMethod.hasModifierProperty(PsiModifier.STATIC); final boolean isStatic = psiMethod.hasModifierProperty(PsiModifier.STATIC);
if (!isStatic) { if (!isStatic) {
@@ -932,16 +932,6 @@ public class ExpressionCodegen extends JetVisitor {
} }
} }
private static Method getMethodDescriptor(PsiMethod method) {
Type returnType = method.isConstructor() ? Type.VOID_TYPE : psiTypeToAsm(method.getReturnType());
PsiParameter[] parameters = method.getParameterList().getParameters();
Type[] parameterTypes = new Type[parameters.length];
for (int i = 0; i < parameters.length; i++) {
parameterTypes[i] = psiTypeToAsm(parameters [i].getType());
}
return new Method(method.getName(), Type.getMethodDescriptor(returnType, parameterTypes));
}
private Type expressionType(JetExpression expr) { private Type expressionType(JetExpression expr) {
return typeMapper.mapType(bindingContext.getExpressionType(expr)); return typeMapper.mapType(bindingContext.getExpressionType(expr));
} }
@@ -951,53 +941,6 @@ public class ExpressionCodegen extends JetVisitor {
return lookupLocal(declarationDescriptor); return lookupLocal(declarationDescriptor);
} }
private static Type psiTypeToAsm(PsiType type) {
if (type instanceof PsiPrimitiveType) {
if (type == PsiType.VOID) {
return Type.VOID_TYPE;
}
if (type == PsiType.INT) {
return Type.INT_TYPE;
}
if (type == PsiType.LONG) {
return Type.LONG_TYPE;
}
if (type == PsiType.BOOLEAN) {
return Type.BOOLEAN_TYPE;
}
if (type == PsiType.BYTE) {
return Type.BYTE_TYPE;
}
if (type == PsiType.SHORT) {
return Type.SHORT_TYPE;
}
if (type == PsiType.CHAR) {
return Type.CHAR_TYPE;
}
if (type == PsiType.FLOAT) {
return Type.FLOAT_TYPE;
}
if (type == PsiType.DOUBLE) {
return Type.DOUBLE_TYPE;
}
}
if (type instanceof PsiClassType) {
PsiClass psiClass = ((PsiClassType) type).resolve();
if (psiClass instanceof PsiTypeParameter) {
final PsiClassType[] extendsListTypes = psiClass.getExtendsListTypes();
if (extendsListTypes.length > 0) {
throw new UnsupportedOperationException("should return common supertype");
}
return OBJECT_TYPE;
}
if (psiClass == null) {
throw new UnsupportedOperationException("unresolved PsiClassType: " + type);
}
return JetTypeMapper.psiClassType(psiClass);
}
throw new UnsupportedOperationException("don't know how to map type " + type + " to ASM");
}
@Override @Override
public void visitDotQualifiedExpression(JetDotQualifiedExpression expression) { public void visitDotQualifiedExpression(JetDotQualifiedExpression expression) {
JetExpression receiver = expression.getReceiverExpression(); JetExpression receiver = expression.getReceiverExpression();
@@ -1492,9 +1435,9 @@ public class ExpressionCodegen extends JetVisitor {
Type type = JetTypeMapper.psiClassType(javaClass); Type type = JetTypeMapper.psiClassType(javaClass);
v.anew(type); v.anew(type);
v.dup(); v.dup();
final Method jvmConstructor = getMethodDescriptor(constructor); final CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructor);
pushMethodArguments(expression, jvmConstructor); pushMethodArguments(expression, callableMethod.getValueParameterTypes());
v.invokespecial(JetTypeMapper.jvmName(javaClass), "<init>", jvmConstructor.getDescriptor()); callableMethod.invoke(v);
return type; return type;
} }
@@ -1,7 +1,6 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiClass; import com.intellij.psi.*;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import jet.typeinfo.TypeInfo; import jet.typeinfo.TypeInfo;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -15,10 +14,7 @@ import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
import org.objectweb.asm.commons.Method; import org.objectweb.asm.commons.Method;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
* @author yole * @author yole
@@ -49,6 +45,78 @@ public class JetTypeMapper {
return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE; return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE;
} }
static Type psiTypeToAsm(PsiType type) {
if (type instanceof PsiPrimitiveType) {
if (type == PsiType.VOID) {
return Type.VOID_TYPE;
}
if (type == PsiType.INT) {
return Type.INT_TYPE;
}
if (type == PsiType.LONG) {
return Type.LONG_TYPE;
}
if (type == PsiType.BOOLEAN) {
return Type.BOOLEAN_TYPE;
}
if (type == PsiType.BYTE) {
return Type.BYTE_TYPE;
}
if (type == PsiType.SHORT) {
return Type.SHORT_TYPE;
}
if (type == PsiType.CHAR) {
return Type.CHAR_TYPE;
}
if (type == PsiType.FLOAT) {
return Type.FLOAT_TYPE;
}
if (type == PsiType.DOUBLE) {
return Type.DOUBLE_TYPE;
}
}
if (type instanceof PsiClassType) {
PsiClass psiClass = ((PsiClassType) type).resolve();
if (psiClass instanceof PsiTypeParameter) {
final PsiClassType[] extendsListTypes = psiClass.getExtendsListTypes();
if (extendsListTypes.length > 0) {
throw new UnsupportedOperationException("should return common supertype");
}
return TYPE_OBJECT;
}
if (psiClass == null) {
throw new UnsupportedOperationException("unresolved PsiClassType: " + type);
}
return psiClassType(psiClass);
}
throw new UnsupportedOperationException("don't know how to map type " + type + " to ASM");
}
static Method getMethodDescriptor(PsiMethod method) {
Type returnType = method.isConstructor() ? Type.VOID_TYPE : psiTypeToAsm(method.getReturnType());
PsiParameter[] parameters = method.getParameterList().getParameters();
Type[] parameterTypes = new Type[parameters.length];
for (int i = 0; i < parameters.length; i++) {
parameterTypes[i] = psiTypeToAsm(parameters[i].getType());
}
return new Method(method.isConstructor() ? "<init>" : method.getName(), Type.getMethodDescriptor(returnType, parameterTypes));
}
static CallableMethod mapToCallableMethod(PsiMethod method) {
String owner = jvmName(method.getContainingClass());
Method signature = getMethodDescriptor(method);
List<Type> valueParameterTypes = new ArrayList<Type>();
Collections.addAll(valueParameterTypes, signature.getArgumentTypes());
int opcode;
if (method.isConstructor()) {
opcode = Opcodes.INVOKESPECIAL;
}
else {
throw new UnsupportedOperationException("TODO");
}
return new CallableMethod(owner, signature, opcode, valueParameterTypes);
}
public String jvmName(ClassDescriptor jetClass, OwnerKind kind) { public String jvmName(ClassDescriptor jetClass, OwnerKind kind) {
PsiElement declaration = bindingContext.getDeclarationPsiElement(jetClass); PsiElement declaration = bindingContext.getDeclarationPsiElement(jetClass);
if (declaration instanceof PsiClass) { if (declaration instanceof PsiClass) {