removing unnneded InstructionAdapterEx

This commit is contained in:
Alex Tkachman
2011-09-11 12:42:50 +03:00
parent 7214993db6
commit 097325d0d6
19 changed files with 259 additions and 285 deletions
@@ -89,6 +89,7 @@ public abstract class ClassBodyCodegen {
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC); propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
} }
//noinspection ConstantConditions
if (!(kind instanceof OwnerKind.DelegateKind) && kind != OwnerKind.INTERFACE && state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) { if (!(kind instanceof OwnerKind.DelegateKind) && kind != OwnerKind.INTERFACE && state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
v.visitField(Opcodes.ACC_PRIVATE, p.getName(), state.getTypeMapper().mapType(propertyDescriptor.getOutType()).getDescriptor(), null, null); v.visitField(Opcodes.ACC_PRIVATE, p.getName(), state.getTypeMapper().mapType(propertyDescriptor.getOutType()).getDescriptor(), null, null);
} }
@@ -20,13 +20,7 @@ public class ClassCodegen {
public void generate(ClassContext parentContext, JetClassOrObject aClass) { public void generate(ClassContext parentContext, JetClassOrObject aClass) {
GenerationState.prepareAnonymousClasses((JetElement) aClass, state.getTypeMapper()); GenerationState.prepareAnonymousClasses((JetElement) aClass, state.getTypeMapper());
if (aClass instanceof JetObjectDeclaration) { generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
}
else {
generateInterface(parentContext, aClass);
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
}
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
final ClassContext contextForInners = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION); final ClassContext contextForInners = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION);
@@ -37,17 +31,9 @@ public class ClassCodegen {
} }
} }
private void generateInterface(ClassContext parentContext, JetClassOrObject aClass) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
final ClassVisitor visitor = state.forClassInterface(descriptor);
new InterfaceBodyCodegen(aClass, parentContext.intoClass(descriptor, OwnerKind.INTERFACE), visitor, state).generate();
}
private void generateImplementation(ClassContext parentContext, JetClassOrObject aClass, OwnerKind kind) { private void generateImplementation(ClassContext parentContext, JetClassOrObject aClass, OwnerKind kind) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
ClassVisitor v = kind == OwnerKind.IMPLEMENTATION ClassVisitor v = state.forClassImplementation(descriptor);
? state.forClassImplementation(descriptor)
: state.forClassDelegatingImplementation(descriptor);
new ImplementationBodyCodegen(aClass, parentContext.intoClass(descriptor, kind), v, state).generate(); new ImplementationBodyCodegen(aClass, parentContext.intoClass(descriptor, kind), v, state).generate();
} }
@@ -154,7 +154,7 @@ public class ClassContext {
public Type enclosingClassType(JetTypeMapper mapper) { public Type enclosingClassType(JetTypeMapper mapper) {
DeclarationDescriptor descriptor = getContextDescriptor(); DeclarationDescriptor descriptor = getContextDescriptor();
if (descriptor instanceof ClassDescriptor) { if (descriptor instanceof ClassDescriptor) {
return Type.getObjectType(mapper.jvmName((ClassDescriptor) descriptor, OwnerKind.INTERFACE)); return Type.getObjectType(mapper.jvmName((ClassDescriptor) descriptor, OwnerKind.IMPLEMENTATION));
} }
if (descriptor instanceof NamespaceDescriptor) { if (descriptor instanceof NamespaceDescriptor) {
@@ -730,6 +730,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
JetType receiverType = bindingContext.get(BindingContext.EXPRESSION_TYPE, r); JetType receiverType = bindingContext.get(BindingContext.EXPRESSION_TYPE, r);
receiver.put(receiverType != null ? typeMapper.mapType(receiverType) : JetTypeMapper.TYPE_OBJECT, v); receiver.put(receiverType != null ? typeMapper.mapType(receiverType) : JetTypeMapper.TYPE_OBJECT, v);
if(receiverType != null) {
ClassDescriptor propReceiverDescriptor = (ClassDescriptor) propertyDescriptor.getContainingDeclaration();
if(!TypeUtils.isInterface(propReceiverDescriptor, bindingContext) && TypeUtils.isInterface(receiverType.getConstructor().getDeclarationDescriptor(), bindingContext)) {
// I hope it happens only in case of required super class for traits
v.checkcast(typeMapper.mapType(propReceiverDescriptor.getDefaultType()));
}
}
} }
return iValue; return iValue;
} }
@@ -752,8 +759,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
} }
else if (descriptor instanceof TypeParameterDescriptor) { else if (descriptor instanceof TypeParameterDescriptor) {
loadTypeParameterTypeInfo((TypeParameterDescriptor) descriptor); TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
loadTypeParameterTypeInfo(typeParameterDescriptor);
v.invokevirtual("jet/typeinfo/TypeInfo", "getClassObject", "()Ljava/lang/Object;"); v.invokevirtual("jet/typeinfo/TypeInfo", "getClassObject", "()Ljava/lang/Object;");
v.checkcast(typeMapper.mapType(typeParameterDescriptor.getClassObjectType()));
return StackValue.onStack(OBJECT_TYPE); return StackValue.onStack(OBJECT_TYPE);
} }
else { else {
@@ -786,14 +796,20 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
isInterface = false; isInterface = false;
} }
else { else {
owner = typeMapper.getOwner(functionDescriptor, OwnerKind.INTERFACE); owner = typeMapper.getOwner(functionDescriptor, OwnerKind.IMPLEMENTATION);
if(containingDeclaration instanceof JavaClassDescriptor) { if(containingDeclaration instanceof JavaClassDescriptor) {
PsiClass psiElement = (PsiClass) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, containingDeclaration); PsiClass psiElement = (PsiClass) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, containingDeclaration);
assert psiElement != null; assert psiElement != null;
isInterface = psiElement.isInterface(); isInterface = psiElement.isInterface();
} }
else else {
isInterface = !(containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).getKind() == ClassKind.OBJECT); if(containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).getKind() == ClassKind.OBJECT)
isInterface = false;
else {
JetClass jetClass = (JetClass) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, containingDeclaration);
isInterface = jetClass == null || jetClass.isTrait();
}
}
} }
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, functionDescriptor.getName(), typeMapper.mapSignature(functionDescriptor.getName(),functionDescriptor).getDescriptor()); v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, functionDescriptor.getName(), typeMapper.mapSignature(functionDescriptor.getName(),functionDescriptor).getDescriptor());
@@ -827,8 +843,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
isInterface = false; isInterface = false;
} }
else { else {
owner = typeMapper.getOwner(propertyDescriptor, OwnerKind.INTERFACE); owner = typeMapper.getOwner(propertyDescriptor, OwnerKind.IMPLEMENTATION);
isInterface = !(containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).getKind() == ClassKind.OBJECT); if(containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).getKind() == ClassKind.OBJECT)
isInterface = false;
else {
JetClass jetClass = (JetClass) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, containingDeclaration);
isInterface = jetClass == null || jetClass.isTrait();
}
} }
return StackValue.property(propertyDescriptor.getName(), owner, typeMapper.mapType(propertyDescriptor.getOutType()), isStatic, isInterface, getter, setter); return StackValue.property(propertyDescriptor.getName(), owner, typeMapper.mapType(propertyDescriptor.getOutType()), isStatic, isInterface, getter, setter);
@@ -971,7 +992,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
for (JetType superType : allSuperTypes) { for (JetType superType : allSuperTypes) {
final DeclarationDescriptor descriptor = superType.getConstructor().getDeclarationDescriptor(); final DeclarationDescriptor descriptor = superType.getConstructor().getDeclarationDescriptor();
if (descriptor != null && superOriginal == descriptor.getOriginal()) { if (descriptor != null && superOriginal.equals(descriptor.getOriginal())) {
return true; return true;
} }
} }
@@ -1795,7 +1816,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (!(descriptor instanceof ClassDescriptor)) { if (!(descriptor instanceof ClassDescriptor)) {
throw new UnsupportedOperationException("don't know how to handle non-class types in as/as?"); throw new UnsupportedOperationException("don't know how to handle non-class types in as/as?");
} }
Type type = JetTypeMapper.boxType(typeMapper.mapType(jetType, OwnerKind.INTERFACE)); Type type = JetTypeMapper.boxType(typeMapper.mapType(jetType));
generateInstanceOf(StackValue.expression(OBJECT_TYPE, expression.getLeft(), this), jetType, true); generateInstanceOf(StackValue.expression(OBJECT_TYPE, expression.getLeft(), this), jetType, true);
Label isInstance = new Label(); Label isInstance = new Label();
v.ifne(isInstance); v.ifne(isInstance);
@@ -1921,7 +1942,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (leaveExpressionOnStack) { if (leaveExpressionOnStack) {
v.dup(); v.dup();
} }
Type type = JetTypeMapper.boxType(typeMapper.mapType(jetType, OwnerKind.INTERFACE)); Type type = JetTypeMapper.boxType(typeMapper.mapType(jetType));
if(jetType.isNullable()) { if(jetType.isNullable()) {
Label nope = new Label(); Label nope = new Label();
Label end = new Label(); Label end = new Label();
@@ -1967,7 +1988,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return; return;
} }
final Type jvmType = typeMapper.mapType(jetType, OwnerKind.INTERFACE); final Type jvmType = typeMapper.mapType(jetType);
v.aconst(jvmType); v.aconst(jvmType);
v.iconst(jetType.isNullable()?1:0); v.iconst(jetType.isNullable()?1:0);
@@ -89,15 +89,11 @@ public class FunctionCodegen {
boolean isStatic = kind == OwnerKind.NAMESPACE; boolean isStatic = kind == OwnerKind.NAMESPACE;
if (isStatic) flags |= Opcodes.ACC_STATIC; if (isStatic) flags |= Opcodes.ACC_STATIC;
boolean isAbstract = kind == OwnerKind.INTERFACE || bodyExpressions == null; boolean isAbstract = bodyExpressions == null;
if (isAbstract) flags |= Opcodes.ACC_ABSTRACT; if (isAbstract) flags |= Opcodes.ACC_ABSTRACT;
if (isAbstract && (kind == OwnerKind.IMPLEMENTATION )) {
return;
}
final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null); final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
if (kind != OwnerKind.INTERFACE) { if (!isAbstract) {
mv.visitCode(); mv.visitCode();
FrameMap frameMap = context.prepareFrame(); FrameMap frameMap = context.prepareFrame();
@@ -22,29 +22,77 @@ import java.util.*;
/** /**
* @author max * @author max
* @author yole * @author yole
* @author alex.tkachman
*/ */
public class ImplementationBodyCodegen extends ClassBodyCodegen { public class ImplementationBodyCodegen extends ClassBodyCodegen {
private JetDelegationSpecifier superCall;
private String superClass = "java/lang/Object";
public ImplementationBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) { public ImplementationBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) {
super(aClass, context, v, state); super(aClass, context, v, state);
} }
private Set<String> getSuperInterfaces(JetClassOrObject aClass) {
List<JetDelegationSpecifier> delegationSpecifiers = aClass.getDelegationSpecifiers();
String superClassName = null;
Set<String> superInterfaces = new LinkedHashSet<String>();
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
JetType superType = state.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
PsiElement superPsi = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
if (superPsi instanceof PsiClass) {
PsiClass psiClass = (PsiClass) superPsi;
String fqn = psiClass.getQualifiedName();
if (psiClass.isInterface()) {
superInterfaces.add(fqn.replace('.', '/'));
}
else {
if (superClassName == null) {
superClassName = fqn.replace('.', '/');
while (psiClass != null) {
for (PsiClass ifs : psiClass.getInterfaces()) {
superInterfaces.add(ifs.getQualifiedName().replace('.', '/'));
}
psiClass = psiClass.getSuperClass();
}
}
else {
throw new RuntimeException("Cannot determine single class to inherit from");
}
}
}
else {
if(superPsi == null || ((JetClass)superPsi).isTrait())
superInterfaces.add(JetTypeMapper.jvmNameForInterface(superClassDescriptor));
}
}
return superInterfaces;
}
@Override @Override
protected void generateDeclaration() { protected void generateDeclaration() {
String superClass = getSuperClass(); getSuperClass();
List<String> interfaces = new ArrayList<String>(); List<String> interfaces = new ArrayList<String>();
interfaces.add("jet/JetObject"); interfaces.add("jet/JetObject");
if (!(myClass instanceof JetObjectDeclaration)) { interfaces.addAll(getSuperInterfaces(myClass));
interfaces.add(JetTypeMapper.jvmNameForInterface(descriptor));
}
else {
interfaces.addAll(InterfaceBodyCodegen.getSuperInterfaces(myClass, state.getBindingContext()));
}
boolean isAbstract = myClass instanceof JetClass && ((JetClass) myClass).hasModifier(JetTokens.ABSTRACT_KEYWORD); boolean isAbstract = false;
boolean isInterface = false;
if(myClass instanceof JetClass) {
if(((JetClass) myClass).hasModifier(JetTokens.ABSTRACT_KEYWORD))
isAbstract = true;
if(((JetClass) myClass).isTrait()) {
isAbstract = true;
isInterface = true;
}
}
v.visit(Opcodes.V1_6, v.visit(Opcodes.V1_6,
Opcodes.ACC_PUBLIC | (isAbstract ? Opcodes.ACC_ABSTRACT : 0), Opcodes.ACC_PUBLIC | (isAbstract ? Opcodes.ACC_ABSTRACT : 0) | (isInterface ? Opcodes.ACC_INTERFACE : 0),
jvmName(), jvmName(),
null, null,
superClass, superClass,
@@ -57,23 +105,34 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
return state.getTypeMapper().jvmName(descriptor, kind); return state.getTypeMapper().jvmName(descriptor, kind);
} }
protected String getSuperClass() { protected void getSuperClass() {
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers(); List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
if (delegationSpecifiers.isEmpty()) return "java/lang/Object"; if(myClass instanceof JetClass && ((JetClass)myClass).isTrait())
return;
JetDelegationSpecifier first = delegationSpecifiers.get(0); for (JetDelegationSpecifier specifier : delegationSpecifiers) {
if (first instanceof JetDelegatorToSuperClass || first instanceof JetDelegatorToSuperCall) { if (specifier instanceof JetDelegatorToSuperClass || specifier instanceof JetDelegatorToSuperCall) {
JetType superType = state.getBindingContext().get(BindingContext.TYPE, first.getTypeReference()); JetType superType = state.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
final PsiElement declaration = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor); final PsiElement declaration = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
if (declaration instanceof PsiClass && ((PsiClass) declaration).isInterface()) { if (declaration != null) {
return "java/lang/Object"; if (declaration instanceof PsiClass) {
if (!((PsiClass) declaration).isInterface()) {
superClass = state.getTypeMapper().jvmName(superClassDescriptor, kind);
superCall = specifier;
return;
}
}
else if(declaration instanceof JetClass) {
if(!((JetClass) declaration).isTrait()) {
superClass = state.getTypeMapper().jvmName(superClassDescriptor, kind);
superCall = specifier;
}
}
}
} }
return state.getTypeMapper().jvmName(superClassDescriptor, kind);
} }
return "java/lang/Object";
} }
@Override @Override
@@ -93,6 +152,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
private void generateFieldForTypeInfo() { private void generateFieldForTypeInfo() {
if(myClass instanceof JetClass && ((JetClass)myClass).isTrait())
return;
final boolean typeInfoIsStatic = descriptor.getTypeConstructor().getParameters().size() == 0; final boolean typeInfoIsStatic = descriptor.getTypeConstructor().getParameters().size() == 0;
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | (typeInfoIsStatic ? Opcodes.ACC_STATIC : 0), "$typeInfo", v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | (typeInfoIsStatic ? Opcodes.ACC_STATIC : 0), "$typeInfo",
"Ljet/typeinfo/TypeInfo;", null, null); "Ljet/typeinfo/TypeInfo;", null, null);
@@ -101,7 +163,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Override @Override
public void generate(InstructionAdapter v) { public void generate(InstructionAdapter v) {
JetTypeMapper typeMapper = state.getTypeMapper(); JetTypeMapper typeMapper = state.getTypeMapper();
ClassCodegen.newTypeInfo(v, false, typeMapper.jvmType(descriptor, OwnerKind.INTERFACE)); ClassCodegen.newTypeInfo(v, false, typeMapper.jvmType(descriptor, OwnerKind.IMPLEMENTATION));
v.putstatic(typeMapper.jvmName(descriptor, kind), "$typeInfo", "Ljet/typeinfo/TypeInfo;"); v.putstatic(typeMapper.jvmName(descriptor, kind), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
} }
}); });
@@ -149,8 +211,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
protected void generatePrimaryConstructor() { protected void generatePrimaryConstructor() {
if(myClass instanceof JetClass && ((JetClass) myClass).isTrait())
return;
ConstructorDescriptor constructorDescriptor = state.getBindingContext().get(BindingContext.CONSTRUCTOR, myClass); ConstructorDescriptor constructorDescriptor = state.getBindingContext().get(BindingContext.CONSTRUCTOR, myClass);
if (constructorDescriptor == null && !(myClass instanceof JetObjectDeclaration) && !isEnum(myClass)) return; // if (constructorDescriptor == null && !(myClass instanceof JetObjectDeclaration) && !isEnum(myClass)) return;
Method method; Method method;
CallableMethod callableMethod; CallableMethod callableMethod;
@@ -166,7 +231,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null); final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null);
mv.visitCode(); mv.visitCode();
Type[] argTypes = method.getArgumentTypes();
List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null
? constructorDescriptor.getValueParameters() ? constructorDescriptor.getValueParameters()
: Collections.<ValueParameterDescriptor>emptyList(); : Collections.<ValueParameterDescriptor>emptyList();
@@ -179,58 +243,32 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
String classname = state.getTypeMapper().jvmName(descriptor, kind); String classname = state.getTypeMapper().jvmName(descriptor, kind);
final Type classType = Type.getType("L" + classname + ";"); final Type classType = Type.getType("L" + classname + ";");
List<JetDelegationSpecifier> specifiers = myClass.getDelegationSpecifiers();
if (specifiers.isEmpty() || !(specifiers.get(0) instanceof JetDelegatorToSuperCall)) {
// TODO correct calculation of super class
String superClass = "java/lang/Object";
if (!specifiers.isEmpty()) {
final JetType superType = state.getBindingContext().get(BindingContext.TYPE, specifiers.get(0).getTypeReference());
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
if (superClassDescriptor.hasConstructors()) {
superClass = getSuperClass();
}
}
iv.load(0, Type.getType("L" + superClass + ";"));
iv.invokespecial(superClass, "<init>", /* TODO super constructor descriptor */"()V");
}
final ClassDescriptor outerDescriptor = getOuterClassDescriptor();
if (outerDescriptor != null && outerDescriptor.getKind() != ClassKind.OBJECT) {
final Type type = JetTypeMapper.jetImplementationType(outerDescriptor);
String interfaceDesc = type.getDescriptor();
final String fieldName = "this$0";
v.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, fieldName, interfaceDesc, null, null);
iv.load(0, classType);
iv.load(frameMap.getOuterThisIndex(), type);
iv.putfield(classname, fieldName, interfaceDesc);
}
HashSet<FunctionDescriptor> overridden = new HashSet<FunctionDescriptor>(); HashSet<FunctionDescriptor> overridden = new HashSet<FunctionDescriptor>();
for (JetDeclaration declaration : myClass.getDeclarations()) { for (JetDeclaration declaration : myClass.getDeclarations()) {
if (declaration instanceof JetFunction) { if (declaration instanceof JetFunction) {
overridden.addAll(state.getBindingContext().get(BindingContext.FUNCTION, (JetNamedFunction) declaration).getOverriddenDescriptors()); overridden.addAll(state.getBindingContext().get(BindingContext.FUNCTION, declaration).getOverriddenDescriptors());
} }
} }
if (superCall == null || superCall instanceof JetDelegatorToSuperClass) {
iv.load(0, Type.getType("L" + superClass + ";"));
iv.invokespecial(superClass, "<init>", "()V");
}
else {
iv.load(0, classType);
ConstructorDescriptor constructorDescriptor1 = (ConstructorDescriptor) state.getBindingContext().get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression());
generateDelegatorToConstructorCall(iv, codegen, (JetDelegatorToSuperCall) superCall, constructorDescriptor1, frameMap);
}
int n = 0; int n = 0;
for (JetDelegationSpecifier specifier : specifiers) { for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
boolean delegateOnStack = specifier instanceof JetDelegatorToSuperCall && n > 0 || if(specifier == superCall)
specifier instanceof JetDelegatorByExpressionSpecifier; continue;
if (delegateOnStack) { if (specifier instanceof JetDelegatorByExpressionSpecifier) {
iv.load(0, classType); iv.load(0, classType);
}
if (specifier instanceof JetDelegatorToSuperCall) {
ConstructorDescriptor constructorDescriptor1 = (ConstructorDescriptor) state.getBindingContext().get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) specifier).getCalleeExpression().getConstructorReferenceExpression());
generateDelegatorToConstructorCall(iv, codegen, (JetDelegatorToSuperCall) specifier, constructorDescriptor1, n == 0, frameMap);
}
else if (specifier instanceof JetDelegatorByExpressionSpecifier) {
codegen.genToJVMStack(((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression()); codegen.genToJVMStack(((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression());
}
if (delegateOnStack) {
JetType superType = state.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference()); JetType superType = state.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
String delegateField = "$delegate_" + n; String delegateField = "$delegate_" + n;
@@ -245,8 +283,17 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
JetTypeMapper.jvmNameForInterface(superClassDescriptor))); JetTypeMapper.jvmNameForInterface(superClassDescriptor)));
generateDelegates(superClass, delegateContext, overridden); generateDelegates(superClass, delegateContext, overridden);
} }
}
n++; final ClassDescriptor outerDescriptor = getOuterClassDescriptor();
if (outerDescriptor != null && outerDescriptor.getKind() != ClassKind.OBJECT) {
final Type type = JetTypeMapper.jetImplementationType(outerDescriptor);
String interfaceDesc = type.getDescriptor();
final String fieldName = "this$0";
v.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, fieldName, interfaceDesc, null, null);
iv.load(0, classType);
iv.load(frameMap.getOuterThisIndex(), type);
iv.putfield(classname, fieldName, interfaceDesc);
} }
if (frameMap.getFirstTypeParameter() > 0 && kind == OwnerKind.IMPLEMENTATION) { if (frameMap.getFirstTypeParameter() > 0 && kind == OwnerKind.IMPLEMENTATION) {
@@ -288,7 +335,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
private void generateDelegatorToConstructorCall(InstructionAdapter iv, ExpressionCodegen codegen, JetCallElement constructorCall, private void generateDelegatorToConstructorCall(InstructionAdapter iv, ExpressionCodegen codegen, JetCallElement constructorCall,
ConstructorDescriptor constructorDescriptor, boolean isJavaSuperclass, ConstructorDescriptor constructorDescriptor,
ConstructorFrameMap frameMap) { ConstructorFrameMap frameMap) {
ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration(); ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
PsiElement declaration = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDecl); PsiElement declaration = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDecl);
@@ -300,13 +347,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
type = JetTypeMapper.jetImplementationType(classDecl); type = JetTypeMapper.jetImplementationType(classDecl);
} }
if (isJavaSuperclass) { iv.load(0, type);
iv.load(0, type);
}
else {
iv.anew(type);
iv.dup();
}
if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) { if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) {
iv.load(frameMap.getOuterThisIndex(), state.getTypeMapper().jvmType((ClassDescriptor) descriptor.getContainingDeclaration(), OwnerKind.IMPLEMENTATION)); iv.load(frameMap.getOuterThisIndex(), state.getTypeMapper().jvmType((ClassDescriptor) descriptor.getContainingDeclaration(), OwnerKind.IMPLEMENTATION));
@@ -324,11 +365,60 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
else if (declaration instanceof JetClassObject) { else if (declaration instanceof JetClassObject) {
generateClassObject((JetClassObject) declaration); generateClassObject((JetClassObject) declaration);
} }
else if (declaration instanceof JetEnumEntry && !((JetEnumEntry) declaration).hasPrimaryConstructor()) {
String name = declaration.getName();
final String desc = "L" + state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION) + ";";
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, name, desc, null, null);
if (myEnumConstants.isEmpty()) {
staticInitializerChunks.add(new CodeChunk() {
@Override
public void generate(InstructionAdapter v) {
initializeEnumConstants(v);
}
});
}
myEnumConstants.add((JetEnumEntry) declaration);
}
else { else {
super.generateDeclaration(propertyCodegen, declaration, functionCodegen); super.generateDeclaration(propertyCodegen, declaration, functionCodegen);
} }
} }
private final List<JetEnumEntry> myEnumConstants = new ArrayList<JetEnumEntry>();
private void initializeEnumConstants(InstructionAdapter v) {
ExpressionCodegen codegen = new ExpressionCodegen(v, new FrameMap(), Type.VOID_TYPE, context, state);
for (JetEnumEntry enumConstant : myEnumConstants) {
// TODO type and constructor parameters
String implClass = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
final List<JetDelegationSpecifier> delegationSpecifiers = enumConstant.getDelegationSpecifiers();
if (delegationSpecifiers.size() > 1) {
throw new UnsupportedOperationException("multiple delegation specifiers for enum constant not supported");
}
v.anew(Type.getObjectType(implClass));
v.dup();
if (delegationSpecifiers.size() == 1) {
final JetDelegationSpecifier specifier = delegationSpecifiers.get(0);
if (specifier instanceof JetDelegatorToSuperCall) {
final JetDelegatorToSuperCall superCall = (JetDelegatorToSuperCall) specifier;
ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) state.getBindingContext().get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression());
CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
codegen.invokeMethodWithArguments(method, superCall);
}
else {
throw new UnsupportedOperationException("unsupported type of enum constant initializer: " + specifier);
}
}
else {
v.invokespecial(implClass, "<init>", "()V");
}
v.putstatic(implClass, enumConstant.getName(), "L" + implClass + ";");
}
}
private void generateSecondaryConstructor(JetConstructor constructor) { private void generateSecondaryConstructor(JetConstructor constructor) {
ConstructorDescriptor constructorDescriptor = state.getBindingContext().get(BindingContext.CONSTRUCTOR, constructor); ConstructorDescriptor constructorDescriptor = state.getBindingContext().get(BindingContext.CONSTRUCTOR, constructor);
if (constructorDescriptor == null) { if (constructorDescriptor == null) {
@@ -351,7 +441,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (!(thisDescriptor instanceof ConstructorDescriptor)) { if (!(thisDescriptor instanceof ConstructorDescriptor)) {
throw new UnsupportedOperationException("expected 'this' delegator to resolve to constructor"); throw new UnsupportedOperationException("expected 'this' delegator to resolve to constructor");
} }
generateDelegatorToConstructorCall(iv, codegen, thisCall, (ConstructorDescriptor) thisDescriptor, true, frameMap); generateDelegatorToConstructorCall(iv, codegen, thisCall, (ConstructorDescriptor) thisDescriptor, frameMap);
} }
else { else {
throw new UnsupportedOperationException("unknown initializer type"); throw new UnsupportedOperationException("unknown initializer type");
@@ -371,7 +461,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
protected void generateTypeInfoInitializer(int firstTypeParameter, int typeParamCount, InstructionAdapter iv) { protected void generateTypeInfoInitializer(int firstTypeParameter, int typeParamCount, InstructionAdapter iv) {
iv.load(0, JetTypeMapper.TYPE_OBJECT); iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.aconst(state.getTypeMapper().jvmType(descriptor, OwnerKind.INTERFACE)); iv.aconst(state.getTypeMapper().jvmType(descriptor, OwnerKind.IMPLEMENTATION));
iv.iconst(0); iv.iconst(0);
iv.iconst(typeParamCount); iv.iconst(typeParamCount);
iv.newarray(JetTypeMapper.TYPE_TYPEINFOPROJECTION); iv.newarray(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
@@ -427,7 +517,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.load(0, JetTypeMapper.TYPE_OBJECT); iv.load(0, JetTypeMapper.TYPE_OBJECT);
Type type = codegen.expressionType(initializer); Type type = codegen.expressionType(initializer);
if(propertyDescriptor.getOutType().isNullable()) if(propertyDescriptor.getOutType().isNullable())
type = state.getTypeMapper().boxType(type); type = JetTypeMapper.boxType(type);
codegen.gen(initializer, type); codegen.gen(initializer, type);
codegen.intermediateValueForProperty(propertyDescriptor, false, false).store(iv); codegen.intermediateValueForProperty(propertyDescriptor, false, false).store(iv);
} }
@@ -479,6 +569,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
private void generateGetTypeInfo() { private void generateGetTypeInfo() {
if(myClass instanceof JetClass && ((JetClass)myClass).isTrait())
return;
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC, final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC,
"getTypeInfo", "getTypeInfo",
"()Ljet/typeinfo/TypeInfo;", "()Ljet/typeinfo/TypeInfo;",
@@ -1,137 +0,0 @@
package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetType;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
* @author yole
*/
public class InterfaceBodyCodegen extends ClassBodyCodegen {
private final List<JetEnumEntry> myEnumConstants = new ArrayList<JetEnumEntry>();
public InterfaceBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) {
super(aClass, context, v, state);
assert context.getContextKind() == OwnerKind.INTERFACE;
}
protected void generateDeclaration() {
Set<String> superInterfaces = getSuperInterfaces(myClass, state.getBindingContext());
String fqName = JetTypeMapper.jvmNameForInterface(descriptor);
v.visit(Opcodes.V1_6,
Opcodes.ACC_PUBLIC | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT,
fqName,
null,
"java/lang/Object",
superInterfaces.toArray(new String[superInterfaces.size()])
);
v.visitSource(myClass.getContainingFile().getName(), null);
}
static Set<String> getSuperInterfaces(JetClassOrObject aClass, final BindingContext bindingContext) {
List<JetDelegationSpecifier> delegationSpecifiers = aClass.getDelegationSpecifiers();
String superClassName = null;
Set<String> superInterfaces = new LinkedHashSet<String>();
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
PsiElement superPsi = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
if (superPsi instanceof PsiClass) {
PsiClass psiClass = (PsiClass) superPsi;
String fqn = psiClass.getQualifiedName();
if (psiClass.isInterface()) {
superInterfaces.add(fqn.replace('.', '/'));
}
else {
if (superClassName == null) {
superClassName = fqn.replace('.', '/');
while (psiClass != null) {
for (PsiClass ifs : psiClass.getInterfaces()) {
superInterfaces.add(ifs.getQualifiedName().replace('.', '/'));
}
psiClass = psiClass.getSuperClass();
}
}
else {
throw new RuntimeException("Cannot determine single class to inherit from");
}
}
}
else {
superInterfaces.add(JetTypeMapper.jvmNameForInterface(superClassDescriptor));
}
}
return superInterfaces;
}
@Override
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
if (declaration instanceof JetEnumEntry && !((JetEnumEntry) declaration).hasPrimaryConstructor()) {
String name = declaration.getName();
final String desc = "L" + state.getTypeMapper().jvmName(descriptor, OwnerKind.INTERFACE) + ";";
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, name, desc, null, null);
if (myEnumConstants.isEmpty()) {
staticInitializerChunks.add(new CodeChunk() {
@Override
public void generate(InstructionAdapter v) {
initializeEnumConstants(v);
}
});
}
myEnumConstants.add((JetEnumEntry) declaration);
}
else {
super.generateDeclaration(propertyCodegen, declaration, functionCodegen);
}
}
private void initializeEnumConstants(InstructionAdapter v) {
ExpressionCodegen codegen = new ExpressionCodegen(v, new FrameMap(), Type.VOID_TYPE, context, state);
for (JetEnumEntry enumConstant : myEnumConstants) {
// TODO type and constructor parameters
String intfClass = state.getTypeMapper().jvmName(descriptor, OwnerKind.INTERFACE);
String implClass = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
final List<JetDelegationSpecifier> delegationSpecifiers = enumConstant.getDelegationSpecifiers();
if (delegationSpecifiers.size() > 1) {
throw new UnsupportedOperationException("multiple delegation specifiers for enum constant not supported");
}
v.anew(Type.getObjectType(implClass));
v.dup();
if (delegationSpecifiers.size() == 1) {
final JetDelegationSpecifier specifier = delegationSpecifiers.get(0);
if (specifier instanceof JetDelegatorToSuperCall) {
final JetDelegatorToSuperCall superCall = (JetDelegatorToSuperCall) specifier;
ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) state.getBindingContext().get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression());
CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
codegen.invokeMethodWithArguments(method, superCall);
}
else {
throw new UnsupportedOperationException("unsupported type of enum constant initializer: " + specifier);
}
}
else {
v.invokespecial(implClass, "<init>", "()V");
}
v.putstatic(intfClass, enumConstant.getName(), "L" + intfClass + ";");
}
}
}
@@ -205,7 +205,7 @@ public class JetTypeMapper {
if (parent instanceof JetClassObject) { if (parent instanceof JetClassObject) {
JetClass containingClass = PsiTreeUtil.getParentOfType(parent, JetClass.class); JetClass containingClass = PsiTreeUtil.getParentOfType(parent, JetClass.class);
final ClassDescriptor containingClassDescriptor = bindingContext.get(BindingContext.CLASS, containingClass); final ClassDescriptor containingClassDescriptor = bindingContext.get(BindingContext.CLASS, containingClass);
return jvmName(containingClassDescriptor, OwnerKind.INTERFACE) + "$$ClassObj"; return jvmName(containingClassDescriptor, OwnerKind.IMPLEMENTATION) + "$$ClassObj";
} }
@SuppressWarnings("SuspiciousMethodCalls") String className = classNamesForAnonymousClasses.get(declaration); @SuppressWarnings("SuspiciousMethodCalls") String className = classNamesForAnonymousClasses.get(declaration);
if (className == null) { if (className == null) {
@@ -226,16 +226,13 @@ public class JetTypeMapper {
if (declaration instanceof JetObjectDeclaration) { if (declaration instanceof JetObjectDeclaration) {
return false; return false;
} }
return kind == OwnerKind.INTERFACE; return jetClass instanceof JetClass ? ((JetClass)jetClass).isTrait() : false;
} }
private static String jetJvmName(ClassDescriptor jetClass, OwnerKind kind) { private static String jetJvmName(ClassDescriptor jetClass, OwnerKind kind) {
if (jetClass.getKind() == ClassKind.OBJECT) { if (jetClass.getKind() == ClassKind.OBJECT) {
return jvmNameForImplementation(jetClass); return jvmNameForImplementation(jetClass);
} }
if (kind == OwnerKind.INTERFACE) {
return jvmNameForInterface(jetClass);
}
else if (kind == OwnerKind.IMPLEMENTATION) { else if (kind == OwnerKind.IMPLEMENTATION) {
return jvmNameForImplementation(jetClass); return jvmNameForImplementation(jetClass);
} }
@@ -277,7 +274,7 @@ public class JetTypeMapper {
} }
public static String jvmNameForImplementation(ClassDescriptor descriptor) { public static String jvmNameForImplementation(ClassDescriptor descriptor) {
return jvmNameForInterface(descriptor) + "$$Impl"; return jvmNameForInterface(descriptor);
} }
public static String jvmNameForDelegatingImplementation(ClassDescriptor descriptor) { public static String jvmNameForDelegatingImplementation(ClassDescriptor descriptor) {
@@ -292,7 +289,7 @@ public class JetTypeMapper {
else if (descriptor.getContainingDeclaration() instanceof ClassDescriptor) { else if (descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor.getContainingDeclaration(); ClassDescriptor classDescriptor = (ClassDescriptor) descriptor.getContainingDeclaration();
if (kind instanceof OwnerKind.DelegateKind) { if (kind instanceof OwnerKind.DelegateKind) {
kind = OwnerKind.INTERFACE; kind = OwnerKind.IMPLEMENTATION;
} }
else { else {
assert classDescriptor != null; assert classDescriptor != null;
@@ -316,11 +313,11 @@ public class JetTypeMapper {
} }
@NotNull public Type mapReturnType(final JetType jetType) { @NotNull public Type mapReturnType(final JetType jetType) {
return mapReturnType(jetType, OwnerKind.INTERFACE); return mapReturnType(jetType, OwnerKind.IMPLEMENTATION);
} }
@NotNull public Type mapType(final JetType jetType) { @NotNull public Type mapType(final JetType jetType) {
return mapType(jetType, OwnerKind.INTERFACE); return mapType(jetType, OwnerKind.IMPLEMENTATION);
} }
@NotNull public Type mapType(@NotNull final JetType jetType, OwnerKind kind) { @NotNull public Type mapType(@NotNull final JetType jetType, OwnerKind kind) {
@@ -483,7 +480,7 @@ public class JetTypeMapper {
} }
else if (functionParent instanceof ClassDescriptor) { else if (functionParent instanceof ClassDescriptor) {
ClassDescriptor containingClass = (ClassDescriptor) functionParent; ClassDescriptor containingClass = (ClassDescriptor) functionParent;
owner = jvmName(containingClass, OwnerKind.INTERFACE); owner = jvmName(containingClass, OwnerKind.IMPLEMENTATION);
invokeOpcode = isInterface(containingClass, OwnerKind.INTERFACE) invokeOpcode = isInterface(containingClass, OwnerKind.INTERFACE)
? Opcodes.INVOKEINTERFACE ? Opcodes.INVOKEINTERFACE
: Opcodes.INVOKEVIRTUAL; : Opcodes.INVOKEVIRTUAL;
@@ -636,7 +633,6 @@ public class JetTypeMapper {
Set<String> result = new HashSet<String>(); Set<String> result = new HashSet<String>();
final ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, jetClass); final ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, jetClass);
if (classDescriptor != null) { if (classDescriptor != null) {
result.add(jvmName(classDescriptor, OwnerKind.INTERFACE));
result.add(jvmName(classDescriptor, OwnerKind.IMPLEMENTATION)); result.add(jvmName(classDescriptor, OwnerKind.IMPLEMENTATION));
} }
return result; return result;
@@ -147,7 +147,7 @@ public class NamespaceCodegen {
return; return;
} }
final Type jvmType = typeMapper.mapType(jetType, OwnerKind.INTERFACE); final Type jvmType = typeMapper.mapType(jetType);
v.aconst(jvmType); v.aconst(jvmType);
v.iconst(jetType.isNullable() ? 1 : 0); v.iconst(jetType.isNullable() ? 1 : 0);
@@ -1,6 +1,7 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertySetterDescriptor; import org.jetbrains.jet.lang.descriptors.PropertySetterDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
@@ -136,14 +137,16 @@ public class PropertyCodegen {
if (kind == OwnerKind.NAMESPACE) { if (kind == OwnerKind.NAMESPACE) {
flags |= Opcodes.ACC_STATIC; flags |= Opcodes.ACC_STATIC;
} }
else if (kind == OwnerKind.INTERFACE) {
PsiElement psiElement = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, propertyDescriptor.getContainingDeclaration());
boolean isTrait = psiElement instanceof JetClass && ((JetClass) psiElement).isTrait();
if(isTrait && !(kind instanceof OwnerKind.DelegateKind))
flags |= Opcodes.ACC_ABSTRACT; flags |= Opcodes.ACC_ABSTRACT;
}
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor).getDescriptor(); final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor).getDescriptor();
String getterName = getterName(propertyDescriptor.getName()); String getterName = getterName(propertyDescriptor.getName());
MethodVisitor mv = v.visitMethod(flags, getterName, signature, null, null); MethodVisitor mv = v.visitMethod(flags, getterName, signature, null, null);
if (kind != OwnerKind.INTERFACE) { if (!isTrait || kind instanceof OwnerKind.DelegateKind) {
mv.visitCode(); mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
if (kind != OwnerKind.NAMESPACE) { if (kind != OwnerKind.NAMESPACE) {
@@ -176,13 +179,15 @@ public class PropertyCodegen {
if (kind == OwnerKind.NAMESPACE) { if (kind == OwnerKind.NAMESPACE) {
flags |= Opcodes.ACC_STATIC; flags |= Opcodes.ACC_STATIC;
} }
else if (kind == OwnerKind.INTERFACE) {
PsiElement psiElement = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, propertyDescriptor.getContainingDeclaration());
boolean isTrait = psiElement instanceof JetClass && ((JetClass) psiElement).isTrait();
if(isTrait && !(kind instanceof OwnerKind.DelegateKind))
flags |= Opcodes.ACC_ABSTRACT; flags |= Opcodes.ACC_ABSTRACT;
}
final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor).getDescriptor(); final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor).getDescriptor();
MethodVisitor mv = v.visitMethod(flags, setterName(propertyDescriptor.getName()), signature, null, null); MethodVisitor mv = v.visitMethod(flags, setterName(propertyDescriptor.getName()), signature, null, null);
if (kind != OwnerKind.INTERFACE) { if (!isTrait || kind instanceof OwnerKind.DelegateKind) {
mv.visitCode(); mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
final Type type = state.getTypeMapper().mapType(propertyDescriptor.getOutType()); final Type type = state.getTypeMapper().mapType(propertyDescriptor.getOutType());
@@ -186,8 +186,8 @@ public abstract class StackValue {
else else
v.iconst(0); v.iconst(0);
} }
else if (type.getSort() == Type.OBJECT && this.type.getSort() == Type.OBJECT) { else if (type.getSort() == Type.OBJECT && this.type.equals(JetTypeMapper.TYPE_OBJECT)) {
// v.checkcast(type); v.checkcast(type);
} }
else if (type.getSort() == Type.OBJECT) { else if (type.getSort() == Type.OBJECT) {
box(this.type, type, v); box(this.type, type, v);
@@ -3,12 +3,16 @@ package org.jetbrains.jet.lang.types;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.ChainedScope; import org.jetbrains.jet.lang.resolve.ChainedScope;
import org.jetbrains.jet.lang.resolve.JetScope; import org.jetbrains.jet.lang.resolve.JetScope;
@@ -342,4 +346,15 @@ public class TypeUtils {
return false; return false;
} }
public static boolean isInterface(DeclarationDescriptor descriptor, BindingContext bindingContext) {
PsiElement psiElement = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor);
if(psiElement instanceof JetClass) {
return ((JetClass)psiElement).isTrait();
}
if(psiElement instanceof PsiClass) {
return ((PsiClass)psiElement).isInterface();
}
return false;
}
} }
@@ -3,6 +3,7 @@ package org.jetbrains.jet.plugin.structureView;
import com.intellij.ide.structureView.StructureViewTreeElement; import com.intellij.ide.structureView.StructureViewTreeElement;
import com.intellij.ide.util.treeView.smartTree.TreeElement; import com.intellij.ide.util.treeView.smartTree.TreeElement;
import com.intellij.navigation.ItemPresentation; import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.util.Iconable; import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.NavigatablePsiElement; import com.intellij.psi.NavigatablePsiElement;
@@ -68,6 +69,11 @@ public class JetStructureViewElement implements StructureViewTreeElement {
? PsiIconUtil.getProvidersIcon(myElement, open ? Iconable.ICON_FLAG_OPEN : Iconable.ICON_FLAG_CLOSED) ? PsiIconUtil.getProvidersIcon(myElement, open ? Iconable.ICON_FLAG_OPEN : Iconable.ICON_FLAG_CLOSED)
: null; : null;
} }
@Override
public TextAttributesKey getTextAttributesKey() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
}; };
} }
+2 -2
View File
@@ -5,7 +5,7 @@ fun box() : String {
val ai = A<Int>(1) val ai = A<Int>(1)
val aai = A<A<Int>>(ai) val aai = A<A<Int>>(ai)
if(aai.t.t != 1) return "fail" if(aai.t.t != 1) return "fail"
/*
aai.t.t = 2 aai.t.t = 2
if(aai.t.t != 2) return "fail" if(aai.t.t != 2) return "fail"
@@ -15,6 +15,6 @@ fun box() : String {
val abi = A<B<Int>>(B<Int>(1)) val abi = A<B<Int>>(B<Int>(1))
if(abi.t.r != 1) return "fail" if(abi.t.r != 1) return "fail"
*/
return "OK" return "OK"
} }
@@ -14,7 +14,9 @@ public class ClassGenTest extends CodegenTestCase {
final Class aClass = loadClass("SimpleClass", generateClassesInFile()); final Class aClass = loadClass("SimpleClass", generateClassesInFile());
final Method[] methods = aClass.getDeclaredMethods(); final Method[] methods = aClass.getDeclaredMethods();
assertEquals(1, methods.length); // public int SimpleClass.foo()
// public jet.typeinfo.TypeInfo SimpleClass.getTypeInfo()
assertEquals(2, methods.length);
} }
public void testArrayListInheritance() throws Exception { public void testArrayListInheritance() throws Exception {
@@ -77,9 +79,7 @@ public class ClassGenTest extends CodegenTestCase {
final ClassFileFactory codegens = generateClassesInFile(); final ClassFileFactory codegens = generateClassesInFile();
final Class aClass = loadClass("Foo", codegens); final Class aClass = loadClass("Foo", codegens);
assertNotNull(aClass.getMethod("x")); assertNotNull(aClass.getMethod("x"));
final Class implClass = loadClass("Foo$$Impl", codegens); assertNotNull(findMethodByName(aClass, "y"));
assertNull(findMethodByName(implClass, "x"));
assertNotNull(findMethodByName(implClass, "y"));
} }
public void testInheritedMethod() throws Exception { public void testInheritedMethod() throws Exception {
@@ -113,7 +113,7 @@ public class ClassGenTest extends CodegenTestCase {
public void testAbstractClass() throws Exception { public void testAbstractClass() throws Exception {
loadText("abstract class SimpleClass() { }"); loadText("abstract class SimpleClass() { }");
final Class aClass = loadAllClasses(generateClassesInFile()).get("SimpleClass$$Impl"); final Class aClass = loadAllClasses(generateClassesInFile()).get("SimpleClass");
assertTrue((aClass.getModifiers() & Modifier.ABSTRACT) != 0); assertTrue((aClass.getModifiers() & Modifier.ABSTRACT) != 0);
} }
@@ -155,6 +155,7 @@ public class ClassGenTest extends CodegenTestCase {
public void testEnumClass() throws Exception { public void testEnumClass() throws Exception {
loadText("enum class Direction { NORTH; SOUTH; EAST; WEST }"); loadText("enum class Direction { NORTH; SOUTH; EAST; WEST }");
final Class direction = loadAllClasses(generateClassesInFile()).get("Direction"); final Class direction = loadAllClasses(generateClassesInFile()).get("Direction");
System.out.println(generateToText());
final Field north = direction.getField("NORTH"); final Field north = direction.getField("NORTH");
assertEquals(direction, north.getType()); assertEquals(direction, north.getType());
assertInstanceOf(north.get(null), direction); assertInstanceOf(north.get(null), direction);
@@ -197,8 +197,7 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
} }
protected Class loadImplementationClass(ClassFileFactory codegens, final String name) { protected Class loadImplementationClass(ClassFileFactory codegens, final String name) {
loadClass(name, codegens); return loadClass(name, codegens);
return loadClass(name + "$$Impl", codegens);
} }
private static class MyClassLoader extends ClassLoader { private static class MyClassLoader extends ClassLoader {
-4
View File
@@ -1,4 +0,0 @@
package jet;
public abstract class Iterable$$Impl implements Iterable {
}
-4
View File
@@ -1,4 +0,0 @@
package jet;
public abstract class Iterator$$Impl implements Iterator {
}
+1 -1
View File
@@ -85,7 +85,7 @@ public abstract class TypeInfo<T> implements JetObject {
public final Object getClassObject() { public final Object getClassObject() {
try { try {
final Class implClass = theClass.getClassLoader().loadClass(theClass.getCanonicalName() + "$$Impl"); final Class implClass = theClass.getClassLoader().loadClass(theClass.getCanonicalName());
final Field classobj = implClass.getField("$classobj"); final Field classobj = implClass.getField("$classobj");
return classobj.get(null); return classobj.get(null);
} catch (Exception e) { } catch (Exception e) {