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:
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user