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) {
|
public StackValue visitSuperExpression(JetSuperExpression expression, StackValue data) {
|
||||||
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
|
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
|
||||||
if (descriptor instanceof ClassDescriptor) {
|
if (descriptor instanceof ClassDescriptor) {
|
||||||
return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor);
|
return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
JetType type = context.getThisDescriptor().getDefaultType();
|
JetType type = context.getThisDescriptor().getDefaultType();
|
||||||
@@ -1104,7 +1104,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
if (!ignoreThisAndReceiver) {
|
if (!ignoreThisAndReceiver) {
|
||||||
final ClassDescriptor captureThis = closure.getCaptureThis();
|
final ClassDescriptor captureThis = closure.getCaptureThis();
|
||||||
if (captureThis != null) {
|
if (captureThis != null) {
|
||||||
generateThisOrOuter(captureThis).put(OBJECT_TYPE, v);
|
generateThisOrOuter(captureThis, false).put(OBJECT_TYPE, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
final ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
|
final ClassifierDescriptor captureReceiver = closure.getCaptureReceiver();
|
||||||
@@ -1370,14 +1370,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
if (!isStatic) {
|
if (!isStatic) {
|
||||||
if (receiver == StackValue.none()) {
|
if (receiver == StackValue.none()) {
|
||||||
if (resolvedCall == null) {
|
if (resolvedCall == null) {
|
||||||
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
|
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration(), false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (resolvedCall.getThisObject() instanceof ExtensionReceiver) {
|
if (resolvedCall.getThisObject() instanceof ExtensionReceiver) {
|
||||||
receiver = generateReceiver(((ExtensionReceiver) resolvedCall.getThisObject()).getDeclarationDescriptor());
|
receiver = generateReceiver(((ExtensionReceiver) resolvedCall.getThisObject()).getDeclarationDescriptor());
|
||||||
}
|
}
|
||||||
else {
|
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);
|
JvmClassName scriptClassName = classNameForScriptDescriptor(bindingContext, scriptDescriptor);
|
||||||
ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) descriptor;
|
ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) descriptor;
|
||||||
final ClassDescriptor scriptClass = bindingContext.get(CLASS_FOR_FUNCTION, scriptDescriptor);
|
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);
|
script.put(script.type, v);
|
||||||
Type fieldType = typeMapper.mapType(valueParameterDescriptor.getType(), JetTypeMapperMode.VALUE);
|
Type fieldType = typeMapper.mapType(valueParameterDescriptor.getType(), JetTypeMapperMode.VALUE);
|
||||||
return StackValue.field(fieldType, scriptClassName, valueParameterDescriptor.getName().getIdentifier(), false);
|
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();
|
final JetExpression receiverExpression = ((ExpressionReceiver) explicitReceiver).getExpression();
|
||||||
if (receiverExpression instanceof JetSuperExpression) {
|
if (receiverExpression instanceof JetSuperExpression) {
|
||||||
superCall = true;
|
superCall = true;
|
||||||
receiver = StackValue.thisOrOuter(this, context.getThisDescriptor());
|
receiver = StackValue.thisOrOuter(this, context.getThisDescriptor(), true);
|
||||||
JetSuperExpression superExpression = (JetSuperExpression) receiverExpression;
|
JetSuperExpression superExpression = (JetSuperExpression) receiverExpression;
|
||||||
PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel());
|
PsiElement enclosingElement = bindingContext.get(BindingContext.LABEL_TARGET, superExpression.getTargetLabel());
|
||||||
ClassDescriptor enclosed = (ClassDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, enclosingElement);
|
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 = unwrapFakeOverride(fd);
|
||||||
fd = (FunctionDescriptor) c.getAccessor(fd);
|
fd = (FunctionDescriptor) c.getAccessor(fd);
|
||||||
superCall = false;
|
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);
|
StackValue.onStack(exprType).put(type, v);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
StackValue.thisOrOuter(this, classReceiverDeclarationDescriptor).put(type, v);
|
StackValue.thisOrOuter(this, classReceiverDeclarationDescriptor, false).put(type, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (descriptor instanceof ScriptReceiver) {
|
else if (descriptor instanceof ScriptReceiver) {
|
||||||
@@ -1963,7 +1963,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public StackValue generateThisOrOuter(@NotNull final ClassDescriptor calleeContainingClass) {
|
public StackValue generateThisOrOuter(@NotNull final ClassDescriptor calleeContainingClass, boolean isSuper) {
|
||||||
PsiElement psiElement = classDescriptorToDeclaration(bindingContext, calleeContainingClass);
|
PsiElement psiElement = classDescriptorToDeclaration(bindingContext, calleeContainingClass);
|
||||||
boolean isObject = psiElement instanceof JetClassOrObject && isNonLiteralObject((JetClassOrObject) psiElement);
|
boolean isObject = psiElement instanceof JetClassOrObject && isNonLiteralObject((JetClassOrObject) psiElement);
|
||||||
|
|
||||||
@@ -1975,11 +1975,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
cur = cur.getParentContext();
|
cur = cur.getParentContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
assert cur != null;
|
assert cur != null;
|
||||||
final ClassDescriptor thisDescriptor = cur.getThisDescriptor();
|
final ClassDescriptor thisDescriptor = cur.getThisDescriptor();
|
||||||
if (DescriptorUtils.isSubclass(thisDescriptor, calleeContainingClass)) {
|
if (!isSuper && thisDescriptor.equals(calleeContainingClass)
|
||||||
if (!isObject || (thisDescriptor == calleeContainingClass)) {
|
|| isSuper && DescriptorUtils.isSubclass(thisDescriptor, calleeContainingClass)) {
|
||||||
|
if (!isObject || (thisDescriptor.equals(calleeContainingClass))) {
|
||||||
return castToRequiredTypeOfInterfaceIfNeeded(result, thisDescriptor, calleeContainingClass);
|
return castToRequiredTypeOfInterfaceIfNeeded(result, thisDescriptor, calleeContainingClass);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -3105,7 +3105,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
public StackValue visitThisExpression(JetThisExpression expression, StackValue receiver) {
|
public StackValue visitThisExpression(JetThisExpression expression, StackValue receiver) {
|
||||||
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
|
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
|
||||||
if (descriptor instanceof ClassDescriptor) {
|
if (descriptor instanceof ClassDescriptor) {
|
||||||
return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor);
|
return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor, false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (descriptor instanceof CallableDescriptor) {
|
if (descriptor instanceof CallableDescriptor) {
|
||||||
|
|||||||
@@ -959,7 +959,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
FrameMap frameMap = context.prepareFrame(state.getTypeMapper());
|
FrameMap frameMap = context.prepareFrame(state.getTypeMapper());
|
||||||
ExpressionCodegen codegen =
|
ExpressionCodegen codegen =
|
||||||
new ExpressionCodegen(mv, frameMap, jvmSignature.getAsmMethod().getReturnType(), context, state);
|
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();
|
Type[] argTypes = function.getArgumentTypes();
|
||||||
List<Type> originalArgTypes = jvmSignature.getValueParameterTypes();
|
List<Type> originalArgTypes = jvmSignature.getValueParameterTypes();
|
||||||
|
|||||||
@@ -330,8 +330,8 @@ public abstract class StackValue {
|
|||||||
return new Composed(prefix, suffix);
|
return new Composed(prefix, suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static StackValue thisOrOuter(ExpressionCodegen codegen, ClassDescriptor descriptor) {
|
public static StackValue thisOrOuter(ExpressionCodegen codegen, ClassDescriptor descriptor, boolean isSuper) {
|
||||||
return new ThisOuter(codegen, descriptor);
|
return new ThisOuter(codegen, descriptor, isSuper);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static StackValue postIncrement(int index, int increment) {
|
public static StackValue postIncrement(int index, int increment) {
|
||||||
@@ -1151,16 +1151,18 @@ public abstract class StackValue {
|
|||||||
private static class ThisOuter extends StackValue {
|
private static class ThisOuter extends StackValue {
|
||||||
private final ExpressionCodegen codegen;
|
private final ExpressionCodegen codegen;
|
||||||
private final ClassDescriptor descriptor;
|
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);
|
super(OBJECT_TYPE);
|
||||||
this.codegen = codegen;
|
this.codegen = codegen;
|
||||||
this.descriptor = descriptor;
|
this.descriptor = descriptor;
|
||||||
|
this.isSuper = isSuper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void put(Type type, InstructionAdapter v) {
|
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
|
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() {
|
public void testThisInConstructor() {
|
||||||
blackBoxFile("objects/thisInConstructor.kt");
|
blackBoxFile("objects/thisInConstructor.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testFlist() {
|
||||||
|
blackBoxFile("objects/flist.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user