use CallableMethod also for Java constructor calls
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user