Refactor mysterious code in ExpressionCodegen

'super' receiver is now generated in visitSuperExpression()
This commit is contained in:
Alexander Udalov
2012-11-02 16:50:46 +04:00
parent 73282c41dc
commit 2edb89b5c5
5 changed files with 151 additions and 40 deletions
@@ -291,14 +291,20 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
@Override
public StackValue visitSuperExpression(JetSuperExpression expression, StackValue data) {
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
if (descriptor instanceof ClassDescriptor) {
return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor, true);
}
else {
JetType type = context.getThisDescriptor().getDefaultType();
return StackValue.local(0, asmType(type));
return StackValue.thisOrOuter(this, getSuperCallLabelTarget(expression), true);
}
private ClassDescriptor getSuperCallLabelTarget(JetSuperExpression expression) {
PsiElement labelPsi = bindingContext.get(BindingContext.LABEL_TARGET, expression.getTargetLabel());
ClassDescriptor labelTarget = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, labelPsi);
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
// "super<descriptor>@labelTarget"
if (labelTarget != null) {
return labelTarget;
}
assert descriptor instanceof ClassDescriptor : "Don't know how to generate super-call to not a class";
ClassDescriptor target = getParentContextSubclassOf((ClassDescriptor) descriptor).getThisDescriptor();
return target;
}
@NotNull
@@ -1738,38 +1744,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
ResolvedCall<? extends CallableDescriptor> resolvedCall
) {
FunctionDescriptor fd = (FunctionDescriptor) resolvedCall.getResultingDescriptor();
boolean superCall = false;
ReceiverValue explicitReceiver = call.getExplicitReceiver();
if (explicitReceiver instanceof ExpressionReceiver) {
final JetExpression receiverExpression = ((ExpressionReceiver) explicitReceiver).getExpression();
if (receiverExpression instanceof JetSuperExpression) {
superCall = true;
receiver = StackValue.thisOrOuter(this, context.getThisDescriptor(), 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 (!isInterface(fd.getContainingDeclaration())) {
if (enclosed == null) {
enclosed = (ClassDescriptor) fd.getContainingDeclaration();
}
if (enclosed != context.getThisDescriptor()) {
CodegenContext c = context;
//noinspection ConstantConditions
while (true) {
if ((c instanceof ClassContext || c instanceof AnonymousClassContext) &&
DescriptorUtils.isSubclass(c.getThisDescriptor(), enclosed)) {
break;
}
c = c.getParentContext();
assert c != null;
}
fd = unwrapFakeOverride(fd);
fd = (FunctionDescriptor) c.getAccessor(fd);
superCall = false;
receiver = StackValue.thisOrOuter(this, enclosed, true);
}
}
}
boolean superCall = isSuperCall(call);
if (superCall && !isInterface(fd.getContainingDeclaration())) {
CodegenContext c = getParentContextSubclassOf((ClassDescriptor) fd.getContainingDeclaration());
fd = (FunctionDescriptor) c.getAccessor(unwrapFakeOverride(fd));
}
fd = accessableFunctionDescriptor(fd);
@@ -1801,6 +1780,35 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
}
}
@Nullable
private static JetSuperExpression getSuperCallExpression(Call call) {
ReceiverValue explicitReceiver = call.getExplicitReceiver();
if (explicitReceiver instanceof ExpressionReceiver) {
JetExpression receiverExpression = ((ExpressionReceiver) explicitReceiver).getExpression();
if (receiverExpression instanceof JetSuperExpression) {
return (JetSuperExpression) receiverExpression;
}
}
return null;
}
private static boolean isSuperCall(Call call) {
return getSuperCallExpression(call) != null;
}
// Find the first parent of the current context which corresponds to a subclass of a given class
private CodegenContext getParentContextSubclassOf(ClassDescriptor descriptor) {
CodegenContext c = context;
while (true) {
if ((c instanceof ClassContext || c instanceof AnonymousClassContext) &&
DescriptorUtils.isSubclass(c.getThisDescriptor(), descriptor)) {
return c;
}
c = c.getParentContext();
assert c != null;
}
}
private StackValue returnValueAsStackValue(FunctionDescriptor fd, Type callReturnType) {
if (callReturnType != Type.VOID_TYPE) {
JetType type = fd.getReturnType();
@@ -2200,7 +2208,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
@Override
public StackValue visitDotQualifiedExpression(JetDotQualifiedExpression expression, StackValue receiver) {
return genQualified(StackValue.none(), expression.getSelectorExpression());
JetExpression receiverExpression = expression.getReceiverExpression();
StackValue receiverValue = receiverExpression instanceof JetSuperExpression ? gen(receiverExpression) : StackValue.none();
return genQualified(receiverValue, expression.getSelectorExpression());
}
@Override
@@ -0,0 +1,38 @@
trait BK {
fun foo(): String
fun bar(): String
}
trait K : BK {
override fun foo() = bar()
}
class A : K {
override fun foo() = "A.foo"
override fun bar() = "A.bar"
class B : K {
override fun foo() = "B.foo"
override fun bar() = "B.bar"
fun test1() = super<K>@A.foo()
fun test2() = super<K>@B.foo()
fun test3() = super<K>.foo()
fun test4() = super@A.foo()
fun test5() = super@B.foo()
fun test6() = super.foo()
}
}
fun box(): String {
val b = A().B()
if (b.test1() != "A.bar") return "test1 ${b.test1()}"
if (b.test2() != "B.bar") return "test2 ${b.test2()}"
if (b.test3() != "B.bar") return "test3 ${b.test3()}"
if (b.test4() != "A.bar") return "test4 ${b.test4()}"
if (b.test5() != "B.bar") return "test5 ${b.test5()}"
if (b.test6() != "B.bar") return "test6 ${b.test6()}"
return "OK"
}
@@ -0,0 +1,38 @@
trait Base {
val foo: String
fun bar(): String
}
abstract class K : Base {
override val foo = bar()
}
class A : K() {
override val foo = "A.foo"
override fun bar() = "A.bar"
class B : K() {
override val foo = "B.foo"
override fun bar() = "B.bar"
fun test1() = super<K>@A.foo
fun test2() = super<K>@B.foo
fun test3() = super<K>.foo
fun test4() = super@A.foo
fun test5() = super@B.foo
fun test6() = super.foo
}
}
fun box(): String {
val b = A().B()
if (b.test1() != "A.bar") return "test1 ${b.test1()}"
if (b.test2() != "B.bar") return "test2 ${b.test2()}"
if (b.test3() != "B.bar") return "test3 ${b.test3()}"
if (b.test4() != "A.bar") return "test4 ${b.test4()}"
if (b.test5() != "B.bar") return "test5 ${b.test5()}"
if (b.test6() != "B.bar") return "test6 ${b.test6()}"
return "OK"
}
@@ -0,0 +1,13 @@
trait T1 {
fun foo() = "O"
}
trait T2 {
fun foo() = "K"
}
class A : T1, T2 {
override fun foo() = super<T1>.foo() + super<T2>.foo()
}
fun box() = A().foo()
@@ -46,6 +46,18 @@ public class SuperGenTest extends CodegenTestCase {
// System.out.println(generateToText());
}
public void testInnerClassLabeledSuper() {
blackBoxFile("super/innerClassLabeledSuper.kt");
}
public void testInnerClassLabeledSuperProperty() {
blackBoxFile("super/innerClassLabeledSuperProperty.kt");
}
public void testMultipleSuperTraits() {
blackBoxFile("super/multipleSuperTraits.kt");
}
public void testEnclosedFun () {
blackBoxFile("/super/enclosedFun.jet");
// System.out.println(generateToText());