bug with delegation from EA

This commit is contained in:
Alex Tkachman
2012-02-22 13:02:48 +02:00
parent c9c81ed70f
commit 18990e2c1b
6 changed files with 164 additions and 109 deletions
@@ -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));
}
}
}
@@ -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<FunctionDescriptor> 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<? extends CallableMemberDescriptor> 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);
}
}
}
}
}
}
@@ -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());
}
}
}
@@ -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"
}
@@ -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");
}