local functions used inside closures
This commit is contained in:
@@ -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()
|
||||
}
|
||||
Reference in New Issue
Block a user