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.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
|
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.JetExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
|
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
@@ -139,6 +140,10 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
final EnclosedValueDescriptor valueDescriptor = closure.get(descriptor);
|
final EnclosedValueDescriptor valueDescriptor = closure.get(descriptor);
|
||||||
answer.addArg(valueDescriptor.getOuterValue());
|
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;
|
return answer;
|
||||||
}
|
}
|
||||||
@@ -230,12 +235,16 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
int argCount = captureThis ? 1 : 0;
|
int argCount = captureThis ? 1 : 0;
|
||||||
argCount += (captureReceiver != null ? 1 : 0);
|
argCount += (captureReceiver != null ? 1 : 0);
|
||||||
|
|
||||||
ArrayList<VariableDescriptor> variableDescriptors = new ArrayList<VariableDescriptor>();
|
ArrayList<DeclarationDescriptor> variableDescriptors = new ArrayList<DeclarationDescriptor>();
|
||||||
|
|
||||||
for (DeclarationDescriptor descriptor : closure.keySet()) {
|
for (DeclarationDescriptor descriptor : closure.keySet()) {
|
||||||
if(descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
|
if(descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
|
||||||
argCount++;
|
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) {
|
else if(descriptor instanceof FunctionDescriptor) {
|
||||||
assert captureReceiver != null;
|
assert captureReceiver != null;
|
||||||
@@ -259,6 +268,10 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
final Type type = sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType());
|
final Type type = sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType());
|
||||||
argTypes[i++] = type;
|
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);
|
final Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
|
||||||
@@ -286,7 +299,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
|||||||
fieldName = "receiver$0";
|
fieldName = "receiver$0";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
VariableDescriptor removed = variableDescriptors.remove(0);
|
DeclarationDescriptor removed = variableDescriptors.remove(0);
|
||||||
fieldName = "$" + removed.getName();
|
fieldName = "$" + removed.getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package org.jetbrains.jet.codegen;
|
|||||||
|
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall;
|
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.Opcodes;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
@@ -58,6 +60,28 @@ public class ObjectOrClosureCodegen {
|
|||||||
return innerValue;
|
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) {
|
if(d instanceof FunctionDescriptor) {
|
||||||
// we are looking for receiver
|
// we are looking for receiver
|
||||||
FunctionDescriptor fd = (FunctionDescriptor) d;
|
FunctionDescriptor fd = (FunctionDescriptor) d;
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
|
fun IntRange.forEach(body : (Int) -> Unit) {
|
||||||
|
for(i in this) {
|
||||||
|
body(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun box() : String {
|
fun box() : String {
|
||||||
var seed = 0
|
var seed = 0
|
||||||
|
|
||||||
fun local(x: Int) {
|
fun local(x: Int) {
|
||||||
fun deep() {
|
fun deep() {
|
||||||
seed += x
|
seed += x
|
||||||
@@ -26,6 +33,14 @@ fun box() : String {
|
|||||||
(-i).iter()
|
(-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