use of org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue in project kotlin by JetBrains.
the class ImplementationBodyCodegen method lookupConstructorExpressionsInClosureIfPresent.
private void lookupConstructorExpressionsInClosureIfPresent() {
if (!state.getClassBuilderMode().generateBodies || descriptor.getConstructors().isEmpty())
return;
KtVisitorVoid visitor = new KtVisitorVoid() {
@Override
public void visitKtElement(@NotNull KtElement e) {
e.acceptChildren(this);
}
@Override
public void visitSimpleNameExpression(@NotNull KtSimpleNameExpression expr) {
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expr);
if (isLocalFunction(descriptor)) {
lookupInContext(descriptor);
} else if (descriptor instanceof CallableMemberDescriptor) {
ResolvedCall<? extends CallableDescriptor> call = CallUtilKt.getResolvedCall(expr, bindingContext);
if (call != null) {
lookupReceivers(call);
}
if (call instanceof VariableAsFunctionResolvedCall) {
lookupReceivers(((VariableAsFunctionResolvedCall) call).getVariableCall());
}
} else if (descriptor instanceof VariableDescriptor) {
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
if (containingDeclaration instanceof ConstructorDescriptor) {
ClassDescriptor classDescriptor = ((ConstructorDescriptor) containingDeclaration).getConstructedClass();
if (classDescriptor == ImplementationBodyCodegen.this.descriptor)
return;
}
lookupInContext(descriptor);
}
}
private void lookupReceivers(@NotNull ResolvedCall<? extends CallableDescriptor> call) {
lookupReceiver(call.getDispatchReceiver());
lookupReceiver(call.getExtensionReceiver());
}
private void lookupReceiver(@Nullable ReceiverValue value) {
if (value instanceof ImplicitReceiver) {
if (value instanceof ExtensionReceiver) {
ReceiverParameterDescriptor parameter = ((ExtensionReceiver) value).getDeclarationDescriptor().getExtensionReceiverParameter();
assert parameter != null : "Extension receiver should exist: " + ((ExtensionReceiver) value).getDeclarationDescriptor();
lookupInContext(parameter);
} else {
lookupInContext(((ImplicitReceiver) value).getDeclarationDescriptor());
}
}
}
private void lookupInContext(@NotNull DeclarationDescriptor toLookup) {
ExpressionCodegen.lookupValuaAndLocalVariableMetadata(toLookup, StackValue.LOCAL_0, state, true, context, null);
}
@Override
public void visitThisExpression(@NotNull KtThisExpression expression) {
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
assert descriptor instanceof CallableDescriptor || descriptor instanceof ClassDescriptor : "'This' reference target should be class or callable descriptor but was " + descriptor;
if (descriptor instanceof ClassDescriptor) {
lookupInContext(descriptor);
}
if (descriptor instanceof CallableDescriptor) {
ReceiverParameterDescriptor parameter = ((CallableDescriptor) descriptor).getExtensionReceiverParameter();
if (parameter != null) {
lookupInContext(parameter);
}
}
}
@Override
public void visitSuperExpression(@NotNull KtSuperExpression expression) {
lookupInContext(ExpressionCodegen.getSuperCallLabelTarget(context, expression));
}
};
for (KtDeclaration declaration : myClass.getDeclarations()) {
if (declaration instanceof KtProperty) {
KtProperty property = (KtProperty) declaration;
KtExpression initializer = property.getDelegateExpressionOrInitializer();
if (initializer != null) {
initializer.accept(visitor);
}
} else if (declaration instanceof KtAnonymousInitializer) {
KtAnonymousInitializer initializer = (KtAnonymousInitializer) declaration;
initializer.accept(visitor);
} else if (declaration instanceof KtSecondaryConstructor) {
KtSecondaryConstructor constructor = (KtSecondaryConstructor) declaration;
constructor.accept(visitor);
}
}
for (KtSuperTypeListEntry specifier : myClass.getSuperTypeListEntries()) {
if (specifier instanceof KtDelegatedSuperTypeEntry) {
KtExpression delegateExpression = ((KtDelegatedSuperTypeEntry) specifier).getDelegateExpression();
assert delegateExpression != null;
delegateExpression.accept(visitor);
} else if (specifier instanceof KtSuperTypeCallEntry) {
specifier.accept(visitor);
}
}
}
use of org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue in project kotlin by JetBrains.
the class FunctionReferenceGenerationStrategy method doGenerateBody.
@Override
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
/*
Here we need to put the arguments from our locals to the stack and invoke the referenced method. Since invocation
of methods is highly dependent on expressions, we create a fake call expression. Then we create a new instance of
ExpressionCodegen and, in order for it to generate code correctly, we save to its 'tempVariables' field every
argument of our fake expression, pointing it to the corresponding index in our locals. This way generation of
every argument boils down to calling LOAD with the corresponding index
*/
KtCallExpression fakeExpression = CodegenUtil.constructFakeFunctionCall(state.getProject(), referencedFunction);
final List<? extends ValueArgument> fakeArguments = fakeExpression.getValueArguments();
final ReceiverValue dispatchReceiver = computeAndSaveReceiver(signature, codegen, referencedFunction.getDispatchReceiverParameter());
final ReceiverValue extensionReceiver = computeAndSaveReceiver(signature, codegen, referencedFunction.getExtensionReceiverParameter());
computeAndSaveArguments(fakeArguments, codegen);
ResolvedCall<CallableDescriptor> fakeResolvedCall = new DelegatingResolvedCall<CallableDescriptor>(resolvedCall) {
private final Map<ValueParameterDescriptor, ResolvedValueArgument> argumentMap;
{
argumentMap = new LinkedHashMap<ValueParameterDescriptor, ResolvedValueArgument>(fakeArguments.size());
int index = 0;
List<ValueParameterDescriptor> parameters = functionDescriptor.getValueParameters();
for (ValueArgument argument : fakeArguments) {
argumentMap.put(parameters.get(index), new ExpressionValueArgument(argument));
index++;
}
}
@Nullable
@Override
public ReceiverValue getExtensionReceiver() {
return extensionReceiver;
}
@Nullable
@Override
public ReceiverValue getDispatchReceiver() {
return dispatchReceiver;
}
@NotNull
@Override
public List<ResolvedValueArgument> getValueArgumentsByIndex() {
return new ArrayList<ResolvedValueArgument>(argumentMap.values());
}
@NotNull
@Override
public Map<ValueParameterDescriptor, ResolvedValueArgument> getValueArguments() {
return argumentMap;
}
};
StackValue result;
Type returnType = codegen.getReturnType();
if (referencedFunction instanceof ConstructorDescriptor) {
if (returnType.getSort() == Type.ARRAY) {
//noinspection ConstantConditions
result = codegen.generateNewArray(fakeExpression, referencedFunction.getReturnType(), fakeResolvedCall);
} else {
result = codegen.generateConstructorCall(fakeResolvedCall, returnType);
}
} else {
Call call = CallMaker.makeCall(fakeExpression, null, null, fakeExpression, fakeArguments);
result = codegen.invokeFunction(call, fakeResolvedCall, StackValue.none());
}
InstructionAdapter v = codegen.v;
result.put(returnType, v);
v.areturn(returnType);
}
use of org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue in project kotlin by JetBrains.
the class StackValue method receiver.
public static StackValue receiver(ResolvedCall<?> resolvedCall, StackValue receiver, ExpressionCodegen codegen, @Nullable Callable callableMethod) {
ReceiverValue callDispatchReceiver = resolvedCall.getDispatchReceiver();
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
if (descriptor instanceof SyntheticFieldDescriptor) {
callDispatchReceiver = ((SyntheticFieldDescriptor) descriptor).getDispatchReceiverForBackend();
}
ReceiverValue callExtensionReceiver = resolvedCall.getExtensionReceiver();
if (callDispatchReceiver != null || callExtensionReceiver != null || isLocalFunCall(callableMethod) || isCallToMemberObjectImportedByName(resolvedCall)) {
ReceiverParameterDescriptor dispatchReceiverParameter = descriptor.getDispatchReceiverParameter();
ReceiverParameterDescriptor extensionReceiverParameter = descriptor.getExtensionReceiverParameter();
if (descriptor instanceof SyntheticFieldDescriptor) {
dispatchReceiverParameter = ((SyntheticFieldDescriptor) descriptor).getDispatchReceiverParameterForBackend();
}
boolean hasExtensionReceiver = callExtensionReceiver != null;
StackValue dispatchReceiver = platformStaticCallIfPresent(genReceiver(hasExtensionReceiver ? none() : receiver, codegen, resolvedCall, callableMethod, callDispatchReceiver, false), descriptor);
StackValue extensionReceiver = genReceiver(receiver, codegen, resolvedCall, callableMethod, callExtensionReceiver, true);
Type type = CallReceiver.calcType(resolvedCall, dispatchReceiverParameter, extensionReceiverParameter, codegen.typeMapper, callableMethod, codegen.getState());
assert type != null : "Could not map receiver type for " + resolvedCall;
return new CallReceiver(dispatchReceiver, extensionReceiver, type);
}
return receiver;
}
use of org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue in project kotlin by JetBrains.
the class RangeCodegenUtil method isPrimitiveRangeToExtension.
public static boolean isPrimitiveRangeToExtension(@NotNull KtSimpleNameExpression operationReference, @NotNull BindingContext bindingContext) {
ResolvedCall<? extends CallableDescriptor> resolvedCall = CallUtilKt.getResolvedCallWithAssert(operationReference, bindingContext);
ReceiverValue receiver = resolvedCall.getDispatchReceiver();
/*
* Range is optimizable if
* 'in' receiver is expression 'rangeTo' from stdlib package
* and its argument has same primitive type as generic range parameter.
* For non-matching primitive types (e.g. int in double range)
* dispatch receiver will be null, because extension method will be called.
*/
if (!(receiver instanceof ExpressionReceiver))
return false;
ExpressionReceiver e = (ExpressionReceiver) receiver;
ResolvedCall<? extends CallableDescriptor> resolvedReceiver = CallUtilKt.getResolvedCall(e.getExpression(), bindingContext);
if (resolvedReceiver == null)
return false;
return isPrimitiveRangeToExtension(resolvedReceiver.getResultingDescriptor());
}
Aggregations