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 org.jetbrains.annotations.NotNull;
020    import org.jetbrains.jet.lang.descriptors.*;
021    import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
022    import org.jetbrains.jet.lang.descriptors.impl.ModuleDescriptorImpl;
023    import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
024    import org.jetbrains.jet.lang.descriptors.impl.MutablePackageFragmentDescriptor;
025    import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
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.*;
032    import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
033    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
034    
035    import java.util.*;
036    
037    public class JvmRuntimeTypes {
038        private final ReflectionTypes reflectionTypes;
039    
040        private final ClassDescriptor functionImpl;
041        private final ClassDescriptor extensionFunctionImpl;
042        private final ClassDescriptor kFunctionImpl;
043        private final ClassDescriptor kMemberFunctionImpl;
044        private final ClassDescriptor kExtensionFunctionImpl;
045    
046        public JvmRuntimeTypes(@NotNull ReflectionTypes reflectionTypes) {
047            this.reflectionTypes = reflectionTypes;
048    
049            ModuleDescriptor fakeModule = new ModuleDescriptorImpl(Name.special("<fake module for functions impl>"),
050                                                                   Collections.<ImportPath>emptyList(), JavaToKotlinClassMap.getInstance());
051    
052            PackageFragmentDescriptor kotlinJvmInternal =
053                    new MutablePackageFragmentDescriptor(fakeModule, new FqName("kotlin.jvm.internal"));
054            PackageFragmentDescriptor kotlinReflectJvmInternal =
055                    new MutablePackageFragmentDescriptor(fakeModule, new FqName("kotlin.reflect.jvm.internal"));
056    
057            this.functionImpl = createClass(kotlinJvmInternal, "FunctionImpl", "out R");
058            this.extensionFunctionImpl = createClass(kotlinJvmInternal, "ExtensionFunctionImpl", "in T", "out R");
059            this.kFunctionImpl = createClass(kotlinReflectJvmInternal, "KFunctionImpl", "out R");
060            this.kExtensionFunctionImpl = createClass(kotlinReflectJvmInternal, "KExtensionFunctionImpl", "in T", "out R");
061            this.kMemberFunctionImpl = createClass(kotlinReflectJvmInternal, "KMemberFunctionImpl", "in T", "out R");
062        }
063    
064        @NotNull
065        private static ClassDescriptor createClass(
066                @NotNull PackageFragmentDescriptor packageFragment,
067                @NotNull String name,
068                @NotNull String... typeParameters
069        ) {
070            MutableClassDescriptor descriptor = new MutableClassDescriptor(packageFragment, packageFragment.getMemberScope(),
071                                                                           ClassKind.CLASS, false, Name.identifier(name), SourceElement.NO_SOURCE);
072            List<TypeParameterDescriptor> typeParameterDescriptors = new ArrayList<TypeParameterDescriptor>(typeParameters.length);
073            for (int i = 0; i < typeParameters.length; i++) {
074                String[] s = typeParameters[i].split(" ");
075                Variance variance = Variance.valueOf(s[0].toUpperCase() + "_VARIANCE");
076                String typeParameterName = s[1];
077                TypeParameterDescriptorImpl typeParameter = TypeParameterDescriptorImpl.createForFurtherModification(
078                        descriptor, Annotations.EMPTY, false, variance, Name.identifier(typeParameterName), i, SourceElement.NO_SOURCE
079                );
080                typeParameter.setInitialized();
081                typeParameterDescriptors.add(typeParameter);
082            }
083    
084            descriptor.setModality(Modality.FINAL);
085            descriptor.setVisibility(Visibilities.PUBLIC);
086            descriptor.setTypeParameterDescriptors(typeParameterDescriptors);
087            descriptor.createTypeConstructor();
088    
089            return descriptor;
090        }
091    
092        @NotNull
093        public Collection<JetType> getSupertypesForClosure(@NotNull FunctionDescriptor descriptor) {
094            ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter();
095    
096            List<TypeProjection> typeArguments = new ArrayList<TypeProjection>(2);
097    
098            ClassDescriptor classDescriptor;
099            if (receiverParameter != null) {
100                classDescriptor = extensionFunctionImpl;
101                typeArguments.add(new TypeProjectionImpl(receiverParameter.getType()));
102            }
103            else {
104                classDescriptor = functionImpl;
105            }
106    
107            //noinspection ConstantConditions
108            typeArguments.add(new TypeProjectionImpl(descriptor.getReturnType()));
109    
110            JetType functionImplType = new JetTypeImpl(
111                    classDescriptor.getDefaultType().getAnnotations(),
112                    classDescriptor.getTypeConstructor(),
113                    false,
114                    typeArguments,
115                    classDescriptor.getMemberScope(typeArguments)
116            );
117    
118            JetType functionType = KotlinBuiltIns.getInstance().getFunctionType(
119                    Annotations.EMPTY,
120                    receiverParameter == null ? null : receiverParameter.getType(),
121                    ExpressionTypingUtils.getValueParametersTypes(descriptor.getValueParameters()),
122                    descriptor.getReturnType()
123            );
124    
125            return Arrays.asList(functionImplType, functionType);
126        }
127    
128        @NotNull
129        public Collection<JetType> getSupertypesForFunctionReference(@NotNull FunctionDescriptor descriptor) {
130            ReceiverParameterDescriptor extensionReceiver = descriptor.getExtensionReceiverParameter();
131            ReceiverParameterDescriptor dispatchReceiver = descriptor.getDispatchReceiverParameter();
132    
133            List<TypeProjection> typeArguments = new ArrayList<TypeProjection>(2);
134    
135            ClassDescriptor classDescriptor;
136            JetType receiverType;
137            if (extensionReceiver != null) {
138                classDescriptor = kExtensionFunctionImpl;
139                receiverType = extensionReceiver.getType();
140                typeArguments.add(new TypeProjectionImpl(receiverType));
141            }
142            else if (dispatchReceiver != null) {
143                classDescriptor = kMemberFunctionImpl;
144                receiverType = dispatchReceiver.getType();
145                typeArguments.add(new TypeProjectionImpl(receiverType));
146            }
147            else {
148                classDescriptor = kFunctionImpl;
149                receiverType = null;
150            }
151    
152            //noinspection ConstantConditions
153            typeArguments.add(new TypeProjectionImpl(descriptor.getReturnType()));
154    
155            JetType kFunctionImplType = new JetTypeImpl(
156                    classDescriptor.getDefaultType().getAnnotations(),
157                    classDescriptor.getTypeConstructor(),
158                    false,
159                    typeArguments,
160                    classDescriptor.getMemberScope(typeArguments)
161            );
162    
163            JetType kFunctionType = reflectionTypes.getKFunctionType(
164                    Annotations.EMPTY,
165                    receiverType,
166                    ExpressionTypingUtils.getValueParametersTypes(descriptor.getValueParameters()),
167                    descriptor.getReturnType(),
168                    extensionReceiver != null
169            );
170    
171            return Arrays.asList(kFunctionImplType, kFunctionType);
172        }
173    }