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) {
PsiField psiField = (PsiField) declaration;
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);
if (!isStatic) {
ensureReceiverOnStack(expression, null);
@@ -833,7 +833,7 @@ public class ExpressionCodegen extends JetVisitor {
private Method generateJavaMethodCall(JetCallExpression expression, PsiMethod psiMethod) {
final PsiClass containingClass = psiMethod.getContainingClass();
String owner = JetTypeMapper.jvmName(containingClass);
Method methodDescriptor = getMethodDescriptor(psiMethod);
Method methodDescriptor = JetTypeMapper.getMethodDescriptor(psiMethod);
final boolean isStatic = psiMethod.hasModifierProperty(PsiModifier.STATIC);
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) {
return typeMapper.mapType(bindingContext.getExpressionType(expr));
}
@@ -951,53 +941,6 @@ public class ExpressionCodegen extends JetVisitor {
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
public void visitDotQualifiedExpression(JetDotQualifiedExpression expression) {
JetExpression receiver = expression.getReceiverExpression();
@@ -1492,9 +1435,9 @@ public class ExpressionCodegen extends JetVisitor {
Type type = JetTypeMapper.psiClassType(javaClass);
v.anew(type);
v.dup();
final Method jvmConstructor = getMethodDescriptor(constructor);
pushMethodArguments(expression, jvmConstructor);
v.invokespecial(JetTypeMapper.jvmName(javaClass), "<init>", jvmConstructor.getDescriptor());
final CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructor);
pushMethodArguments(expression, callableMethod.getValueParameterTypes());
callableMethod.invoke(v);
return type;
}
@@ -1,7 +1,6 @@
package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import jet.typeinfo.TypeInfo;
import org.jetbrains.annotations.NotNull;
@@ -15,10 +14,7 @@ import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* @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;
}
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) {
PsiElement declaration = bindingContext.getDeclarationPsiElement(jetClass);
if (declaration instanceof PsiClass) {