From 18990e2c1b71f2d055c5dcb30b86ac0120b3a4b5 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Wed, 22 Feb 2012 13:02:48 +0200 Subject: [PATCH] bug with delegation from EA --- .../jet/codegen/FunctionCodegen.java | 40 ++++- .../codegen/ImplementationBodyCodegen.java | 38 +++-- .../jet/codegen/PropertyCodegen.java | 14 ++ .../testData/codegen/classes/delegation2.kt | 24 +++ .../jetbrains/jet/codegen/ClassGenTest.java | 4 + examples/src/guice-kotlin/guice-kotlin.iws | 153 +++++++----------- 6 files changed, 164 insertions(+), 109 deletions(-) create mode 100644 compiler/testData/codegen/classes/delegation2.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index c53d9cfd5fb..90dfd5ae47c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -459,9 +459,47 @@ public class FunctionCodegen { iv.aconst(null); iv.areturn(overriden.getReturnType()); endVisit(mv, "bridge method", state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, functionDescriptor)); - mv.visitEnd(); } } } + public void genDelegate(FunctionDescriptor functionDescriptor, CallableMemberDescriptor overriddenDescriptor, StackValue field) { + JvmMethodSignature jvmMethodSignature = state.getTypeMapper().mapSignature(functionDescriptor.getName(), functionDescriptor); + genDelegate(functionDescriptor, overriddenDescriptor, field, jvmMethodSignature); + } + + public void genDelegate(CallableMemberDescriptor functionDescriptor, CallableMemberDescriptor overriddenDescriptor, StackValue field, JvmMethodSignature jvmMethodSignature) { + Method method = jvmMethodSignature.getAsmMethod(); + int flags = ACC_PUBLIC | ACC_SYNTHETIC; // TODO. + + final MethodVisitor mv = v.newMethod(null, flags, method.getName(), method.getDescriptor(), null, null); + if (v.generateCode()) { + mv.visitCode(); + + Type[] argTypes = method.getArgumentTypes(); + 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); + if(argType.getSort() == Type.OBJECT) { + StackValue.onStack(JetTypeMapper.TYPE_OBJECT).put(method.getArgumentTypes()[i], iv); + } + + //noinspection AssignmentToForLoopParameter + reg += argType.getSize(); + } + + iv.load(0, JetTypeMapper.TYPE_OBJECT); + field.put(field.type, iv); + ClassDescriptor classDescriptor = (ClassDescriptor) overriddenDescriptor.getContainingDeclaration(); + String internalName = state.getTypeMapper().mapType(classDescriptor.getDefaultType()).getInternalName(); + if(classDescriptor.getKind() == ClassKind.TRAIT) + iv.invokeinterface(internalName, method.getName(), method.getDescriptor()); + else + iv.invokevirtual(internalName, method.getName(), method.getDescriptor()); + iv.areturn(method.getReturnType()); + endVisit(mv, "delegate method", state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, functionDescriptor)); + } + } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index f485711eb6b..25d4cc0ddac 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -567,17 +567,18 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference()); assert superType != null; ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); - String delegateField = "$delegate_" + n; - Type fieldType = typeMapper.mapType(superClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION); + String delegateField = "$delegate_" + (n++); + Type fieldType = typeMapper.mapType(superClassDescriptor.getDefaultType()); String fieldDesc = fieldType.getDescriptor(); v.newField(specifier, ACC_PRIVATE, delegateField, fieldDesc, /*TODO*/null, null); - iv.putfield(classname, delegateField, fieldDesc); + StackValue field = StackValue.field(fieldType, classname, delegateField, false); + field.store(iv); JetClass superClass = (JetClass) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor); final CodegenContext delegateContext = context.intoClass(superClassDescriptor, new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false), - typeMapper.mapType(superClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName()), state.getTypeMapper()); - generateDelegates(superClass, delegateContext, overridden); + typeMapper.mapType(superClassDescriptor.getDefaultType()).getInternalName()), state.getTypeMapper()); + generateDelegates(superClass, delegateContext, field); } } @@ -657,7 +658,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } - private void generateDelegationToTraitImpl(ExpressionCodegen codegen, @NotNull FunctionDescriptor fun) { + private void generateDelegationToTraitImpl(ExpressionCodegen codegen, FunctionDescriptor fun) { DeclarationDescriptor containingDeclaration = fun.getContainingDeclaration(); if(containingDeclaration instanceof ClassDescriptor) { ClassDescriptor declaration = (ClassDescriptor) containingDeclaration; @@ -902,17 +903,26 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } - protected void generateDelegates(JetClass toClass, CodegenContext delegateContext, Set overriden) { + protected void generateDelegates(JetClass toClass, CodegenContext delegateContext, StackValue field) { final FunctionCodegen functionCodegen = new FunctionCodegen(delegateContext, v, state); final PropertyCodegen propertyCodegen = new PropertyCodegen(delegateContext, v, functionCodegen, state); - for (JetDeclaration declaration : toClass.getDeclarations()) { - if (declaration instanceof JetProperty) { - propertyCodegen.gen((JetProperty) declaration); - } - else if (declaration instanceof JetNamedFunction) { - if (!overriden.contains(bindingContext.get(BindingContext.FUNCTION, declaration))) { - functionCodegen.gen((JetNamedFunction) declaration); + ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, toClass); + for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) { + if (declaration instanceof CallableMemberDescriptor) { + CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) declaration; + if (callableMemberDescriptor.getKind() == CallableMemberDescriptor.Kind.DELEGATION) { + Set overriddenDescriptors = callableMemberDescriptor.getOverriddenDescriptors(); + for (CallableMemberDescriptor overriddenDescriptor : overriddenDescriptors) { + if(overriddenDescriptor.getContainingDeclaration() == classDescriptor) { + if (declaration instanceof PropertyDescriptor) { + propertyCodegen.genDelegate((PropertyDescriptor) declaration, (PropertyDescriptor) overriddenDescriptor, field); + } + else if (declaration instanceof NamedFunctionDescriptor) { + functionCodegen.genDelegate((NamedFunctionDescriptor) declaration, overriddenDescriptor, field); + } + } + } } } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java index a80dd9998d9..4d7e484b410 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PropertyCodegen.java @@ -30,6 +30,10 @@ import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.commons.InstructionAdapter; +import org.objectweb.asm.commons.Method; + +import static org.objectweb.asm.Opcodes.ACC_PUBLIC; +import static org.objectweb.asm.Opcodes.ACC_SYNTHETIC; /** * @author max @@ -271,4 +275,14 @@ public class PropertyCodegen { public static String setterName(String propertyName) { return JvmAbi.SETTER_PREFIX + StringUtil.capitalizeWithJavaBeanConvention(propertyName); } + + public void genDelegate(PropertyDescriptor declaration, PropertyDescriptor overriddenDescriptor, StackValue field) { + JvmPropertyAccessorSignature jvmPropertyAccessorSignature = state.getTypeMapper().mapGetterSignature(declaration, OwnerKind.IMPLEMENTATION); + functionCodegen.genDelegate(declaration, overriddenDescriptor, field, jvmPropertyAccessorSignature.getJvmMethodSignature()); + + if(declaration.isVar()) { + jvmPropertyAccessorSignature = state.getTypeMapper().mapSetterSignature(declaration, OwnerKind.IMPLEMENTATION); + functionCodegen.genDelegate(declaration, overriddenDescriptor, field, jvmPropertyAccessorSignature.getJvmMethodSignature()); + } + } } diff --git a/compiler/testData/codegen/classes/delegation2.kt b/compiler/testData/codegen/classes/delegation2.kt new file mode 100644 index 00000000000..30a154ff2ec --- /dev/null +++ b/compiler/testData/codegen/classes/delegation2.kt @@ -0,0 +1,24 @@ +trait Trait1 { + fun foo() : String +} + +trait Trait2 { + fun bar() : String +} + +class T1 : Trait1{ + override fun foo() = "aaa" +} + +class T2 : Trait2{ + override fun bar() = "bbb" +} + +class C(a:Trait1, b:Trait2) : Trait1 by a, Trait2 by b + +fun box() : String { + val c = C(T1(),T2()) + if(c.foo() != "aaa") return "fail" + if(c.bar() != "bbb") return "fail" + return "OK" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java index bb20d5b8069..d48048b0900 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -47,6 +47,10 @@ public class ClassGenTest extends CodegenTestCase { blackBoxFile("classes/inheritance.jet"); } + public void testInheritanceAndDelegation2() throws Exception { + blackBoxFile("classes/delegation2.kt"); + } + public void testFunDelegation() throws Exception { blackBoxFile("classes/funDelegation.jet"); } diff --git a/examples/src/guice-kotlin/guice-kotlin.iws b/examples/src/guice-kotlin/guice-kotlin.iws index 7803ff96873..f54737e4561 100644 --- a/examples/src/guice-kotlin/guice-kotlin.iws +++ b/examples/src/guice-kotlin/guice-kotlin.iws @@ -58,28 +58,19 @@ - + - + - - + + - - - - - - - - - - + @@ -130,10 +121,10 @@ - + - + @@ -167,10 +158,9 @@ - @@ -203,16 +193,6 @@ - - - - - - - - @@ -237,6 +217,16 @@ + + + + + + + + @@ -506,7 +496,7 @@ - + @@ -515,22 +505,23 @@ - + - - + - + - + + + @@ -590,112 +581,86 @@ - - - - - - - - - - - - - - - + - - - + - - - + - - - + - - - - - - - - - - + - - - + + + + + + + + + + + - - - + - - - + - - - + - - - + + + + + + - + + + + + + - - - - - - - - +