Realization of class object fields as static fields of outer class
#KT-2213 Fixed
This commit is contained in:
@@ -34,8 +34,12 @@ public class AccessorForPropertyDescriptor extends PropertyDescriptorImpl {
|
|||||||
pd.isVar(), Name.identifier(pd.getName() + "$b$" + index),
|
pd.isVar(), Name.identifier(pd.getName() + "$b$" + index),
|
||||||
Kind.DECLARATION);
|
Kind.DECLARATION);
|
||||||
|
|
||||||
JetType receiverType = DescriptorUtils.getReceiverParameterType(pd.getReceiverParameter());
|
boolean isStaticProperty = AsmUtil.isPropertyWithBackingFieldInOuterClass(pd)
|
||||||
setType(pd.getType(), Collections.<TypeParameterDescriptorImpl>emptyList(), pd.getExpectedThisObject(), receiverType);
|
&& !AsmUtil.isClassObjectWithBackingFieldsInOuter(containingDeclaration);
|
||||||
|
JetType receiverType = !isStaticProperty ? DescriptorUtils.getReceiverParameterType(pd.getReceiverParameter()) : null;
|
||||||
|
|
||||||
|
setType(pd.getType(), Collections.<TypeParameterDescriptorImpl>emptyList(), isStaticProperty ? null : pd.getExpectedThisObject(),
|
||||||
|
receiverType);
|
||||||
initialize(new Getter(this), new Setter(this));
|
initialize(new Getter(this), new Setter(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ import org.jetbrains.jet.codegen.binding.CalculatedClosure;
|
|||||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||||
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||||
@@ -50,6 +49,7 @@ import static org.jetbrains.asm4.Opcodes.*;
|
|||||||
import static org.jetbrains.jet.codegen.CodegenUtil.*;
|
import static org.jetbrains.jet.codegen.CodegenUtil.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject;
|
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isClassObject;
|
||||||
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isEnumEntry;
|
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isEnumEntry;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isKindOf;
|
||||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
|
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
|
||||||
|
|
||||||
public class AsmUtil {
|
public class AsmUtil {
|
||||||
@@ -589,10 +589,57 @@ public class AsmUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isPropertyWithBackingFieldInOuterClass(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||||
|
return isPropertyWithSpecialBackingField(propertyDescriptor.getContainingDeclaration(), ClassKind.CLASS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getVisibilityForSpecialPropertyBackingField(@NotNull PropertyDescriptor propertyDescriptor, boolean isDelegate) {
|
||||||
|
boolean isExtensionProperty = propertyDescriptor.getReceiverParameter() != null;
|
||||||
|
if (isDelegate || isExtensionProperty) {
|
||||||
|
return ACC_PRIVATE;
|
||||||
|
} else {
|
||||||
|
return areBothAccessorDefault(propertyDescriptor) ? getVisibilityAccessFlag(descriptorForVisibility(propertyDescriptor)) : ACC_PRIVATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MemberDescriptor descriptorForVisibility(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||||
|
if (!propertyDescriptor.isVar() ) {
|
||||||
|
return propertyDescriptor;
|
||||||
|
} else {
|
||||||
|
return propertyDescriptor.getSetter() != null ? propertyDescriptor.getSetter() : propertyDescriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isPropertyWithBackingFieldCopyInOuterClass(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||||
|
boolean isExtensionProperty = propertyDescriptor.getReceiverParameter() != null;
|
||||||
|
return !propertyDescriptor.isVar() && !isExtensionProperty
|
||||||
|
&& isPropertyWithSpecialBackingField(propertyDescriptor.getContainingDeclaration(), ClassKind.TRAIT)
|
||||||
|
&& areBothAccessorDefault(propertyDescriptor)
|
||||||
|
&& getVisibilityForSpecialPropertyBackingField(propertyDescriptor, false) == ACC_PUBLIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isClassObjectWithBackingFieldsInOuter(@NotNull DeclarationDescriptor classObject) {
|
||||||
|
return isPropertyWithSpecialBackingField(classObject, ClassKind.CLASS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean areBothAccessorDefault(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||||
|
return isAccessorWithEmptyBody(propertyDescriptor.getGetter())
|
||||||
|
&& (!propertyDescriptor.isVar() || isAccessorWithEmptyBody(propertyDescriptor.getSetter()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isAccessorWithEmptyBody(@Nullable PropertyAccessorDescriptor accessorDescriptor) {
|
||||||
|
return accessorDescriptor == null || !accessorDescriptor.hasBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isPropertyWithSpecialBackingField(@NotNull DeclarationDescriptor classObject, ClassKind kind) {
|
||||||
|
return isClassObject(classObject) && isKindOf(classObject.getContainingDeclaration(), kind);
|
||||||
|
}
|
||||||
|
|
||||||
public static Type comparisonOperandType(Type left, Type right) {
|
public static Type comparisonOperandType(Type left, Type right) {
|
||||||
if (left == Type.DOUBLE_TYPE || right == Type.DOUBLE_TYPE) return Type.DOUBLE_TYPE;
|
if (left == Type.DOUBLE_TYPE || right == Type.DOUBLE_TYPE) return Type.DOUBLE_TYPE;
|
||||||
if (left == Type.FLOAT_TYPE || right == Type.FLOAT_TYPE) return Type.FLOAT_TYPE;
|
if (left == Type.FLOAT_TYPE || right == Type.FLOAT_TYPE) return Type.FLOAT_TYPE;
|
||||||
if (left == Type.LONG_TYPE || right == Type.LONG_TYPE) return Type.LONG_TYPE;
|
if (left == Type.LONG_TYPE || right == Type.LONG_TYPE) return Type.LONG_TYPE;
|
||||||
return Type.INT_TYPE;
|
return Type.INT_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,9 +17,10 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.asm4.MethodVisitor;
|
import org.jetbrains.asm4.MethodVisitor;
|
||||||
import org.jetbrains.asm4.Type;
|
import org.jetbrains.asm4.Type;
|
||||||
import org.jetbrains.jet.codegen.context.CodegenContext;
|
import org.jetbrains.jet.codegen.context.ClassContext;
|
||||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
@@ -40,12 +41,20 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
|
|||||||
protected final OwnerKind kind;
|
protected final OwnerKind kind;
|
||||||
protected final ClassDescriptor descriptor;
|
protected final ClassDescriptor descriptor;
|
||||||
protected final ClassBuilder v;
|
protected final ClassBuilder v;
|
||||||
protected final CodegenContext context;
|
protected final ClassContext context;
|
||||||
|
|
||||||
protected final List<CodeChunk> staticInitializerChunks = new ArrayList<CodeChunk>();
|
private MethodVisitor clInitMethod;
|
||||||
|
|
||||||
protected ClassBodyCodegen(JetClassOrObject aClass, CodegenContext context, ClassBuilder v, GenerationState state) {
|
private ExpressionCodegen clInitCodegen;
|
||||||
super(state);
|
|
||||||
|
protected ClassBodyCodegen(
|
||||||
|
@NotNull JetClassOrObject aClass,
|
||||||
|
@NotNull ClassContext context,
|
||||||
|
@NotNull ClassBuilder v,
|
||||||
|
@NotNull GenerationState state,
|
||||||
|
@Nullable MemberCodegen parentCodegen
|
||||||
|
) {
|
||||||
|
super(state, parentCodegen);
|
||||||
descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
||||||
myClass = aClass;
|
myClass = aClass;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
@@ -53,7 +62,7 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
|
|||||||
this.v = v;
|
this.v = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void generate() {
|
public void generate() {
|
||||||
generateDeclaration();
|
generateDeclaration();
|
||||||
|
|
||||||
generateClassBody();
|
generateClassBody();
|
||||||
@@ -72,18 +81,20 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
|
|||||||
|
|
||||||
private void generateClassBody() {
|
private void generateClassBody() {
|
||||||
FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
|
FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
|
||||||
PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen);
|
PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, this);
|
||||||
|
|
||||||
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
if (kind != OwnerKind.TRAIT_IMPL) {
|
||||||
//generate nested classes first and only then generate class body. It necessary to access to nested CodegenContexts
|
//generate nested classes first and only then generate class body. It necessary to access to nested CodegenContexts
|
||||||
if (shouldProcessFirst(declaration)) {
|
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
||||||
generateDeclaration(propertyCodegen, declaration, functionCodegen);
|
if (shouldProcessFirst(declaration)) {
|
||||||
|
generateDeclaration(propertyCodegen, declaration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
||||||
if (!shouldProcessFirst(declaration)) {
|
if (!shouldProcessFirst(declaration)) {
|
||||||
generateDeclaration(propertyCodegen, declaration, functionCodegen);
|
generateDeclaration(propertyCodegen, declaration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +105,8 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
|
|||||||
return false == (declaration instanceof JetProperty || declaration instanceof JetNamedFunction);
|
return false == (declaration instanceof JetProperty || declaration instanceof JetNamedFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
|
|
||||||
|
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration) {
|
||||||
if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) {
|
if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) {
|
||||||
genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v);
|
genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v);
|
||||||
}
|
}
|
||||||
@@ -137,23 +149,39 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateStaticInitializer() {
|
private void generateStaticInitializer() {
|
||||||
if (staticInitializerChunks.size() > 0) {
|
if (clInitMethod != null) {
|
||||||
MethodVisitor mv = v.newMethod(null, ACC_STATIC, "<clinit>", "()V", null, null);
|
createOrGetClInitMethod();
|
||||||
|
|
||||||
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||||
mv.visitCode();
|
ExpressionCodegen codegen = createOrGetClInitCodegen();
|
||||||
|
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, new FrameMap(), Type.VOID_TYPE, context, state);
|
createOrGetClInitMethod().visitInsn(RETURN);
|
||||||
|
|
||||||
for (CodeChunk chunk : staticInitializerChunks) {
|
|
||||||
chunk.generate(codegen);
|
|
||||||
}
|
|
||||||
|
|
||||||
mv.visitInsn(RETURN);
|
|
||||||
FunctionCodegen.endVisit(codegen.v, "static initializer", myClass);
|
FunctionCodegen.endVisit(codegen.v, "static initializer", myClass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
protected MethodVisitor createOrGetClInitMethod() {
|
||||||
|
if (clInitMethod == null) {
|
||||||
|
clInitMethod = v.newMethod(null, ACC_STATIC, "<clinit>", "()V", null, null);
|
||||||
|
}
|
||||||
|
return clInitMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
protected ExpressionCodegen createOrGetClInitCodegen() {
|
||||||
|
assert state.getClassBuilderMode() == ClassBuilderMode.FULL;
|
||||||
|
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||||
|
if (clInitCodegen == null) {
|
||||||
|
MethodVisitor method = createOrGetClInitMethod();
|
||||||
|
method.visitCode();
|
||||||
|
clInitCodegen = new ExpressionCodegen(method, new FrameMap(), Type.VOID_TYPE, context, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return clInitCodegen;
|
||||||
|
}
|
||||||
|
|
||||||
private void generateRemoveInIterator() {
|
private void generateRemoveInIterator() {
|
||||||
// generates stub 'remove' function for subclasses of Iterator to be compatible with java.util.Iterator
|
// generates stub 'remove' function for subclasses of Iterator to be compatible with java.util.Iterator
|
||||||
if (DescriptorUtils.isIteratorWithoutRemoveImpl(descriptor)) {
|
if (DescriptorUtils.isIteratorWithoutRemoveImpl(descriptor)) {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import org.jetbrains.jet.codegen.context.NamespaceContext;
|
|||||||
import org.jetbrains.jet.codegen.signature.BothSignatureWriter;
|
import org.jetbrains.jet.codegen.signature.BothSignatureWriter;
|
||||||
import org.jetbrains.jet.codegen.signature.JvmMethodParameterKind;
|
import org.jetbrains.jet.codegen.signature.JvmMethodParameterKind;
|
||||||
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
|
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
|
||||||
|
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
|
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
|
||||||
@@ -263,14 +264,26 @@ public class CodegenUtil {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean couldUseDirectAccessToProperty(PropertyDescriptor propertyDescriptor, boolean forGetter, boolean isInsideClass, boolean isDelegated) {
|
public static boolean couldUseDirectAccessToProperty(@NotNull PropertyDescriptor propertyDescriptor, boolean forGetter, boolean isInsideClass, boolean isDelegated) {
|
||||||
PropertyAccessorDescriptor accessorDescriptor = forGetter ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter();
|
PropertyAccessorDescriptor accessorDescriptor = forGetter ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter();
|
||||||
boolean isExtensionProperty = propertyDescriptor.getReceiverParameter() != null;
|
boolean isExtensionProperty = propertyDescriptor.getReceiverParameter() != null;
|
||||||
|
boolean specialTypeProperty = isDelegated ||
|
||||||
|
isExtensionProperty ||
|
||||||
|
DescriptorUtils.isClassObject(propertyDescriptor.getContainingDeclaration()) ||
|
||||||
|
JetTypeMapper.isAccessor(propertyDescriptor);
|
||||||
return isInsideClass &&
|
return isInsideClass &&
|
||||||
!isDelegated &&
|
!specialTypeProperty &&
|
||||||
!isExtensionProperty &&
|
|
||||||
(accessorDescriptor == null ||
|
(accessorDescriptor == null ||
|
||||||
accessorDescriptor.isDefault() &&
|
accessorDescriptor.isDefault() &&
|
||||||
(!DescriptorUtils.isExternallyAccessible(propertyDescriptor) || accessorDescriptor.getModality() == Modality.FINAL));
|
(!DescriptorUtils.isExternallyAccessible(propertyDescriptor) || accessorDescriptor.getModality() == Modality.FINAL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static ImplementationBodyCodegen getParentBodyCodegen(@Nullable MemberCodegen classBodyCodegen) {
|
||||||
|
assert classBodyCodegen != null &&
|
||||||
|
classBodyCodegen
|
||||||
|
.getParentCodegen() instanceof ImplementationBodyCodegen : "Class object should have appropriate parent BodyCodegen";
|
||||||
|
|
||||||
|
return ((ImplementationBodyCodegen) classBodyCodegen.getParentCodegen());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
private int myLastLineNumber = -1;
|
private int myLastLineNumber = -1;
|
||||||
|
|
||||||
final InstructionAdapter v;
|
final InstructionAdapter v;
|
||||||
|
final MethodVisitor methodVisitor;
|
||||||
final FrameMap myFrameMap;
|
final FrameMap myFrameMap;
|
||||||
final JetTypeMapper typeMapper;
|
final JetTypeMapper typeMapper;
|
||||||
|
|
||||||
@@ -121,8 +122,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
//noinspection SuspiciousMethodCalls
|
//noinspection SuspiciousMethodCalls
|
||||||
CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor);
|
CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor);
|
||||||
|
|
||||||
CodegenContext objectContext = context.intoAnonymousClass(classDescriptor, this);
|
ClassContext objectContext = context.intoAnonymousClass(classDescriptor, this);
|
||||||
ImplementationBodyCodegen implementationBodyCodegen = new ImplementationBodyCodegen(objectDeclaration, objectContext, classBuilder, state);
|
ImplementationBodyCodegen implementationBodyCodegen = new ImplementationBodyCodegen(objectDeclaration, objectContext, classBuilder, state, null);
|
||||||
|
|
||||||
implementationBodyCodegen.generate();
|
implementationBodyCodegen.generate();
|
||||||
|
|
||||||
@@ -164,7 +165,15 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
this.typeMapper = state.getTypeMapper();
|
this.typeMapper = state.getTypeMapper();
|
||||||
this.returnType = returnType;
|
this.returnType = returnType;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.v = new InstructionAdapter(v) {
|
this.methodVisitor = v;
|
||||||
|
this.v = createInstructionAdapter(methodVisitor);
|
||||||
|
this.bindingContext = state.getBindingContext();
|
||||||
|
this.context = context;
|
||||||
|
this.statementVisitor = new CodegenStatementVisitor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected InstructionAdapter createInstructionAdapter(MethodVisitor mv) {
|
||||||
|
return new InstructionAdapter(methodVisitor) {
|
||||||
@Override
|
@Override
|
||||||
public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
|
public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
|
||||||
super.visitLocalVariable(name, desc, signature, start, end,
|
super.visitLocalVariable(name, desc, signature, start, end,
|
||||||
@@ -172,9 +181,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
localVariableNames.add(name);
|
localVariableNames.add(name);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.bindingContext = state.getBindingContext();
|
|
||||||
this.context = context;
|
|
||||||
this.statementVisitor = new CodegenStatementVisitor(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public GenerationState getState() {
|
public GenerationState getState() {
|
||||||
@@ -275,9 +281,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
ClassBuilder classBuilder = state.getFactory().newVisitor(className.getInternalName(), declaration.getContainingFile()
|
ClassBuilder classBuilder = state.getFactory().newVisitor(className.getInternalName(), declaration.getContainingFile()
|
||||||
);
|
);
|
||||||
|
|
||||||
CodegenContext objectContext = context.intoAnonymousClass(descriptor, this);
|
ClassContext objectContext = context.intoAnonymousClass(descriptor, this);
|
||||||
|
|
||||||
new ImplementationBodyCodegen(declaration, objectContext, classBuilder, state).generate();
|
new ImplementationBodyCodegen(declaration, objectContext, classBuilder, state, null).generate();
|
||||||
return StackValue.none();
|
return StackValue.none();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1673,26 +1679,26 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public StackValue.Property intermediateValueForProperty(
|
public StackValue.Property intermediateValueForProperty(
|
||||||
PropertyDescriptor propertyDescriptor,
|
@NotNull PropertyDescriptor propertyDescriptor,
|
||||||
boolean forceField,
|
boolean forceField,
|
||||||
@Nullable JetSuperExpression superExpression
|
@Nullable JetSuperExpression superExpression
|
||||||
) {
|
) {
|
||||||
return intermediateValueForProperty(propertyDescriptor, forceField, superExpression, false);
|
return intermediateValueForProperty(propertyDescriptor, forceField, superExpression, MethodKind.GENERAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public StackValue.Property intermediateValueForProperty(
|
public StackValue.Property intermediateValueForProperty(
|
||||||
PropertyDescriptor propertyDescriptor,
|
@NotNull PropertyDescriptor propertyDescriptor,
|
||||||
boolean forceField,
|
boolean forceField,
|
||||||
@Nullable JetSuperExpression superExpression,
|
@Nullable JetSuperExpression superExpression,
|
||||||
@NotNull boolean forceSpecialFlag
|
@NotNull MethodKind methodKind
|
||||||
) {
|
) {
|
||||||
JetTypeMapper typeMapper = state.getTypeMapper();
|
JetTypeMapper typeMapper = state.getTypeMapper();
|
||||||
|
|
||||||
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
||||||
assert containingDeclaration != null;
|
assert containingDeclaration != null;
|
||||||
|
|
||||||
boolean isStatic = containingDeclaration instanceof NamespaceDescriptor;
|
boolean isBackingFieldInAnotherClass = AsmUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor);
|
||||||
|
boolean isStatic = containingDeclaration instanceof NamespaceDescriptor || isBackingFieldInAnotherClass;
|
||||||
boolean isSuper = superExpression != null;
|
boolean isSuper = superExpression != null;
|
||||||
boolean isInsideClass = isCallInsideSameClassAsDeclared(propertyDescriptor, context);
|
boolean isInsideClass = isCallInsideSameClassAsDeclared(propertyDescriptor, context);
|
||||||
boolean isInsideModule = isCallInsideSameModuleAsDeclared(propertyDescriptor, context);
|
boolean isInsideModule = isCallInsideSameModuleAsDeclared(propertyDescriptor, context);
|
||||||
@@ -1700,10 +1706,25 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
JetType delegateType = getPropertyDelegateType(propertyDescriptor, state.getBindingContext());
|
JetType delegateType = getPropertyDelegateType(propertyDescriptor, state.getBindingContext());
|
||||||
boolean isDelegatedProperty = delegateType != null;
|
boolean isDelegatedProperty = delegateType != null;
|
||||||
|
|
||||||
|
|
||||||
CallableMethod callableGetter = null;
|
CallableMethod callableGetter = null;
|
||||||
CallableMethod callableSetter = null;
|
CallableMethod callableSetter = null;
|
||||||
|
|
||||||
if (!forceField) {
|
boolean skipPropertyAccessors = forceField && !isBackingFieldInAnotherClass;
|
||||||
|
|
||||||
|
CodegenContext backingFieldContext = context.getParentContext();
|
||||||
|
|
||||||
|
if (isBackingFieldInAnotherClass && forceField) {
|
||||||
|
//delegate call to classObject owner : OWNER
|
||||||
|
backingFieldContext = context.findParentContextWithDescriptor(containingDeclaration.getContainingDeclaration());
|
||||||
|
int flags = AsmUtil.getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegatedProperty);
|
||||||
|
skipPropertyAccessors = (flags & ACC_PRIVATE) == 0 || methodKind == MethodKind.SYNTHETIC_ACCESSOR || methodKind == MethodKind.INITIALIZER;
|
||||||
|
if (!skipPropertyAccessors) {
|
||||||
|
propertyDescriptor = (PropertyDescriptor) backingFieldContext.getAccessor(propertyDescriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!skipPropertyAccessors) {
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
if (couldUseDirectAccessToProperty(propertyDescriptor, true, isInsideClass, isDelegatedProperty)) {
|
if (couldUseDirectAccessToProperty(propertyDescriptor, true, isInsideClass, isDelegatedProperty)) {
|
||||||
callableGetter = null;
|
callableGetter = null;
|
||||||
@@ -1721,7 +1742,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
propertyDescriptor = accessablePropertyDescriptor(propertyDescriptor);
|
propertyDescriptor = accessablePropertyDescriptor(propertyDescriptor);
|
||||||
|
|
||||||
if (propertyDescriptor.getGetter() != null) {
|
if (propertyDescriptor.getGetter() != null) {
|
||||||
callableGetter = typeMapper.mapToCallableMethod(propertyDescriptor.getGetter(), isSuper || forceSpecialFlag, isInsideClass, isInsideModule, OwnerKind.IMPLEMENTATION);
|
callableGetter = typeMapper
|
||||||
|
.mapToCallableMethod(propertyDescriptor.getGetter(), isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind,
|
||||||
|
isInsideClass, isInsideModule, OwnerKind.IMPLEMENTATION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1731,7 +1754,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
callableSetter = null;
|
callableSetter = null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
callableSetter = typeMapper.mapToCallableMethod(propertyDescriptor.getSetter(), isSuper || forceSpecialFlag, isInsideClass, isInsideModule, OwnerKind.IMPLEMENTATION);
|
callableSetter = typeMapper.mapToCallableMethod(propertyDescriptor.getSetter(), isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, isInsideClass, isInsideModule, OwnerKind.IMPLEMENTATION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1742,7 +1765,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
|
|
||||||
propertyDescriptor = unwrapFakeOverride(propertyDescriptor);
|
propertyDescriptor = unwrapFakeOverride(propertyDescriptor);
|
||||||
if (callableMethod == null) {
|
if (callableMethod == null) {
|
||||||
owner = typeMapper.getOwner(propertyDescriptor, context.getContextKind(), isInsideModule);
|
owner = typeMapper.getOwner(isBackingFieldInAnotherClass ? propertyDescriptor.getContainingDeclaration() : propertyDescriptor, context.getContextKind(), isInsideModule);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
owner = callableMethod.getOwner();
|
owner = callableMethod.getOwner();
|
||||||
@@ -2316,8 +2339,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Type expressionType(JetExpression expr) {
|
public Type expressionType(JetExpression expr) {
|
||||||
JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, expr);
|
return typeMapper.expressionType(expr);
|
||||||
return asmTypeOrVoid(type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int indexOfLocal(JetReferenceExpression lhs) {
|
public int indexOfLocal(JetReferenceExpression lhs) {
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public abstract class FunctionGenerationStrategy<T extends CallableDescriptor> {
|
|||||||
|
|
||||||
public abstract static class CodegenBased<T extends CallableDescriptor> extends FunctionGenerationStrategy<T> {
|
public abstract static class CodegenBased<T extends CallableDescriptor> extends FunctionGenerationStrategy<T> {
|
||||||
|
|
||||||
private final GenerationState state;
|
protected final GenerationState state;
|
||||||
|
|
||||||
protected final T callableDescriptor;
|
protected final T callableDescriptor;
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import org.jetbrains.asm4.commons.Method;
|
|||||||
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
|
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
|
||||||
import org.jetbrains.jet.codegen.binding.CodegenBinding;
|
import org.jetbrains.jet.codegen.binding.CodegenBinding;
|
||||||
import org.jetbrains.jet.codegen.binding.MutableClosure;
|
import org.jetbrains.jet.codegen.binding.MutableClosure;
|
||||||
import org.jetbrains.jet.codegen.context.CodegenContext;
|
import org.jetbrains.jet.codegen.context.ClassContext;
|
||||||
import org.jetbrains.jet.codegen.context.ConstructorContext;
|
import org.jetbrains.jet.codegen.context.ConstructorContext;
|
||||||
import org.jetbrains.jet.codegen.context.MethodContext;
|
import org.jetbrains.jet.codegen.context.MethodContext;
|
||||||
import org.jetbrains.jet.codegen.signature.*;
|
import org.jetbrains.jet.codegen.signature.*;
|
||||||
@@ -67,6 +67,7 @@ import static org.jetbrains.jet.codegen.CodegenUtil.*;
|
|||||||
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
|
import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration;
|
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration;
|
||||||
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
|
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isKindOf;
|
||||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
|
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
|
||||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
|
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
|
||||||
|
|
||||||
@@ -79,13 +80,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
private final Type classAsmType;
|
private final Type classAsmType;
|
||||||
|
|
||||||
private final FunctionCodegen functionCodegen;
|
private final FunctionCodegen functionCodegen;
|
||||||
private final PropertyCodegen propertyCodegen;
|
private final PropertyCodegen propertyCodegen;
|
||||||
|
|
||||||
public ImplementationBodyCodegen(JetClassOrObject aClass, CodegenContext context, ClassBuilder v, GenerationState state) {
|
private List<PropertyDescriptor> classObjectPropertiesToCopy;
|
||||||
super(aClass, context, v, state);
|
|
||||||
|
public ImplementationBodyCodegen(
|
||||||
|
@NotNull JetClassOrObject aClass,
|
||||||
|
@NotNull ClassContext context,
|
||||||
|
@NotNull ClassBuilder v,
|
||||||
|
@NotNull GenerationState state,
|
||||||
|
@Nullable MemberCodegen parentCodegen
|
||||||
|
) {
|
||||||
|
super(aClass, context, v, state, parentCodegen);
|
||||||
this.classAsmType = typeMapper.mapType(descriptor.getDefaultType(), JetTypeMapperMode.IMPL);
|
this.classAsmType = typeMapper.mapType(descriptor.getDefaultType(), JetTypeMapperMode.IMPL);
|
||||||
this.functionCodegen = new FunctionCodegen(context, v, state);
|
this.functionCodegen = new FunctionCodegen(context, v, state);
|
||||||
this.propertyCodegen = new PropertyCodegen(context, v, this.functionCodegen);
|
this.propertyCodegen = new PropertyCodegen(context, v, this.functionCodegen, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -429,6 +438,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
protected void generateSyntheticParts() {
|
protected void generateSyntheticParts() {
|
||||||
generateFieldForSingleton();
|
generateFieldForSingleton();
|
||||||
|
|
||||||
|
generateClassObjectBackingFieldCopies();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
generatePrimaryConstructor();
|
generatePrimaryConstructor();
|
||||||
}
|
}
|
||||||
@@ -446,7 +457,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
generateSyntheticAccessors();
|
generateSyntheticAccessors();
|
||||||
|
|
||||||
generateEnumMethods();
|
generateEnumMethodsAndConstInitializers();
|
||||||
|
|
||||||
generateFunctionsForDataClasses();
|
generateFunctionsForDataClasses();
|
||||||
|
|
||||||
@@ -750,25 +761,33 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
MethodContext functionContext = context.intoFunction(function);
|
MethodContext functionContext = context.intoFunction(function);
|
||||||
FunctionCodegen.generateDefaultIfNeeded(functionContext, state, v, methodSignature, function, OwnerKind.IMPLEMENTATION,
|
FunctionCodegen.generateDefaultIfNeeded(functionContext, state, v, methodSignature, function, OwnerKind.IMPLEMENTATION,
|
||||||
new DefaultParameterValueLoader() {
|
new DefaultParameterValueLoader() {
|
||||||
@Override
|
@Override
|
||||||
public void putValueOnStack(
|
public void putValueOnStack(
|
||||||
ValueParameterDescriptor descriptor,
|
ValueParameterDescriptor descriptor,
|
||||||
ExpressionCodegen codegen
|
ExpressionCodegen codegen
|
||||||
) {
|
) {
|
||||||
assert (KotlinBuiltIns.getInstance()
|
assert (KotlinBuiltIns.getInstance().isData((ClassDescriptor) function.getContainingDeclaration()))
|
||||||
.isData((ClassDescriptor) function.getContainingDeclaration()))
|
: "Trying to create function with default arguments for function that isn't presented in code for class without data annotation";
|
||||||
: "Trying to create function with default arguments for function that isn't presented in code for class without data annotation";
|
PropertyDescriptor propertyDescriptor = codegen.getBindingContext().get(
|
||||||
PropertyDescriptor propertyDescriptor = codegen.getBindingContext().get(
|
BindingContext.VALUE_PARAMETER_AS_PROPERTY, descriptor);
|
||||||
BindingContext.VALUE_PARAMETER_AS_PROPERTY, descriptor);
|
assert propertyDescriptor != null
|
||||||
assert propertyDescriptor !=
|
: "Trying to generate default value for parameter of copy function that doesn't correspond to any property";
|
||||||
null : "Trying to generate default value for parameter of copy function that doesn't correspond to any property";
|
codegen.v.load(0, thisDescriptorType);
|
||||||
codegen.v.load(0, thisDescriptorType);
|
Type propertyType = codegen.typeMapper.mapType(propertyDescriptor.getType());
|
||||||
Type propertyType = codegen.typeMapper.mapType(propertyDescriptor.getType());
|
codegen.intermediateValueForProperty(propertyDescriptor, false, null).put(propertyType, codegen.v);
|
||||||
codegen.intermediateValueForProperty(propertyDescriptor, false, null)
|
}
|
||||||
.put(propertyType, codegen.v);
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
private void generateEnumMethodsAndConstInitializers() {
|
||||||
|
if (!myEnumConstants.isEmpty()) {
|
||||||
|
generateEnumMethods();
|
||||||
|
|
||||||
|
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||||
|
initializeEnumConstants(createOrGetClInitCodegen());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateEnumMethods() {
|
private void generateEnumMethods() {
|
||||||
@@ -827,7 +846,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (entry.getValue() instanceof PropertyDescriptor) {
|
else if (entry.getValue() instanceof PropertyDescriptor) {
|
||||||
PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
|
final PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
|
||||||
final PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
|
final PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
|
||||||
|
|
||||||
|
|
||||||
@@ -837,9 +856,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
new FunctionGenerationStrategy.CodegenBased<PropertyGetterDescriptor>(state, getter) {
|
new FunctionGenerationStrategy.CodegenBased<PropertyGetterDescriptor>(state, getter) {
|
||||||
@Override
|
@Override
|
||||||
public void doGenerateBody(ExpressionCodegen codegen, JvmMethodSignature signature) {
|
public void doGenerateBody(ExpressionCodegen codegen, JvmMethodSignature signature) {
|
||||||
StackValue.Property property = codegen.intermediateValueForProperty(original, false, null, true);
|
|
||||||
InstructionAdapter iv = codegen.v;
|
InstructionAdapter iv = codegen.v;
|
||||||
iv.load(0, OBJECT_TYPE);
|
boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) && !isClassObject(bridge.getContainingDeclaration());
|
||||||
|
StackValue.Property property = codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR);
|
||||||
|
if (!forceField) {
|
||||||
|
iv.load(0, OBJECT_TYPE);
|
||||||
|
}
|
||||||
property.put(property.type, iv);
|
property.put(property.type, iv);
|
||||||
iv.areturn(signature.getAsmMethod().getReturnType());
|
iv.areturn(signature.getAsmMethod().getReturnType());
|
||||||
}
|
}
|
||||||
@@ -854,12 +876,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
new FunctionGenerationStrategy.CodegenBased<PropertySetterDescriptor>(state, setter) {
|
new FunctionGenerationStrategy.CodegenBased<PropertySetterDescriptor>(state, setter) {
|
||||||
@Override
|
@Override
|
||||||
public void doGenerateBody(ExpressionCodegen codegen, JvmMethodSignature signature) {
|
public void doGenerateBody(ExpressionCodegen codegen, JvmMethodSignature signature) {
|
||||||
StackValue.Property property = codegen.intermediateValueForProperty(original, false, null, true);
|
boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) && !isClassObject(bridge.getContainingDeclaration());
|
||||||
|
StackValue.Property property = codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR);
|
||||||
InstructionAdapter iv = codegen.v;
|
InstructionAdapter iv = codegen.v;
|
||||||
|
|
||||||
iv.load(0, OBJECT_TYPE);
|
|
||||||
Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
|
Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
|
||||||
for (int i = 1, reg = 1; i < argTypes.length; i++) {
|
for (int i = 0, reg = 0; i < argTypes.length; i++) {
|
||||||
Type argType = argTypes[i];
|
Type argType = argTypes[i];
|
||||||
iv.load(reg, argType);
|
iv.load(reg, argType);
|
||||||
//noinspection AssignmentToForLoopParameter
|
//noinspection AssignmentToForLoopParameter
|
||||||
@@ -915,22 +937,64 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
if (!(isNonLiteralObject(myClass) || hasClassObject) || isEnumClass) return;
|
if (!(isNonLiteralObject(myClass) || hasClassObject) || isEnumClass) return;
|
||||||
|
|
||||||
final ClassDescriptor fieldTypeDescriptor = hasClassObject ? descriptor.getClassObjectDescriptor() : descriptor;
|
ClassDescriptor fieldTypeDescriptor = hasClassObject ? descriptor.getClassObjectDescriptor() : descriptor;
|
||||||
assert fieldTypeDescriptor != null;
|
assert fieldTypeDescriptor != null;
|
||||||
final StackValue.Field field = StackValue.singleton(fieldTypeDescriptor, typeMapper);
|
StackValue.Field field = StackValue.singleton(fieldTypeDescriptor, typeMapper);
|
||||||
JetClassOrObject original = hasClassObject ? ((JetClass) myClass).getClassObject().getObjectDeclaration() : myClass;
|
JetClassOrObject original = hasClassObject ? ((JetClass) myClass).getClassObject().getObjectDeclaration() : myClass;
|
||||||
|
|
||||||
v.newField(original, ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null);
|
v.newField(original, ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null);
|
||||||
|
|
||||||
staticInitializerChunks.add(new CodeChunk() {
|
if (!AsmUtil.isClassObjectWithBackingFieldsInOuter(fieldTypeDescriptor)) {
|
||||||
@Override
|
genInitSingleton(fieldTypeDescriptor, field);
|
||||||
public void generate(ExpressionCodegen codegen) {
|
}
|
||||||
ConstructorDescriptor constructorDescriptor = DescriptorUtils.getConstructorOfSingletonObject(fieldTypeDescriptor);
|
}
|
||||||
FunctionDescriptor fd = codegen.accessableFunctionDescriptor(constructorDescriptor);
|
|
||||||
generateMethodCallTo(fd, codegen.v);
|
private void generateClassObjectBackingFieldCopies() {
|
||||||
field.store(field.type, codegen.v);
|
if (classObjectPropertiesToCopy != null) {
|
||||||
|
for (PropertyDescriptor propertyDescriptor : classObjectPropertiesToCopy) {
|
||||||
|
|
||||||
|
v.newField(null, ACC_STATIC | ACC_FINAL | ACC_PUBLIC, propertyDescriptor.getName().asString(), typeMapper.mapType(propertyDescriptor).getDescriptor(), null, null);
|
||||||
|
|
||||||
|
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||||
|
ExpressionCodegen codegen = createOrGetClInitCodegen();
|
||||||
|
int classObjectIndex = putClassObjectInLocalVar(codegen);
|
||||||
|
StackValue.local(classObjectIndex, OBJECT_TYPE).put(OBJECT_TYPE, codegen.v);
|
||||||
|
copyFieldFromClassObject(propertyDescriptor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int putClassObjectInLocalVar(ExpressionCodegen codegen) {
|
||||||
|
FrameMap frameMap = codegen.myFrameMap;
|
||||||
|
ClassDescriptor classObjectDescriptor = descriptor.getClassObjectDescriptor();
|
||||||
|
int classObjectIndex = frameMap.getIndex(classObjectDescriptor);
|
||||||
|
if (classObjectIndex == -1) {
|
||||||
|
classObjectIndex = frameMap.enter(classObjectDescriptor, OBJECT_TYPE);
|
||||||
|
StackValue classObject = StackValue.singleton(classObjectDescriptor, typeMapper);
|
||||||
|
classObject.put(classObject.type, codegen.v);
|
||||||
|
StackValue.local(classObjectIndex, classObject.type).store(classObject.type, codegen.v);
|
||||||
|
}
|
||||||
|
return classObjectIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void copyFieldFromClassObject(PropertyDescriptor propertyDescriptor) {
|
||||||
|
ExpressionCodegen codegen = createOrGetClInitCodegen();
|
||||||
|
StackValue property = codegen.intermediateValueForProperty(propertyDescriptor, false, null);
|
||||||
|
property.put(property.type, codegen.v);
|
||||||
|
StackValue.Field field = StackValue.field(property.type, JvmClassName.byClassDescriptor(descriptor),
|
||||||
|
propertyDescriptor.getName().asString(), true);
|
||||||
|
field.store(field.type, codegen.v);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void genInitSingleton(ClassDescriptor fieldTypeDescriptor, StackValue.Field field) {
|
||||||
|
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||||
|
ConstructorDescriptor constructorDescriptor = DescriptorUtils.getConstructorOfSingletonObject(fieldTypeDescriptor);
|
||||||
|
ExpressionCodegen codegen = createOrGetClInitCodegen();
|
||||||
|
FunctionDescriptor fd = codegen.accessableFunctionDescriptor(constructorDescriptor);
|
||||||
|
generateMethodCallTo(fd, codegen.v);
|
||||||
|
field.store(field.type, codegen.v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void generatePrimaryConstructor() {
|
protected void generatePrimaryConstructor() {
|
||||||
@@ -981,9 +1045,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generatePrimaryConstructorImpl(
|
private void generatePrimaryConstructorImpl(
|
||||||
ConstructorDescriptor constructorDescriptor,
|
@Nullable ConstructorDescriptor constructorDescriptor,
|
||||||
ExpressionCodegen codegen,
|
@NotNull final ExpressionCodegen codegen,
|
||||||
MutableClosure closure
|
@Nullable MutableClosure closure
|
||||||
) {
|
) {
|
||||||
List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null
|
List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null
|
||||||
? constructorDescriptor.getValueParameters()
|
? constructorDescriptor.getValueParameters()
|
||||||
@@ -1035,7 +1099,17 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
curParam++;
|
curParam++;
|
||||||
}
|
}
|
||||||
|
|
||||||
generateInitializers(codegen, iv, myClass.getDeclarations(), bindingContext, state);
|
boolean generateInitializerInOuter = isClassObjectWithBackingFieldsInOuter(descriptor);
|
||||||
|
if (generateInitializerInOuter) {
|
||||||
|
ImplementationBodyCodegen parentCodegen = getParentBodyCodegen(this);
|
||||||
|
//generate object$
|
||||||
|
parentCodegen.genInitSingleton(descriptor, StackValue.singleton(descriptor, typeMapper));
|
||||||
|
parentCodegen.generateInitializers(parentCodegen.createOrGetClInitCodegen(),
|
||||||
|
myClass.getDeclarations(), bindingContext, state);
|
||||||
|
} else {
|
||||||
|
generateInitializers(codegen, myClass.getDeclarations(), bindingContext, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
iv.visitInsn(RETURN);
|
iv.visitInsn(RETURN);
|
||||||
}
|
}
|
||||||
@@ -1225,7 +1299,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateTraitMethods() {
|
private void generateTraitMethods() {
|
||||||
if (myClass instanceof JetClass && ((JetClass) myClass).isTrait()) {
|
if (JetPsiUtil.isTrait(myClass)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1425,29 +1499,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
|
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration) {
|
||||||
if (declaration instanceof JetEnumEntry) {
|
if (declaration instanceof JetEnumEntry) {
|
||||||
String name = declaration.getName();
|
String name = declaration.getName();
|
||||||
String desc = "L" + classAsmType.getInternalName() + ";";
|
String desc = "L" + classAsmType.getInternalName() + ";";
|
||||||
v.newField(declaration, ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL, name, desc, null, null);
|
v.newField(declaration, ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL, name, desc, null, null);
|
||||||
if (myEnumConstants.isEmpty()) {
|
|
||||||
staticInitializerChunks.add(new CodeChunk() {
|
|
||||||
@Override
|
|
||||||
public void generate(ExpressionCodegen codegen) {
|
|
||||||
initializeEnumConstants(codegen.v);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
myEnumConstants.add((JetEnumEntry) declaration);
|
myEnumConstants.add((JetEnumEntry) declaration);
|
||||||
}
|
}
|
||||||
|
|
||||||
super.generateDeclaration(propertyCodegen, declaration, functionCodegen);
|
super.generateDeclaration(propertyCodegen, declaration);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final List<JetEnumEntry> myEnumConstants = new ArrayList<JetEnumEntry>();
|
private final List<JetEnumEntry> myEnumConstants = new ArrayList<JetEnumEntry>();
|
||||||
|
|
||||||
private void initializeEnumConstants(InstructionAdapter iv) {
|
private void initializeEnumConstants(ExpressionCodegen codegen) {
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(iv, new FrameMap(), Type.VOID_TYPE, context, state);
|
InstructionAdapter iv = codegen.v;
|
||||||
int ordinal = -1;
|
int ordinal = -1;
|
||||||
JetType myType = descriptor.getDefaultType();
|
JetType myType = descriptor.getDefaultType();
|
||||||
Type myAsmType = typeMapper.mapType(myType, JetTypeMapperMode.IMPL);
|
Type myAsmType = typeMapper.mapType(myType, JetTypeMapperMode.IMPL);
|
||||||
@@ -1509,14 +1575,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void generateInitializers(
|
public static void generateInitializers(
|
||||||
@NotNull ExpressionCodegen codegen, @NotNull InstructionAdapter iv, @NotNull List<JetDeclaration> declarations,
|
@NotNull ExpressionCodegen codegen, @NotNull List<JetDeclaration> declarations,
|
||||||
@NotNull BindingContext bindingContext, @NotNull GenerationState state
|
@NotNull BindingContext bindingContext, @NotNull GenerationState state
|
||||||
) {
|
) {
|
||||||
JetTypeMapper typeMapper = state.getTypeMapper();
|
JetTypeMapper typeMapper = state.getTypeMapper();
|
||||||
for (JetDeclaration declaration : declarations) {
|
for (JetDeclaration declaration : declarations) {
|
||||||
if (declaration instanceof JetProperty) {
|
if (declaration instanceof JetProperty) {
|
||||||
if (shouldInitializeProperty((JetProperty) declaration, typeMapper)) {
|
if (shouldInitializeProperty((JetProperty) declaration, typeMapper)) {
|
||||||
initializeProperty(codegen, bindingContext, iv, (JetProperty) declaration, false);
|
initializeProperty(codegen, bindingContext, (JetProperty) declaration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (declaration instanceof JetClassInitializer) {
|
else if (declaration instanceof JetClassInitializer) {
|
||||||
@@ -1525,16 +1591,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void initializeProperty(
|
public static void initializeProperty(
|
||||||
@NotNull ExpressionCodegen codegen,
|
@NotNull ExpressionCodegen codegen,
|
||||||
@NotNull BindingContext bindingContext,
|
@NotNull BindingContext bindingContext,
|
||||||
@NotNull InstructionAdapter iv,
|
@NotNull JetProperty property
|
||||||
@NotNull JetProperty property,
|
|
||||||
boolean isStatic
|
|
||||||
) {
|
) {
|
||||||
if (!isStatic) {
|
|
||||||
iv.load(0, OBJECT_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(BindingContext.VARIABLE, property);
|
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(BindingContext.VARIABLE, property);
|
||||||
assert propertyDescriptor != null;
|
assert propertyDescriptor != null;
|
||||||
@@ -1543,14 +1605,20 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
assert initializer != null : "shouldInitializeProperty must return false if initializer is null";
|
assert initializer != null : "shouldInitializeProperty must return false if initializer is null";
|
||||||
|
|
||||||
JetType jetType = getPropertyOrDelegateType(bindingContext, property, propertyDescriptor);
|
JetType jetType = getPropertyOrDelegateType(bindingContext, property, propertyDescriptor);
|
||||||
|
|
||||||
|
StackValue.Property propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, null, MethodKind.INITIALIZER);
|
||||||
|
|
||||||
|
if (!propValue.isStatic) {
|
||||||
|
codegen.v.load(0, OBJECT_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
Type type = codegen.expressionType(initializer);
|
Type type = codegen.expressionType(initializer);
|
||||||
if (jetType.isNullable()) {
|
if (jetType.isNullable()) {
|
||||||
type = boxType(type);
|
type = boxType(type);
|
||||||
}
|
}
|
||||||
codegen.gen(initializer, type);
|
codegen.gen(initializer, type);
|
||||||
|
|
||||||
StackValue.Property propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, null);
|
propValue.store(type, codegen.v);
|
||||||
propValue.store(type, iv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean shouldInitializeProperty(
|
public static boolean shouldInitializeProperty(
|
||||||
@@ -1699,4 +1767,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addClassObjectPropertyToCopy(PropertyDescriptor descriptor) {
|
||||||
|
if (classObjectPropertiesToCopy == null) {
|
||||||
|
classObjectPropertiesToCopy = new ArrayList<PropertyDescriptor>();
|
||||||
|
}
|
||||||
|
classObjectPropertiesToCopy.add(descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,22 +17,32 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.codegen.context.ClassContext;
|
||||||
import org.jetbrains.jet.codegen.context.CodegenContext;
|
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||||
import org.jetbrains.jet.codegen.state.GenerationStateAware;
|
import org.jetbrains.jet.codegen.state.GenerationStateAware;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.jet.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
|
|
||||||
|
|
||||||
public class MemberCodegen extends GenerationStateAware {
|
public class MemberCodegen extends GenerationStateAware {
|
||||||
public MemberCodegen(@NotNull GenerationState state) {
|
|
||||||
|
@Nullable
|
||||||
|
private MemberCodegen parentCodegen;
|
||||||
|
|
||||||
|
public MemberCodegen(@NotNull GenerationState state, @Nullable MemberCodegen parentCodegen) {
|
||||||
super(state);
|
super(state);
|
||||||
|
this.parentCodegen = parentCodegen;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public MemberCodegen getParentCodegen() {
|
||||||
|
return parentCodegen;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void genFunctionOrProperty(
|
public void genFunctionOrProperty(
|
||||||
@@ -54,7 +64,7 @@ public class MemberCodegen extends GenerationStateAware {
|
|||||||
}
|
}
|
||||||
else if (functionOrProperty instanceof JetProperty) {
|
else if (functionOrProperty instanceof JetProperty) {
|
||||||
try {
|
try {
|
||||||
new PropertyCodegen(context, classBuilder, functionCodegen).gen((JetProperty) functionOrProperty);
|
new PropertyCodegen(context, classBuilder, functionCodegen, this).gen((JetProperty) functionOrProperty);
|
||||||
}
|
}
|
||||||
catch (CompilationException e) {
|
catch (CompilationException e) {
|
||||||
throw e;
|
throw e;
|
||||||
@@ -80,8 +90,8 @@ public class MemberCodegen extends GenerationStateAware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ClassBuilder classBuilder = state.getFactory().forClassImplementation(descriptor, aClass.getContainingFile());
|
ClassBuilder classBuilder = state.getFactory().forClassImplementation(descriptor, aClass.getContainingFile());
|
||||||
CodegenContext classContext = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state);
|
ClassContext classContext = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state);
|
||||||
new ImplementationBodyCodegen(aClass, classContext, classBuilder, state).generate();
|
new ImplementationBodyCodegen(aClass, classContext, classBuilder, state, this).generate();
|
||||||
classBuilder.done();
|
classBuilder.done();
|
||||||
|
|
||||||
if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) {
|
if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) {
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2013 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
|
public enum MethodKind {
|
||||||
|
GENERAL,
|
||||||
|
INITIALIZER,
|
||||||
|
SYNTHETIC_ACCESSOR
|
||||||
|
}
|
||||||
@@ -26,11 +26,9 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.asm4.AnnotationVisitor;
|
import org.jetbrains.asm4.AnnotationVisitor;
|
||||||
import org.jetbrains.asm4.MethodVisitor;
|
import org.jetbrains.asm4.MethodVisitor;
|
||||||
import org.jetbrains.asm4.Type;
|
import org.jetbrains.asm4.Type;
|
||||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
|
||||||
import org.jetbrains.jet.codegen.context.CodegenContext;
|
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
@@ -56,7 +54,7 @@ public class NamespaceCodegen extends MemberCodegen {
|
|||||||
GenerationState state,
|
GenerationState state,
|
||||||
Collection<JetFile> namespaceFiles
|
Collection<JetFile> namespaceFiles
|
||||||
) {
|
) {
|
||||||
super(state);
|
super(state, null);
|
||||||
checkAllFilesHaveSameNamespace(namespaceFiles);
|
checkAllFilesHaveSameNamespace(namespaceFiles);
|
||||||
|
|
||||||
this.v = v;
|
this.v = v;
|
||||||
@@ -218,7 +216,7 @@ public class NamespaceCodegen extends MemberCodegen {
|
|||||||
|
|
||||||
for (JetDeclaration declaration : properties) {
|
for (JetDeclaration declaration : properties) {
|
||||||
ImplementationBodyCodegen.
|
ImplementationBodyCodegen.
|
||||||
initializeProperty(codegen, state.getBindingContext(), new InstructionAdapter(mv), (JetProperty) declaration, true);
|
initializeProperty(codegen, state.getBindingContext(), (JetProperty) declaration);
|
||||||
}
|
}
|
||||||
|
|
||||||
mv.visitInsn(RETURN);
|
mv.visitInsn(RETURN);
|
||||||
|
|||||||
@@ -19,24 +19,29 @@ 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 com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.asm4.FieldVisitor;
|
import org.jetbrains.asm4.FieldVisitor;
|
||||||
import org.jetbrains.asm4.MethodVisitor;
|
import org.jetbrains.asm4.MethodVisitor;
|
||||||
import org.jetbrains.asm4.Type;
|
import org.jetbrains.asm4.Type;
|
||||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||||
|
import org.jetbrains.jet.codegen.context.ClassContext;
|
||||||
import org.jetbrains.jet.codegen.context.CodegenContext;
|
import org.jetbrains.jet.codegen.context.CodegenContext;
|
||||||
import org.jetbrains.jet.codegen.context.MethodContext;
|
import org.jetbrains.jet.codegen.context.MethodContext;
|
||||||
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
|
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
|
||||||
import org.jetbrains.jet.codegen.signature.JvmPropertyAccessorSignature;
|
import org.jetbrains.jet.codegen.signature.JvmPropertyAccessorSignature;
|
||||||
import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter;
|
import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter;
|
||||||
|
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||||
import org.jetbrains.jet.codegen.state.GenerationStateAware;
|
import org.jetbrains.jet.codegen.state.GenerationStateAware;
|
||||||
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
|
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
|
||||||
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||||
|
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
|
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
|
||||||
import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils;
|
import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
@@ -46,31 +51,44 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
|||||||
|
|
||||||
import static org.jetbrains.asm4.Opcodes.*;
|
import static org.jetbrains.asm4.Opcodes.*;
|
||||||
import static org.jetbrains.jet.codegen.AsmUtil.getDeprecatedAccessFlag;
|
import static org.jetbrains.jet.codegen.AsmUtil.getDeprecatedAccessFlag;
|
||||||
|
import static org.jetbrains.jet.codegen.AsmUtil.getVisibilityForSpecialPropertyBackingField;
|
||||||
import static org.jetbrains.jet.codegen.CodegenUtil.*;
|
import static org.jetbrains.jet.codegen.CodegenUtil.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
|
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
|
||||||
|
|
||||||
public class PropertyCodegen extends GenerationStateAware {
|
public class PropertyCodegen extends GenerationStateAware {
|
||||||
|
@NotNull
|
||||||
private final FunctionCodegen functionCodegen;
|
private final FunctionCodegen functionCodegen;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
private final ClassBuilder v;
|
private final ClassBuilder v;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
private final CodegenContext context;
|
private final CodegenContext context;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private MemberCodegen classBodyCodegen;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
private final OwnerKind kind;
|
private final OwnerKind kind;
|
||||||
|
|
||||||
public PropertyCodegen(CodegenContext context, ClassBuilder v, FunctionCodegen functionCodegen) {
|
public PropertyCodegen(
|
||||||
|
@NotNull CodegenContext context,
|
||||||
|
@NotNull ClassBuilder v,
|
||||||
|
@NotNull FunctionCodegen functionCodegen,
|
||||||
|
@Nullable MemberCodegen classBodyCodegen
|
||||||
|
) {
|
||||||
super(functionCodegen.getState());
|
super(functionCodegen.getState());
|
||||||
this.v = v;
|
this.v = v;
|
||||||
this.functionCodegen = functionCodegen;
|
this.functionCodegen = functionCodegen;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
this.classBodyCodegen = classBodyCodegen;
|
||||||
this.kind = context.getContextKind();
|
this.kind = context.getContextKind();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void gen(JetProperty p) {
|
public void gen(JetProperty p) {
|
||||||
VariableDescriptor descriptor = bindingContext.get(BindingContext.VARIABLE, p);
|
PropertyDescriptor propertyDescriptor = DescriptorUtils.getPropertyDescriptor(p, bindingContext);
|
||||||
if (!(descriptor instanceof PropertyDescriptor)) {
|
|
||||||
throw new UnsupportedOperationException("expect a property to have a property descriptor");
|
|
||||||
}
|
|
||||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
|
||||||
assert kind instanceof OwnerKind.StaticDelegateKind || kind == OwnerKind.NAMESPACE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.TRAIT_IMPL
|
assert kind instanceof OwnerKind.StaticDelegateKind || kind == OwnerKind.NAMESPACE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.TRAIT_IMPL
|
||||||
: "Generating property with a wrong kind (" + kind + "): " + descriptor;
|
: "Generating property with a wrong kind (" + kind + "): " + propertyDescriptor;
|
||||||
|
|
||||||
if (kind != OwnerKind.TRAIT_IMPL && !(kind instanceof OwnerKind.StaticDelegateKind)) {
|
if (kind != OwnerKind.TRAIT_IMPL && !(kind instanceof OwnerKind.StaticDelegateKind)) {
|
||||||
generateBackingField(p, propertyDescriptor);
|
generateBackingField(p, propertyDescriptor);
|
||||||
@@ -89,7 +107,7 @@ public class PropertyCodegen extends GenerationStateAware {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateBackingField(PsiElement p, PropertyDescriptor propertyDescriptor) {
|
private void generateBackingField(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor) {
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
boolean hasBackingField = bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor);
|
boolean hasBackingField = bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor);
|
||||||
boolean isDelegated = p instanceof JetProperty && ((JetProperty) p).getDelegateExpression() != null;
|
boolean isDelegated = p instanceof JetProperty && ((JetProperty) p).getDelegateExpression() != null;
|
||||||
@@ -108,25 +126,56 @@ public class PropertyCodegen extends GenerationStateAware {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private FieldVisitor generatePropertyDelegateAccess(JetProperty p, PropertyDescriptor propertyDescriptor) {
|
private FieldVisitor generateBackingField(JetNamedDeclaration element, PropertyDescriptor propertyDescriptor, boolean isDelegate, JetType jetType, Object defaultValue) {
|
||||||
int modifiers = ACC_PRIVATE | ACC_FINAL | getDeprecatedAccessFlag(propertyDescriptor);
|
int modifiers = getDeprecatedAccessFlag(propertyDescriptor);
|
||||||
if (kind == OwnerKind.NAMESPACE) {
|
|
||||||
modifiers |= ACC_STATIC;
|
|
||||||
}
|
|
||||||
if (KotlinBuiltIns.getInstance().isVolatile(propertyDescriptor)) {
|
if (KotlinBuiltIns.getInstance().isVolatile(propertyDescriptor)) {
|
||||||
modifiers |= ACC_VOLATILE;
|
modifiers |= ACC_VOLATILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (kind == OwnerKind.NAMESPACE) {
|
||||||
|
modifiers |= ACC_STATIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!propertyDescriptor.isVar() || isDelegate) {
|
||||||
|
modifiers |= ACC_FINAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type type = typeMapper.mapType(jetType);
|
||||||
|
|
||||||
|
ClassBuilder builder = v;
|
||||||
|
|
||||||
|
if (AsmUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor)) {
|
||||||
|
modifiers |= ACC_STATIC | getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegate);
|
||||||
|
builder = getParentBodyCodegen(classBodyCodegen).v;
|
||||||
|
} else {
|
||||||
|
if (kind != OwnerKind.NAMESPACE || isDelegate) {
|
||||||
|
modifiers |= ACC_PRIVATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AsmUtil.isPropertyWithBackingFieldCopyInOuterClass(propertyDescriptor)) {
|
||||||
|
ImplementationBodyCodegen parentBodyCodegen = getParentBodyCodegen(classBodyCodegen);
|
||||||
|
parentBodyCodegen.addClassObjectPropertyToCopy(propertyDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
String name = isDelegate ? JvmAbi.getPropertyDelegateName(propertyDescriptor.getName()) : propertyDescriptor.getName().asString();
|
||||||
|
|
||||||
|
return builder.newField(element, modifiers, name, type.getDescriptor(),
|
||||||
|
null, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FieldVisitor generatePropertyDelegateAccess(JetProperty p, PropertyDescriptor propertyDescriptor) {
|
||||||
JetType delegateType = bindingContext.get(BindingContext.EXPRESSION_TYPE, p.getDelegateExpression());
|
JetType delegateType = bindingContext.get(BindingContext.EXPRESSION_TYPE, p.getDelegateExpression());
|
||||||
if (delegateType == null) {
|
if (delegateType == null) {
|
||||||
// If delegate expression is unresolved reference
|
// If delegate expression is unresolved reference
|
||||||
delegateType = ErrorUtils.createErrorType("Delegate type");
|
delegateType = ErrorUtils.createErrorType("Delegate type");
|
||||||
}
|
}
|
||||||
Type type = typeMapper.mapType(delegateType);
|
|
||||||
return v.newField(p, modifiers, JvmAbi.getPropertyDelegateName(propertyDescriptor.getName()), type.getDescriptor(),
|
return generateBackingField(p, propertyDescriptor, true, delegateType, null);
|
||||||
null, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private FieldVisitor generateBackingFieldAccess(PsiElement p, PropertyDescriptor propertyDescriptor) {
|
private FieldVisitor generateBackingFieldAccess(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor) {
|
||||||
Object value = null;
|
Object value = null;
|
||||||
if (p instanceof JetProperty && !ImplementationBodyCodegen.shouldInitializeProperty((JetProperty) p, typeMapper)) {
|
if (p instanceof JetProperty && !ImplementationBodyCodegen.shouldInitializeProperty((JetProperty) p, typeMapper)) {
|
||||||
JetExpression initializer = ((JetProperty) p).getInitializer();
|
JetExpression initializer = ((JetProperty) p).getInitializer();
|
||||||
@@ -135,22 +184,8 @@ public class PropertyCodegen extends GenerationStateAware {
|
|||||||
value = compileTimeValue != null ? compileTimeValue.getValue() : null;
|
value = compileTimeValue != null ? compileTimeValue.getValue() : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int modifiers;
|
|
||||||
if (kind == OwnerKind.NAMESPACE) {
|
return generateBackingField(p, propertyDescriptor, false, propertyDescriptor.getType(), value);
|
||||||
modifiers = ACC_STATIC;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
modifiers = ACC_PRIVATE;
|
|
||||||
}
|
|
||||||
if (!propertyDescriptor.isVar()) {
|
|
||||||
modifiers |= ACC_FINAL;
|
|
||||||
}
|
|
||||||
modifiers |= getDeprecatedAccessFlag(propertyDescriptor);
|
|
||||||
if (KotlinBuiltIns.getInstance().isVolatile(propertyDescriptor)) {
|
|
||||||
modifiers |= ACC_VOLATILE;
|
|
||||||
}
|
|
||||||
Type type = typeMapper.mapType(propertyDescriptor);
|
|
||||||
return v.newField(p, modifiers, propertyDescriptor.getName().asString(), type.getDescriptor(), null, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateGetter(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor, JetPropertyAccessor getter) {
|
private void generateGetter(JetNamedDeclaration p, PropertyDescriptor propertyDescriptor, JetPropertyAccessor getter) {
|
||||||
@@ -166,10 +201,10 @@ public class PropertyCodegen extends GenerationStateAware {
|
|||||||
FunctionGenerationStrategy strategy;
|
FunctionGenerationStrategy strategy;
|
||||||
if (defaultGetter) {
|
if (defaultGetter) {
|
||||||
if (p instanceof JetProperty && ((JetProperty) p).getDelegateExpression() != null) {
|
if (p instanceof JetProperty && ((JetProperty) p).getDelegateExpression() != null) {
|
||||||
strategy = new DefaultPropertyWithDelegateAccessorStrategy(getterDescriptor);
|
strategy = new DefaultPropertyWithDelegateAccessorStrategy(state, getterDescriptor);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
strategy = new DefaultPropertyAccessorStrategy(getterDescriptor);
|
strategy = new DefaultPropertyAccessorStrategy(state, getterDescriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -197,10 +232,10 @@ public class PropertyCodegen extends GenerationStateAware {
|
|||||||
FunctionGenerationStrategy strategy;
|
FunctionGenerationStrategy strategy;
|
||||||
if (defaultSetter) {
|
if (defaultSetter) {
|
||||||
if (p instanceof JetProperty && ((JetProperty) p).getDelegateExpression() != null) {
|
if (p instanceof JetProperty && ((JetProperty) p).getDelegateExpression() != null) {
|
||||||
strategy = new DefaultPropertyWithDelegateAccessorStrategy(setterDescriptor);
|
strategy = new DefaultPropertyWithDelegateAccessorStrategy(state, setterDescriptor);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
strategy = new DefaultPropertyAccessorStrategy(setterDescriptor);
|
strategy = new DefaultPropertyAccessorStrategy(state, setterDescriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -216,90 +251,82 @@ public class PropertyCodegen extends GenerationStateAware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class DefaultPropertyAccessorStrategy extends FunctionGenerationStrategy {
|
private static class DefaultPropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased<PropertyAccessorDescriptor> {
|
||||||
private final PropertyAccessorDescriptor descriptor;
|
|
||||||
|
|
||||||
public DefaultPropertyAccessorStrategy(@NotNull PropertyAccessorDescriptor descriptor) {
|
public DefaultPropertyAccessorStrategy(
|
||||||
this.descriptor = descriptor;
|
@NotNull GenerationState state,
|
||||||
|
@NotNull PropertyAccessorDescriptor callableDescriptor
|
||||||
|
) {
|
||||||
|
super(state, callableDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateBody(
|
public void doGenerateBody(
|
||||||
@NotNull MethodVisitor mv,
|
ExpressionCodegen codegen, JvmMethodSignature signature
|
||||||
@NotNull JvmMethodSignature signature,
|
|
||||||
@NotNull MethodContext context
|
|
||||||
) {
|
) {
|
||||||
generateDefaultAccessor(descriptor, new InstructionAdapter(mv), typeMapper, context);
|
generateDefaultAccessor(callableDescriptor, codegen.v, codegen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void generateDefaultAccessor(
|
private static void generateDefaultAccessor(
|
||||||
@NotNull PropertyAccessorDescriptor accessorDescriptor,
|
@NotNull PropertyAccessorDescriptor accessorDescriptor,
|
||||||
@NotNull InstructionAdapter iv,
|
@NotNull InstructionAdapter iv,
|
||||||
@NotNull JetTypeMapper typeMapper,
|
@NotNull ExpressionCodegen codegen
|
||||||
@NotNull CodegenContext context
|
|
||||||
) {
|
) {
|
||||||
|
JetTypeMapper typeMapper = codegen.typeMapper;
|
||||||
|
CodegenContext context = codegen.context;
|
||||||
OwnerKind kind = context.getContextKind();
|
OwnerKind kind = context.getContextKind();
|
||||||
|
|
||||||
PropertyDescriptor propertyDescriptor = accessorDescriptor.getCorrespondingProperty();
|
PropertyDescriptor propertyDescriptor = accessorDescriptor.getCorrespondingProperty();
|
||||||
Type type = typeMapper.mapType(propertyDescriptor);
|
Type type = typeMapper.mapType(propertyDescriptor);
|
||||||
|
|
||||||
|
int paramCode = 0;
|
||||||
|
if (kind != OwnerKind.NAMESPACE) {
|
||||||
|
iv.load(0, OBJECT_TYPE);
|
||||||
|
paramCode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
StackValue property = codegen.intermediateValueForProperty(accessorDescriptor.getCorrespondingProperty(), true, null);
|
||||||
|
|
||||||
if (accessorDescriptor instanceof PropertyGetterDescriptor) {
|
if (accessorDescriptor instanceof PropertyGetterDescriptor) {
|
||||||
if (kind != OwnerKind.NAMESPACE) {
|
property.put(type, iv);
|
||||||
iv.load(0, OBJECT_TYPE);
|
|
||||||
}
|
|
||||||
iv.visitFieldInsn(
|
|
||||||
kind == OwnerKind.NAMESPACE ? GETSTATIC : GETFIELD,
|
|
||||||
typeMapper.getOwner(propertyDescriptor, kind, isCallInsideSameModuleAsDeclared(propertyDescriptor, context)).getInternalName(),
|
|
||||||
propertyDescriptor.getName().asString(),
|
|
||||||
type.getDescriptor());
|
|
||||||
iv.areturn(type);
|
iv.areturn(type);
|
||||||
}
|
}
|
||||||
else if (accessorDescriptor instanceof PropertySetterDescriptor) {
|
else if (accessorDescriptor instanceof PropertySetterDescriptor) {
|
||||||
int paramCode = 0;
|
|
||||||
if (kind != OwnerKind.NAMESPACE) {
|
|
||||||
iv.load(0, OBJECT_TYPE);
|
|
||||||
paramCode = 1;
|
|
||||||
}
|
|
||||||
ReceiverParameterDescriptor receiverParameter = propertyDescriptor.getReceiverParameter();
|
ReceiverParameterDescriptor receiverParameter = propertyDescriptor.getReceiverParameter();
|
||||||
if (receiverParameter != null) {
|
if (receiverParameter != null) {
|
||||||
paramCode += typeMapper.mapType(receiverParameter.getType()).getSize();
|
paramCode += typeMapper.mapType(receiverParameter.getType()).getSize();
|
||||||
}
|
}
|
||||||
iv.load(paramCode, type);
|
iv.load(paramCode, type);
|
||||||
iv.visitFieldInsn(kind == OwnerKind.NAMESPACE ? PUTSTATIC : PUTFIELD,
|
|
||||||
typeMapper.getOwner(propertyDescriptor, kind, isCallInsideSameModuleAsDeclared(propertyDescriptor, context)).getInternalName(),
|
|
||||||
propertyDescriptor.getName().asString(),
|
|
||||||
type.getDescriptor());
|
|
||||||
|
|
||||||
|
property.store(type, iv);
|
||||||
iv.visitInsn(RETURN);
|
iv.visitInsn(RETURN);
|
||||||
} else {
|
} else {
|
||||||
assert false : "Unreachable state";
|
assert false : "Unreachable state";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DefaultPropertyWithDelegateAccessorStrategy extends FunctionGenerationStrategy {
|
private static class DefaultPropertyWithDelegateAccessorStrategy extends FunctionGenerationStrategy.CodegenBased<PropertyAccessorDescriptor> {
|
||||||
private final PropertyAccessorDescriptor descriptor;
|
public DefaultPropertyWithDelegateAccessorStrategy(@NotNull GenerationState state, @NotNull PropertyAccessorDescriptor descriptor) {
|
||||||
|
super(state, descriptor);
|
||||||
public DefaultPropertyWithDelegateAccessorStrategy(@NotNull PropertyAccessorDescriptor descriptor) {
|
|
||||||
this.descriptor = descriptor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generateBody(
|
public void doGenerateBody(
|
||||||
@NotNull MethodVisitor mv,
|
@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature
|
||||||
@NotNull JvmMethodSignature signature,
|
|
||||||
@NotNull MethodContext context
|
|
||||||
) {
|
) {
|
||||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
JetTypeMapper typeMapper = codegen.typeMapper;
|
||||||
ExpressionCodegen codegen = new ExpressionCodegen(
|
OwnerKind kind = codegen.context.getContextKind();
|
||||||
mv, getFrameMap(typeMapper, context), signature.getAsmMethod().getReturnType(), context, state);
|
InstructionAdapter iv = codegen.v;
|
||||||
|
BindingContext bindingContext = state.getBindingContext();
|
||||||
|
|
||||||
ResolvedCall<FunctionDescriptor> resolvedCall =
|
ResolvedCall<FunctionDescriptor> resolvedCall =
|
||||||
bindingContext.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, descriptor);
|
bindingContext.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, callableDescriptor);
|
||||||
|
|
||||||
Call call = bindingContext.get(BindingContext.DELEGATED_PROPERTY_CALL, descriptor);
|
Call call = bindingContext.get(BindingContext.DELEGATED_PROPERTY_CALL, callableDescriptor);
|
||||||
assert call != null : "Call should be recorded for delegate call " + signature.toString();
|
assert call != null : "Call should be recorded for delegate call " + signature.toString();
|
||||||
|
|
||||||
PropertyDescriptor property = descriptor.getCorrespondingProperty();
|
PropertyDescriptor property = callableDescriptor.getCorrespondingProperty();
|
||||||
Type asmType = typeMapper.mapType(property);
|
Type asmType = typeMapper.mapType(property);
|
||||||
|
|
||||||
if (kind != OwnerKind.NAMESPACE) {
|
if (kind != OwnerKind.NAMESPACE) {
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public class ScriptCodegen extends MemberCodegen {
|
|||||||
private Method scriptConstructorMethod;
|
private Method scriptConstructorMethod;
|
||||||
|
|
||||||
public ScriptCodegen(@NotNull GenerationState state) {
|
public ScriptCodegen(@NotNull GenerationState state) {
|
||||||
super(state);
|
super(state, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -145,7 +145,6 @@ public class ScriptCodegen extends MemberCodegen {
|
|||||||
|
|
||||||
ImplementationBodyCodegen.generateInitializers(
|
ImplementationBodyCodegen.generateInitializers(
|
||||||
new ExpressionCodegen(instructionAdapter, frameMap, Type.VOID_TYPE, context, state),
|
new ExpressionCodegen(instructionAdapter, frameMap, Type.VOID_TYPE, context, state),
|
||||||
instructionAdapter,
|
|
||||||
scriptDeclaration.getDeclarations(),
|
scriptDeclaration.getDeclarations(),
|
||||||
bindingContext,
|
bindingContext,
|
||||||
state);
|
state);
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import org.jetbrains.jet.codegen.context.CodegenContext;
|
import org.jetbrains.jet.codegen.context.ClassContext;
|
||||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||||
import org.jetbrains.jet.codegen.state.JetTypeMapperMode;
|
import org.jetbrains.jet.codegen.state.JetTypeMapperMode;
|
||||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||||
@@ -24,8 +24,8 @@ import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
|||||||
import static org.jetbrains.asm4.Opcodes.*;
|
import static org.jetbrains.asm4.Opcodes.*;
|
||||||
|
|
||||||
public class TraitImplBodyCodegen extends ClassBodyCodegen {
|
public class TraitImplBodyCodegen extends ClassBodyCodegen {
|
||||||
public TraitImplBodyCodegen(JetClassOrObject aClass, CodegenContext context, ClassBuilder v, GenerationState state) {
|
public TraitImplBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassBuilder v, GenerationState state) {
|
||||||
super(aClass, context, v, state);
|
super(aClass, context, v, state, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -22,9 +22,8 @@ import org.jetbrains.jet.codegen.OwnerKind;
|
|||||||
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
|
|
||||||
import static org.jetbrains.jet.codegen.binding.CodegenBinding.CLOSURE;
|
public class AnonymousClassContext extends ClassContext {
|
||||||
|
|
||||||
public class AnonymousClassContext extends CodegenContext {
|
|
||||||
public AnonymousClassContext(
|
public AnonymousClassContext(
|
||||||
@NotNull JetTypeMapper typeMapper,
|
@NotNull JetTypeMapper typeMapper,
|
||||||
@NotNull ClassDescriptor contextDescriptor,
|
@NotNull ClassDescriptor contextDescriptor,
|
||||||
@@ -33,14 +32,7 @@ public class AnonymousClassContext extends CodegenContext {
|
|||||||
@Nullable LocalLookup localLookup
|
@Nullable LocalLookup localLookup
|
||||||
) {
|
) {
|
||||||
//noinspection SuspiciousMethodCalls
|
//noinspection SuspiciousMethodCalls
|
||||||
super(contextDescriptor, contextKind, parentContext, typeMapper.getBindingContext().get(CLOSURE, contextDescriptor),
|
super(typeMapper, contextDescriptor, contextKind, parentContext, localLookup);
|
||||||
contextDescriptor, localLookup);
|
|
||||||
initOuterExpression(typeMapper, contextDescriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isStatic() {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -146,31 +146,37 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
|||||||
return contextKind;
|
return contextKind;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public CodegenContext intoNamespace(@NotNull NamespaceDescriptor descriptor) {
|
public CodegenContext intoNamespace(@NotNull NamespaceDescriptor descriptor) {
|
||||||
return new NamespaceContext(descriptor, this, OwnerKind.NAMESPACE);
|
return new NamespaceContext(descriptor, this, OwnerKind.NAMESPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public CodegenContext intoNamespacePart(String delegateTo, NamespaceDescriptor descriptor) {
|
public CodegenContext intoNamespacePart(String delegateTo, NamespaceDescriptor descriptor) {
|
||||||
return new NamespaceContext(descriptor, this, new OwnerKind.StaticDelegateKind(delegateTo));
|
return new NamespaceContext(descriptor, this, new OwnerKind.StaticDelegateKind(delegateTo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public ClassContext intoClass(ClassDescriptor descriptor, OwnerKind kind, GenerationState state) {
|
public ClassContext intoClass(ClassDescriptor descriptor, OwnerKind kind, GenerationState state) {
|
||||||
return new ClassContext(state.getTypeMapper(), descriptor, kind, this, null);
|
return new ClassContext(state.getTypeMapper(), descriptor, kind, this, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CodegenContext intoAnonymousClass(
|
@NotNull
|
||||||
ClassDescriptor descriptor,
|
public ClassContext intoAnonymousClass(
|
||||||
ExpressionCodegen expressionCodegen
|
@NotNull ClassDescriptor descriptor,
|
||||||
|
@NotNull ExpressionCodegen expressionCodegen
|
||||||
) {
|
) {
|
||||||
JetTypeMapper typeMapper = expressionCodegen.getState().getTypeMapper();
|
JetTypeMapper typeMapper = expressionCodegen.getState().getTypeMapper();
|
||||||
return new AnonymousClassContext(typeMapper, descriptor, OwnerKind.IMPLEMENTATION, this,
|
return new AnonymousClassContext(typeMapper, descriptor, OwnerKind.IMPLEMENTATION, this,
|
||||||
expressionCodegen);
|
expressionCodegen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public MethodContext intoFunction(FunctionDescriptor descriptor) {
|
public MethodContext intoFunction(FunctionDescriptor descriptor) {
|
||||||
return new MethodContext(descriptor, getContextKind(), this);
|
return new MethodContext(descriptor, getContextKind(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public ConstructorContext intoConstructor(ConstructorDescriptor descriptor) {
|
public ConstructorContext intoConstructor(ConstructorDescriptor descriptor) {
|
||||||
if (descriptor == null) {
|
if (descriptor == null) {
|
||||||
descriptor = new ConstructorDescriptorImpl(getThisDescriptor(), Collections.<AnnotationDescriptor>emptyList(), true)
|
descriptor = new ConstructorDescriptorImpl(getThisDescriptor(), Collections.<AnnotationDescriptor>emptyList(), true)
|
||||||
@@ -180,6 +186,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
|||||||
return new ConstructorContext(descriptor, getContextKind(), this);
|
return new ConstructorContext(descriptor, getContextKind(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public CodegenContext intoScript(@NotNull ScriptDescriptor script, @NotNull ClassDescriptor classDescriptor) {
|
public CodegenContext intoScript(@NotNull ScriptDescriptor script, @NotNull ClassDescriptor classDescriptor) {
|
||||||
return new ScriptContext(script, classDescriptor, OwnerKind.IMPLEMENTATION, this, closure);
|
return new ScriptContext(script, classDescriptor, OwnerKind.IMPLEMENTATION, this, closure);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import org.jetbrains.jet.codegen.context.EnclosedValueDescriptor;
|
|||||||
import org.jetbrains.jet.codegen.signature.*;
|
import org.jetbrains.jet.codegen.signature.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall;
|
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetFile;
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||||
@@ -961,4 +962,15 @@ public class JetTypeMapper extends BindingTraceAware {
|
|||||||
}
|
}
|
||||||
return new CallableMethod(owner, null, null, descriptor, INVOKEINTERFACE, owner, receiverParameterType, owner.getAsmType());
|
return new CallableMethod(owner, null, null, descriptor, INVOKEINTERFACE, owner, receiverParameterType, owner.getAsmType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Type expressionType(JetExpression expr) {
|
||||||
|
JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, expr);
|
||||||
|
return asmTypeOrVoid(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Type asmTypeOrVoid(@Nullable JetType type) {
|
||||||
|
return type == null ? Type.VOID_TYPE : mapType(type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -553,6 +553,10 @@ public class JetPsiUtil {
|
|||||||
return getOutermostClassOrObject(classOrObject) == null;
|
return getOutermostClassOrObject(classOrObject) == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isTrait(@NotNull JetClassOrObject classOrObject) {
|
||||||
|
return classOrObject instanceof JetClass && ((JetClass) classOrObject).isTrait();
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static JetClassOrObject getOutermostClassOrObject(@NotNull JetClassOrObject classOrObject) {
|
public static JetClassOrObject getOutermostClassOrObject(@NotNull JetClassOrObject classOrObject) {
|
||||||
JetClassOrObject current = classOrObject;
|
JetClassOrObject current = classOrObject;
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.descriptors.impl.AnonymousFunctionDescriptor;
|
|||||||
import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorParent;
|
import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorParent;
|
||||||
import org.jetbrains.jet.lang.psi.JetElement;
|
import org.jetbrains.jet.lang.psi.JetElement;
|
||||||
import org.jetbrains.jet.lang.psi.JetFunction;
|
import org.jetbrains.jet.lang.psi.JetFunction;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetProperty;
|
||||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||||
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
|
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
|
||||||
@@ -289,6 +290,10 @@ public class DescriptorUtils {
|
|||||||
return isKindOf(descriptor, ClassKind.ENUM_CLASS);
|
return isKindOf(descriptor, ClassKind.ENUM_CLASS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isClass(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
return isKindOf(descriptor, ClassKind.CLASS);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isKindOf(@NotNull JetType jetType, @NotNull ClassKind classKind) {
|
public static boolean isKindOf(@NotNull JetType jetType, @NotNull ClassKind classKind) {
|
||||||
ClassifierDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
ClassifierDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||||
return isKindOf(descriptor, classKind);
|
return isKindOf(descriptor, classKind);
|
||||||
@@ -572,4 +577,13 @@ public class DescriptorUtils {
|
|||||||
}
|
}
|
||||||
return allSuperclasses;
|
return allSuperclasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static PropertyDescriptor getPropertyDescriptor(@NotNull JetProperty property, @NotNull BindingContext bindingContext) {
|
||||||
|
VariableDescriptor descriptor = bindingContext.get(BindingContext.VARIABLE, property);
|
||||||
|
if (!(descriptor instanceof PropertyDescriptor)) {
|
||||||
|
throw new UnsupportedOperationException("expect a property to have a property descriptor");
|
||||||
|
}
|
||||||
|
return (PropertyDescriptor) descriptor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user