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);
}
//noinspection ConstantConditions
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);
}
@@ -20,13 +20,7 @@ public class ClassCodegen {
public void generate(ClassContext parentContext, JetClassOrObject aClass) {
GenerationState.prepareAnonymousClasses((JetElement) aClass, state.getTypeMapper());
if (aClass instanceof JetObjectDeclaration) {
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
}
else {
generateInterface(parentContext, aClass);
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
}
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
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) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
ClassVisitor v = kind == OwnerKind.IMPLEMENTATION
? state.forClassImplementation(descriptor)
: state.forClassDelegatingImplementation(descriptor);
ClassVisitor v = state.forClassImplementation(descriptor);
new ImplementationBodyCodegen(aClass, parentContext.intoClass(descriptor, kind), v, state).generate();
}
@@ -154,7 +154,7 @@ public class ClassContext {
public Type enclosingClassType(JetTypeMapper mapper) {
DeclarationDescriptor descriptor = getContextDescriptor();
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) {
@@ -730,6 +730,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
JetType receiverType = bindingContext.get(BindingContext.EXPRESSION_TYPE, r);
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;
}
@@ -752,8 +759,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
}
else if (descriptor instanceof TypeParameterDescriptor) {
loadTypeParameterTypeInfo((TypeParameterDescriptor) descriptor);
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
loadTypeParameterTypeInfo(typeParameterDescriptor);
v.invokevirtual("jet/typeinfo/TypeInfo", "getClassObject", "()Ljava/lang/Object;");
v.checkcast(typeMapper.mapType(typeParameterDescriptor.getClassObjectType()));
return StackValue.onStack(OBJECT_TYPE);
}
else {
@@ -786,14 +796,20 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
isInterface = false;
}
else {
owner = typeMapper.getOwner(functionDescriptor, OwnerKind.INTERFACE);
owner = typeMapper.getOwner(functionDescriptor, OwnerKind.IMPLEMENTATION);
if(containingDeclaration instanceof JavaClassDescriptor) {
PsiClass psiElement = (PsiClass) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, containingDeclaration);
assert psiElement != null;
isInterface = psiElement.isInterface();
}
else
isInterface = !(containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).getKind() == ClassKind.OBJECT);
else {
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());
@@ -827,8 +843,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
isInterface = false;
}
else {
owner = typeMapper.getOwner(propertyDescriptor, OwnerKind.INTERFACE);
isInterface = !(containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).getKind() == ClassKind.OBJECT);
owner = typeMapper.getOwner(propertyDescriptor, OwnerKind.IMPLEMENTATION);
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);
@@ -971,7 +992,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
for (JetType superType : allSuperTypes) {
final DeclarationDescriptor descriptor = superType.getConstructor().getDeclarationDescriptor();
if (descriptor != null && superOriginal == descriptor.getOriginal()) {
if (descriptor != null && superOriginal.equals(descriptor.getOriginal())) {
return true;
}
}
@@ -1795,7 +1816,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
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, OwnerKind.INTERFACE));
Type type = JetTypeMapper.boxType(typeMapper.mapType(jetType));
generateInstanceOf(StackValue.expression(OBJECT_TYPE, expression.getLeft(), this), jetType, true);
Label isInstance = new Label();
v.ifne(isInstance);
@@ -1921,7 +1942,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (leaveExpressionOnStack) {
v.dup();
}
Type type = JetTypeMapper.boxType(typeMapper.mapType(jetType, OwnerKind.INTERFACE));
Type type = JetTypeMapper.boxType(typeMapper.mapType(jetType));
if(jetType.isNullable()) {
Label nope = new Label();
Label end = new Label();
@@ -1967,7 +1988,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return;
}
final Type jvmType = typeMapper.mapType(jetType, OwnerKind.INTERFACE);
final Type jvmType = typeMapper.mapType(jetType);
v.aconst(jvmType);
v.iconst(jetType.isNullable()?1:0);
@@ -89,15 +89,11 @@ public class FunctionCodegen {
boolean isStatic = kind == OwnerKind.NAMESPACE;
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 && (kind == OwnerKind.IMPLEMENTATION )) {
return;
}
final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
if (kind != OwnerKind.INTERFACE) {
if (!isAbstract) {
mv.visitCode();
FrameMap frameMap = context.prepareFrame();
@@ -22,29 +22,77 @@ import java.util.*;
/**
* @author max
* @author yole
* @author alex.tkachman
*/
public class ImplementationBodyCodegen extends ClassBodyCodegen {
private JetDelegationSpecifier superCall;
private String superClass = "java/lang/Object";
public ImplementationBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState 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
protected void generateDeclaration() {
String superClass = getSuperClass();
getSuperClass();
List<String> interfaces = new ArrayList<String>();
interfaces.add("jet/JetObject");
if (!(myClass instanceof JetObjectDeclaration)) {
interfaces.add(JetTypeMapper.jvmNameForInterface(descriptor));
}
else {
interfaces.addAll(InterfaceBodyCodegen.getSuperInterfaces(myClass, state.getBindingContext()));
}
interfaces.addAll(getSuperInterfaces(myClass));
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,
Opcodes.ACC_PUBLIC | (isAbstract ? Opcodes.ACC_ABSTRACT : 0),
Opcodes.ACC_PUBLIC | (isAbstract ? Opcodes.ACC_ABSTRACT : 0) | (isInterface ? Opcodes.ACC_INTERFACE : 0),
jvmName(),
null,
superClass,
@@ -57,23 +105,34 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
return state.getTypeMapper().jvmName(descriptor, kind);
}
protected String getSuperClass() {
protected void getSuperClass() {
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);
if (first instanceof JetDelegatorToSuperClass || first instanceof JetDelegatorToSuperCall) {
JetType superType = state.getBindingContext().get(BindingContext.TYPE, first.getTypeReference());
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
final PsiElement declaration = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
if (declaration instanceof PsiClass && ((PsiClass) declaration).isInterface()) {
return "java/lang/Object";
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
if (specifier instanceof JetDelegatorToSuperClass || specifier instanceof JetDelegatorToSuperCall) {
JetType superType = state.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
final PsiElement declaration = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
if (declaration != null) {
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
@@ -93,6 +152,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
private void generateFieldForTypeInfo() {
if(myClass instanceof JetClass && ((JetClass)myClass).isTrait())
return;
final boolean typeInfoIsStatic = descriptor.getTypeConstructor().getParameters().size() == 0;
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | (typeInfoIsStatic ? Opcodes.ACC_STATIC : 0), "$typeInfo",
"Ljet/typeinfo/TypeInfo;", null, null);
@@ -101,7 +163,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Override
public void generate(InstructionAdapter v) {
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;");
}
});
@@ -149,8 +211,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
protected void generatePrimaryConstructor() {
if(myClass instanceof JetClass && ((JetClass) myClass).isTrait())
return;
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;
CallableMethod callableMethod;
@@ -166,7 +231,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null);
mv.visitCode();
Type[] argTypes = method.getArgumentTypes();
List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null
? constructorDescriptor.getValueParameters()
: Collections.<ValueParameterDescriptor>emptyList();
@@ -179,58 +243,32 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
String classname = state.getTypeMapper().jvmName(descriptor, kind);
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>();
for (JetDeclaration declaration : myClass.getDeclarations()) {
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;
for (JetDelegationSpecifier specifier : specifiers) {
boolean delegateOnStack = specifier instanceof JetDelegatorToSuperCall && n > 0 ||
specifier instanceof JetDelegatorByExpressionSpecifier;
for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
if(specifier == superCall)
continue;
if (delegateOnStack) {
if (specifier instanceof JetDelegatorByExpressionSpecifier) {
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());
}
if (delegateOnStack) {
JetType superType = state.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
String delegateField = "$delegate_" + n;
@@ -245,8 +283,17 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
JetTypeMapper.jvmNameForInterface(superClassDescriptor)));
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) {
@@ -288,7 +335,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
private void generateDelegatorToConstructorCall(InstructionAdapter iv, ExpressionCodegen codegen, JetCallElement constructorCall,
ConstructorDescriptor constructorDescriptor, boolean isJavaSuperclass,
ConstructorDescriptor constructorDescriptor,
ConstructorFrameMap frameMap) {
ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
PsiElement declaration = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDecl);
@@ -300,13 +347,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
type = JetTypeMapper.jetImplementationType(classDecl);
}
if (isJavaSuperclass) {
iv.load(0, type);
}
else {
iv.anew(type);
iv.dup();
}
iv.load(0, type);
if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) {
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) {
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 {
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) {
ConstructorDescriptor constructorDescriptor = state.getBindingContext().get(BindingContext.CONSTRUCTOR, constructor);
if (constructorDescriptor == null) {
@@ -351,7 +441,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (!(thisDescriptor instanceof ConstructorDescriptor)) {
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 {
throw new UnsupportedOperationException("unknown initializer type");
@@ -371,7 +461,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
protected void generateTypeInfoInitializer(int firstTypeParameter, int typeParamCount, InstructionAdapter iv) {
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(typeParamCount);
iv.newarray(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
@@ -427,7 +517,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.load(0, JetTypeMapper.TYPE_OBJECT);
Type type = codegen.expressionType(initializer);
if(propertyDescriptor.getOutType().isNullable())
type = state.getTypeMapper().boxType(type);
type = JetTypeMapper.boxType(type);
codegen.gen(initializer, type);
codegen.intermediateValueForProperty(propertyDescriptor, false, false).store(iv);
}
@@ -479,6 +569,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
private void generateGetTypeInfo() {
if(myClass instanceof JetClass && ((JetClass)myClass).isTrait())
return;
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC,
"getTypeInfo",
"()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) {
JetClass containingClass = PsiTreeUtil.getParentOfType(parent, JetClass.class);
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);
if (className == null) {
@@ -226,16 +226,13 @@ public class JetTypeMapper {
if (declaration instanceof JetObjectDeclaration) {
return false;
}
return kind == OwnerKind.INTERFACE;
return jetClass instanceof JetClass ? ((JetClass)jetClass).isTrait() : false;
}
private static String jetJvmName(ClassDescriptor jetClass, OwnerKind kind) {
if (jetClass.getKind() == ClassKind.OBJECT) {
return jvmNameForImplementation(jetClass);
}
if (kind == OwnerKind.INTERFACE) {
return jvmNameForInterface(jetClass);
}
else if (kind == OwnerKind.IMPLEMENTATION) {
return jvmNameForImplementation(jetClass);
}
@@ -277,7 +274,7 @@ public class JetTypeMapper {
}
public static String jvmNameForImplementation(ClassDescriptor descriptor) {
return jvmNameForInterface(descriptor) + "$$Impl";
return jvmNameForInterface(descriptor);
}
public static String jvmNameForDelegatingImplementation(ClassDescriptor descriptor) {
@@ -292,7 +289,7 @@ public class JetTypeMapper {
else if (descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor.getContainingDeclaration();
if (kind instanceof OwnerKind.DelegateKind) {
kind = OwnerKind.INTERFACE;
kind = OwnerKind.IMPLEMENTATION;
}
else {
assert classDescriptor != null;
@@ -316,11 +313,11 @@ public class JetTypeMapper {
}
@NotNull public Type mapReturnType(final JetType jetType) {
return mapReturnType(jetType, OwnerKind.INTERFACE);
return mapReturnType(jetType, OwnerKind.IMPLEMENTATION);
}
@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) {
@@ -483,7 +480,7 @@ public class JetTypeMapper {
}
else if (functionParent instanceof ClassDescriptor) {
ClassDescriptor containingClass = (ClassDescriptor) functionParent;
owner = jvmName(containingClass, OwnerKind.INTERFACE);
owner = jvmName(containingClass, OwnerKind.IMPLEMENTATION);
invokeOpcode = isInterface(containingClass, OwnerKind.INTERFACE)
? Opcodes.INVOKEINTERFACE
: Opcodes.INVOKEVIRTUAL;
@@ -636,7 +633,6 @@ public class JetTypeMapper {
Set<String> result = new HashSet<String>();
final ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, jetClass);
if (classDescriptor != null) {
result.add(jvmName(classDescriptor, OwnerKind.INTERFACE));
result.add(jvmName(classDescriptor, OwnerKind.IMPLEMENTATION));
}
return result;
@@ -147,7 +147,7 @@ public class NamespaceCodegen {
return;
}
final Type jvmType = typeMapper.mapType(jetType, OwnerKind.INTERFACE);
final Type jvmType = typeMapper.mapType(jetType);
v.aconst(jvmType);
v.iconst(jetType.isNullable() ? 1 : 0);
@@ -1,6 +1,7 @@
package org.jetbrains.jet.codegen;
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.PropertySetterDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
@@ -136,14 +137,16 @@ public class PropertyCodegen {
if (kind == OwnerKind.NAMESPACE) {
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;
}
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor).getDescriptor();
String getterName = getterName(propertyDescriptor.getName());
MethodVisitor mv = v.visitMethod(flags, getterName, signature, null, null);
if (kind != OwnerKind.INTERFACE) {
if (!isTrait || kind instanceof OwnerKind.DelegateKind) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
if (kind != OwnerKind.NAMESPACE) {
@@ -176,13 +179,15 @@ public class PropertyCodegen {
if (kind == OwnerKind.NAMESPACE) {
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;
}
final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor).getDescriptor();
MethodVisitor mv = v.visitMethod(flags, setterName(propertyDescriptor.getName()), signature, null, null);
if (kind != OwnerKind.INTERFACE) {
if (!isTrait || kind instanceof OwnerKind.DelegateKind) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
final Type type = state.getTypeMapper().mapType(propertyDescriptor.getOutType());
@@ -186,8 +186,8 @@ public abstract class StackValue {
else
v.iconst(0);
}
else if (type.getSort() == Type.OBJECT && this.type.getSort() == Type.OBJECT) {
// v.checkcast(type);
else if (type.getSort() == Type.OBJECT && this.type.equals(JetTypeMapper.TYPE_OBJECT)) {
v.checkcast(type);
}
else if (type.getSort() == Type.OBJECT) {
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.Maps;
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.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
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.JetScope;
@@ -342,4 +346,15 @@ public class TypeUtils {
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.util.treeView.smartTree.TreeElement;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.util.text.StringUtil;
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)
: 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 aai = A<A<Int>>(ai)
if(aai.t.t != 1) return "fail"
/*
aai.t.t = 2
if(aai.t.t != 2) return "fail"
@@ -15,6 +15,6 @@ fun box() : String {
val abi = A<B<Int>>(B<Int>(1))
if(abi.t.r != 1) return "fail"
*/
return "OK"
}
@@ -14,7 +14,9 @@ public class ClassGenTest extends CodegenTestCase {
final Class aClass = loadClass("SimpleClass", generateClassesInFile());
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 {
@@ -77,9 +79,7 @@ public class ClassGenTest extends CodegenTestCase {
final ClassFileFactory codegens = generateClassesInFile();
final Class aClass = loadClass("Foo", codegens);
assertNotNull(aClass.getMethod("x"));
final Class implClass = loadClass("Foo$$Impl", codegens);
assertNull(findMethodByName(implClass, "x"));
assertNotNull(findMethodByName(implClass, "y"));
assertNotNull(findMethodByName(aClass, "y"));
}
public void testInheritedMethod() throws Exception {
@@ -113,7 +113,7 @@ public class ClassGenTest extends CodegenTestCase {
public void testAbstractClass() throws Exception {
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);
}
@@ -155,6 +155,7 @@ public class ClassGenTest extends CodegenTestCase {
public void testEnumClass() throws Exception {
loadText("enum class Direction { NORTH; SOUTH; EAST; WEST }");
final Class direction = loadAllClasses(generateClassesInFile()).get("Direction");
System.out.println(generateToText());
final Field north = direction.getField("NORTH");
assertEquals(direction, north.getType());
assertInstanceOf(north.get(null), direction);
@@ -197,8 +197,7 @@ public abstract class CodegenTestCase extends LightCodeInsightFixtureTestCase {
}
protected Class loadImplementationClass(ClassFileFactory codegens, final String name) {
loadClass(name, codegens);
return loadClass(name + "$$Impl", codegens);
return loadClass(name, codegens);
}
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() {
try {
final Class implClass = theClass.getClassLoader().loadClass(theClass.getCanonicalName() + "$$Impl");
final Class implClass = theClass.getClassLoader().loadClass(theClass.getCanonicalName());
final Field classobj = implClass.getField("$classobj");
return classobj.get(null);
} catch (Exception e) {