enclosed super properties
This commit is contained in:
@@ -1,7 +1,10 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
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.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||||
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;
|
||||||
@@ -11,6 +14,7 @@ import org.objectweb.asm.commons.InstructionAdapter;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,12 +41,12 @@ public abstract class ClassBodyCodegen {
|
|||||||
this.v = v;
|
this.v = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generate() {
|
public final void generate(@Nullable HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
|
||||||
generateDeclaration();
|
generateDeclaration();
|
||||||
|
|
||||||
generateClassBody();
|
generateClassBody();
|
||||||
|
|
||||||
generateSyntheticParts();
|
generateSyntheticParts(accessors);
|
||||||
|
|
||||||
generateStaticInitializer();
|
generateStaticInitializer();
|
||||||
|
|
||||||
@@ -51,7 +55,7 @@ public abstract class ClassBodyCodegen {
|
|||||||
|
|
||||||
protected abstract void generateDeclaration();
|
protected abstract void generateDeclaration();
|
||||||
|
|
||||||
protected void generateSyntheticParts() {
|
protected void generateSyntheticParts(HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateClassBody() {
|
private void generateClassBody() {
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
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.descriptors.FunctionDescriptor;
|
||||||
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 java.util.HashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author max
|
* @author max
|
||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
@@ -15,29 +19,30 @@ public class ClassCodegen {
|
|||||||
this.state = state;
|
this.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generate(ClassContext parentContext, JetClassOrObject aClass) {
|
public void generate(ClassContext context, JetClassOrObject aClass) {
|
||||||
GenerationState.prepareAnonymousClasses((JetElement) aClass, state.getTypeMapper());
|
GenerationState.prepareAnonymousClasses((JetElement) aClass, state.getTypeMapper());
|
||||||
|
|
||||||
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
||||||
|
|
||||||
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
|
final ClassContext contextForInners = context.intoClass(null, descriptor, OwnerKind.IMPLEMENTATION);
|
||||||
|
|
||||||
final ClassContext contextForInners = parentContext.intoClass(null, descriptor, OwnerKind.IMPLEMENTATION);
|
|
||||||
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
||||||
if (declaration instanceof JetClass && !(declaration instanceof JetEnumEntry)) {
|
if (declaration instanceof JetClass && !(declaration instanceof JetEnumEntry)) {
|
||||||
generate(contextForInners, (JetClass) declaration);
|
generate(contextForInners, (JetClass) declaration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generateImplementation(context, aClass, OwnerKind.IMPLEMENTATION, contextForInners.accessors);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateImplementation(ClassContext parentContext, JetClassOrObject aClass, OwnerKind kind) {
|
private void generateImplementation(ClassContext context, JetClassOrObject aClass, OwnerKind kind, HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
|
||||||
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
||||||
ClassBuilder v = state.forClassImplementation(descriptor);
|
ClassBuilder v = state.forClassImplementation(descriptor);
|
||||||
new ImplementationBodyCodegen(aClass, parentContext.intoClass(null, descriptor, kind), v, state).generate();
|
ClassContext classContext = context.intoClass(null, descriptor, kind);
|
||||||
|
new ImplementationBodyCodegen(aClass, classContext, v, state).generate(accessors);
|
||||||
|
|
||||||
if(aClass instanceof JetClass && ((JetClass)aClass).isTrait()) {
|
if(aClass instanceof JetClass && ((JetClass)aClass).isTrait()) {
|
||||||
v = state.forTraitImplementation(descriptor);
|
v = state.forTraitImplementation(descriptor);
|
||||||
new TraitImplBodyCodegen(aClass, parentContext.intoClass(null, descriptor, OwnerKind.TRAIT_IMPL), v, state).generate();
|
new TraitImplBodyCodegen(aClass, context.intoClass(null, descriptor, OwnerKind.TRAIT_IMPL), v, state).generate(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,21 @@
|
|||||||
package org.jetbrains.jet.codegen;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
import org.jetbrains.jet.lang.psi.JetTypeReference;
|
||||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
import org.objectweb.asm.commons.InstructionAdapter;
|
import org.objectweb.asm.commons.InstructionAdapter;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.lang.diagnostics.Errors.WRONG_GETTER_RETURN_TYPE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @author max
|
* @author max
|
||||||
@@ -21,11 +26,12 @@ public class ClassContext {
|
|||||||
private final DeclarationDescriptor contextType;
|
private final DeclarationDescriptor contextType;
|
||||||
private final OwnerKind contextKind;
|
private final OwnerKind contextKind;
|
||||||
private final StackValue thisExpression;
|
private final StackValue thisExpression;
|
||||||
private final ClassContext parentContext;
|
final ClassContext parentContext;
|
||||||
public final FunctionOrClosureCodegen closure;
|
public final FunctionOrClosureCodegen closure;
|
||||||
private boolean thisWasUsed = false;
|
private boolean thisWasUsed = false;
|
||||||
|
|
||||||
HashMap<JetType,Integer> typeInfoConstants;
|
HashMap<JetType,Integer> typeInfoConstants;
|
||||||
|
HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors;
|
||||||
|
|
||||||
public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext, FunctionOrClosureCodegen closureCodegen) {
|
public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext, FunctionOrClosureCodegen closureCodegen) {
|
||||||
this.contextType = contextType;
|
this.contextType = contextType;
|
||||||
@@ -194,4 +200,59 @@ public class ClassContext {
|
|||||||
}
|
}
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeclarationDescriptor getAccessor(DeclarationDescriptor descriptor) {
|
||||||
|
if(accessors == null) {
|
||||||
|
accessors = new HashMap<DeclarationDescriptor,DeclarationDescriptor>();
|
||||||
|
}
|
||||||
|
descriptor = descriptor.getOriginal();
|
||||||
|
DeclarationDescriptor accessor = accessors.get(descriptor);
|
||||||
|
if(accessor != null)
|
||||||
|
return accessor;
|
||||||
|
|
||||||
|
if(descriptor instanceof FunctionDescriptor) {
|
||||||
|
FunctionDescriptorImpl myAccessor = new FunctionDescriptorImpl(contextType,
|
||||||
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
|
descriptor.getName() + "$bridge$" + accessors.size());
|
||||||
|
FunctionDescriptor fd = (FunctionDescriptor) descriptor;
|
||||||
|
myAccessor.initialize(fd.getReceiverParameter().exists() ? fd.getReceiverParameter().getType() : null,
|
||||||
|
fd.getExpectedThisObject(),
|
||||||
|
fd.getTypeParameters(),
|
||||||
|
fd.getValueParameters(),
|
||||||
|
fd.getReturnType(),
|
||||||
|
fd.getModality(),
|
||||||
|
fd.getVisibility());
|
||||||
|
accessor = myAccessor;
|
||||||
|
}
|
||||||
|
else if(descriptor instanceof PropertyDescriptor) {
|
||||||
|
PropertyDescriptor pd = (PropertyDescriptor) descriptor;
|
||||||
|
PropertyDescriptor myAccessor = new PropertyDescriptor(contextType,
|
||||||
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
|
pd.getModality(),
|
||||||
|
pd.getVisibility(),
|
||||||
|
pd.isVar(),
|
||||||
|
pd.getReceiverParameter().exists() ? pd.getReceiverParameter().getType() : null,
|
||||||
|
pd.getExpectedThisObject(),
|
||||||
|
pd.getName() + "$bridge$" + accessors.size(),
|
||||||
|
pd.getInType(),
|
||||||
|
pd.getOutType());
|
||||||
|
PropertyGetterDescriptor pgd = new PropertyGetterDescriptor(
|
||||||
|
myAccessor, Collections.<AnnotationDescriptor>emptyList(), myAccessor.getModality(),
|
||||||
|
myAccessor.getVisibility(),
|
||||||
|
myAccessor.getOutType(), false, false);
|
||||||
|
PropertySetterDescriptor psd = new PropertySetterDescriptor(
|
||||||
|
myAccessor.getModality(),
|
||||||
|
myAccessor.getVisibility(),
|
||||||
|
myAccessor,
|
||||||
|
Collections.<AnnotationDescriptor>emptyList(),
|
||||||
|
false, false);
|
||||||
|
myAccessor.initialize(Collections.<TypeParameterDescriptor>emptyList(), pgd, psd);
|
||||||
|
accessor = myAccessor;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
accessors.put(descriptor, accessor);
|
||||||
|
return accessor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
// if(hND != null)
|
// if(hND != null)
|
||||||
// invokeFunctionNoParams(hND, Type.BOOLEAN_TYPE, v);
|
// invokeFunctionNoParams(hND, Type.BOOLEAN_TYPE, v);
|
||||||
// else
|
// else
|
||||||
intermediateValueForProperty((PropertyDescriptor) hasNextDescriptor, false, false, false).put(Type.BOOLEAN_TYPE, v);
|
intermediateValueForProperty((PropertyDescriptor) hasNextDescriptor, false, null).put(Type.BOOLEAN_TYPE, v);
|
||||||
}
|
}
|
||||||
v.ifeq(end);
|
v.ifeq(end);
|
||||||
|
|
||||||
@@ -813,9 +813,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
boolean isStatic = container instanceof NamespaceDescriptorImpl;
|
boolean isStatic = container instanceof NamespaceDescriptorImpl;
|
||||||
final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL ;
|
final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL ;
|
||||||
JetExpression r = getReceiverForSelector(expression);
|
JetExpression r = getReceiverForSelector(expression);
|
||||||
final boolean forceInterface = r != null && !(r instanceof JetThisExpression);
|
|
||||||
final boolean isSuper = r instanceof JetSuperExpression;
|
final boolean isSuper = r instanceof JetSuperExpression;
|
||||||
final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField, forceInterface, isSuper);
|
final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField, isSuper ? (JetSuperExpression)r : null);
|
||||||
if (!isStatic) {
|
if (!isStatic) {
|
||||||
if (receiver == StackValue.none()) {
|
if (receiver == StackValue.none()) {
|
||||||
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
|
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
|
||||||
@@ -913,11 +912,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
StackValue.onStack(typeMapper.mapType(functionDescriptor.getReturnType())).coerce(type, v);
|
StackValue.onStack(typeMapper.mapType(functionDescriptor.getReturnType())).coerce(type, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean forceField, boolean forceInterface, boolean isSuper) {
|
public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean forceField, @Nullable JetSuperExpression superExpression) {
|
||||||
|
boolean isSuper = superExpression != null;
|
||||||
|
|
||||||
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
||||||
boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl;
|
boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl;
|
||||||
propertyDescriptor = propertyDescriptor.getOriginal();
|
propertyDescriptor = propertyDescriptor.getOriginal();
|
||||||
boolean isInsideClass = !forceInterface && containingDeclaration == context.getContextClass() && contextKind() != OwnerKind.TRAIT_IMPL;
|
boolean isInsideClass = containingDeclaration == context.getContextClass() && contextKind() != OwnerKind.TRAIT_IMPL;
|
||||||
Method getter;
|
Method getter;
|
||||||
Method setter;
|
Method setter;
|
||||||
if (forceField) {
|
if (forceField) {
|
||||||
@@ -926,11 +927,33 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
getter = isInsideClass && (propertyDescriptor.getGetter() == null || propertyDescriptor.getGetter().isDefault())
|
if (isInsideClass && (propertyDescriptor.getGetter() == null || propertyDescriptor.getGetter().isDefault())) {
|
||||||
? null : typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
|
getter = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(isSuper) {
|
||||||
|
PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel());
|
||||||
|
ClassDescriptor enclosed = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, enclosingElement);
|
||||||
|
if(!CodegenUtil.isInterface(propertyDescriptor.getContainingDeclaration())) {
|
||||||
|
if(enclosed != null && enclosed != context.getContextClass()) {
|
||||||
|
ClassContext c = context;
|
||||||
|
while(c.getContextDescriptor() != enclosed) {
|
||||||
|
c = c.getParentContext();
|
||||||
|
}
|
||||||
|
propertyDescriptor = (PropertyDescriptor) c.getAccessor(propertyDescriptor);
|
||||||
|
isSuper = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getter = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
|
||||||
|
}
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
setter = isInsideClass && (propertyDescriptor.getSetter() == null || propertyDescriptor.getSetter().isDefault())
|
if (isInsideClass && (propertyDescriptor.getSetter() == null || propertyDescriptor.getSetter().isDefault())) {
|
||||||
? null : typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
|
setter = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setter = typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String owner;
|
String owner;
|
||||||
@@ -973,8 +996,21 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
boolean superCall = false;
|
boolean superCall = false;
|
||||||
if (expression.getParent() instanceof JetQualifiedExpression) {
|
if (expression.getParent() instanceof JetQualifiedExpression) {
|
||||||
final JetExpression receiverExpression = ((JetQualifiedExpression) expression.getParent()).getReceiverExpression();
|
final JetExpression receiverExpression = ((JetQualifiedExpression) expression.getParent()).getReceiverExpression();
|
||||||
if(receiverExpression instanceof JetSuperExpression) {
|
if (receiverExpression instanceof JetSuperExpression) {
|
||||||
superCall = true;
|
superCall = true;
|
||||||
|
JetSuperExpression superExpression = (JetSuperExpression) receiverExpression;
|
||||||
|
PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel());
|
||||||
|
ClassDescriptor enclosed = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, enclosingElement);
|
||||||
|
if(!CodegenUtil.isInterface(fd.getContainingDeclaration())) {
|
||||||
|
if(enclosed != null && enclosed != context.getContextClass()) {
|
||||||
|
ClassContext c = context;
|
||||||
|
while(c.getContextDescriptor() != enclosed) {
|
||||||
|
c = c.getParentContext();
|
||||||
|
}
|
||||||
|
fd = c.getAccessor((FunctionDescriptor) fd);
|
||||||
|
superCall = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2459,7 +2495,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) call);
|
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) call);
|
||||||
if (descriptor instanceof PropertyDescriptor) {
|
if (descriptor instanceof PropertyDescriptor) {
|
||||||
v.load(subjectLocal, subjectType);
|
v.load(subjectLocal, subjectType);
|
||||||
conditionValue = intermediateValueForProperty((PropertyDescriptor) descriptor, false, false, false);
|
conditionValue = intermediateValueForProperty((PropertyDescriptor) descriptor, false, null);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException("unknown simple name resolve result: " + descriptor);
|
throw new UnsupportedOperationException("unknown simple name resolve result: " + descriptor);
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ public class GenerationState {
|
|||||||
closure.name = nameAndVisitor.getFirst();
|
closure.name = nameAndVisitor.getFirst();
|
||||||
final ClassContext objectContext = closure.context.intoClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION);
|
final ClassContext objectContext = closure.context.intoClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION);
|
||||||
|
|
||||||
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate();
|
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate(null);
|
||||||
|
|
||||||
ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration);
|
ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration);
|
||||||
CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
|
CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
|
||||||
|
|||||||
@@ -154,9 +154,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void generateSyntheticParts() {
|
protected void generateSyntheticParts(HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
|
||||||
generateFieldForObjectInstance();
|
generateFieldForObjectInstance();
|
||||||
generateFieldForClassObject();
|
generateFieldForClassObject();
|
||||||
|
generateAccessors(accessors);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
generatePrimaryConstructor();
|
generatePrimaryConstructor();
|
||||||
@@ -168,6 +169,81 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
generateGetTypeInfo();
|
generateGetTypeInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void generateAccessors(HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
|
||||||
|
if(accessors != null) {
|
||||||
|
for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : accessors.entrySet()) {
|
||||||
|
if(entry.getValue() instanceof FunctionDescriptor) {
|
||||||
|
FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue();
|
||||||
|
FunctionDescriptor original = (FunctionDescriptor) entry.getKey();
|
||||||
|
|
||||||
|
Method method = state.getTypeMapper().mapSignature(bridge.getName(), bridge);
|
||||||
|
Method originalMethod = state.getTypeMapper().mapSignature(original.getName(), original);
|
||||||
|
Type[] argTypes = method.getArgumentTypes();
|
||||||
|
|
||||||
|
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, bridge.getName(), method.getDescriptor(), null, null);
|
||||||
|
mv.visitCode();
|
||||||
|
|
||||||
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
|
|
||||||
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||||
|
Type argType = argTypes[i];
|
||||||
|
iv.load(reg, argType);
|
||||||
|
//noinspection AssignmentToForLoopParameter
|
||||||
|
reg += argType.getSize();
|
||||||
|
}
|
||||||
|
iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
|
||||||
|
|
||||||
|
iv.areturn(method.getReturnType());
|
||||||
|
mv.visitMaxs(0,0);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
else if(entry.getValue() instanceof PropertyDescriptor) {
|
||||||
|
PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
|
||||||
|
PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
|
||||||
|
|
||||||
|
Method method = state.getTypeMapper().mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION);
|
||||||
|
Method originalMethod = state.getTypeMapper().mapGetterSignature(original, OwnerKind.IMPLEMENTATION);
|
||||||
|
MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
|
||||||
|
mv.visitCode();
|
||||||
|
|
||||||
|
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||||
|
|
||||||
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
|
||||||
|
|
||||||
|
iv.areturn(method.getReturnType());
|
||||||
|
mv.visitMaxs(0,0);
|
||||||
|
mv.visitEnd();
|
||||||
|
|
||||||
|
method = state.getTypeMapper().mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION);
|
||||||
|
originalMethod = state.getTypeMapper().mapSetterSignature(original, OwnerKind.IMPLEMENTATION);
|
||||||
|
mv = v.newMethod(null, Opcodes.ACC_PUBLIC|Opcodes.ACC_BRIDGE|Opcodes.ACC_FINAL, method.getName(), method.getDescriptor(), null, null);
|
||||||
|
mv.visitCode();
|
||||||
|
|
||||||
|
iv = new InstructionAdapter(mv);
|
||||||
|
|
||||||
|
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||||
|
Type[] argTypes = method.getArgumentTypes();
|
||||||
|
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||||
|
Type argType = argTypes[i];
|
||||||
|
iv.load(reg, argType);
|
||||||
|
//noinspection AssignmentToForLoopParameter
|
||||||
|
reg += argType.getSize();
|
||||||
|
}
|
||||||
|
iv.invokespecial(state.getTypeMapper().getOwner(original, OwnerKind.IMPLEMENTATION), originalMethod.getName(), originalMethod.getDescriptor());
|
||||||
|
|
||||||
|
iv.areturn(method.getReturnType());
|
||||||
|
mv.visitMaxs(0,0);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void generateFieldForObjectInstance() {
|
private void generateFieldForObjectInstance() {
|
||||||
if (isNonLiteralObject()) {
|
if (isNonLiteralObject()) {
|
||||||
Type type = state.getTypeMapper().jetImplementationType(descriptor);
|
Type type = state.getTypeMapper().jetImplementationType(descriptor);
|
||||||
@@ -654,7 +730,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
if(propertyDescriptor.getOutType().isNullable())
|
if(propertyDescriptor.getOutType().isNullable())
|
||||||
type = JetTypeMapper.boxType(type);
|
type = JetTypeMapper.boxType(type);
|
||||||
codegen.gen(initializer, type);
|
codegen.gen(initializer, type);
|
||||||
codegen.intermediateValueForProperty(propertyDescriptor, false, false, false).store(iv);
|
codegen.intermediateValueForProperty(propertyDescriptor, false, null).store(iv);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import jet.JetObject;
|
|||||||
import jet.typeinfo.TypeInfo;
|
import jet.typeinfo.TypeInfo;
|
||||||
import jet.typeinfo.TypeInfoProjection;
|
import jet.typeinfo.TypeInfoProjection;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
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;
|
||||||
@@ -19,6 +20,8 @@ import org.objectweb.asm.commons.Method;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import static org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yole
|
* @author yole
|
||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
@@ -319,14 +322,14 @@ public class JetTypeMapper {
|
|||||||
if (functionParent instanceof NamespaceDescriptor) {
|
if (functionParent instanceof NamespaceDescriptor) {
|
||||||
assert !superCall;
|
assert !superCall;
|
||||||
owner = NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(functionParent));
|
owner = NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(functionParent));
|
||||||
invokeOpcode = Opcodes.INVOKESTATIC;
|
invokeOpcode = INVOKESTATIC;
|
||||||
thisClass = null;
|
thisClass = null;
|
||||||
}
|
}
|
||||||
else if (functionDescriptor instanceof ConstructorDescriptor) {
|
else if (functionDescriptor instanceof ConstructorDescriptor) {
|
||||||
assert !superCall;
|
assert !superCall;
|
||||||
ClassDescriptor containingClass = (ClassDescriptor) functionParent;
|
ClassDescriptor containingClass = (ClassDescriptor) functionParent;
|
||||||
owner = jvmName(containingClass, OwnerKind.IMPLEMENTATION);
|
owner = jvmName(containingClass, OwnerKind.IMPLEMENTATION);
|
||||||
invokeOpcode = Opcodes.INVOKESPECIAL;
|
invokeOpcode = INVOKESPECIAL;
|
||||||
thisClass = null;
|
thisClass = null;
|
||||||
}
|
}
|
||||||
else if (functionParent instanceof ClassDescriptor) {
|
else if (functionParent instanceof ClassDescriptor) {
|
||||||
@@ -486,16 +489,16 @@ public class JetTypeMapper {
|
|||||||
List<Type> valueParameterTypes = new ArrayList<Type>();
|
List<Type> valueParameterTypes = new ArrayList<Type>();
|
||||||
final Method method = mapConstructorSignature(descriptor, valueParameterTypes);
|
final Method method = mapConstructorSignature(descriptor, valueParameterTypes);
|
||||||
String owner = jvmName(descriptor.getContainingDeclaration(), kind);
|
String owner = jvmName(descriptor.getContainingDeclaration(), kind);
|
||||||
return new CallableMethod(owner, method, Opcodes.INVOKESPECIAL, valueParameterTypes);
|
return new CallableMethod(owner, method, INVOKESPECIAL, valueParameterTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getAccessModifiers(JetDeclaration p, int defaultFlags) {
|
static int getAccessModifiers(JetDeclaration p, int defaultFlags) {
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
if (p.hasModifier(JetTokens.PUBLIC_KEYWORD)) {
|
if (p.hasModifier(JetTokens.PUBLIC_KEYWORD)) {
|
||||||
flags |= Opcodes.ACC_PUBLIC;
|
flags |= ACC_PUBLIC;
|
||||||
}
|
}
|
||||||
else if (p.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
|
else if (p.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
|
||||||
flags |= Opcodes.ACC_PRIVATE;
|
flags |= ACC_PRIVATE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
flags |= defaultFlags;
|
flags |= defaultFlags;
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public class NamespaceCodegen {
|
|||||||
if (initializer != null && !(initializer instanceof JetConstantExpression)) {
|
if (initializer != null && !(initializer instanceof JetConstantExpression)) {
|
||||||
final PropertyDescriptor descriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration);
|
final PropertyDescriptor descriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration);
|
||||||
codegen.genToJVMStack(initializer);
|
codegen.genToJVMStack(initializer);
|
||||||
codegen.intermediateValueForProperty(descriptor, true, false, false).store(new InstructionAdapter(mv));
|
codegen.intermediateValueForProperty(descriptor, true, null).store(new InstructionAdapter(mv));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -642,12 +642,12 @@ public abstract class StackValue {
|
|||||||
v.visitMethodInsn(Opcodes.INVOKESTATIC, owner + "$$TImpl", getter.getName(), getter.getDescriptor().replace("(","(L" + owner + ";"));
|
v.visitMethodInsn(Opcodes.INVOKESTATIC, owner + "$$TImpl", getter.getName(), getter.getDescriptor().replace("(","(L" + owner + ";"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (getter == null) {
|
if (getter == null) {
|
||||||
v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, owner, name, this.type.getDescriptor());
|
v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, owner, name, this.type.getDescriptor());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isSuper ? Opcodes.INVOKESPECIAL : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, getter.getName(), getter.getDescriptor());
|
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isSuper ? Opcodes.INVOKESPECIAL : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, getter.getName(), getter.getDescriptor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
coerce(type, v);
|
coerce(type, v);
|
||||||
}
|
}
|
||||||
@@ -658,10 +658,10 @@ public abstract class StackValue {
|
|||||||
v.visitMethodInsn(Opcodes.INVOKESTATIC, owner + "$$TImpl", setter.getName(), setter.getDescriptor().replace("(","(L" + owner + ";"));
|
v.visitMethodInsn(Opcodes.INVOKESTATIC, owner + "$$TImpl", setter.getName(), setter.getDescriptor().replace("(","(L" + owner + ";"));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (setter == null) {
|
if (setter == null) {
|
||||||
v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner, name, this.type.getDescriptor());
|
v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner, name, this.type.getDescriptor());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isSuper ? Opcodes.INVOKESPECIAL : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, setter.getName(), setter.getDescriptor());
|
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isSuper ? Opcodes.INVOKESPECIAL : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, setter.getName(), setter.getDescriptor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
trait BK {
|
||||||
|
fun x() : Int = 50
|
||||||
|
}
|
||||||
|
|
||||||
|
trait K : BK {
|
||||||
|
override fun x() : Int = super.x() * 2
|
||||||
|
}
|
||||||
|
|
||||||
|
open class M() {
|
||||||
|
open fun x() : Int = 10
|
||||||
|
|
||||||
|
open var y = 500
|
||||||
|
}
|
||||||
|
|
||||||
|
open class N() : M(), K {
|
||||||
|
|
||||||
|
override fun x() : Int = 20
|
||||||
|
|
||||||
|
override var y = 200
|
||||||
|
|
||||||
|
open class C() : K {
|
||||||
|
fun test1() = x()
|
||||||
|
fun test2() = super<M>@N.x()
|
||||||
|
fun test3() = super<K>@N.x()
|
||||||
|
fun test4() = super<K>.x()
|
||||||
|
fun test5() = y
|
||||||
|
fun test6() : Int {
|
||||||
|
super<M>@N.y += 200
|
||||||
|
return super<M>@N.y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
if (N().C().test1() != 100) return "test1 fail";
|
||||||
|
if (N().C().test2() != 10) return "test2 fail";
|
||||||
|
if (N().C().test3() != 100) return "test3 fail";
|
||||||
|
if (N().C().test4() != 100) return "test4 fail";
|
||||||
|
if (N().C().test5() != 200) return "test5 fail";
|
||||||
|
if (N().C().test6() != 700) return "test6 fail";
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
@@ -15,4 +15,9 @@ public class SuperGenTest extends CodegenTestCase {
|
|||||||
blackBoxFile("/super/basicmethod.jet");
|
blackBoxFile("/super/basicmethod.jet");
|
||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testEnclosedMethod () {
|
||||||
|
blackBoxFile("/super/enclosed.jet");
|
||||||
|
System.out.println(generateToText());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user