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;
|
PsiMethod method = (PsiMethod) declarationPsiElement;
|
||||||
if (method.hasModifierProperty(PsiModifier.STATIC)) {
|
if (method.hasModifierProperty(PsiModifier.STATIC)) {
|
||||||
PsiClass containingClass = method.getContainingClass();
|
PsiClass containingClass = method.getContainingClass();
|
||||||
String owner = containingClass.getQualifiedName().replace(".", "/");
|
v.visitMethodInsn(Opcodes.INVOKESTATIC, jvmName(containingClass), method.getName(), getMethodDescriptor(method));
|
||||||
v.visitMethodInsn(Opcodes.INVOKESTATIC, owner, method.getName(), getMethodDescriptor(method));
|
|
||||||
boxIfNeeded(method.getReturnType());
|
boxIfNeeded(method.getReturnType());
|
||||||
}
|
}
|
||||||
else {
|
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) {
|
private void boxIfNeeded(PsiType type) {
|
||||||
if (type == PsiType.LONG) {
|
if (type == PsiType.LONG) {
|
||||||
v.invokestatic("java/lang/Long", "valueOf", "(J)Ljava/lang/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 {
|
else {
|
||||||
throw new UnsupportedOperationException("Don't know how to box type " + type);
|
throw new UnsupportedOperationException("Don't know how to box type " + type);
|
||||||
}
|
}
|
||||||
@@ -318,10 +324,20 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
if (type == PsiType.VOID) {
|
if (type == PsiType.VOID) {
|
||||||
return Type.VOID_TYPE;
|
return Type.VOID_TYPE;
|
||||||
}
|
}
|
||||||
|
if (type == PsiType.INT) {
|
||||||
|
return Type.INT_TYPE;
|
||||||
|
}
|
||||||
if (type == PsiType.LONG) {
|
if (type == PsiType.LONG) {
|
||||||
return Type.LONG_TYPE;
|
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");
|
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 ClassVisitor v;
|
||||||
private final BindingContext bindingContext;
|
private final BindingContext bindingContext;
|
||||||
private final JetStandardLibrary standardLibrary;
|
private final JetStandardLibrary standardLibrary;
|
||||||
|
private final JetTypeMapper typeMapper;
|
||||||
|
|
||||||
public FunctionCodegen(ClassVisitor v, JetStandardLibrary standardLibrary, BindingContext bindingContext) {
|
public FunctionCodegen(ClassVisitor v, JetStandardLibrary standardLibrary, BindingContext bindingContext) {
|
||||||
this.v = v;
|
this.v = v;
|
||||||
this.bindingContext = bindingContext;
|
this.bindingContext = bindingContext;
|
||||||
this.standardLibrary = standardLibrary;
|
this.standardLibrary = standardLibrary;
|
||||||
|
typeMapper = new JetTypeMapper(standardLibrary);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void gen(JetFunction f, JetNamespace owner) {
|
public void gen(JetFunction f, JetNamespace owner) {
|
||||||
final List<JetParameter> parameters = f.getValueParameters();
|
final List<JetParameter> parameters = f.getValueParameters();
|
||||||
Type[] parameterTypes = new Type[parameters.size()];
|
Type[] parameterTypes = new Type[parameters.size()];
|
||||||
for (int i = 0; i < parameters.size(); i++) {
|
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();
|
final JetTypeReference returnTypeRef = f.getReturnTypeRef();
|
||||||
Type returnType;
|
Type returnType;
|
||||||
if (returnTypeRef == null) {
|
if (returnTypeRef == null) {
|
||||||
final FunctionDescriptor functionDescriptor = bindingContext.getFunctionDescriptor(f);
|
final FunctionDescriptor functionDescriptor = bindingContext.getFunctionDescriptor(f);
|
||||||
final JetType type = functionDescriptor.getUnsubstitutedReturnType();
|
final JetType type = functionDescriptor.getUnsubstitutedReturnType();
|
||||||
if (type.equals(JetStandardClasses.getUnitType())) {
|
returnType = typeMapper.mapType(type);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
returnType = mapTypeReference(returnTypeRef);
|
returnType = typeMapper.mapType(bindingContext.resolveTypeReference(returnTypeRef));
|
||||||
}
|
}
|
||||||
Method method = new Method(f.getName(), returnType, parameterTypes);
|
Method method = new Method(f.getName(), returnType, parameterTypes);
|
||||||
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
|
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
|
||||||
@@ -88,41 +82,6 @@ public class FunctionCodegen {
|
|||||||
return false;
|
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) {
|
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(); }
|
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);
|
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) {
|
private void loadFile(final String name) {
|
||||||
myFixture.configureByFile(JetParsingTest.getTestDataDir() + "/codegen/" + name);
|
myFixture.configureByFile(JetParsingTest.getTestDataDir() + "/codegen/" + name);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user