more progress on traits

This commit is contained in:
Alex Tkachman
2011-09-12 21:23:42 +03:00
parent 4c5d74ea93
commit cf639cf084
9 changed files with 186 additions and 25 deletions
@@ -1813,23 +1813,25 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference);
assert jetType != null;
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
if (!(descriptor instanceof ClassDescriptor)) {
throw new UnsupportedOperationException("don't know how to handle non-class types in as/as?");
}
Type type = JetTypeMapper.boxType(typeMapper.mapType(jetType));
generateInstanceOf(StackValue.expression(OBJECT_TYPE, expression.getLeft(), this), jetType, true);
Label isInstance = new Label();
v.ifne(isInstance);
v.pop();
if (opToken == JetTokens.AS_SAFE) {
v.aconst(null);
if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptor) {
Type type = JetTypeMapper.boxType(typeMapper.mapType(jetType));
generateInstanceOf(StackValue.expression(OBJECT_TYPE, expression.getLeft(), this), jetType, true);
Label isInstance = new Label();
v.ifne(isInstance);
v.pop();
if (opToken == JetTokens.AS_SAFE) {
v.aconst(null);
}
else {
throwNewException(CLASS_TYPE_CAST_EXCEPTION);
}
v.mark(isInstance);
v.checkcast(type);
return StackValue.onStack(type);
}
else {
throwNewException(CLASS_TYPE_CAST_EXCEPTION);
throw new UnsupportedOperationException("don't know how to handle non-class types in as/as?");
}
v.mark(isInstance);
v.checkcast(type);
return StackValue.onStack(type);
}
}
@@ -1962,7 +1964,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
}
private void generateTypeInfo(JetType jetType) {
void generateTypeInfo(JetType jetType) {
String knownTypeInfo = typeMapper.isKnownTypeInfo(jetType);
if(knownTypeInfo != null) {
v.getstatic("jet/typeinfo/TypeInfo", knownTypeInfo, "Ljet/typeinfo/TypeInfo;");
@@ -9,6 +9,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.Variance;
import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.ClassVisitor;
@@ -109,7 +110,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
protected void getSuperClass() {
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
if(myClass instanceof JetClass && ((JetClass)myClass).isTrait())
if(myClass instanceof JetClass && ((JetClass) myClass).isTrait())
return;
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
@@ -150,6 +151,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
generateGetTypeInfo();
//genGetSuperTypesTypeInfo();
}
private void generateFieldForTypeInfo() {
@@ -240,6 +242,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final InstructionAdapter iv = new InstructionAdapter(mv);
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state);
for(int slot = 0; slot != frameMap.getTypeParameterCount(); ++slot) {
codegen.addTypeParameter(constructorDescriptor.getTypeParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO));
}
String classname = state.getTypeMapper().jvmName(descriptor, kind);
final Type classType = Type.getType("L" + classname + ";");
@@ -348,7 +354,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
reg += argType.getSize();
}
String fdescriptor = function.getDescriptor().replace("(","(L" + state.getTypeMapper().jvmName((ClassDescriptor) fun.getContainingDeclaration(),OwnerKind.IMPLEMENTATION) + ";");
ClassDescriptor containingDeclaration = (ClassDescriptor) fun.getContainingDeclaration();
JetType jetType = TraitImplBodyCodegen.getSuperClass(containingDeclaration, state.getBindingContext());
Type type = state.getTypeMapper().mapType(jetType);
if(type.getInternalName().equals("java/lang/Object")) {
jetType = containingDeclaration.getDefaultType();
type = state.getTypeMapper().mapType(jetType);
}
String fdescriptor = function.getDescriptor().replace("(","(" + type.getDescriptor());
iv.invokestatic(state.getTypeMapper().jvmName((ClassDescriptor) fun.getContainingDeclaration(), OwnerKind.TRAIT_IMPL), function.getName(), fdescriptor);
iv.areturn(function.getReturnType());
mv.visitMaxs(0, 0);
@@ -530,7 +544,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.dup();
iv.iconst(i);
iv.load(firstTypeParameter + i, JetTypeMapper.TYPE_OBJECT);
ExpressionCodegen.genTypeInfoToProjection(iv, Variance.INVARIANT);
iv.checkcast(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
iv.astore(JetTypeMapper.TYPE_OBJECT);
}
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
@@ -648,4 +662,50 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private void generateClassObject(JetClassObject declaration) {
state.forClass().generate(context, declaration.getObjectDeclaration());
}
private void genGetSuperTypesTypeInfo() {
if(!(myClass instanceof JetClass) || ((JetClass)myClass).isTrait()) {
return;
}
String sig = getGetSuperTypesTypeInfoSignature(descriptor.getDefaultType());
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC|Opcodes.ACC_STATIC,
"$$getSuperTypesTypeInfo",
sig,
null /* TODO */,
null);
mv.visitCode();
InstructionAdapter v = new InstructionAdapter(mv);
ExpressionCodegen codegen = new ExpressionCodegen(v, new FrameMap(), Type.VOID_TYPE, context, state);
v.load(0, JetTypeMapper.TYPE_OBJECT);
int k = 1;
for (TypeParameterDescriptor parameterDescriptor : descriptor.getTypeConstructor().getParameters()) {
codegen.addTypeParameter(parameterDescriptor, StackValue.local(k++, JetTypeMapper.TYPE_TYPEINFO));
}
for(JetType superType : descriptor.getTypeConstructor().getSupertypes()) {
for (TypeProjection typeProjection : superType.getArguments()) {
codegen.generateTypeInfo(typeProjection.getType());
}
v.invokestatic(state.getTypeMapper().mapType(superType).getInternalName(), "$$getSuperTypesTypeInfo", getGetSuperTypesTypeInfoSignature(superType));
}
v.areturn(Type.VOID_TYPE);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
private static String getGetSuperTypesTypeInfoSignature(JetType type) {
List<TypeParameterDescriptor> typeParameters = type.getConstructor().getParameters();
StringBuilder sb = new StringBuilder("(Ljava/util/Set;");
for(TypeParameterDescriptor tp : typeParameters)
sb.append("Ljet/typeinfo/TypeInfo;");
sb.append(")V");
return sb.toString();
}
}
@@ -439,8 +439,13 @@ public class JetTypeMapper {
}
FunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, f);
if(kind == OwnerKind.TRAIT_IMPL) {
JetType jetType = ((ClassDescriptor)functionDescriptor.getContainingDeclaration()).getDefaultType();
final Type type = mapType(jetType);
ClassDescriptor containingDeclaration = (ClassDescriptor) functionDescriptor.getContainingDeclaration();
JetType jetType = TraitImplBodyCodegen.getSuperClass(containingDeclaration, bindingContext);
Type type = mapType(jetType);
if(type.getInternalName().equals("java/lang/Object")) {
jetType = containingDeclaration.getDefaultType();
type = mapType(jetType);
}
valueParameterTypes.add(type);
parameterTypes.add(type);
}
@@ -1,9 +1,11 @@
package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetNamedFunction;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes;
@@ -16,6 +18,33 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
super(aClass, context, v, state);
}
//todo not needed when frontend will be able to calculate properly
static JetType getSuperClass(ClassDescriptor myClassDescr, BindingContext bindingContext) {
JetClassOrObject myClass = (JetClassOrObject) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, myClassDescr);
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
if (specifier instanceof JetDelegatorToSuperClass || specifier instanceof JetDelegatorToSuperCall) {
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
final PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
if (declaration != null) {
if (declaration instanceof PsiClass) {
if (!((PsiClass) declaration).isInterface()) {
return superClassDescriptor.getDefaultType();
}
}
else if(declaration instanceof JetClass) {
if(!((JetClass) declaration).isTrait()) {
return superClassDescriptor.getDefaultType();
}
}
}
}
}
return null;
}
@Override
protected void generateDeclaration() {
v.visit(Opcodes.V1_6,