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 017package org.jetbrains.jet.codegen; 018 019import com.google.common.collect.ImmutableMap; 020import org.jetbrains.annotations.NotNull; 021import org.jetbrains.annotations.Nullable; 022import org.jetbrains.jet.lang.descriptors.*; 023import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; 024import org.jetbrains.jet.lang.resolve.java.JvmClassName; 025import org.jetbrains.jet.lang.resolve.name.Name; 026import org.jetbrains.jet.lang.resolve.scopes.JetScope; 027import org.jetbrains.jet.lang.types.JetType; 028import org.jetbrains.jet.lang.types.JetTypeImpl; 029import org.jetbrains.jet.lang.types.TypeProjection; 030import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 031 032import java.util.ArrayList; 033import java.util.List; 034 035public 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}