diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java index 7a9ff954f9c3ecb4bf9636f73ceee5a92431b4ef..d16da2e54b1642af07902f8dbcf208b664c995cc 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java @@ -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 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 accessors) { } private void generateClassBody() { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java index 434fa8cf5f2e70430c8e4f198b8d0ed1cd7d11a0..ef3c7bfc6fd90c035e20c4814f26f74843e314c6 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java @@ -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 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); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassContext.java index 34b0c6062b69b2c6e6a72e839e968eabb0f178ab..74e12a5228e2c0cfd26dac93e141c21c1f7f4d92 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassContext.java @@ -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 typeInfoConstants; + HashMap 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(); + } + descriptor = descriptor.getOriginal(); + DeclarationDescriptor accessor = accessors.get(descriptor); + if(accessor != null) + return accessor; + + if(descriptor instanceof FunctionDescriptor) { + FunctionDescriptorImpl myAccessor = new FunctionDescriptorImpl(contextType, + Collections.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.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.emptyList(), myAccessor.getModality(), + myAccessor.getVisibility(), + myAccessor.getOutType(), false, false); + PropertySetterDescriptor psd = new PropertySetterDescriptor( + myAccessor.getModality(), + myAccessor.getVisibility(), + myAccessor, + Collections.emptyList(), + false, false); + myAccessor.initialize(Collections.emptyList(), pgd, psd); + accessor = myAccessor; + } + else { + throw new UnsupportedOperationException(); + } + accessors.put(descriptor, accessor); + return accessor; + } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index a22ee10ccade61310e749edf98dcc9d79f8100cd..e1417c28c82e7eaf75953c6a31670f8de9049fb5 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -302,7 +302,7 @@ public class ExpressionCodegen extends JetVisitor { // 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 { 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.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 { } 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 { 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 { 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); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java index 5c50f0bcf7bb2eaf714a87f10f8da785782dd4eb..a517e32fe52d90593bba160533db4d022d9f45f9 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java @@ -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); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 246ec23a07a3c58931626736bd3192e1b3ec74a4..3b49f22f6433af5c03e7e86fd66e642bb7560f8b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -154,9 +154,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } @Override - protected void generateSyntheticParts() { + protected void generateSyntheticParts(HashMap accessors) { generateFieldForObjectInstance(); generateFieldForClassObject(); + generateAccessors(accessors); try { generatePrimaryConstructor(); @@ -168,6 +169,81 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { generateGetTypeInfo(); } + private void generateAccessors(HashMap accessors) { + if(accessors != null) { + for (Map.Entry 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); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index e889f3b0323eb87e95d94368c36cb0ddadcb7d43..992181a0ca7dd0874d7b0c050f16daf3f836edf5 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -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 valueParameterTypes = new ArrayList(); 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; diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index f31a07fa7257796da27cb74904226312b39a3c50..f0ea12f8ae3ea51696142112d56fcc060b206904 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -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)); } } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index 88badb3e2b8df2299bc04c4e468f1e00d7bc5dd2..402aee6463e164eae133de93ffed1636355a1b40 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -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()); } } diff --git a/compiler/testData/codegen/super/enclosed.jet b/compiler/testData/codegen/super/enclosed.jet new file mode 100644 index 0000000000000000000000000000000000000000..705e0b602c2a1dae23408a8c1218b814cc4b5fbc --- /dev/null +++ b/compiler/testData/codegen/super/enclosed.jet @@ -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@N.x() + fun test3() = super@N.x() + fun test4() = super.x() + fun test5() = y + fun test6() : Int { + super@N.y += 200 + return super@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"; +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/SuperGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/SuperGenTest.java index 45bf1a6c19b5db559f75e2c48534f552c76d99b2..86bbd2b935edd666eded06e1b98f4aaa5d949f2e 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/SuperGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/SuperGenTest.java @@ -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()); + } }