Support inlining in scripts and outer expression capturing

#KT-7744 Fixed
This commit is contained in:
Michael Bogdanov
2015-05-18 13:23:12 +03:00
parent 226350b4ba
commit 5cb9671803
6 changed files with 59 additions and 3 deletions
@@ -54,6 +54,7 @@ import java.util.*;
import static org.jetbrains.kotlin.codegen.AsmUtil.calculateInnerClassAccessFlags;
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.asmTypeForScriptDescriptor;
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
import static org.jetbrains.kotlin.descriptors.SourceElement.NO_SOURCE;
import static org.jetbrains.kotlin.resolve.BindingContext.VARIABLE;
@@ -242,8 +243,12 @@ public abstract class MemberCodegen<T extends JetElement/* TODO: & JetDeclaratio
private void writeInnerClass(@NotNull ClassDescriptor innerClass) {
DeclarationDescriptor containing = innerClass.getContainingDeclaration();
String outerClassInternalName =
containing instanceof ClassDescriptor ? typeMapper.mapClass((ClassDescriptor) containing).getInternalName() : null;
String outerClassInternalName = null;
if (containing instanceof ClassDescriptor) {
outerClassInternalName = typeMapper.mapClass((ClassDescriptor) containing).getInternalName();
} else if (containing instanceof ScriptDescriptor) {
outerClassInternalName = asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) containing).getInternalName();
}
String innerName = innerClass.getName().isSpecial() ? null : innerClass.getName().asString();
@@ -280,6 +285,8 @@ public abstract class MemberCodegen<T extends JetElement/* TODO: & JetDeclaratio
}
else if (outermost instanceof PackageContext && !(outermost instanceof PackageFacadeContext)) {
return PackagePartClassUtils.getPackagePartType(element.getContainingJetFile());
} else if (outermost instanceof ScriptContext) {
return asmTypeForScriptDescriptor(bindingContext, ((ScriptContext) outermost).getScriptDescriptor());
}
return null;
}
@@ -371,7 +371,7 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
String peek = peekFromStack(nameStack);
String name = safeIdentifier(descriptor.getName()).asString();
if (containingDeclaration instanceof ClassDescriptor) {
if (containingDeclaration instanceof ClassDescriptor || containingDeclaration instanceof ScriptDescriptor) {
return peek + '$' + name;
}
else if (containingDeclaration instanceof PackageFragmentDescriptor) {
@@ -58,6 +58,7 @@ import java.util.*;
import static org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags;
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLASS_FOR_SCRIPT;
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.addInlineMarker;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isFunctionLiteral;
import static org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage.getResolvedCallWithAssert;
@@ -574,6 +575,14 @@ public class InlineCodegen extends CallGenerator {
OwnerKind kind = DescriptorUtils.isTrait(descriptor) ? OwnerKind.TRAIT_IMPL : OwnerKind.IMPLEMENTATION;
return parent.intoClass((ClassDescriptor) descriptor, kind, state);
}
else if (descriptor instanceof ScriptDescriptor) {
ClassDescriptor classDescriptorForScript = state.getBindingContext().get(CLASS_FOR_SCRIPT, (ScriptDescriptor) descriptor);
assert classDescriptorForScript != null : "Can't find class for script: " + descriptor;
List<ScriptDescriptor> earlierScripts = state.getEarlierScriptsForReplInterpreter();
return parent.intoScript((ScriptDescriptor) descriptor,
earlierScripts == null ? Collections.emptyList() : earlierScripts,
classDescriptorForScript);
}
else if (descriptor instanceof FunctionDescriptor) {
return parent.intoFunction((FunctionDescriptor) descriptor);
}
@@ -0,0 +1,14 @@
// expected: rv: 2
@inline fun foo(l: (Int) -> Int ): Int {
return l(1)
}
fun bar(p: Int): Int {
return p + 1
}
fun main(): Int {
return foo { x -> bar(x) }
}
main()
@@ -0,0 +1,14 @@
// expected: rv: 2
fun foo(l: (Int) -> Int ): Int {
return l(1)
}
fun bar(p: Int): Int {
return p + 1
}
fun main(): Int {
return foo { x -> bar(x) }
}
main()
@@ -47,6 +47,18 @@ public class ScriptCodegenTestGenerated extends AbstractScriptCodegenTest {
doTest(fileName);
}
@TestMetadata("inline.kts")
public void testInline() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/script/inline.kts");
doTest(fileName);
}
@TestMetadata("outerCapture.kts")
public void testOuterCapture() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/script/outerCapture.kts");
doTest(fileName);
}
@TestMetadata("parameter.kts")
public void testParameter() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/script/parameter.kts");