Simplify function hierarchy in reflection

Get rid of all classes except kotlin.reflect.KFunction, which will be used to
represent all kinds of simple functions.

Lots of changes to test data are related to the fact that KFunction is not an
extension function (as opposed to KMemberFunction and KExtensionFunction who
were) and so a member or an extension function reference now requires all
arguments be passed to it in the parentheses, including receivers. This is
probably temporary until we support calling any function both as a free
function and as an extension. In JS, functions and extension functions are not
interchangeable, so tests on this behavior are removed until this is supported
This commit is contained in:
Alexander Udalov
2015-06-23 20:34:25 +03:00
parent 3549e1e035
commit c3b97e0668
113 changed files with 350 additions and 534 deletions
@@ -225,53 +225,35 @@ public class ClosureCodegen extends MemberCodegen<JetElement> {
@NotNull
public StackValue putInstanceOnStack(@NotNull final ExpressionCodegen codegen) {
return StackValue.operation(asmType, new Function1<InstructionAdapter, Unit>() {
@Override
public Unit invoke(InstructionAdapter v) {
if (isConst(closure)) {
v.getstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, asmType.getDescriptor());
}
else {
v.anew(asmType);
v.dup();
return StackValue.operation(
functionReferenceTarget != null ? K_FUNCTION : asmType,
new Function1<InstructionAdapter, Unit>() {
@Override
public Unit invoke(InstructionAdapter v) {
if (isConst(closure)) {
v.getstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, asmType.getDescriptor());
}
else {
v.anew(asmType);
v.dup();
codegen.pushClosureOnStack(classDescriptor, true, codegen.defaultCallGenerator);
v.invokespecial(asmType.getInternalName(), "<init>", constructor.getDescriptor(), false);
}
codegen.pushClosureOnStack(classDescriptor, true, codegen.defaultCallGenerator);
v.invokespecial(asmType.getInternalName(), "<init>", constructor.getDescriptor(), false);
}
if (functionReferenceTarget != null) {
equipFunctionReferenceWithReflection(v, functionReferenceTarget);
}
if (functionReferenceTarget != null) {
v.invokestatic(REFLECTION, "function", Type.getMethodDescriptor(K_FUNCTION, FUNCTION_REFERENCE), false);
}
return Unit.INSTANCE$;
}
});
return Unit.INSTANCE$;
}
}
);
}
private static void equipFunctionReferenceWithReflection(@NotNull InstructionAdapter v, @NotNull FunctionDescriptor target) {
DeclarationDescriptor container = target.getContainingDeclaration();
Type type;
if (container instanceof PackageFragmentDescriptor) {
type = target.getExtensionReceiverParameter() != null
? K_TOP_LEVEL_EXTENSION_FUNCTION
: K_TOP_LEVEL_FUNCTION;
}
else if (container instanceof ClassDescriptor) {
type = K_MEMBER_FUNCTION;
}
else {
type = K_LOCAL_FUNCTION;
}
Method method = method("function", K_FUNCTION, FUNCTION_REFERENCE);
v.invokestatic(REFLECTION, method.getName(), method.getDescriptor(), false);
StackValue.coerce(K_FUNCTION, type, v);
}
private void generateConstInstance() {
MethodVisitor mv = v.newMethod(OtherOrigin(element, funDescriptor), ACC_STATIC | ACC_SYNTHETIC, "<clinit>", "()V", null, ArrayUtil.EMPTY_STRING_ARRAY);
MethodVisitor mv = v.newMethod(OtherOrigin(element, funDescriptor), ACC_STATIC | ACC_SYNTHETIC, "<clinit>", "()V", null,
ArrayUtil.EMPTY_STRING_ARRAY);
InstructionAdapter iv = new InstructionAdapter(mv);
v.newField(OtherOrigin(element, funDescriptor), ACC_STATIC | ACC_FINAL | ACC_PUBLIC, JvmAbi.INSTANCE_FIELD, asmType.getDescriptor(),
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.codegen;
import kotlin.KotlinPackage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.state.GenerationState;
@@ -133,8 +134,14 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
}
private void computeAndSaveArguments(@NotNull List<? extends ValueArgument> fakeArguments, @NotNull ExpressionCodegen codegen) {
for (ValueParameterDescriptor parameter : callableDescriptor.getValueParameters()) {
ValueArgument fakeArgument = fakeArguments.get(parameter.getIndex());
int receivers = (referencedFunction.getDispatchReceiverParameter() != null ? 1 : 0) +
(referencedFunction.getExtensionReceiverParameter() != null ? 1 : 0);
List<ValueParameterDescriptor> parameters = KotlinPackage.drop(callableDescriptor.getValueParameters(), receivers);
for (int i = 0; i < parameters.size(); i++) {
ValueParameterDescriptor parameter = parameters.get(i);
ValueArgument fakeArgument = fakeArguments.get(i);
Type type = state.getTypeMapper().mapType(parameter);
int localIndex = codegen.myFrameMap.getIndex(parameter);
codegen.tempVariables.put(fakeArgument.getArgumentExpression(), StackValue.local(localIndex, type));