diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 9be82e1639b..fd04f0f85e8 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -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), "", jvmConstructor.getDescriptor()); + final CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructor); + pushMethodArguments(expression, callableMethod.getValueParameterTypes()); + callableMethod.invoke(v); return type; } diff --git a/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 6a2ff81dbe0..e3e66039076 100644 --- a/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -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() ? "" : method.getName(), Type.getMethodDescriptor(returnType, parameterTypes)); + } + + static CallableMethod mapToCallableMethod(PsiMethod method) { + String owner = jvmName(method.getContainingClass()); + Method signature = getMethodDescriptor(method); + List valueParameterTypes = new ArrayList(); + 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) {