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.ImmutableList;
020 import com.google.common.collect.ImmutableMap;
021 import org.jetbrains.annotations.NotNull;
022 import org.jetbrains.annotations.Nullable;
023 import org.jetbrains.jet.lang.descriptors.*;
024 import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
025 import org.jetbrains.jet.lang.descriptors.impl.MutablePackageFragmentDescriptor;
026 import org.jetbrains.jet.lang.reflect.ReflectionTypes;
027 import org.jetbrains.jet.lang.resolve.ImportPath;
028 import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap;
029 import org.jetbrains.jet.lang.resolve.name.FqName;
030 import org.jetbrains.jet.lang.resolve.name.Name;
031 import org.jetbrains.jet.lang.types.JetType;
032 import org.jetbrains.jet.lang.types.JetTypeImpl;
033 import org.jetbrains.jet.lang.types.TypeProjection;
034 import org.jetbrains.jet.lang.types.TypeProjectionImpl;
035 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
036
037 import java.util.ArrayList;
038 import java.util.Collections;
039 import java.util.List;
040 import java.util.Map;
041
042 public class JvmFunctionImplTypes {
043 private final ReflectionTypes reflectionTypes;
044 private final ModuleDescriptor fakeModule;
045
046 private volatile List<Functions> functionsList;
047 private volatile List<KFunctions> kFunctionsList;
048 private volatile Map<ClassDescriptor, ClassDescriptor> kFunctionToImplMap;
049
050 private static class Functions {
051 public final ClassDescriptor functionImpl;
052 public final ClassDescriptor extensionFunctionImpl;
053
054 public Functions(
055 @NotNull ClassDescriptor functionImpl,
056 @NotNull ClassDescriptor extensionFunctionImpl
057 ) {
058 this.functionImpl = functionImpl;
059 this.extensionFunctionImpl = extensionFunctionImpl;
060 }
061 }
062
063 private static class KFunctions {
064 public final ClassDescriptor kFunctionImpl;
065 public final ClassDescriptor kMemberFunctionImpl;
066 public final ClassDescriptor kExtensionFunctionImpl;
067
068 public KFunctions(
069 @NotNull ClassDescriptor kFunctionImpl,
070 @NotNull ClassDescriptor kMemberFunctionImpl,
071 @NotNull ClassDescriptor kExtensionFunctionImpl
072 ) {
073 this.kFunctionImpl = kFunctionImpl;
074 this.kMemberFunctionImpl = kMemberFunctionImpl;
075 this.kExtensionFunctionImpl = kExtensionFunctionImpl;
076 }
077 }
078
079 public JvmFunctionImplTypes(@NotNull ReflectionTypes reflectionTypes) {
080 this.reflectionTypes = reflectionTypes;
081 this.fakeModule = new ModuleDescriptorImpl(Name.special("<fake module for functions impl>"), Collections.<ImportPath>emptyList(),
082 JavaToKotlinClassMap.getInstance());
083 }
084
085 @NotNull
086 private List<Functions> getFunctionsImplList() {
087 if (functionsList == null) {
088 MutablePackageFragmentDescriptor kotlin = new MutablePackageFragmentDescriptor(fakeModule, new FqName("kotlin"));
089 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
090
091 ImmutableList.Builder<Functions> builder = ImmutableList.builder();
092 for (int i = 0; i < KotlinBuiltIns.FUNCTION_TRAIT_COUNT; i++) {
093 builder.add(new Functions(
094 createFunctionImpl(kotlin, "FunctionImpl" + i, builtIns.getFunction(i)),
095 createFunctionImpl(kotlin, "ExtensionFunctionImpl" + i, builtIns.getExtensionFunction(i))
096 ));
097 }
098 functionsList = builder.build();
099 }
100 return functionsList;
101 }
102
103 @NotNull
104 private List<KFunctions> getKFunctionsImplList() {
105 if (kFunctionsList == null) {
106 MutablePackageFragmentDescriptor reflect = new MutablePackageFragmentDescriptor(fakeModule, new FqName("kotlin.reflect"));
107
108 ImmutableList.Builder<KFunctions> builder = ImmutableList.builder();
109 for (int i = 0; i < KotlinBuiltIns.FUNCTION_TRAIT_COUNT; i++) {
110 builder.add(new KFunctions(
111 createFunctionImpl(reflect, "KFunctionImpl" + i, reflectionTypes.getKFunction(i)),
112 createFunctionImpl(reflect, "KMemberFunctionImpl" + i, reflectionTypes.getKMemberFunction(i)),
113 createFunctionImpl(reflect, "KExtensionFunctionImpl" + i, reflectionTypes.getKExtensionFunction(i))
114 ));
115 }
116 kFunctionsList = builder.build();
117 }
118 return kFunctionsList;
119 }
120
121 @NotNull
122 private Map<ClassDescriptor, ClassDescriptor> getKFunctionToImplMap() {
123 if (kFunctionToImplMap == null) {
124 ImmutableMap.Builder<ClassDescriptor, ClassDescriptor> builder = ImmutableMap.builder();
125 for (int i = 0; i < KotlinBuiltIns.FUNCTION_TRAIT_COUNT; i++) {
126 KFunctions kFunctions = getKFunctionsImplList().get(i);
127 builder.put(reflectionTypes.getKFunction(i), kFunctions.kFunctionImpl);
128 builder.put(reflectionTypes.getKMemberFunction(i), kFunctions.kMemberFunctionImpl);
129 builder.put(reflectionTypes.getKExtensionFunction(i), kFunctions.kExtensionFunctionImpl);
130 }
131 kFunctionToImplMap = builder.build();
132 }
133 return kFunctionToImplMap;
134 }
135
136
137 @Nullable
138 public ClassDescriptor kFunctionTypeToImpl(@NotNull JetType functionType) {
139 //noinspection SuspiciousMethodCalls
140 return getKFunctionToImplMap().get(functionType.getConstructor().getDeclarationDescriptor());
141 }
142
143 @NotNull
144 public JetType getSuperTypeForClosure(@NotNull FunctionDescriptor descriptor, boolean kFunction) {
145 int arity = descriptor.getValueParameters().size();
146
147 ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter();
148 ReceiverParameterDescriptor expectedThisObject = descriptor.getExpectedThisObject();
149
150 List<TypeProjection> typeArguments = new ArrayList<TypeProjection>(arity + 2);
151 if (receiverParameter != null) {
152 typeArguments.add(new TypeProjectionImpl(receiverParameter.getType()));
153 }
154 else if (kFunction && expectedThisObject != null) {
155 typeArguments.add(new TypeProjectionImpl(expectedThisObject.getType()));
156 }
157
158 for (ValueParameterDescriptor parameter : descriptor.getValueParameters()) {
159 typeArguments.add(new TypeProjectionImpl(parameter.getType()));
160 }
161
162 //noinspection ConstantConditions
163 typeArguments.add(new TypeProjectionImpl(descriptor.getReturnType()));
164
165 ClassDescriptor classDescriptor;
166 if (kFunction) {
167 KFunctions kFunctions = getKFunctionsImplList().get(arity);
168 if (expectedThisObject != null) {
169 classDescriptor = kFunctions.kMemberFunctionImpl;
170 }
171 else if (receiverParameter != null) {
172 classDescriptor = kFunctions.kExtensionFunctionImpl;
173 }
174 else {
175 classDescriptor = kFunctions.kFunctionImpl;
176 }
177 }
178 else {
179 Functions functions = getFunctionsImplList().get(arity);
180 if (receiverParameter != null) {
181 classDescriptor = functions.extensionFunctionImpl;
182 }
183 else {
184 classDescriptor = functions.functionImpl;
185 }
186 }
187
188 return new JetTypeImpl(
189 classDescriptor.getDefaultType().getAnnotations(),
190 classDescriptor.getTypeConstructor(),
191 false,
192 typeArguments,
193 classDescriptor.getMemberScope(typeArguments)
194 );
195 }
196
197 @NotNull
198 private static ClassDescriptor createFunctionImpl(
199 @NotNull PackageFragmentDescriptor containingDeclaration,
200 @NotNull String name,
201 @NotNull ClassDescriptor functionInterface
202 ) {
203 MutableClassDescriptor functionImpl = new MutableClassDescriptor(
204 containingDeclaration,
205 containingDeclaration.getMemberScope(),
206 ClassKind.CLASS,
207 false,
208 Name.identifier(name)
209 );
210 functionImpl.setModality(Modality.FINAL);
211 functionImpl.setVisibility(Visibilities.PUBLIC);
212 functionImpl.setTypeParameterDescriptors(functionInterface.getDefaultType().getConstructor().getParameters());
213 functionImpl.createTypeConstructor();
214
215 return functionImpl;
216 }
217 }