001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.jet.codegen;
018
019 import com.google.common.collect.ImmutableMap;
020 import org.jetbrains.annotations.NotNull;
021 import org.jetbrains.annotations.Nullable;
022 import org.jetbrains.jet.lang.descriptors.*;
023 import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
024 import org.jetbrains.jet.lang.resolve.java.JvmClassName;
025 import org.jetbrains.jet.lang.resolve.name.Name;
026 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
027 import org.jetbrains.jet.lang.types.JetType;
028 import org.jetbrains.jet.lang.types.JetTypeImpl;
029 import org.jetbrains.jet.lang.types.TypeProjection;
030 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
031
032 import java.util.ArrayList;
033 import java.util.List;
034
035 public class FunctionTypesUtil {
036 private static final List<ClassDescriptor> FUNCTIONS;
037 private static final List<ClassDescriptor> EXTENSION_FUNCTIONS;
038 private static final List<ClassDescriptor> K_FUNCTIONS;
039 private static final List<ClassDescriptor> K_MEMBER_FUNCTIONS;
040 private static final List<ClassDescriptor> K_EXTENSION_FUNCTIONS;
041
042 private static final ImmutableMap<ClassDescriptor, ClassDescriptor> FUNCTION_TO_IMPL;
043
044 static {
045 int n = KotlinBuiltIns.FUNCTION_TRAIT_COUNT;
046 FUNCTIONS = new ArrayList<ClassDescriptor>(n);
047 EXTENSION_FUNCTIONS = new ArrayList<ClassDescriptor>(n);
048 K_FUNCTIONS = new ArrayList<ClassDescriptor>(n);
049 K_MEMBER_FUNCTIONS = new ArrayList<ClassDescriptor>(n);
050 K_EXTENSION_FUNCTIONS = new ArrayList<ClassDescriptor>(n);
051
052 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
053 for (int i = 0; i < n; i++) {
054 Name functionImpl = Name.identifier("FunctionImpl" + i);
055 FUNCTIONS.add(createFunctionImplDescriptor(functionImpl, builtIns.getFunction(i)));
056
057 Name extensionFunctionImpl = Name.identifier("ExtensionFunctionImpl" + i);
058 EXTENSION_FUNCTIONS.add(createFunctionImplDescriptor(extensionFunctionImpl, builtIns.getExtensionFunction(i)));
059
060 Name kFunctionImpl = Name.identifier("KFunctionImpl" + i);
061 K_FUNCTIONS.add(createFunctionImplDescriptor(kFunctionImpl, builtIns.getKFunction(i)));
062
063 Name kMemberFunctionImpl = Name.identifier("KMemberFunctionImpl" + i);
064 K_MEMBER_FUNCTIONS.add(createFunctionImplDescriptor(kMemberFunctionImpl, builtIns.getKMemberFunction(i)));
065
066 Name kExtensionFunctionImpl = Name.identifier("KExtensionFunctionImpl" + i);
067 K_EXTENSION_FUNCTIONS.add(createFunctionImplDescriptor(kExtensionFunctionImpl, builtIns.getKExtensionFunction(i)));
068 }
069
070 ImmutableMap.Builder<ClassDescriptor, ClassDescriptor> builder = ImmutableMap.builder();
071 for (int i = 0; i < n; i++) {
072 builder.put(builtIns.getKFunction(i), K_FUNCTIONS.get(i));
073 builder.put(builtIns.getKMemberFunction(i), K_MEMBER_FUNCTIONS.get(i));
074 builder.put(builtIns.getKExtensionFunction(i), K_EXTENSION_FUNCTIONS.get(i));
075 }
076 FUNCTION_TO_IMPL = builder.build();
077 }
078
079 private FunctionTypesUtil() {
080 }
081
082
083 @Nullable
084 public static ClassDescriptor functionTypeToImpl(@NotNull JetType functionType) {
085 //noinspection SuspiciousMethodCalls
086 return FUNCTION_TO_IMPL.get(functionType.getConstructor().getDeclarationDescriptor());
087 }
088
089 @NotNull
090 public static JetType getSuperTypeForClosure(@NotNull FunctionDescriptor descriptor, boolean kFunction) {
091 int arity = descriptor.getValueParameters().size();
092
093 ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter();
094 ReceiverParameterDescriptor expectedThisObject = descriptor.getExpectedThisObject();
095
096 List<TypeProjection> typeArguments = new ArrayList<TypeProjection>(arity + 2);
097 if (receiverParameter != null) {
098 typeArguments.add(new TypeProjection(receiverParameter.getType()));
099 }
100 else if (kFunction && expectedThisObject != null) {
101 typeArguments.add(new TypeProjection(expectedThisObject.getType()));
102 }
103
104 for (ValueParameterDescriptor parameter : descriptor.getValueParameters()) {
105 typeArguments.add(new TypeProjection(parameter.getType()));
106 }
107
108 typeArguments.add(new TypeProjection(descriptor.getReturnType()));
109
110 ClassDescriptor classDescriptor;
111 if (kFunction) {
112 if (expectedThisObject != null) {
113 classDescriptor = K_MEMBER_FUNCTIONS.get(arity);
114 }
115 else if (receiverParameter != null) {
116 classDescriptor = K_EXTENSION_FUNCTIONS.get(arity);
117 }
118 else {
119 classDescriptor = K_FUNCTIONS.get(arity);
120 }
121 }
122 else {
123 if (receiverParameter != null) {
124 classDescriptor = EXTENSION_FUNCTIONS.get(arity);
125 }
126 else {
127 classDescriptor = FUNCTIONS.get(arity);
128 }
129 }
130
131 return new JetTypeImpl(
132 classDescriptor.getDefaultType().getAnnotations(),
133 classDescriptor.getTypeConstructor(),
134 false,
135 typeArguments,
136 classDescriptor.getMemberScope(typeArguments)
137 );
138 }
139
140 @NotNull
141 private static ClassDescriptor createFunctionImplDescriptor(@NotNull Name name, @NotNull ClassDescriptor functionInterface) {
142 JetScope builtInsScope = KotlinBuiltIns.getInstance().getBuiltInsScope();
143
144 MutableClassDescriptor functionImpl = new MutableClassDescriptor(
145 builtInsScope.getContainingDeclaration(),
146 builtInsScope,
147 ClassKind.CLASS,
148 false,
149 name
150 );
151 functionImpl.setModality(Modality.FINAL);
152 functionImpl.setVisibility(Visibilities.PUBLIC);
153 functionImpl.setTypeParameterDescriptors(functionInterface.getDefaultType().getConstructor().getParameters());
154 functionImpl.createTypeConstructor();
155
156 return functionImpl;
157 }
158
159 @NotNull
160 public static JvmClassName getFunctionTraitClassName(@NotNull FunctionDescriptor descriptor) {
161 int paramCount = descriptor.getValueParameters().size();
162 if (descriptor.getReceiverParameter() != null) {
163 return JvmClassName.byInternalName("jet/ExtensionFunction" + paramCount);
164 }
165 else {
166 return JvmClassName.byInternalName("jet/Function" + paramCount);
167 }
168 }
169
170 @NotNull
171 public static JvmClassName getFunctionImplClassName(@NotNull FunctionDescriptor descriptor) {
172 int paramCount = descriptor.getValueParameters().size();
173 if (descriptor.getReceiverParameter() != null) {
174 return JvmClassName.byInternalName("jet/ExtensionFunctionImpl" + paramCount);
175 }
176 else {
177 return JvmClassName.byInternalName("jet/FunctionImpl" + paramCount);
178 }
179 }
180 }