diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 1de993847c0..46a4c4be556 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -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 variableDescriptors = new ArrayList(); + ArrayList variableDescriptors = new ArrayList(); 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("", 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(); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java index 6dd8f626125..2c6b7065a30 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java @@ -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; diff --git a/compiler/testData/codegen/functions/localFunction.kt b/compiler/testData/codegen/functions/localFunction.kt index be1e98e6dde..9ec49ecbeda 100644 --- a/compiler/testData/codegen/functions/localFunction.kt +++ b/compiler/testData/codegen/functions/localFunction.kt @@ -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() } \ No newline at end of file