From b346c16c833f1e8fec3657961c06bb71fe076521 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 24 Mar 2011 15:49:16 +0100 Subject: [PATCH] type mapper refactored; more stuff works for function calls --- .../jet/codegen/ExpressionCodegen.java | 20 +++++++- .../jet/codegen/FunctionCodegen.java | 51 ++----------------- .../jetbrains/jet/codegen/JetTypeMapper.java | 44 ++++++++++++++++ idea/testData/codegen/currentTime.jet | 2 - idea/testData/codegen/identityHashCode.jet | 1 + .../jet/codegen/NamespaceGenTest.java | 9 ++++ 6 files changed, 77 insertions(+), 50 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java create mode 100644 idea/testData/codegen/identityHashCode.jet diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 04e7ca0ebd6..54b3320acbe 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -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"); } diff --git a/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java index baa8d1bacc2..a7168b9d20f 100644 --- a/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -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 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 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) { } diff --git a/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java new file mode 100644 index 00000000000..78696d5163a --- /dev/null +++ b/idea/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -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); + } +} diff --git a/idea/testData/codegen/currentTime.jet b/idea/testData/codegen/currentTime.jet index 3a19bf8c5c0..f0edc76752a 100644 --- a/idea/testData/codegen/currentTime.jet +++ b/idea/testData/codegen/currentTime.jet @@ -1,3 +1 @@ -import java.lang.* - fun f() : Long { return System.currentTimeMillis(); } \ No newline at end of file diff --git a/idea/testData/codegen/identityHashCode.jet b/idea/testData/codegen/identityHashCode.jet new file mode 100644 index 00000000000..7b31bf7b5d8 --- /dev/null +++ b/idea/testData/codegen/identityHashCode.jet @@ -0,0 +1 @@ +fun f(o: Any) : Int { return System.identityHashCode(o); } \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java index e2149f672ac..6da578cfa2f 100644 --- a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java @@ -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); }