type mapper refactored; more stuff works for function calls
This commit is contained in:
@@ -276,8 +276,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
PsiMethod method = (PsiMethod) declarationPsiElement;
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
String owner = containingClass.getQualifiedName().replace(".", "/");
|
||||
v.visitMethodInsn(Opcodes.INVOKESTATIC, owner, method.getName(), getMethodDescriptor(method));
|
||||
v.visitMethodInsn(Opcodes.INVOKESTATIC, jvmName(containingClass), method.getName(), getMethodDescriptor(method));
|
||||
boxIfNeeded(method.getReturnType());
|
||||
}
|
||||
else {
|
||||
@@ -294,10 +293,17 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
private static String jvmName(PsiClass containingClass) {
|
||||
return containingClass.getQualifiedName().replace(".", "/");
|
||||
}
|
||||
|
||||
private void boxIfNeeded(PsiType type) {
|
||||
if (type == PsiType.LONG) {
|
||||
v.invokestatic("java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
|
||||
}
|
||||
else if (type == PsiType.INT) {
|
||||
v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("Don't know how to box type " + type);
|
||||
}
|
||||
@@ -318,10 +324,20 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
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 instanceof PsiClassType) {
|
||||
PsiClass psiClass = ((PsiClassType) type).resolve();
|
||||
if (psiClass == null) {
|
||||
throw new UnsupportedOperationException("unresolved PsiClassType: " + type);
|
||||
}
|
||||
return Type.getType("L" + jvmName(psiClass) + ";");
|
||||
}
|
||||
throw new UnsupportedOperationException("don't know how to map type " + type + " to ASM");
|
||||
}
|
||||
|
||||
|
||||
@@ -18,36 +18,30 @@ public class FunctionCodegen {
|
||||
private final ClassVisitor v;
|
||||
private final BindingContext bindingContext;
|
||||
private final JetStandardLibrary standardLibrary;
|
||||
private final JetTypeMapper typeMapper;
|
||||
|
||||
public FunctionCodegen(ClassVisitor v, JetStandardLibrary standardLibrary, BindingContext bindingContext) {
|
||||
this.v = v;
|
||||
this.bindingContext = bindingContext;
|
||||
this.standardLibrary = standardLibrary;
|
||||
typeMapper = new JetTypeMapper(standardLibrary);
|
||||
}
|
||||
|
||||
public void gen(JetFunction f, JetNamespace owner) {
|
||||
final List<JetParameter> parameters = f.getValueParameters();
|
||||
Type[] parameterTypes = new Type[parameters.size()];
|
||||
for (int i = 0; i < parameters.size(); i++) {
|
||||
parameterTypes[i] = mapTypeReference(parameters.get(i).getTypeReference());
|
||||
parameterTypes[i] = typeMapper.mapType(bindingContext.resolveTypeReference(parameters.get(i).getTypeReference()));
|
||||
}
|
||||
final JetTypeReference returnTypeRef = f.getReturnTypeRef();
|
||||
Type returnType;
|
||||
if (returnTypeRef == null) {
|
||||
final FunctionDescriptor functionDescriptor = bindingContext.getFunctionDescriptor(f);
|
||||
final JetType type = functionDescriptor.getUnsubstitutedReturnType();
|
||||
if (type.equals(JetStandardClasses.getUnitType())) {
|
||||
returnType = Type.VOID_TYPE;
|
||||
}
|
||||
else if (type.equals(standardLibrary.getIntType())) {
|
||||
returnType = Type.getType(Integer.class);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("don't know how to map type " + type);
|
||||
}
|
||||
returnType = typeMapper.mapType(type);
|
||||
}
|
||||
else {
|
||||
returnType = mapTypeReference(returnTypeRef);
|
||||
returnType = typeMapper.mapType(bindingContext.resolveTypeReference(returnTypeRef));
|
||||
}
|
||||
Method method = new Method(f.getName(), returnType, parameterTypes);
|
||||
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
|
||||
@@ -88,41 +82,6 @@ public class FunctionCodegen {
|
||||
return false;
|
||||
}
|
||||
|
||||
private Type mapTypeReference(JetTypeReference typeRef) {
|
||||
if (typeRef == null) {
|
||||
throw new UnsupportedOperationException("Cannot evaluate type for parameter with no type ref");
|
||||
}
|
||||
final JetTypeElement typeElement = typeRef.getTypeElement();
|
||||
if (typeElement instanceof JetUserType) {
|
||||
final JetUserType userType = (JetUserType) typeElement;
|
||||
return mapType(userType.getReferencedName(), userType.getTypeArguments());
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException("Unknown type " + typeRef);
|
||||
}
|
||||
|
||||
private Type mapType(final String name, final List<JetTypeProjection> typeArguments) {
|
||||
if ("Array".equals(name)) {
|
||||
if (typeArguments.size() != 1) {
|
||||
throw new UnsupportedOperationException("arrays must have one type argument");
|
||||
}
|
||||
final JetTypeReference elementTypeRef = typeArguments.get(0).getTypeReference();
|
||||
Type elementType = mapTypeReference(elementTypeRef);
|
||||
return Type.getType("[" + elementType.getDescriptor());
|
||||
}
|
||||
|
||||
if ("String".equals(name)) {
|
||||
return Type.getType(String.class);
|
||||
}
|
||||
if ("Int".equals(name)) {
|
||||
return Type.getType(Integer.class);
|
||||
}
|
||||
if ("Long".equals(name)) {
|
||||
return Type.getType(Long.class);
|
||||
}
|
||||
throw new UnsupportedOperationException("Unknown type " + name);
|
||||
}
|
||||
|
||||
public void gen(JetFunction f, JetClass owner) {
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class JetTypeMapper {
|
||||
private final JetStandardLibrary standardLibrary;
|
||||
|
||||
public JetTypeMapper(JetStandardLibrary standardLibrary) {
|
||||
this.standardLibrary = standardLibrary;
|
||||
}
|
||||
|
||||
public Type mapType(final JetType jetType) {
|
||||
if (jetType.equals(JetStandardClasses.getUnitType())) {
|
||||
return Type.VOID_TYPE;
|
||||
}
|
||||
if (jetType.equals(standardLibrary.getIntType())) {
|
||||
return Type.getType(Integer.class);
|
||||
}
|
||||
if (jetType.equals(standardLibrary.getLongType())) {
|
||||
return Type.getType(Long.class);
|
||||
}
|
||||
if (jetType.equals(standardLibrary.getStringType())) {
|
||||
return Type.getType(String.class);
|
||||
}
|
||||
|
||||
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||
if (standardLibrary.getArray().equals(descriptor)) {
|
||||
if (jetType.getArguments().size() != 1) {
|
||||
throw new UnsupportedOperationException("arrays must have one type argument");
|
||||
}
|
||||
TypeProjection memberType = jetType.getArguments().get(0);
|
||||
Type elementType = mapType(memberType.getType());
|
||||
return Type.getType("[" + elementType.getDescriptor());
|
||||
}
|
||||
if (JetStandardClasses.getAny().equals(descriptor)) {
|
||||
return Type.getType(Object.class);
|
||||
}
|
||||
throw new UnsupportedOperationException("Unknown type " + jetType);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1 @@
|
||||
import java.lang.*
|
||||
|
||||
fun f() : Long { return System.currentTimeMillis(); }
|
||||
@@ -0,0 +1 @@
|
||||
fun f(o: Any) : Int { return System.identityHashCode(o); }
|
||||
@@ -79,6 +79,15 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
|
||||
assertTrue(Math.abs(returnValue - currentTime) <= 1L);
|
||||
}
|
||||
|
||||
public void testIdentityHashCode() throws Exception {
|
||||
loadFile("identityHashCode.jet");
|
||||
final Class aClass = generateToClass();
|
||||
final Method main = firstMethod(aClass);
|
||||
Object o = new Object();
|
||||
final int returnValue = (Integer) main.invoke(null, o);
|
||||
assertEquals(returnValue, System.identityHashCode(o));
|
||||
}
|
||||
|
||||
private void loadFile(final String name) {
|
||||
myFixture.configureByFile(JetParsingTest.getTestDataDir() + "/codegen/" + name);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user