Proper this for closure classes

This commit is contained in:
Maxim Shafirov
2011-07-05 22:09:23 +04:00
parent da5d3e80c2
commit c1e2849e17
3 changed files with 35 additions and 30 deletions
@@ -14,15 +14,17 @@ public class ClassContext {
public static final ClassContext STATIC = new ClassContext(null, OwnerKind.NAMESPACE, null, null); public static final ClassContext STATIC = new ClassContext(null, OwnerKind.NAMESPACE, null, null);
private final DeclarationDescriptor contextType; private final DeclarationDescriptor contextType;
private final OwnerKind contextKind; private final OwnerKind contextKind;
private final StackValue thisExpression;
private final ClassContext parentContext; private final ClassContext parentContext;
public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext) { public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext) {
this.contextType = contextType; this.contextType = contextType;
this.contextKind = contextKind; this.contextKind = contextKind;
this.thisExpression = thisExpression;
this.parentContext = parentContext; this.parentContext = parentContext;
} }
public DeclarationDescriptor getContextType() { public DeclarationDescriptor getContextDescriptor() {
return contextType; return contextType;
} }
@@ -31,20 +33,8 @@ public class ClassContext {
} }
public StackValue getThisExpression() { public StackValue getThisExpression() {
int thisIdx = -1; if (thisExpression != null) return thisExpression;
if (getContextKind() != OwnerKind.NAMESPACE) { return parentContext != null ? parentContext.getThisExpression() : null;
thisIdx++;
}
if (hasReceiver()) {
thisIdx++;
}
if (thisIdx == -1) {
throw new RuntimeException("Has no this!" + contextType);
}
return StackValue.local(thisIdx, JetTypeMapper.TYPE_OBJECT);
} }
public ClassContext intoNamespace(NamespaceDescriptor descriptor) { public ClassContext intoNamespace(NamespaceDescriptor descriptor) {
@@ -61,15 +51,30 @@ public class ClassContext {
else { else {
thisValue = StackValue.local(0, JetTypeMapper.TYPE_OBJECT); thisValue = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
} }
return new ClassContext(descriptor, kind, thisValue, this); return new ClassContext(descriptor, kind, thisValue, this);
} }
public ClassContext intoFunction(FunctionDescriptor descriptor) { public ClassContext intoFunction(FunctionDescriptor descriptor) {
return new ClassContext(descriptor, getContextKind(), StackValue.local(0, JetTypeMapper.TYPE_OBJECT), this); int thisIdx = -1;
if (getContextKind() != OwnerKind.NAMESPACE) {
thisIdx++;
}
final boolean hasReceiver = descriptor.getReceiverType() != null;
if (hasReceiver) {
thisIdx++;
}
return new ClassContext(descriptor, getContextKind(), hasReceiver ? StackValue.local(thisIdx, JetTypeMapper.TYPE_OBJECT) : null, this);
} }
public ClassContext intoClosure() { public ClassContext intoClosure(String internalClassName) {
return new ClassContext(null, OwnerKind.IMPLEMENTATION, StackValue.local(0, JetTypeMapper.TYPE_OBJECT), this); // TODO! final DeclarationDescriptor contextDescriptor = getContextClass();
StackValue outerClass = contextDescriptor instanceof ClassDescriptor
? StackValue.instanceField(JetTypeMapper.jetImplementationType((ClassDescriptor) contextDescriptor), internalClassName, "this$0")
: StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
return new ClassContext(null, OwnerKind.IMPLEMENTATION, outerClass, this);
} }
public FrameMap prepareFrame() { public FrameMap prepareFrame() {
@@ -100,13 +105,18 @@ public class ClassContext {
public Type jvmType(JetTypeMapper mapper) { public Type jvmType(JetTypeMapper mapper) {
if (contextType instanceof ClassDescriptor) { if (contextType instanceof ClassDescriptor) {
if (contextKind == OwnerKind.INTERFACE) {
System.out.println("OOps?!");
}
return mapper.jvmType((ClassDescriptor) contextType, contextKind); return mapper.jvmType((ClassDescriptor) contextType, contextKind);
} }
else { else {
return JetTypeMapper.TYPE_OBJECT; // TODO? return JetTypeMapper.TYPE_OBJECT; // TODO?
} }
} }
public DeclarationDescriptor getContextClass() {
DeclarationDescriptor descriptor = getContextDescriptor();
if (descriptor == null || descriptor instanceof ClassDescriptor || descriptor instanceof NamespaceDescriptor) return descriptor;
final ClassContext parent = getParentContext();
return parent != null ? parent.getContextClass() : null;
}
} }
@@ -36,7 +36,7 @@ public class ClosureCodegen {
public ClosureCodegen(GenerationState state, ExpressionCodegen exprContext, ClassContext context) { public ClosureCodegen(GenerationState state, ExpressionCodegen exprContext, ClassContext context) {
this.state = state; this.state = state;
this.exprContext = exprContext; this.exprContext = exprContext;
this.context = context.intoClosure(); this.context = context;
} }
public static Method erasedInvokeSignature(FunctionDescriptor fd) { public static Method erasedInvokeSignature(FunctionDescriptor fd) {
@@ -125,7 +125,7 @@ public class ClosureCodegen {
} }
private void generateBody(FunctionDescriptor funDescriptor, ClassVisitor cv, JetFunctionLiteral body) { private void generateBody(FunctionDescriptor funDescriptor, ClassVisitor cv, JetFunctionLiteral body) {
FunctionCodegen fc = new FunctionCodegen(context, cv, state); FunctionCodegen fc = new FunctionCodegen(context.intoClosure(name), cv, state);
fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor); fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor);
} }
@@ -311,12 +311,7 @@ public class ExpressionCodegen extends JetVisitor {
} }
private DeclarationDescriptor contextType() { private DeclarationDescriptor contextType() {
DeclarationDescriptor descriptor = context.getContextType(); return context.getContextClass();
while (descriptor != null) {
if (descriptor instanceof ClassDescriptor || descriptor instanceof NamespaceDescriptor) return descriptor;
descriptor = descriptor.getContainingDeclaration();
}
return descriptor;
} }
private OwnerKind contextKind() { private OwnerKind contextKind() {
@@ -923,7 +918,7 @@ public class ExpressionCodegen extends JetVisitor {
ClassContext parentContext = cur.getParentContext(); ClassContext parentContext = cur.getParentContext();
if (parentContext == null) break; if (parentContext == null) break;
final DeclarationDescriptor curContextType = cur.getContextType(); final DeclarationDescriptor curContextType = cur.getContextDescriptor();
if (curContextType instanceof ClassDescriptor) { if (curContextType instanceof ClassDescriptor) {
if (isSubclass((ClassDescriptor) curContextType, calleeContainingClass)) break; if (isSubclass((ClassDescriptor) curContextType, calleeContainingClass)) break;