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.context;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.jet.codegen.OwnerKind;
022    import org.jetbrains.jet.codegen.StackValue;
023    import org.jetbrains.jet.codegen.binding.MutableClosure;
024    import org.jetbrains.jet.codegen.state.GenerationState;
025    import org.jetbrains.jet.lang.descriptors.*;
026    import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
027    import org.jetbrains.org.objectweb.asm.Label;
028    
029    public class MethodContext extends CodegenContext<CallableMemberDescriptor> {
030        private final boolean isInliningLambda;
031        private Label methodStartLabel;
032    
033        protected MethodContext(
034                @NotNull FunctionDescriptor contextDescriptor,
035                @NotNull OwnerKind contextKind,
036                @NotNull CodegenContext parentContext,
037                @Nullable MutableClosure closure,
038                boolean isInliningLambda
039        ) {
040            super(contextDescriptor instanceof PropertyAccessorDescriptor
041                  ? ((PropertyAccessorDescriptor) contextDescriptor).getCorrespondingProperty()
042                  : contextDescriptor, contextKind, parentContext, closure,
043                  parentContext.hasThisDescriptor() ? parentContext.getThisDescriptor() : null, null);
044            this.isInliningLambda = isInliningLambda;
045        }
046    
047        @NotNull
048        @Override
049        public CodegenContext getParentContext() {
050            //noinspection ConstantConditions
051            return super.getParentContext();
052        }
053    
054        @Override
055        public StackValue lookupInContext(DeclarationDescriptor d, @Nullable StackValue result, GenerationState state, boolean ignoreNoOuter) {
056            if (getContextDescriptor() == d) {
057                return result != null ? result : StackValue.local(0, AsmTypeConstants.OBJECT_TYPE);
058            }
059    
060            return getParentContext().lookupInContext(d, result, state, ignoreNoOuter);
061        }
062    
063        @Override
064        public boolean isStatic() {
065            return getParentContext().isStatic();
066        }
067    
068        @Override
069        public StackValue getOuterExpression(StackValue prefix, boolean ignoreNoOuter) {
070            return getParentContext().getOuterExpression(prefix, false);
071        }
072    
073        @Nullable
074        public Label getMethodStartLabel() {
075            return methodStartLabel;
076        }
077    
078        public void setMethodStartLabel(@NotNull Label methodStartLabel) {
079            this.methodStartLabel = methodStartLabel;
080        }
081    
082        @Override
083        public String toString() {
084            return "Method: " + getContextDescriptor();
085        }
086    
087        public boolean isInlineFunction() {
088            DeclarationDescriptor descriptor = getContextDescriptor();
089            if (descriptor instanceof SimpleFunctionDescriptor) {
090                return ((SimpleFunctionDescriptor) descriptor).getInlineStrategy().isInline();
091            }
092            return false;
093        }
094    
095        public boolean isInliningLambda() {
096            return isInliningLambda;
097        }
098    
099        public boolean isSpecialStackValue(StackValue stackValue) {
100            if (isInliningLambda && stackValue instanceof StackValue.Composed) {
101                StackValue prefix = ((StackValue.Composed) stackValue).prefix;
102                StackValue suffix = ((StackValue.Composed) stackValue).suffix;
103                if (prefix instanceof StackValue.Local && ((StackValue.Local) prefix).index == 0) {
104                    return suffix instanceof StackValue.Field;
105                }
106            }
107            return false;
108        }
109    }