Finally, green tests
This commit is contained in:
@@ -9,20 +9,23 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
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, null);
|
||||
private final DeclarationDescriptor contextType;
|
||||
private final OwnerKind contextKind;
|
||||
private final StackValue thisExpression;
|
||||
private final ClassContext parentContext;
|
||||
private final ClosureCodegen closure;
|
||||
private boolean thisWasUsed = false;
|
||||
|
||||
public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext) {
|
||||
public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext, ClosureCodegen closureCodegen) {
|
||||
this.contextType = contextType;
|
||||
this.contextKind = contextKind;
|
||||
this.thisExpression = thisExpression;
|
||||
this.parentContext = parentContext;
|
||||
closure = closureCodegen;
|
||||
}
|
||||
|
||||
public DeclarationDescriptor getContextDescriptor() {
|
||||
@@ -34,13 +37,15 @@ public class ClassContext {
|
||||
}
|
||||
|
||||
public StackValue getThisExpression() {
|
||||
if (parentContext == null) return null;
|
||||
|
||||
thisWasUsed = true;
|
||||
if (thisExpression != null) return thisExpression;
|
||||
return parentContext != null ? parentContext.getThisExpression() : null;
|
||||
return parentContext.getThisExpression();
|
||||
}
|
||||
|
||||
public ClassContext intoNamespace(NamespaceDescriptor descriptor) {
|
||||
return new ClassContext(descriptor, OwnerKind.NAMESPACE, null, this);
|
||||
return new ClassContext(descriptor, OwnerKind.NAMESPACE, null, this, null);
|
||||
}
|
||||
|
||||
public ClassContext intoClass(ClassDescriptor descriptor, OwnerKind kind) {
|
||||
@@ -54,7 +59,7 @@ public class ClassContext {
|
||||
thisValue = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
|
||||
}
|
||||
|
||||
return new ClassContext(descriptor, kind, thisValue, this);
|
||||
return new ClassContext(descriptor, kind, thisValue, this, null);
|
||||
}
|
||||
|
||||
public ClassContext intoFunction(FunctionDescriptor descriptor) {
|
||||
@@ -68,15 +73,15 @@ public class ClassContext {
|
||||
thisIdx++;
|
||||
}
|
||||
|
||||
return new ClassContext(descriptor, getContextKind(), hasReceiver ? StackValue.local(thisIdx, JetTypeMapper.TYPE_OBJECT) : null, this);
|
||||
return new ClassContext(descriptor, getContextKind(), hasReceiver ? StackValue.local(thisIdx, JetTypeMapper.TYPE_OBJECT) : null, this, null);
|
||||
}
|
||||
|
||||
public ClassContext intoClosure(String internalClassName) {
|
||||
final DeclarationDescriptor contextDescriptor = getContextClass();
|
||||
StackValue outerClass = contextDescriptor instanceof ClassDescriptor
|
||||
? StackValue.instanceField(JetTypeMapper.jetInterfaceType((ClassDescriptor) contextDescriptor), internalClassName, "this$0")
|
||||
public ClassContext intoClosure(String internalClassName, ClosureCodegen closureCodegen) {
|
||||
final Type type = enclosingClassType(closureCodegen.state.getTypeMapper());
|
||||
StackValue outerClass = type != null
|
||||
? StackValue.instanceField(type, internalClassName, "this$0")
|
||||
: StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
|
||||
return new ClassContext(null, OwnerKind.IMPLEMENTATION, outerClass, this);
|
||||
return new ClassContext(null, OwnerKind.IMPLEMENTATION, outerClass, this, closureCodegen);
|
||||
}
|
||||
|
||||
public FrameMap prepareFrame() {
|
||||
@@ -109,6 +114,9 @@ public class ClassContext {
|
||||
if (contextType instanceof ClassDescriptor) {
|
||||
return mapper.jvmType((ClassDescriptor) contextType, contextKind);
|
||||
}
|
||||
else if (closure != null) {
|
||||
return Type.getObjectType(closure.name);
|
||||
}
|
||||
else {
|
||||
return parentContext != null ? parentContext.jvmType(mapper) : JetTypeMapper.TYPE_OBJECT;
|
||||
}
|
||||
@@ -125,4 +133,35 @@ public class ClassContext {
|
||||
public boolean isThisWasUsed() {
|
||||
return thisWasUsed;
|
||||
}
|
||||
|
||||
public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v) {
|
||||
final ClosureCodegen top = closure;
|
||||
if (top != null) {
|
||||
final StackValue answer = top.lookupInContext(d);
|
||||
if (answer != null) return answer;
|
||||
|
||||
final StackValue thisContext = getThisExpression();
|
||||
thisContext.put(thisContext.type, v);
|
||||
}
|
||||
|
||||
return parentContext != null ? parentContext.lookupInContext(d, v) : null;
|
||||
}
|
||||
|
||||
public Type enclosingClassType(JetTypeMapper mapper) {
|
||||
DeclarationDescriptor descriptor = getContextDescriptor();
|
||||
if (descriptor instanceof ClassDescriptor) {
|
||||
return Type.getObjectType(mapper.jvmName((ClassDescriptor) descriptor, OwnerKind.INTERFACE));
|
||||
}
|
||||
|
||||
if (descriptor instanceof NamespaceDescriptor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (closure != null) {
|
||||
return Type.getObjectType(closure.name);
|
||||
}
|
||||
|
||||
final ClassContext parent = getParentContext();
|
||||
return parent != null ? parent.enclosingClassType(mapper) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteral;
|
||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
@@ -22,11 +25,11 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ClosureCodegen {
|
||||
private final GenerationState state;
|
||||
public final GenerationState state;
|
||||
private final ExpressionCodegen exprContext;
|
||||
private final ClassContext context;
|
||||
private ClassVisitor cv = null;
|
||||
private String name = null;
|
||||
public String name = null;
|
||||
|
||||
private Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = new LinkedHashMap<DeclarationDescriptor, EnclosedValueDescriptor>();
|
||||
|
||||
@@ -107,12 +110,14 @@ public class ClosureCodegen {
|
||||
|
||||
|
||||
generateBridge(name, funDescriptor, cv);
|
||||
final boolean captureThis = generateBody(funDescriptor, cv, fun.getFunctionLiteral());
|
||||
boolean captureThis = generateBody(funDescriptor, cv, fun.getFunctionLiteral());
|
||||
final Type enclosingType = context.enclosingClassType(state.getTypeMapper());
|
||||
if (enclosingType == null) captureThis = false;
|
||||
|
||||
final Method constructor = generateConstructor(funClass, captureThis);
|
||||
|
||||
if (captureThis) {
|
||||
cv.visitField(Opcodes.ACC_PRIVATE, "this$0", enclosingClassType().getDescriptor(), null, null);
|
||||
cv.visitField(Opcodes.ACC_PRIVATE, "this$0", enclosingType.getDescriptor(), null, null);
|
||||
}
|
||||
|
||||
cv.visitEnd();
|
||||
@@ -125,12 +130,8 @@ public class ClosureCodegen {
|
||||
return answer;
|
||||
}
|
||||
|
||||
private Type enclosingClassType() {
|
||||
return Type.getObjectType(state.getTypeMapper().jvmName((ClassDescriptor) context.getContextClass(), OwnerKind.INTERFACE));
|
||||
}
|
||||
|
||||
private boolean generateBody(FunctionDescriptor funDescriptor, ClassVisitor cv, JetFunctionLiteral body) {
|
||||
final ClassContext closureContext = context.intoClosure(name);
|
||||
final ClassContext closureContext = context.intoClosure(name, this);
|
||||
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
|
||||
fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor);
|
||||
return closureContext.isThisWasUsed();
|
||||
@@ -184,7 +185,7 @@ public class ClosureCodegen {
|
||||
int i = 0;
|
||||
if (captureThis) {
|
||||
i = 1;
|
||||
argTypes[0] = enclosingClassType();
|
||||
argTypes[0] = context.enclosingClassType(state.getTypeMapper());
|
||||
}
|
||||
|
||||
for (DeclarationDescriptor descriptor : closure.keySet()) {
|
||||
|
||||
@@ -501,7 +501,7 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
generateBlock(expression.getFunctionLiteral().getBodyExpression().getStatements());
|
||||
}
|
||||
else {
|
||||
final GeneratedAnonymousClassDescriptor closure = state.generateClosure(expression, this, context);
|
||||
final GeneratedAnonymousClassDescriptor closure = new ClosureCodegen(state, this, context).gen(expression);
|
||||
|
||||
v.anew(Type.getObjectType(closure.getClassname()));
|
||||
v.dup();
|
||||
@@ -668,12 +668,13 @@ public class ExpressionCodegen extends JetVisitor {
|
||||
}
|
||||
}
|
||||
else {
|
||||
final StackValue value = state.lookupInContext(descriptor);
|
||||
// receiver
|
||||
StackValue.local(0, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, v);
|
||||
|
||||
final StackValue value = context.lookupInContext(descriptor, v);
|
||||
if (value == null) {
|
||||
throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
|
||||
}
|
||||
// receiver
|
||||
StackValue.local(0, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, v);
|
||||
myStack.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import com.intellij.util.containers.Stack;
|
||||
import org.jetbrains.jet.lang.ErrorHandler;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -23,7 +22,6 @@ public class GenerationState {
|
||||
|
||||
private JetTypeMapper typeMapper;
|
||||
private final Stack<BindingContext> bindingContexts = new Stack<BindingContext>();
|
||||
private final Stack<ClosureCodegen> closureContexts = new Stack<ClosureCodegen>();
|
||||
private final JetStandardLibrary standardLibrary;
|
||||
|
||||
public GenerationState(Project project, boolean text) {
|
||||
@@ -94,18 +92,6 @@ public class GenerationState {
|
||||
}
|
||||
}
|
||||
|
||||
public GeneratedAnonymousClassDescriptor generateClosure(JetFunctionLiteralExpression literal, ExpressionCodegen context, ClassContext classContext) {
|
||||
final ClosureCodegen codegen = new ClosureCodegen(this, context, classContext);
|
||||
closureContexts.push(codegen);
|
||||
try {
|
||||
return codegen.gen(literal);
|
||||
}
|
||||
finally {
|
||||
final ClosureCodegen popped = closureContexts.pop();
|
||||
assert popped == codegen;
|
||||
}
|
||||
}
|
||||
|
||||
public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, ExpressionCodegen context, ClassContext classContext) {
|
||||
Pair<String, ClassVisitor> nameAndVisitor = forAnonymousSubclass(literal.getObjectDeclaration());
|
||||
|
||||
@@ -115,11 +101,6 @@ public class GenerationState {
|
||||
return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, new Method("<init>", "()V"), false);
|
||||
}
|
||||
|
||||
public StackValue lookupInContext(DeclarationDescriptor d) {
|
||||
final ClosureCodegen top = closureContexts.peek();
|
||||
return top != null ? top.lookupInContext(d) : null;
|
||||
}
|
||||
|
||||
void prepareAnonymousClasses(JetElement aClass) {
|
||||
aClass.acceptChildren(new JetVisitor() {
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user