fixed bug with compilation of this/outer. no need to check context hierarchy for superclasses except case of super call.

This commit is contained in:
Alex Tkachman
2012-08-31 17:41:28 +03:00
parent c5711cccda
commit a54776196a
5 changed files with 77 additions and 18 deletions
@@ -279,7 +279,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
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);
return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor, true);
}
else {
JetType type = context.getThisDescriptor().getDefaultType();
@@ -1104,7 +1104,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
if (!ignoreThisAndReceiver) {
final ClassDescriptor captureThis = closure.getCaptureThis();
if (captureThis != null) {
generateThisOrOuter(captureThis).put(OBJECT_TYPE, v);
generateThisOrOuter(captureThis, false).put(OBJECT_TYPE, v);
}
final ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
@@ -1370,14 +1370,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
if (!isStatic) {
if (receiver == StackValue.none()) {
if (resolvedCall == null) {
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration(), false);
}
else {
if (resolvedCall.getThisObject() instanceof ExtensionReceiver) {
receiver = generateReceiver(((ExtensionReceiver) resolvedCall.getThisObject()).getDeclarationDescriptor());
}
else {
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration(), false);
}
}
}
@@ -1448,7 +1448,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
JvmClassName scriptClassName = classNameForScriptDescriptor(bindingContext, scriptDescriptor);
ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) descriptor;
final ClassDescriptor scriptClass = bindingContext.get(CLASS_FOR_FUNCTION, scriptDescriptor);
final StackValue script = StackValue.thisOrOuter(this, scriptClass);
final StackValue script = StackValue.thisOrOuter(this, scriptClass, false);
script.put(script.type, v);
Type fieldType = typeMapper.mapType(valueParameterDescriptor.getType(), JetTypeMapperMode.VALUE);
return StackValue.field(fieldType, scriptClassName, valueParameterDescriptor.getName().getIdentifier(), false);
@@ -1687,7 +1687,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
final JetExpression receiverExpression = ((ExpressionReceiver) explicitReceiver).getExpression();
if (receiverExpression instanceof JetSuperExpression) {
superCall = true;
receiver = StackValue.thisOrOuter(this, context.getThisDescriptor());
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);
@@ -1706,7 +1706,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
fd = unwrapFakeOverride(fd);
fd = (FunctionDescriptor) c.getAccessor(fd);
superCall = false;
receiver = StackValue.thisOrOuter(this, enclosed);
receiver = StackValue.thisOrOuter(this, enclosed, true);
}
}
}
@@ -1877,7 +1877,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
StackValue.onStack(exprType).put(type, v);
}
else {
StackValue.thisOrOuter(this, classReceiverDeclarationDescriptor).put(type, v);
StackValue.thisOrOuter(this, classReceiverDeclarationDescriptor, false).put(type, v);
}
}
else if (descriptor instanceof ScriptReceiver) {
@@ -1963,7 +1963,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
throw new UnsupportedOperationException();
}
public StackValue generateThisOrOuter(@NotNull final ClassDescriptor calleeContainingClass) {
public StackValue generateThisOrOuter(@NotNull final ClassDescriptor calleeContainingClass, boolean isSuper) {
PsiElement psiElement = classDescriptorToDeclaration(bindingContext, calleeContainingClass);
boolean isObject = psiElement instanceof JetClassOrObject && isNonLiteralObject((JetClassOrObject) psiElement);
@@ -1975,11 +1975,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
cur = cur.getParentContext();
}
assert cur != null;
final ClassDescriptor thisDescriptor = cur.getThisDescriptor();
if (DescriptorUtils.isSubclass(thisDescriptor, calleeContainingClass)) {
if (!isObject || (thisDescriptor == calleeContainingClass)) {
if (!isSuper && thisDescriptor.equals(calleeContainingClass)
|| isSuper && DescriptorUtils.isSubclass(thisDescriptor, calleeContainingClass)) {
if (!isObject || (thisDescriptor.equals(calleeContainingClass))) {
return castToRequiredTypeOfInterfaceIfNeeded(result, thisDescriptor, calleeContainingClass);
}
else {
@@ -3105,7 +3105,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
public StackValue visitThisExpression(JetThisExpression expression, StackValue receiver) {
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
if (descriptor instanceof ClassDescriptor) {
return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor);
return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor, false);
}
else {
if (descriptor instanceof CallableDescriptor) {
@@ -959,7 +959,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
FrameMap frameMap = context.prepareFrame(state.getTypeMapper());
ExpressionCodegen codegen =
new ExpressionCodegen(mv, frameMap, jvmSignature.getAsmMethod().getReturnType(), context, state);
codegen.generateThisOrOuter(descriptor); // ??? wouldn't it be addClosureToConstructorParameters good idea to put it?
codegen.generateThisOrOuter(descriptor, false); // ??? wouldn't it be addClosureToConstructorParameters good idea to put it?
Type[] argTypes = function.getArgumentTypes();
List<Type> originalArgTypes = jvmSignature.getValueParameterTypes();
@@ -330,8 +330,8 @@ public abstract class StackValue {
return new Composed(prefix, suffix);
}
public static StackValue thisOrOuter(ExpressionCodegen codegen, ClassDescriptor descriptor) {
return new ThisOuter(codegen, descriptor);
public static StackValue thisOrOuter(ExpressionCodegen codegen, ClassDescriptor descriptor, boolean isSuper) {
return new ThisOuter(codegen, descriptor, isSuper);
}
public static StackValue postIncrement(int index, int increment) {
@@ -1151,16 +1151,18 @@ public abstract class StackValue {
private static class ThisOuter extends StackValue {
private final ExpressionCodegen codegen;
private final ClassDescriptor descriptor;
private final boolean isSuper;
public ThisOuter(ExpressionCodegen codegen, ClassDescriptor descriptor) {
public ThisOuter(ExpressionCodegen codegen, ClassDescriptor descriptor, boolean isSuper) {
super(OBJECT_TYPE);
this.codegen = codegen;
this.descriptor = descriptor;
this.isSuper = isSuper;
}
@Override
public void put(Type type, InstructionAdapter v) {
final StackValue stackValue = codegen.generateThisOrOuter(descriptor);
final StackValue stackValue = codegen.generateThisOrOuter(descriptor, isSuper);
stackValue.put(stackValue.type, v); // no coercion here
}
}
@@ -0,0 +1,53 @@
public abstract class FList<T>() {
public abstract val head: T
public abstract val tail: FList<T>
public abstract val empty: Boolean
class object {
val emptyFList = object: FList<Any>() {
public override val head: Any
get() = throw UnsupportedOperationException();
public override val tail: FList<Any>
get() = this
public override val empty: Boolean
get() = true
}
}
public fun plus(head: T): FList<T> = object : FList<T>() {
override public val head: T
get() = head
override public val empty: Boolean
get() = false
override public val tail: FList<T>
get() = this@FList
}
}
public fun <T> emptyFList(): FList<T> = FList.emptyFList as FList<T>
public fun <T> FList<T>.reverse(where: FList<T> = emptyFList<T>()) : FList<T> =
if(empty) where else tail.reverse(where + head)
public fun <T> FList<T>.iterator(): Iterator<T> = object: Iterator<T> {
private var cur: FList<T> = this@iterator
override public fun next(): T {
val res = cur.head
cur = cur.tail
return res
}
override public fun hasNext(): Boolean = !cur.empty
}
fun box() : String {
var r = ""
for(s in (emptyFList<String>() + "O" + "K").reverse()) {
r += s
}
return r
}
@@ -91,4 +91,8 @@ public class ObjectGenTest extends CodegenTestCase {
public void testThisInConstructor() {
blackBoxFile("objects/thisInConstructor.kt");
}
public void testFlist() {
blackBoxFile("objects/flist.kt");
}
}