enclosed super properties
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
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.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -11,6 +14,7 @@ import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -37,12 +41,12 @@ public abstract class ClassBodyCodegen {
|
||||
this.v = v;
|
||||
}
|
||||
|
||||
public void generate() {
|
||||
public final void generate(@Nullable HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
|
||||
generateDeclaration();
|
||||
|
||||
generateClassBody();
|
||||
|
||||
generateSyntheticParts();
|
||||
generateSyntheticParts(accessors);
|
||||
|
||||
generateStaticInitializer();
|
||||
|
||||
@@ -51,7 +55,7 @@ public abstract class ClassBodyCodegen {
|
||||
|
||||
protected abstract void generateDeclaration();
|
||||
|
||||
protected void generateSyntheticParts() {
|
||||
protected void generateSyntheticParts(HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
|
||||
}
|
||||
|
||||
private void generateClassBody() {
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
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.resolve.BindingContext;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
* @author alex.tkachman
|
||||
@@ -15,29 +19,30 @@ public class ClassCodegen {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public void generate(ClassContext parentContext, JetClassOrObject aClass) {
|
||||
public void generate(ClassContext context, JetClassOrObject aClass) {
|
||||
GenerationState.prepareAnonymousClasses((JetElement) aClass, state.getTypeMapper());
|
||||
|
||||
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
||||
|
||||
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
|
||||
|
||||
final ClassContext contextForInners = parentContext.intoClass(null, descriptor, OwnerKind.IMPLEMENTATION);
|
||||
final ClassContext contextForInners = context.intoClass(null, descriptor, OwnerKind.IMPLEMENTATION);
|
||||
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
||||
if (declaration instanceof JetClass && !(declaration instanceof JetEnumEntry)) {
|
||||
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);
|
||||
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()) {
|
||||
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;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
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.NamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetTypeReference;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.WRONG_GETTER_RETURN_TYPE;
|
||||
|
||||
/*
|
||||
* @author max
|
||||
@@ -21,11 +26,12 @@ public class ClassContext {
|
||||
private final DeclarationDescriptor contextType;
|
||||
private final OwnerKind contextKind;
|
||||
private final StackValue thisExpression;
|
||||
private final ClassContext parentContext;
|
||||
final ClassContext parentContext;
|
||||
public final FunctionOrClosureCodegen closure;
|
||||
private boolean thisWasUsed = false;
|
||||
|
||||
HashMap<JetType,Integer> typeInfoConstants;
|
||||
HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors;
|
||||
|
||||
public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext, FunctionOrClosureCodegen closureCodegen) {
|
||||
this.contextType = contextType;
|
||||
@@ -194,4 +200,59 @@ public class ClassContext {
|
||||
}
|
||||
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)
|
||||
// invokeFunctionNoParams(hND, Type.BOOLEAN_TYPE, v);
|
||||
// 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);
|
||||
|
||||
@@ -813,9 +813,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
boolean isStatic = container instanceof NamespaceDescriptorImpl;
|
||||
final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL ;
|
||||
JetExpression r = getReceiverForSelector(expression);
|
||||
final boolean forceInterface = r != null && !(r instanceof JetThisExpression);
|
||||
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 (receiver == StackValue.none()) {
|
||||
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);
|
||||
}
|
||||
|
||||
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();
|
||||
boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl;
|
||||
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 setter;
|
||||
if (forceField) {
|
||||
@@ -926,11 +927,33 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
else {
|
||||
//noinspection ConstantConditions
|
||||
getter = isInsideClass && (propertyDescriptor.getGetter() == null || propertyDescriptor.getGetter().isDefault())
|
||||
? null : typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
if (isInsideClass && (propertyDescriptor.getGetter() == null || propertyDescriptor.getGetter().isDefault())) {
|
||||
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
|
||||
setter = isInsideClass && (propertyDescriptor.getSetter() == null || propertyDescriptor.getSetter().isDefault())
|
||||
? null : typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
if (isInsideClass && (propertyDescriptor.getSetter() == null || propertyDescriptor.getSetter().isDefault())) {
|
||||
setter = null;
|
||||
}
|
||||
else {
|
||||
setter = typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
}
|
||||
}
|
||||
|
||||
String owner;
|
||||
@@ -973,8 +996,21 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
boolean superCall = false;
|
||||
if (expression.getParent() instanceof JetQualifiedExpression) {
|
||||
final JetExpression receiverExpression = ((JetQualifiedExpression) expression.getParent()).getReceiverExpression();
|
||||
if(receiverExpression instanceof JetSuperExpression) {
|
||||
if (receiverExpression instanceof JetSuperExpression) {
|
||||
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);
|
||||
if (descriptor instanceof PropertyDescriptor) {
|
||||
v.load(subjectLocal, subjectType);
|
||||
conditionValue = intermediateValueForProperty((PropertyDescriptor) descriptor, false, false, false);
|
||||
conditionValue = intermediateValueForProperty((PropertyDescriptor) descriptor, false, null);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("unknown simple name resolve result: " + descriptor);
|
||||
|
||||
@@ -122,7 +122,7 @@ public class GenerationState {
|
||||
closure.name = nameAndVisitor.getFirst();
|
||||
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);
|
||||
CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
|
||||
@@ -154,9 +154,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateSyntheticParts() {
|
||||
protected void generateSyntheticParts(HashMap<DeclarationDescriptor, DeclarationDescriptor> accessors) {
|
||||
generateFieldForObjectInstance();
|
||||
generateFieldForClassObject();
|
||||
generateAccessors(accessors);
|
||||
|
||||
try {
|
||||
generatePrimaryConstructor();
|
||||
@@ -168,6 +169,81 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
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() {
|
||||
if (isNonLiteralObject()) {
|
||||
Type type = state.getTypeMapper().jetImplementationType(descriptor);
|
||||
@@ -654,7 +730,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
if(propertyDescriptor.getOutType().isNullable())
|
||||
type = JetTypeMapper.boxType(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.TypeInfoProjection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -19,6 +20,8 @@ import org.objectweb.asm.commons.Method;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
* @author alex.tkachman
|
||||
@@ -319,14 +322,14 @@ public class JetTypeMapper {
|
||||
if (functionParent instanceof NamespaceDescriptor) {
|
||||
assert !superCall;
|
||||
owner = NamespaceCodegen.getJVMClassName(DescriptorRenderer.getFQName(functionParent));
|
||||
invokeOpcode = Opcodes.INVOKESTATIC;
|
||||
invokeOpcode = INVOKESTATIC;
|
||||
thisClass = null;
|
||||
}
|
||||
else if (functionDescriptor instanceof ConstructorDescriptor) {
|
||||
assert !superCall;
|
||||
ClassDescriptor containingClass = (ClassDescriptor) functionParent;
|
||||
owner = jvmName(containingClass, OwnerKind.IMPLEMENTATION);
|
||||
invokeOpcode = Opcodes.INVOKESPECIAL;
|
||||
invokeOpcode = INVOKESPECIAL;
|
||||
thisClass = null;
|
||||
}
|
||||
else if (functionParent instanceof ClassDescriptor) {
|
||||
@@ -486,16 +489,16 @@ public class JetTypeMapper {
|
||||
List<Type> valueParameterTypes = new ArrayList<Type>();
|
||||
final Method method = mapConstructorSignature(descriptor, valueParameterTypes);
|
||||
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) {
|
||||
int flags = 0;
|
||||
if (p.hasModifier(JetTokens.PUBLIC_KEYWORD)) {
|
||||
flags |= Opcodes.ACC_PUBLIC;
|
||||
flags |= ACC_PUBLIC;
|
||||
}
|
||||
else if (p.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
|
||||
flags |= Opcodes.ACC_PRIVATE;
|
||||
flags |= ACC_PRIVATE;
|
||||
}
|
||||
else {
|
||||
flags |= defaultFlags;
|
||||
|
||||
@@ -93,7 +93,7 @@ public class NamespaceCodegen {
|
||||
if (initializer != null && !(initializer instanceof JetConstantExpression)) {
|
||||
final PropertyDescriptor descriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration);
|
||||
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 + ";"));
|
||||
}
|
||||
else {
|
||||
if (getter == null) {
|
||||
v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, owner, name, this.type.getDescriptor());
|
||||
}
|
||||
else {
|
||||
if (getter == null) {
|
||||
v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, owner, name, this.type.getDescriptor());
|
||||
}
|
||||
else {
|
||||
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isSuper ? Opcodes.INVOKESPECIAL : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, getter.getName(), getter.getDescriptor());
|
||||
}
|
||||
}
|
||||
}
|
||||
coerce(type, v);
|
||||
}
|
||||
@@ -658,10 +658,10 @@ public abstract class StackValue {
|
||||
v.visitMethodInsn(Opcodes.INVOKESTATIC, owner + "$$TImpl", setter.getName(), setter.getDescriptor().replace("(","(L" + owner + ";"));
|
||||
}
|
||||
else {
|
||||
if (setter == null) {
|
||||
v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner, name, this.type.getDescriptor());
|
||||
}
|
||||
else {
|
||||
if (setter == null) {
|
||||
v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner, name, this.type.getDescriptor());
|
||||
}
|
||||
else {
|
||||
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");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testEnclosedMethod () {
|
||||
blackBoxFile("/super/enclosed.jet");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user