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.state;
018    
019    import com.google.common.collect.Lists;
020    import com.intellij.psi.PsiElement;
021    import org.jetbrains.annotations.NotNull;
022    import org.jetbrains.annotations.Nullable;
023    import org.jetbrains.asm4.Type;
024    import org.jetbrains.jet.codegen.*;
025    import org.jetbrains.jet.codegen.binding.BindingTraceAware;
026    import org.jetbrains.jet.codegen.binding.CalculatedClosure;
027    import org.jetbrains.jet.codegen.binding.CodegenBinding;
028    import org.jetbrains.jet.codegen.context.EnclosedValueDescriptor;
029    import org.jetbrains.jet.codegen.signature.BothSignatureWriter;
030    import org.jetbrains.jet.codegen.signature.JvmMethodParameterKind;
031    import org.jetbrains.jet.codegen.signature.JvmMethodParameterSignature;
032    import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
033    import org.jetbrains.jet.lang.descriptors.*;
034    import org.jetbrains.jet.lang.psi.*;
035    import org.jetbrains.jet.lang.resolve.BindingContext;
036    import org.jetbrains.jet.lang.resolve.BindingContextUtils;
037    import org.jetbrains.jet.lang.resolve.BindingTrace;
038    import org.jetbrains.jet.lang.resolve.DescriptorUtils;
039    import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor;
040    import org.jetbrains.jet.lang.resolve.java.*;
041    import org.jetbrains.jet.lang.resolve.java.mapping.KotlinToJavaTypesMap;
042    import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
043    import org.jetbrains.jet.lang.resolve.name.Name;
044    import org.jetbrains.jet.lang.types.*;
045    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
046    
047    import java.util.ArrayList;
048    import java.util.Collections;
049    import java.util.List;
050    import java.util.Map;
051    
052    import static org.jetbrains.asm4.Opcodes.*;
053    import static org.jetbrains.jet.codegen.AsmUtil.boxType;
054    import static org.jetbrains.jet.codegen.AsmUtil.getTraitImplThisParameterType;
055    import static org.jetbrains.jet.codegen.CodegenUtil.*;
056    import static org.jetbrains.jet.codegen.FunctionTypesUtil.getFunctionTraitClassName;
057    import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
058    
059    public class JetTypeMapper extends BindingTraceAware {
060    
061        private final ClassBuilderMode classBuilderMode;
062    
063        public JetTypeMapper(BindingTrace bindingTrace, ClassBuilderMode mode) {
064            super(bindingTrace);
065            classBuilderMode = mode;
066        }
067    
068        private enum JetTypeMapperMode {
069            /**
070             * foo.Bar is mapped to Lfoo/Bar;
071             */
072            IMPL,
073            /**
074             * jet.Int is mapped to I
075             */
076            VALUE,
077            /**
078             * jet.Int is mapped to Ljava/lang/Integer;
079             */
080            TYPE_PARAMETER,
081            /**
082             * jet.Int is mapped to Ljava/lang/Integer;
083             * No projections allowed in immediate arguments
084             */
085            SUPER_TYPE
086        }
087    
088        @NotNull
089        public Type getOwner(@NotNull DeclarationDescriptor descriptor, @NotNull OwnerKind kind, boolean isInsideModule) {
090            DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
091            if (containingDeclaration instanceof NamespaceDescriptor) {
092                return asmTypeForNamespace((NamespaceDescriptor) containingDeclaration, descriptor, isInsideModule);
093            }
094            else if (containingDeclaration instanceof ClassDescriptor) {
095                ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
096                return kind == OwnerKind.TRAIT_IMPL ? mapTraitImpl(classDescriptor) : mapClass(classDescriptor);
097            }
098            else if (containingDeclaration instanceof ScriptDescriptor) {
099                return asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) containingDeclaration);
100            }
101            else {
102                throw new UnsupportedOperationException("don't know how to generate owner for parent " + containingDeclaration);
103            }
104        }
105    
106        @NotNull
107        private JavaNamespaceKind getNsKind(@NotNull NamespaceDescriptor ns) {
108            JavaNamespaceKind javaNamespaceKind = bindingContext.get(JavaBindingContext.JAVA_NAMESPACE_KIND, ns);
109            Boolean src = bindingContext.get(BindingContext.NAMESPACE_IS_SRC, ns);
110    
111            if (javaNamespaceKind == null && src == null) {
112                throw new IllegalStateException("unknown namespace origin: " + ns);
113            }
114    
115            if (javaNamespaceKind != null) {
116                if (javaNamespaceKind == JavaNamespaceKind.CLASS_STATICS && src != null) {
117                    throw new IllegalStateException(
118                            "conflicting namespace " + ns + ": it is both java statics and from src");
119                }
120                return javaNamespaceKind;
121            }
122            else {
123                return JavaNamespaceKind.PROPER;
124            }
125        }
126    
127        @NotNull
128        private Type asmTypeForNamespace(
129                @NotNull NamespaceDescriptor namespace,
130                @NotNull DeclarationDescriptor descriptor,
131                boolean insideModule
132        ) {
133            StringBuilder r = new StringBuilder();
134    
135            List<DeclarationDescriptor> path = getPathWithoutRootNsAndModule(namespace);
136    
137            for (DeclarationDescriptor pathElement : path) {
138                NamespaceDescriptor ns = (NamespaceDescriptor) pathElement;
139                if (r.length() > 0) {
140                    JavaNamespaceKind nsKind = getNsKind((NamespaceDescriptor) ns.getContainingDeclaration());
141                    if (nsKind == JavaNamespaceKind.PROPER) {
142                        r.append("/");
143                    }
144                    else if (nsKind == JavaNamespaceKind.CLASS_STATICS) {
145                        r.append("$");
146                    }
147                }
148                r.append(ns.getName());
149            }
150    
151            if (getNsKind(namespace) == JavaNamespaceKind.PROPER) {
152                if (r.length() > 0) {
153                    r.append("/");
154                }
155    
156                JetFile file = BindingContextUtils.getContainingFile(bindingContext, descriptor);
157                if (insideModule && file != null) {
158                    String internalName = NamespaceCodegen.getNamespacePartInternalName(file);
159                    r.append(internalName.substring(r.length()));
160                }
161                else {
162                    r.append(PackageClassUtils.getPackageClassName(namespace.getFqName()));
163                }
164            }
165    
166            if (r.length() == 0) {
167                throw new IllegalStateException("internal error: failed to generate classname for " + namespace);
168            }
169    
170            return Type.getObjectType(r.toString());
171        }
172    
173        @NotNull
174        public static List<DeclarationDescriptor> getPathWithoutRootNsAndModule(@NotNull NamespaceDescriptor descriptor) {
175            List<DeclarationDescriptor> path = new ArrayList<DeclarationDescriptor>();
176            DeclarationDescriptor current = descriptor;
177            while (true) {
178                if (current instanceof NamespaceDescriptor && DescriptorUtils.isRootNamespace((NamespaceDescriptor) current)) {
179                    return Lists.reverse(path);
180                }
181                path.add(current);
182                assert current != null : "Namespace must have a parent: " + descriptor;
183                current = current.getContainingDeclaration();
184            }
185        }
186    
187        @NotNull
188        public Type mapReturnType(@NotNull JetType jetType) {
189            return mapReturnType(jetType, null);
190        }
191    
192        @NotNull
193        private Type mapReturnType(@NotNull JetType jetType, @Nullable BothSignatureWriter signatureVisitor) {
194            if (jetType.equals(KotlinBuiltIns.getInstance().getUnitType())) {
195                if (signatureVisitor != null) {
196                    signatureVisitor.writeAsmType(Type.VOID_TYPE);
197                }
198                return Type.VOID_TYPE;
199            }
200            else if (jetType.equals(KotlinBuiltIns.getInstance().getNothingType())) {
201                if (signatureVisitor != null) {
202                    signatureVisitor.writeNothing();
203                }
204                return Type.VOID_TYPE;
205            }
206            if (jetType.equals(KotlinBuiltIns.getInstance().getNullableNothingType())) {
207                if (signatureVisitor != null) {
208                    signatureVisitor.writeNullableNothing();
209                }
210                return AsmTypeConstants.OBJECT_TYPE;
211            }
212            return mapType(jetType, signatureVisitor, JetTypeMapperMode.VALUE, Variance.OUT_VARIANCE, false);
213        }
214    
215        @NotNull
216        private Type mapType(@NotNull JetType jetType, @NotNull JetTypeMapperMode mode) {
217            return mapType(jetType, null, mode);
218        }
219    
220        @NotNull
221        public Type mapSupertype(@NotNull JetType jetType, @Nullable BothSignatureWriter signatureVisitor) {
222            return mapType(jetType, signatureVisitor, JetTypeMapperMode.SUPER_TYPE);
223        }
224    
225        @NotNull
226        public Type mapClass(@NotNull ClassifierDescriptor classifier) {
227            return mapType(classifier.getDefaultType(), null, JetTypeMapperMode.IMPL);
228        }
229    
230        @NotNull
231        public Type mapType(@NotNull JetType jetType) {
232            return mapType(jetType, null, JetTypeMapperMode.VALUE);
233        }
234    
235        @NotNull
236        public Type mapType(@NotNull VariableDescriptor variableDescriptor) {
237            return mapType(variableDescriptor.getType(), null, JetTypeMapperMode.VALUE);
238        }
239    
240        @NotNull
241        public Type mapType(@NotNull ClassifierDescriptor classifierDescriptor) {
242            return mapType(classifierDescriptor.getDefaultType(), null, JetTypeMapperMode.VALUE);
243        }
244    
245        @NotNull
246        private Type mapType(@NotNull JetType jetType, @Nullable BothSignatureWriter signatureVisitor, @NotNull JetTypeMapperMode mode) {
247            return mapType(jetType, signatureVisitor, mode, Variance.INVARIANT, false);
248        }
249    
250        @NotNull
251        public Type mapType(
252                @NotNull JetType jetType,
253                @Nullable BothSignatureWriter signatureVisitor,
254                @NotNull JetTypeMapperMode kind,
255                @NotNull Variance howThisTypeIsUsed,
256                boolean arrayParameter
257        ) {
258            Type known = null;
259            DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
260    
261            if (descriptor instanceof ClassDescriptor) {
262                FqNameUnsafe className = DescriptorUtils.getFQName(descriptor);
263                if (className.isSafe()) {
264                    known = KotlinToJavaTypesMap.getInstance().getJavaAnalog(className.toSafe(), jetType.isNullable());
265                }
266            }
267    
268            boolean projectionsAllowed = kind != JetTypeMapperMode.SUPER_TYPE;
269            if (known != null) {
270                if (kind == JetTypeMapperMode.VALUE) {
271                    return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed);
272                }
273                else if (kind == JetTypeMapperMode.TYPE_PARAMETER || kind == JetTypeMapperMode.SUPER_TYPE) {
274                    return mapKnownAsmType(jetType, boxType(known), signatureVisitor, howThisTypeIsUsed, arrayParameter, projectionsAllowed);
275                }
276                else if (kind == JetTypeMapperMode.IMPL) {
277                    // TODO: enable and fix tests
278                    //throw new IllegalStateException("must not map known type to IMPL when not compiling builtins: " + jetType);
279                    return mapKnownAsmType(jetType, known, signatureVisitor, howThisTypeIsUsed);
280                }
281                else {
282                    throw new IllegalStateException("unknown kind: " + kind);
283                }
284            }
285    
286            TypeConstructor constructor = jetType.getConstructor();
287            if (constructor instanceof IntersectionTypeConstructor) {
288                jetType = CommonSupertypes.commonSupertype(new ArrayList<JetType>(constructor.getSupertypes()));
289            }
290    
291            if (descriptor == null) {
292                throw new UnsupportedOperationException("no descriptor for type constructor of " + jetType);
293            }
294    
295            if (ErrorUtils.isError(descriptor)) {
296                if (classBuilderMode != ClassBuilderMode.LIGHT_CLASSES) {
297                    throw new IllegalStateException(generateErrorMessageForErrorType(descriptor));
298                }
299                Type asmType = Type.getObjectType("error/NonExistentClass");
300                if (signatureVisitor != null) {
301                    signatureVisitor.writeAsmType(asmType);
302                }
303                return asmType;
304            }
305    
306            if (descriptor instanceof ClassDescriptor && KotlinBuiltIns.getInstance().isArray(jetType)) {
307                if (jetType.getArguments().size() != 1) {
308                    throw new UnsupportedOperationException("arrays must have one type argument");
309                }
310                TypeProjection memberProjection = jetType.getArguments().get(0);
311                JetType memberType = memberProjection.getType();
312    
313                if (signatureVisitor != null) {
314                    signatureVisitor.writeArrayType();
315                    mapType(memberType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER, memberProjection.getProjectionKind(), true);
316                    signatureVisitor.writeArrayEnd();
317                }
318    
319                Type r;
320                if (!isGenericsArray(jetType)) {
321                    r = Type.getType("[" + boxType(mapType(memberType, kind)).getDescriptor());
322                }
323                else {
324                    r = AsmTypeConstants.JAVA_ARRAY_GENERIC_TYPE;
325                }
326                return r;
327            }
328    
329            if (descriptor instanceof ClassDescriptor) {
330                Type asmType = getAsmType(bindingTrace, descriptor);
331                writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, projectionsAllowed);
332                return asmType;
333            }
334    
335            if (descriptor instanceof TypeParameterDescriptor) {
336                TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
337                Type type = mapType(typeParameterDescriptor.getUpperBoundsAsType(), kind);
338                if (signatureVisitor != null) {
339                    signatureVisitor.writeTypeVariable(typeParameterDescriptor.getName(), type);
340                }
341                return type;
342            }
343    
344            throw new UnsupportedOperationException("Unknown type " + jetType);
345        }
346    
347        @NotNull
348        public Type mapTraitImpl(@NotNull ClassDescriptor descriptor) {
349            return Type.getObjectType(getAsmType(bindingTrace, descriptor).getInternalName() + JvmAbi.TRAIT_IMPL_SUFFIX);
350        }
351    
352        private String generateErrorMessageForErrorType(@NotNull DeclarationDescriptor descriptor) {
353            PsiElement declarationElement = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor);
354            PsiElement parentDeclarationElement = null;
355            if (declarationElement != null) {
356                DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
357                if (containingDeclaration != null) {
358                    parentDeclarationElement = BindingContextUtils.descriptorToDeclaration(bindingContext, containingDeclaration);
359                }
360            }
361    
362            return String.format("Error types are not allowed when classBuilderMode = %s. For declaration %s:%s in %s:%s",
363                          classBuilderMode,
364                          declarationElement,
365                          declarationElement != null ? declarationElement.getText() : "null",
366                          parentDeclarationElement,
367                          parentDeclarationElement != null ? parentDeclarationElement.getText() : "null");
368        }
369    
370        private void writeGenericType(
371                BothSignatureWriter signatureVisitor,
372                Type asmType,
373                JetType jetType,
374                Variance howThisTypeIsUsed,
375                boolean projectionsAllowed
376        ) {
377            if (signatureVisitor != null) {
378                signatureVisitor.writeClassBegin(asmType);
379    
380                List<TypeProjection> arguments = jetType.getArguments();
381                for (TypeParameterDescriptor parameter : jetType.getConstructor().getParameters()) {
382                    TypeProjection argument = arguments.get(parameter.getIndex());
383    
384                    Variance projectionKind = projectionsAllowed
385                                              ? getEffectiveVariance(
386                                                        parameter.getVariance(),
387                                                        argument.getProjectionKind(),
388                                                        howThisTypeIsUsed
389                                                )
390                                              : Variance.INVARIANT;
391                    signatureVisitor.writeTypeArgument(projectionKind);
392    
393                    mapType(argument.getType(), signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
394                    signatureVisitor.writeTypeArgumentEnd();
395                }
396                signatureVisitor.writeClassEnd();
397            }
398        }
399    
400        private static Variance getEffectiveVariance(Variance parameterVariance, Variance projectionKind, Variance howThisTypeIsUsed) {
401            // Return type must not contain wildcards
402            if (howThisTypeIsUsed == Variance.OUT_VARIANCE) return projectionKind;
403    
404            if (parameterVariance == Variance.INVARIANT) {
405                return projectionKind;
406            }
407            if (projectionKind == Variance.INVARIANT) {
408                return parameterVariance;
409            }
410            if (parameterVariance == projectionKind) {
411                return parameterVariance;
412            }
413    
414            // In<out X> = In<*>
415            // Out<in X> = Out<*>
416            return Variance.OUT_VARIANCE;
417        }
418    
419        private Type mapKnownAsmType(
420                JetType jetType,
421                Type asmType,
422                @Nullable BothSignatureWriter signatureVisitor,
423                @NotNull Variance howThisTypeIsUsed
424        ) {
425            return mapKnownAsmType(jetType, asmType, signatureVisitor, howThisTypeIsUsed, false, true);
426        }
427    
428        private Type mapKnownAsmType(
429                JetType jetType,
430                Type asmType,
431                @Nullable BothSignatureWriter signatureVisitor,
432                @NotNull Variance howThisTypeIsUsed,
433                boolean arrayParameter,
434                boolean allowProjections
435        ) {
436            if (signatureVisitor != null) {
437                if (jetType.getArguments().isEmpty()) {
438                    if (arrayParameter && howThisTypeIsUsed == Variance.IN_VARIANCE) {
439                        asmType = AsmTypeConstants.OBJECT_TYPE;
440                    }
441                    signatureVisitor.writeAsmType(asmType);
442                }
443                else {
444                    writeGenericType(signatureVisitor, asmType, jetType, howThisTypeIsUsed, allowProjections);
445                }
446            }
447            return asmType;
448        }
449    
450        @NotNull
451        public CallableMethod mapToCallableMethod(
452                @NotNull FunctionDescriptor functionDescriptor,
453                boolean superCall,
454                boolean isInsideClass,
455                boolean isInsideModule,
456                OwnerKind kind
457        ) {
458            DeclarationDescriptor functionParent = functionDescriptor.getOriginal().getContainingDeclaration();
459    
460            functionDescriptor = unwrapFakeOverride(functionDescriptor);
461    
462            JvmMethodSignature descriptor = mapSignature(functionDescriptor.getOriginal(), true, kind);
463            Type owner;
464            Type ownerForDefaultImpl;
465            Type ownerForDefaultParam;
466            int invokeOpcode;
467            Type thisClass;
468            Type calleeType = null;
469    
470            if (isLocalNamedFun(functionDescriptor) || functionDescriptor instanceof ExpressionAsFunctionDescriptor) {
471                if (functionDescriptor instanceof ExpressionAsFunctionDescriptor) {
472                    JetExpression expression = JetPsiUtil.deparenthesize(((ExpressionAsFunctionDescriptor) functionDescriptor).getExpression());
473                    if (expression instanceof JetFunctionLiteralExpression) {
474                        expression = ((JetFunctionLiteralExpression) expression).getFunctionLiteral();
475                    }
476                    functionDescriptor = bindingContext.get(BindingContext.FUNCTION, expression);
477                }
478                functionDescriptor = functionDescriptor.getOriginal();
479    
480                owner = asmTypeForAnonymousClass(bindingContext, functionDescriptor);
481                ownerForDefaultImpl = ownerForDefaultParam = thisClass = owner;
482                invokeOpcode = INVOKEVIRTUAL;
483                descriptor = mapSignature("invoke", functionDescriptor, true, kind);
484                calleeType = owner;
485            }
486            else if (functionParent instanceof NamespaceDescriptor) {
487                assert !superCall;
488                owner = asmTypeForNamespace((NamespaceDescriptor) functionParent, functionDescriptor, isInsideModule);
489                ownerForDefaultImpl = ownerForDefaultParam = owner;
490                invokeOpcode = INVOKESTATIC;
491                thisClass = null;
492            }
493            else if (functionDescriptor instanceof ConstructorDescriptor) {
494                assert !superCall;
495                owner = mapClass((ClassDescriptor) functionParent);
496                ownerForDefaultImpl = ownerForDefaultParam = owner;
497                invokeOpcode = INVOKESPECIAL;
498                thisClass = null;
499            }
500            else if (functionParent instanceof ScriptDescriptor) {
501                thisClass = owner = ownerForDefaultParam = ownerForDefaultImpl =
502                        asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) functionParent);
503                invokeOpcode = INVOKEVIRTUAL;
504            }
505            else if (functionParent instanceof ClassDescriptor) {
506    
507                FunctionDescriptor declarationFunctionDescriptor = findAnyDeclaration(functionDescriptor);
508    
509                ClassDescriptor currentOwner = (ClassDescriptor) functionParent;
510                ClassDescriptor declarationOwner = (ClassDescriptor) declarationFunctionDescriptor.getContainingDeclaration();
511    
512                boolean originalIsInterface = isInterface(declarationOwner);
513                boolean currentIsInterface = isInterface(currentOwner);
514    
515                boolean isAccessor = isAccessor(functionDescriptor);
516    
517                ClassDescriptor receiver;
518                if (currentIsInterface && !originalIsInterface) {
519                    receiver = declarationOwner;
520                }
521                else {
522                    receiver = currentOwner;
523                }
524    
525                // TODO: TYPE_PARAMETER is hack here
526    
527                boolean isInterface = originalIsInterface && currentIsInterface;
528                owner = mapType(receiver.getDefaultType(), JetTypeMapperMode.TYPE_PARAMETER);
529    
530                ClassDescriptor declarationOwnerForDefault = (ClassDescriptor) findBaseDeclaration(functionDescriptor).getContainingDeclaration();
531                ownerForDefaultParam = mapType(declarationOwnerForDefault.getDefaultType(), JetTypeMapperMode.TYPE_PARAMETER);
532                ownerForDefaultImpl = Type.getObjectType(
533                        ownerForDefaultParam.getInternalName() + (isInterface(declarationOwnerForDefault) ? JvmAbi.TRAIT_IMPL_SUFFIX : ""));
534                if (isInterface) {
535                    invokeOpcode = superCall ? INVOKESTATIC : INVOKEINTERFACE;
536                }
537                else {
538                    if (isAccessor) {
539                        invokeOpcode = INVOKESTATIC;
540                    }
541                    else {
542                        boolean isPrivateFunInvocation = isInsideClass && functionDescriptor.getVisibility() == Visibilities.PRIVATE;
543                        invokeOpcode = superCall || isPrivateFunInvocation ? INVOKESPECIAL : INVOKEVIRTUAL;
544                    }
545                }
546    
547                if (isInterface && superCall) {
548                    descriptor = mapSignature(functionDescriptor, false, OwnerKind.TRAIT_IMPL);
549                    owner = Type.getObjectType(owner.getInternalName() + JvmAbi.TRAIT_IMPL_SUFFIX);
550                }
551                thisClass = mapType(receiver.getDefaultType());
552            }
553            else {
554                throw new UnsupportedOperationException("unknown function parent");
555            }
556    
557    
558            Type receiverParameterType;
559            ReceiverParameterDescriptor receiverParameter = functionDescriptor.getOriginal().getReceiverParameter();
560            if (receiverParameter != null) {
561                receiverParameterType = mapType(receiverParameter.getType());
562            }
563            else {
564                receiverParameterType = null;
565            }
566            return new CallableMethod(
567                    owner, ownerForDefaultImpl, ownerForDefaultParam, descriptor, invokeOpcode,
568                    thisClass, receiverParameterType, calleeType);
569        }
570    
571        public static boolean isAccessor(@NotNull CallableMemberDescriptor descriptor) {
572            return descriptor instanceof AccessorForFunctionDescriptor ||
573                   descriptor instanceof AccessorForPropertyDescriptor ||
574                   descriptor instanceof AccessorForPropertyDescriptor.Getter ||
575                   descriptor instanceof AccessorForPropertyDescriptor.Setter;
576        }
577    
578        @NotNull
579        private static FunctionDescriptor findAnyDeclaration(@NotNull FunctionDescriptor function) {
580            if (function.getKind() == CallableMemberDescriptor.Kind.DECLARATION) {
581                return function;
582            }
583            return findBaseDeclaration(function);
584        }
585    
586        @NotNull
587        private static FunctionDescriptor findBaseDeclaration(@NotNull FunctionDescriptor function) {
588            if (function.getOverriddenDescriptors().isEmpty()) {
589                return function;
590            }
591            else {
592                // TODO: prefer class to interface
593                return findBaseDeclaration(function.getOverriddenDescriptors().iterator().next());
594            }
595        }
596    
597        @NotNull
598        public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f, boolean needGenericSignature, @NotNull OwnerKind kind) {
599            String name = f.getName().asString();
600            if (f instanceof PropertyAccessorDescriptor) {
601                boolean isGetter = f instanceof PropertyGetterDescriptor;
602                name = getPropertyAccessorName(((PropertyAccessorDescriptor) f).getCorrespondingProperty(), isGetter);
603            }
604            return mapSignature(name, f, needGenericSignature, kind);
605        }
606    
607        @NotNull
608        public JvmMethodSignature mapSignature(@NotNull Name functionName, @NotNull FunctionDescriptor f) {
609            return mapSignature(functionName.asString(), f, false, OwnerKind.IMPLEMENTATION);
610        }
611    
612        @NotNull
613        public JvmMethodSignature mapSignature(@NotNull FunctionDescriptor f) {
614            return mapSignature(f.getName(), f);
615        }
616    
617        @NotNull
618        private JvmMethodSignature mapSignature(
619                @NotNull String methodName,
620                @NotNull FunctionDescriptor f,
621                boolean needGenericSignature,
622                @NotNull OwnerKind kind
623        ) {
624            if (kind == OwnerKind.TRAIT_IMPL) {
625                needGenericSignature = false;
626            }
627    
628            BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, needGenericSignature);
629    
630            writeFormalTypeParameters(f.getTypeParameters(), signatureVisitor);
631    
632            signatureVisitor.writeParametersStart();
633            writeThisIfNeeded(f, kind, signatureVisitor);
634            writeReceiverIfNeeded(f.getReceiverParameter(), signatureVisitor);
635    
636            for (ValueParameterDescriptor parameter : f.getValueParameters()) {
637                writeParameter(signatureVisitor, parameter.getType());
638            }
639    
640            if (f instanceof ConstructorDescriptor) {
641                writeVoidReturn(signatureVisitor);
642            }
643            else {
644                signatureVisitor.writeReturnType();
645                JetType returnType = f.getReturnType();
646                assert returnType != null : "Function " + f + " has no return type";
647                mapReturnType(returnType, signatureVisitor);
648                signatureVisitor.writeReturnTypeEnd();
649            }
650    
651            return signatureVisitor.makeJvmMethodSignature(methodName);
652        }
653    
654        private static void writeVoidReturn(@NotNull BothSignatureWriter signatureVisitor) {
655            signatureVisitor.writeReturnType();
656            signatureVisitor.writeAsmType(Type.VOID_TYPE);
657            signatureVisitor.writeReturnTypeEnd();
658        }
659    
660        @Nullable
661        public String mapFieldSignature(@NotNull JetType backingFieldType) {
662            BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.TYPE, true);
663            mapType(backingFieldType, signatureVisitor, JetTypeMapperMode.VALUE);
664            return signatureVisitor.makeJavaGenericSignature();
665        }
666    
667        private void writeThisIfNeeded(
668                @NotNull CallableMemberDescriptor descriptor,
669                @NotNull OwnerKind kind,
670                @NotNull BothSignatureWriter signatureVisitor
671        ) {
672            if (kind == OwnerKind.TRAIT_IMPL) {
673                ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration();
674                Type type = getTraitImplThisParameterType(containingDeclaration, this);
675    
676                signatureVisitor.writeParameterType(JvmMethodParameterKind.THIS);
677                signatureVisitor.writeAsmType(type);
678                signatureVisitor.writeParameterTypeEnd();
679            }
680            else {
681                writeThisForAccessorIfNeeded(descriptor, signatureVisitor);
682            }
683        }
684    
685        private void writeThisForAccessorIfNeeded(@NotNull CallableMemberDescriptor descriptor, @NotNull BothSignatureWriter signatureVisitor) {
686            if (isAccessor(descriptor) && descriptor.getExpectedThisObject() != null) {
687                signatureVisitor.writeParameterType(JvmMethodParameterKind.THIS);
688                mapType(((ClassifierDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), signatureVisitor, JetTypeMapperMode.VALUE);
689                signatureVisitor.writeParameterTypeEnd();
690            }
691        }
692    
693    
694        public void writeFormalTypeParameters(List<TypeParameterDescriptor> typeParameters, BothSignatureWriter signatureVisitor) {
695            if (signatureVisitor == null) return;
696    
697            for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
698                writeFormalTypeParameter(typeParameterDescriptor, signatureVisitor);
699            }
700        }
701    
702        private void writeFormalTypeParameter(TypeParameterDescriptor typeParameterDescriptor, BothSignatureWriter signatureVisitor) {
703            signatureVisitor.writeFormalTypeParameter(typeParameterDescriptor.getName().asString());
704    
705            classBound:
706            {
707                signatureVisitor.writeClassBound();
708    
709                for (JetType jetType : typeParameterDescriptor.getUpperBounds()) {
710                    if (jetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
711                        if (!isInterface(jetType)) {
712                            mapType(jetType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
713                            break classBound;
714                        }
715                    }
716                }
717    
718                // "extends Object" is optional according to ClassFileFormat-Java5.pdf
719                // but javac complaints to signature:
720                // <P:>Ljava/lang/Object;
721                // TODO: avoid writing java/lang/Object if interface list is not empty
722            }
723            signatureVisitor.writeClassBoundEnd();
724    
725            for (JetType jetType : typeParameterDescriptor.getUpperBounds()) {
726                if (jetType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
727                    if (isInterface(jetType)) {
728                        signatureVisitor.writeInterfaceBound();
729                        mapType(jetType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
730                        signatureVisitor.writeInterfaceBoundEnd();
731                    }
732                }
733                if (jetType.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
734                    signatureVisitor.writeInterfaceBound();
735                    mapType(jetType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
736                    signatureVisitor.writeInterfaceBoundEnd();
737                }
738            }
739        }
740    
741        private void writeReceiverIfNeeded(@Nullable ReceiverParameterDescriptor receiver, BothSignatureWriter signatureWriter) {
742            if (receiver != null) {
743                signatureWriter.writeParameterType(JvmMethodParameterKind.RECEIVER);
744                mapType(receiver.getType(), signatureWriter, JetTypeMapperMode.VALUE);
745                signatureWriter.writeParameterTypeEnd();
746            }
747        }
748    
749        @NotNull
750        public static String getPropertyAccessorName(@NotNull PropertyDescriptor descriptor, boolean isGetter) {
751            DeclarationDescriptor parentDescriptor = descriptor.getContainingDeclaration();
752            boolean isAnnotation = parentDescriptor instanceof ClassDescriptor &&
753                                   ((ClassDescriptor) parentDescriptor).getKind() == ClassKind.ANNOTATION_CLASS;
754            return isAnnotation ? descriptor.getName().asString() :
755                   isGetter ? PropertyCodegen.getterName(descriptor.getName()) : PropertyCodegen.setterName(descriptor.getName());
756        }
757    
758        @NotNull
759        public JvmMethodSignature mapGetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
760            // TODO: do not genClassOrObject generics if not needed
761            BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true);
762    
763            writeFormalTypeParameters(descriptor.getTypeParameters(), signatureWriter);
764    
765            signatureWriter.writeParametersStart();
766            writeThisIfNeeded(descriptor, kind, signatureWriter);
767            writeReceiverIfNeeded(descriptor.getReceiverParameter(), signatureWriter);
768    
769            signatureWriter.writeReturnType();
770            mapType(descriptor.getType(), signatureWriter, JetTypeMapperMode.VALUE, Variance.OUT_VARIANCE, false);
771            signatureWriter.writeReturnTypeEnd();
772    
773            String name = getPropertyAccessorName(descriptor, true);
774            return signatureWriter.makeJvmMethodSignature(name);
775        }
776    
777    
778        @NotNull
779        public JvmMethodSignature mapSetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
780            assert descriptor.isVar();
781    
782            // TODO: generics signature is not always needed
783            BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true);
784    
785            writeFormalTypeParameters(descriptor.getTypeParameters(), signatureWriter);
786    
787            signatureWriter.writeParametersStart();
788            writeThisIfNeeded(descriptor, kind, signatureWriter);
789            writeReceiverIfNeeded(descriptor.getReceiverParameter(), signatureWriter);
790            writeParameter(signatureWriter, descriptor.getType());
791    
792            writeVoidReturn(signatureWriter);
793    
794            String name = getPropertyAccessorName(descriptor, false);
795            return signatureWriter.makeJvmMethodSignature(name);
796        }
797    
798        private void writeParameter(@NotNull BothSignatureWriter signatureWriter, @NotNull JetType outType) {
799            signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE);
800            mapType(outType, signatureWriter, JetTypeMapperMode.VALUE);
801            signatureWriter.writeParameterTypeEnd();
802        }
803    
804        @NotNull
805        public JvmMethodSignature mapConstructorSignature(@NotNull ConstructorDescriptor descriptor) {
806            return mapConstructorSignature(descriptor, bindingContext.get(CodegenBinding.CLOSURE, descriptor.getContainingDeclaration()));
807        }
808    
809        @NotNull
810        public JvmMethodSignature mapConstructorSignature(@NotNull ConstructorDescriptor descriptor, @Nullable CalculatedClosure closure) {
811    
812            BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true);
813    
814            // constructor type parmeters are fake
815            writeFormalTypeParameters(Collections.<TypeParameterDescriptor>emptyList(), signatureWriter);
816    
817            signatureWriter.writeParametersStart();
818    
819            ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
820            ClassDescriptor captureThis = getExpectedThisObjectForConstructorCall(descriptor, closure);
821            if (captureThis != null) {
822                signatureWriter.writeParameterType(JvmMethodParameterKind.OUTER);
823                mapType(captureThis.getDefaultType(), signatureWriter, JetTypeMapperMode.VALUE);
824                signatureWriter.writeParameterTypeEnd();
825            }
826    
827            ClassifierDescriptor captureReceiver = closure != null ? closure.getCaptureReceiver() : null;
828            if (captureReceiver != null) {
829                signatureWriter.writeParameterType(JvmMethodParameterKind.RECEIVER);
830                mapType(captureReceiver.getDefaultType(), signatureWriter, JetTypeMapperMode.VALUE);
831                signatureWriter.writeParameterTypeEnd();
832            }
833    
834            if (containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY) {
835                signatureWriter.writeParameterType(JvmMethodParameterKind.ENUM_NAME);
836                mapType(KotlinBuiltIns.getInstance().getStringType(), signatureWriter, JetTypeMapperMode.VALUE);
837                signatureWriter.writeParameterTypeEnd();
838                signatureWriter.writeParameterType(JvmMethodParameterKind.ENUM_ORDINAL);
839                mapType(KotlinBuiltIns.getInstance().getIntType(), signatureWriter, JetTypeMapperMode.VALUE);
840                signatureWriter.writeParameterTypeEnd();
841            }
842    
843            if (closure != null) {
844                for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closure.getCaptureVariables().entrySet()) {
845                    DeclarationDescriptor variableDescriptor = entry.getKey();
846                    Type type = null;
847                    if (variableDescriptor instanceof VariableDescriptor && !(variableDescriptor instanceof PropertyDescriptor)) {
848                        Type sharedVarType = getSharedVarType(variableDescriptor);
849                        if (sharedVarType == null) {
850                            sharedVarType = mapType(((VariableDescriptor) variableDescriptor).getType());
851                        }
852                        type = sharedVarType;
853                    }
854                    else if (isLocalNamedFun(variableDescriptor)) {
855                        type = asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) variableDescriptor);
856                    }
857    
858                    if (type != null) {
859                        signatureWriter.writeParameterType(JvmMethodParameterKind.SHARED_VAR);
860                        signatureWriter.writeAsmType(type);
861                        signatureWriter.writeParameterTypeEnd();
862                    }
863                }
864    
865                JetDelegatorToSuperCall superCall = closure.getSuperCall();
866                if (superCall != null) {
867                    DeclarationDescriptor superDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET,
868                                                                                                        superCall
869                                                                                                                .getCalleeExpression()
870                                                                                                                .getConstructorReferenceExpression());
871    
872                    if(superDescriptor instanceof ConstructorDescriptor) {
873                        ConstructorDescriptor superConstructor = (ConstructorDescriptor) superDescriptor;
874    
875                        if (isObjectLiteral(bindingContext, descriptor.getContainingDeclaration())) {
876                            List<JvmMethodParameterSignature> types = mapConstructorSignature(superConstructor).getKotlinParameterTypes();
877                            if (types != null) {
878                                for (JvmMethodParameterSignature type : types) {
879                                    signatureWriter.writeParameterType(JvmMethodParameterKind.SUPER_CALL_PARAM);
880                                    signatureWriter.writeAsmType(type.getAsmType());
881                                    signatureWriter.writeParameterTypeEnd();
882                                }
883                            }
884                        }
885                    }
886                }
887            }
888    
889            for (ValueParameterDescriptor parameter : descriptor.getOriginal().getValueParameters()) {
890                writeParameter(signatureWriter, parameter.getType());
891            }
892    
893            writeVoidReturn(signatureWriter);
894    
895            return signatureWriter.makeJvmMethodSignature("<init>");
896        }
897    
898        @NotNull
899        public JvmMethodSignature mapScriptSignature(@NotNull ScriptDescriptor script, @NotNull List<ScriptDescriptor> importedScripts) {
900            BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, false);
901    
902            writeFormalTypeParameters(Collections.<TypeParameterDescriptor>emptyList(), signatureWriter);
903    
904            signatureWriter.writeParametersStart();
905    
906            for (ScriptDescriptor importedScript : importedScripts) {
907                signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE);
908                ClassDescriptor descriptor = bindingContext.get(CLASS_FOR_SCRIPT, importedScript);
909                assert descriptor != null;
910                mapType(descriptor.getDefaultType(), signatureWriter, JetTypeMapperMode.VALUE);
911                signatureWriter.writeParameterTypeEnd();
912            }
913    
914            for (ValueParameterDescriptor valueParameter : script.getValueParameters()) {
915                writeParameter(signatureWriter, valueParameter.getType());
916            }
917    
918            writeVoidReturn(signatureWriter);
919    
920            return signatureWriter.makeJvmMethodSignature("<init>");
921        }
922    
923        @NotNull
924        public CallableMethod mapToCallableMethod(@NotNull ConstructorDescriptor descriptor) {
925            return mapToCallableMethod(descriptor, bindingContext.get(CodegenBinding.CLOSURE, descriptor.getContainingDeclaration()));
926        }
927    
928        @NotNull
929        public CallableMethod mapToCallableMethod(@NotNull ConstructorDescriptor descriptor, @Nullable CalculatedClosure closure) {
930            JvmMethodSignature method = mapConstructorSignature(descriptor, closure);
931            ClassDescriptor container = descriptor.getContainingDeclaration();
932            Type owner = mapClass(container);
933            if (owner.getSort() != Type.OBJECT) {
934                throw new IllegalStateException("type must have been mapped to object: " + container.getDefaultType() + ", actual: " + owner);
935            }
936            return new CallableMethod(owner, owner, owner, method, INVOKESPECIAL, null, null, null);
937        }
938    
939    
940        private static boolean isGenericsArray(JetType type) {
941            return KotlinBuiltIns.getInstance().isArray(type) &&
942                   type.getArguments().get(0).getType().getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor;
943        }
944    
945        public Type getSharedVarType(DeclarationDescriptor descriptor) {
946            if (descriptor instanceof PropertyDescriptor) {
947                return StackValue.sharedTypeForType(mapType(((PropertyDescriptor) descriptor).getReceiverParameter().getType()));
948            }
949            else if (descriptor instanceof SimpleFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) {
950                return asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor);
951            }
952            else if (descriptor instanceof FunctionDescriptor) {
953                return StackValue.sharedTypeForType(mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType()));
954            }
955            else if (descriptor instanceof VariableDescriptor && isVarCapturedInClosure(bindingContext, descriptor)) {
956                JetType outType = ((VariableDescriptor) descriptor).getType();
957                return StackValue.sharedTypeForType(mapType(outType));
958            }
959            return null;
960        }
961    
962        @NotNull
963        public CallableMethod mapToFunctionInvokeCallableMethod(@NotNull FunctionDescriptor fd) {
964            JvmMethodSignature descriptor = erasedInvokeSignature(fd);
965            Type owner = getFunctionTraitClassName(fd);
966            Type receiverParameterType;
967            ReceiverParameterDescriptor receiverParameter = fd.getOriginal().getReceiverParameter();
968            if (receiverParameter != null) {
969                receiverParameterType = mapType(receiverParameter.getType());
970            }
971            else {
972                receiverParameterType = null;
973            }
974            return new CallableMethod(owner, null, null, descriptor, INVOKEINTERFACE, owner, receiverParameterType, owner);
975        }
976    
977        @NotNull
978        public Type expressionType(JetExpression expr) {
979            JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, expr);
980            return asmTypeOrVoid(type);
981        }
982    
983        @NotNull
984        private Type asmTypeOrVoid(@Nullable JetType type) {
985            return type == null ? Type.VOID_TYPE : mapType(type);
986        }
987    }