type mapper refactored; more stuff works for function calls

This commit is contained in:
Dmitry Jemerov
2011-03-24 15:49:16 +01:00
parent 802f6e1c7d
commit b346c16c83
6 changed files with 77 additions and 50 deletions
@@ -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);
}
}
-2
View File
@@ -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);
}