local functions used inside closures

This commit is contained in:
Alex Tkachman
2012-01-30 16:05:08 +02:00
parent f3b7d9511d
commit 92ef6aed77
3 changed files with 56 additions and 4 deletions
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -139,6 +140,10 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
final EnclosedValueDescriptor valueDescriptor = closure.get(descriptor);
answer.addArg(valueDescriptor.getOuterValue());
}
else if(descriptor instanceof NamedFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
final EnclosedValueDescriptor valueDescriptor = closure.get(descriptor);
answer.addArg(valueDescriptor.getOuterValue());
}
}
return answer;
}
@@ -230,12 +235,16 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
int argCount = captureThis ? 1 : 0;
argCount += (captureReceiver != null ? 1 : 0);
ArrayList<VariableDescriptor> variableDescriptors = new ArrayList<VariableDescriptor>();
ArrayList<DeclarationDescriptor> variableDescriptors = new ArrayList<DeclarationDescriptor>();
for (DeclarationDescriptor descriptor : closure.keySet()) {
if(descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
argCount++;
variableDescriptors.add((VariableDescriptor) descriptor);
variableDescriptors.add(descriptor);
}
else if(descriptor instanceof NamedFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
argCount++;
variableDescriptors.add(descriptor);
}
else if(descriptor instanceof FunctionDescriptor) {
assert captureReceiver != null;
@@ -259,6 +268,10 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
final Type type = sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType());
argTypes[i++] = type;
}
else if(descriptor instanceof NamedFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
final Type type = Type.getObjectType(state.getTypeMapper().classNameForAnonymousClass((JetElement) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor)));
argTypes[i++] = type;
}
}
final Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
@@ -286,7 +299,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
fieldName = "receiver$0";
}
else {
VariableDescriptor removed = variableDescriptors.remove(0);
DeclarationDescriptor removed = variableDescriptors.remove(0);
fieldName = "$" + removed.getName();
}
}
@@ -2,6 +2,8 @@ package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
@@ -58,6 +60,28 @@ public class ObjectOrClosureCodegen {
return innerValue;
}
if(d instanceof NamedFunctionDescriptor && d.getContainingDeclaration() instanceof FunctionDescriptor) {
FunctionDescriptor vd = (FunctionDescriptor) d;
final int idx = exprContext.lookupLocal(vd);
if (idx < 0) return null;
JetElement expression = (JetElement) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, vd);
String cn = state.getTypeMapper().classNameForAnonymousClass(expression);
Type localType = Type.getObjectType(cn);
StackValue outerValue = StackValue.local(idx, localType);
final String fieldName = "$" + vd.getName();
StackValue innerValue = StackValue.field(localType, name, fieldName, false);
cv.newField(null, Opcodes.ACC_PUBLIC, fieldName, localType.getDescriptor(), null, null);
answer = new EnclosedValueDescriptor(d, innerValue, outerValue);
closure.put(d, answer);
return innerValue;
}
if(d instanceof FunctionDescriptor) {
// we are looking for receiver
FunctionDescriptor fd = (FunctionDescriptor) d;
@@ -1,5 +1,12 @@
fun IntRange.forEach(body : (Int) -> Unit) {
for(i in this) {
body(i)
}
}
fun box() : String {
var seed = 0
fun local(x: Int) {
fun deep() {
seed += x
@@ -26,6 +33,14 @@ fun box() : String {
(-i).iter()
}
fun local2(y: Int) {
seed += y
}
return if(seed == 15) "OK" else seed.toString()
(1..5).forEach {
local2(it)
}
return if(seed == 30) "OK" else seed.toString()
}