Storing info about expressions which should be generated as SAM values.

This commit is contained in:
Evgeny Gerashchenko
2013-06-25 23:21:27 +04:00
parent e58bd5b6ec
commit 779ea1d7b8
4 changed files with 118 additions and 34 deletions
@@ -53,7 +53,6 @@ import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.java.*;
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.receivers.*;
import org.jetbrains.jet.lang.types.JetType;
@@ -1888,24 +1887,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return invokeFunction(call, receiver, resolvedCall);
}
@Nullable
private FunctionDescriptor getOriginalIfSamAdapter(@NotNull CallableDescriptor fun) {
if (!(fun instanceof FunctionDescriptor)) {
return null;
private void samAwareGen(@NotNull JetExpression expression, @NotNull Type defaultType) {
ClassDescriptorFromJvmBytecode samInterface = bindingContext.get(CodegenBinding.SAM_VALUE, expression);
if (samInterface != null) {
genSamInterfaceValue(expression, samInterface);
}
FunctionDescriptor original = ((FunctionDescriptor) fun).getOriginal();
if (original.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) {
return bindingContext.get(JavaBindingContext.SAM_ADAPTER_FUNCTION_TO_ORIGINAL, original);
else {
gen(expression, defaultType);
}
if (original.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
for (FunctionDescriptor overridden : original.getOverriddenDescriptors()) {
FunctionDescriptor originalIfSamAdapter = getOriginalIfSamAdapter(overridden);
if (originalIfSamAdapter != null) {
return originalIfSamAdapter;
}
}
}
return null;
}
private StackValue invokeSamConstructor(
@@ -2064,7 +2053,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
return typeMapper.mapToFunctionInvokeCallableMethod(createInvoke(fd));
}
else {
SimpleFunctionDescriptor originalOfSamAdapter = (SimpleFunctionDescriptor) getOriginalIfSamAdapter(fd);
SimpleFunctionDescriptor originalOfSamAdapter = (SimpleFunctionDescriptor) SamCodegenUtil
.getOriginalIfSamAdapter(bindingContext, fd);
return typeMapper.mapToCallableMethod(originalOfSamAdapter != null ? originalOfSamAdapter : fd, superCall,
isCallInsideSameClassAsDeclared(fd, context),
isCallInsideSameModuleAsDeclared(fd, context),
@@ -2298,31 +2288,19 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
int mask = 0;
FunctionDescriptor originalOfSamAdapter = getOriginalIfSamAdapter(fd);
for (ValueParameterDescriptor valueParameter : fd.getValueParameters()) {
ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex());
Type parameterType = valueParameterTypes.get(valueParameter.getIndex());
if (resolvedValueArgument instanceof ExpressionValueArgument) {
ValueArgument valueArgument = ((ExpressionValueArgument) resolvedValueArgument).getValueArgument();
assert valueArgument != null;
JetExpression argumentExpression = valueArgument.getArgumentExpression();
assert argumentExpression != null : valueArgument.asElement().getText();
if (originalOfSamAdapter != null) {
JetType samAdapterType = originalOfSamAdapter.getValueParameters().get(valueParameter.getIndex()).getType();
if (SingleAbstractMethodUtils.isSamType(samAdapterType)) {
ClassDescriptorFromJvmBytecode samInterface = (ClassDescriptorFromJvmBytecode) samAdapterType.getConstructor().getDeclarationDescriptor();
assert samInterface != null;
genSamInterfaceValue(argumentExpression, samInterface);
continue;
}
}
gen(argumentExpression, valueParameterTypes.get(valueParameter.getIndex()));
samAwareGen(argumentExpression, parameterType);
}
else if (resolvedValueArgument instanceof DefaultValueArgument) {
Type type = valueParameterTypes.get(valueParameter.getIndex());
pushDefaultValueOnStack(type, v);
pushDefaultValueOnStack(parameterType, v);
mask |= (1 << valueParameter.getIndex());
}
else if (resolvedValueArgument instanceof VarargValueArgument) {
@@ -3274,7 +3252,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
//See StackValue.receiver for more info
pushClosureOnStack(closure, resolvedCall.getThisObject().exists() || resolvedCall.getReceiverArgument().exists());
ConstructorDescriptor originalOfSamAdapter = (ConstructorDescriptor) getOriginalIfSamAdapter(constructorDescriptor);
ConstructorDescriptor originalOfSamAdapter = (ConstructorDescriptor) SamCodegenUtil
.getOriginalIfSamAdapter(bindingContext, constructorDescriptor);
CallableMethod method = typeMapper.mapToCallableMethod(originalOfSamAdapter == null ? constructorDescriptor : originalOfSamAdapter);
invokeMethodWithArguments(method, resolvedCall, null, StackValue.none());
@@ -0,0 +1,50 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.JavaBindingContext;
public class SamCodegenUtil {
@Nullable
public static FunctionDescriptor getOriginalIfSamAdapter(@NotNull BindingContext bindingContext, @NotNull CallableDescriptor fun) {
if (!(fun instanceof FunctionDescriptor)) {
return null;
}
FunctionDescriptor original = ((FunctionDescriptor) fun).getOriginal();
if (original.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) {
return bindingContext.get(JavaBindingContext.SAM_ADAPTER_FUNCTION_TO_ORIGINAL, original);
}
if (original.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
for (FunctionDescriptor overridden : original.getOverriddenDescriptors()) {
FunctionDescriptor originalIfSamAdapter = getOriginalIfSamAdapter(bindingContext, overridden);
if (originalIfSamAdapter != null) {
return originalIfSamAdapter;
}
}
}
return null;
}
private SamCodegenUtil() {
}
}
@@ -19,6 +19,7 @@ package org.jetbrains.jet.codegen.binding;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.SamCodegenUtil;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.ClassDescriptorImpl;
@@ -26,10 +27,14 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.model.ExpressionValueArgument;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
@@ -37,6 +42,7 @@ import org.jetbrains.jet.lang.types.JetType;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.jetbrains.jet.codegen.CodegenUtil.peekFromStack;
@@ -339,4 +345,50 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
return null;
}
}
@Override
public void visitCallExpression(JetCallExpression expression) {
super.visitCallExpression(expression);
ResolvedCall<? extends CallableDescriptor> call = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression());
if (call == null) {
return;
}
CallableDescriptor descriptor = call.getResultingDescriptor();
if (!(descriptor instanceof FunctionDescriptor)) {
return;
}
FunctionDescriptor original = SamCodegenUtil.getOriginalIfSamAdapter(bindingContext, descriptor);
if (original == null) {
return;
}
List<ResolvedValueArgument> valueArguments = call.getValueArgumentsByIndex();
for (ValueParameterDescriptor valueParameter : original.getValueParameters()) {
ClassDescriptorFromJvmBytecode samInterface = getInterfaceIfSamType(valueParameter.getType());
if (samInterface == null) {
continue;
}
ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex());
assert resolvedValueArgument instanceof ExpressionValueArgument : resolvedValueArgument;
ValueArgument valueArgument = ((ExpressionValueArgument) resolvedValueArgument).getValueArgument();
assert valueArgument != null;
JetExpression argumentExpression = valueArgument.getArgumentExpression();
assert argumentExpression != null : valueArgument.asElement().getText();
bindingTrace.record(CodegenBinding.SAM_VALUE, argumentExpression, samInterface);
}
}
@Nullable
private static ClassDescriptorFromJvmBytecode getInterfaceIfSamType(@NotNull JetType originalType) {
if (!SingleAbstractMethodUtils.isSamType(originalType)) {
return null;
}
ClassDescriptorFromJvmBytecode samInterface =
(ClassDescriptorFromJvmBytecode) originalType.getConstructor().getDeclarationDescriptor();
assert samInterface != null;
return samInterface;
}
}
@@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
@@ -57,6 +58,8 @@ public class CodegenBinding {
public static final WritableSlice<ClassDescriptor, Collection<ClassDescriptor>> INNER_CLASSES = Slices.createSimpleSlice();
public static final WritableSlice<JetExpression, ClassDescriptorFromJvmBytecode> SAM_VALUE = Slices.createSimpleSlice();
private CodegenBinding() {
}