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.asm4.Type;
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.resolve.ImportPath;
027 import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap;
028 import org.jetbrains.jet.lang.resolve.name.FqName;
029 import org.jetbrains.jet.lang.resolve.name.Name;
030 import org.jetbrains.jet.lang.types.JetType;
031 import org.jetbrains.jet.lang.types.JetTypeImpl;
032 import org.jetbrains.jet.lang.types.TypeProjection;
033 import org.jetbrains.jet.lang.types.TypeProjectionImpl;
034 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
035
036 import java.util.ArrayList;
037 import java.util.Collections;
038 import java.util.List;
039
040 import static org.jetbrains.jet.lang.types.lang.KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME;
041
042 public class FunctionTypesUtil {
043 private static final List<ClassDescriptor> FUNCTIONS;
044 private static final List<ClassDescriptor> EXTENSION_FUNCTIONS;
045 private static final List<ClassDescriptor> K_FUNCTIONS;
046 private static final List<ClassDescriptor> K_MEMBER_FUNCTIONS;
047 private static final List<ClassDescriptor> K_EXTENSION_FUNCTIONS;
048
049 private static final ImmutableMap<ClassDescriptor, ClassDescriptor> FUNCTION_TO_IMPL;
050
051 static {
052 int n = KotlinBuiltIns.FUNCTION_TRAIT_COUNT;
053 FUNCTIONS = new ArrayList<ClassDescriptor>(n);
054 EXTENSION_FUNCTIONS = new ArrayList<ClassDescriptor>(n);
055 K_FUNCTIONS = new ArrayList<ClassDescriptor>(n);
056 K_MEMBER_FUNCTIONS = new ArrayList<ClassDescriptor>(n);
057 K_EXTENSION_FUNCTIONS = new ArrayList<ClassDescriptor>(n);
058
059 ModuleDescriptor module = new ModuleDescriptorImpl(Name.special("<fake module for functions impl>"),
060 Collections.<ImportPath>emptyList(), JavaToKotlinClassMap.getInstance());
061 MutablePackageFragmentDescriptor kotlin = new MutablePackageFragmentDescriptor(module, new FqName("kotlin"));
062 MutablePackageFragmentDescriptor reflect = new MutablePackageFragmentDescriptor(module, new FqName("kotlin.reflect"));
063
064 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
065 for (int i = 0; i < n; i++) {
066 createFunctionImpl(FUNCTIONS, kotlin, "FunctionImpl" + i, builtIns.getFunction(i));
067 createFunctionImpl(EXTENSION_FUNCTIONS, kotlin, "ExtensionFunctionImpl" + i, builtIns.getExtensionFunction(i));
068 createFunctionImpl(K_FUNCTIONS, reflect, "KFunctionImpl" + i, builtIns.getKFunction(i));
069 createFunctionImpl(K_MEMBER_FUNCTIONS, reflect, "KMemberFunctionImpl" + i, builtIns.getKMemberFunction(i));
070 createFunctionImpl(K_EXTENSION_FUNCTIONS, reflect, "KExtensionFunctionImpl" + i, builtIns.getKExtensionFunction(i));
071 }
072
073 ImmutableMap.Builder<ClassDescriptor, ClassDescriptor> builder = ImmutableMap.builder();
074 for (int i = 0; i < n; i++) {
075 builder.put(builtIns.getKFunction(i), K_FUNCTIONS.get(i));
076 builder.put(builtIns.getKMemberFunction(i), K_MEMBER_FUNCTIONS.get(i));
077 builder.put(builtIns.getKExtensionFunction(i), K_EXTENSION_FUNCTIONS.get(i));
078 }
079 FUNCTION_TO_IMPL = builder.build();
080 }
081
082 private FunctionTypesUtil() {
083 }
084
085
086 @Nullable
087 public static ClassDescriptor functionTypeToImpl(@NotNull JetType functionType) {
088 //noinspection SuspiciousMethodCalls
089 return FUNCTION_TO_IMPL.get(functionType.getConstructor().getDeclarationDescriptor());
090 }
091
092 @NotNull
093 public static JetType getSuperTypeForClosure(@NotNull FunctionDescriptor descriptor, boolean kFunction) {
094 int arity = descriptor.getValueParameters().size();
095
096 ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter();
097 ReceiverParameterDescriptor expectedThisObject = descriptor.getExpectedThisObject();
098
099 List<TypeProjection> typeArguments = new ArrayList<TypeProjection>(arity + 2);
100 if (receiverParameter != null) {
101 typeArguments.add(new TypeProjectionImpl(receiverParameter.getType()));
102 }
103 else if (kFunction && expectedThisObject != null) {
104 typeArguments.add(new TypeProjectionImpl(expectedThisObject.getType()));
105 }
106
107 for (ValueParameterDescriptor parameter : descriptor.getValueParameters()) {
108 typeArguments.add(new TypeProjectionImpl(parameter.getType()));
109 }
110
111 typeArguments.add(new TypeProjectionImpl(descriptor.getReturnType()));
112
113 ClassDescriptor classDescriptor;
114 if (kFunction) {
115 if (expectedThisObject != null) {
116 classDescriptor = K_MEMBER_FUNCTIONS.get(arity);
117 }
118 else if (receiverParameter != null) {
119 classDescriptor = K_EXTENSION_FUNCTIONS.get(arity);
120 }
121 else {
122 classDescriptor = K_FUNCTIONS.get(arity);
123 }
124 }
125 else {
126 if (receiverParameter != null) {
127 classDescriptor = EXTENSION_FUNCTIONS.get(arity);
128 }
129 else {
130 classDescriptor = FUNCTIONS.get(arity);
131 }
132 }
133
134 return new JetTypeImpl(
135 classDescriptor.getDefaultType().getAnnotations(),
136 classDescriptor.getTypeConstructor(),
137 false,
138 typeArguments,
139 classDescriptor.getMemberScope(typeArguments)
140 );
141 }
142
143 private static void createFunctionImpl(
144 @NotNull List<ClassDescriptor> result,
145 @NotNull PackageFragmentDescriptor containingDeclaration,
146 @NotNull String name,
147 @NotNull ClassDescriptor functionInterface
148 ) {
149 MutableClassDescriptor functionImpl = new MutableClassDescriptor(
150 containingDeclaration,
151 containingDeclaration.getMemberScope(),
152 ClassKind.CLASS,
153 false,
154 Name.identifier(name)
155 );
156 functionImpl.setModality(Modality.FINAL);
157 functionImpl.setVisibility(Visibilities.PUBLIC);
158 functionImpl.setTypeParameterDescriptors(functionInterface.getDefaultType().getConstructor().getParameters());
159 functionImpl.createTypeConstructor();
160
161 result.add(functionImpl);
162 }
163
164 @NotNull
165 public static Type getFunctionTraitClassName(@NotNull FunctionDescriptor descriptor) {
166 int paramCount = descriptor.getValueParameters().size();
167 if (descriptor.getReceiverParameter() != null) {
168 return Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/ExtensionFunction" + paramCount);
169 }
170 else {
171 return Type.getObjectType(BUILT_INS_PACKAGE_FQ_NAME + "/Function" + paramCount);
172 }
173 }
174
175 @NotNull
176 public static Type getFunctionImplType(@NotNull FunctionDescriptor descriptor) {
177 int paramCount = descriptor.getValueParameters().size();
178 if (descriptor.getReceiverParameter() != null) {
179 return Type.getObjectType("kotlin/ExtensionFunctionImpl" + paramCount);
180 }
181 else {
182 return Type.getObjectType("kotlin/FunctionImpl" + paramCount);
183 }
184 }
185 }