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