From 9e28fe70c11a0528e6fec2a0c134b97339720e78 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Fri, 8 Jul 2011 14:34:48 +0400 Subject: [PATCH] Finally, green tests --- .../jetbrains/jet/codegen/ClassContext.java | 61 +++++++++++++++---- .../jetbrains/jet/codegen/ClosureCodegen.java | 23 +++---- .../jet/codegen/ExpressionCodegen.java | 9 +-- .../jet/codegen/GenerationState.java | 19 ------ 4 files changed, 67 insertions(+), 45 deletions(-) diff --git a/idea/src/org/jetbrains/jet/codegen/ClassContext.java b/idea/src/org/jetbrains/jet/codegen/ClassContext.java index 2559082cd47..87e92d070f7 100644 --- a/idea/src/org/jetbrains/jet/codegen/ClassContext.java +++ b/idea/src/org/jetbrains/jet/codegen/ClassContext.java @@ -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; + } } diff --git a/idea/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/idea/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 84c20b00f4c..9af17666bcc 100644 --- a/idea/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -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 closure = new LinkedHashMap(); @@ -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()) { diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 5ad0ab7a7a1..fc1751cafd1 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -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); } } diff --git a/idea/src/org/jetbrains/jet/codegen/GenerationState.java b/idea/src/org/jetbrains/jet/codegen/GenerationState.java index 198f3b69d3f..7077ec4cc3b 100644 --- a/idea/src/org/jetbrains/jet/codegen/GenerationState.java +++ b/idea/src/org/jetbrains/jet/codegen/GenerationState.java @@ -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 bindingContexts = new Stack(); - private final Stack closureContexts = new Stack(); 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 nameAndVisitor = forAnonymousSubclass(literal.getObjectDeclaration()); @@ -115,11 +101,6 @@ public class GenerationState { return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, new Method("", "()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