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.AsmUtil;
022 import org.jetbrains.jet.codegen.JvmCodegenUtil;
023 import org.jetbrains.jet.codegen.OwnerKind;
024 import org.jetbrains.jet.codegen.StackValue;
025 import org.jetbrains.jet.codegen.binding.MutableClosure;
026 import org.jetbrains.jet.codegen.state.GenerationState;
027 import org.jetbrains.jet.codegen.state.JetTypeMapper;
028 import org.jetbrains.jet.lang.descriptors.*;
029 import org.jetbrains.org.objectweb.asm.Label;
030 import org.jetbrains.org.objectweb.asm.Type;
031
032 public class MethodContext extends CodegenContext<CallableMemberDescriptor> {
033 private final boolean isInliningLambda;
034 private Label methodStartLabel;
035
036 protected MethodContext(
037 @NotNull FunctionDescriptor contextDescriptor,
038 @NotNull OwnerKind contextKind,
039 @NotNull CodegenContext parentContext,
040 @Nullable MutableClosure closure,
041 boolean isInliningLambda
042 ) {
043 super(JvmCodegenUtil.getDirectMember(contextDescriptor), contextKind, parentContext, closure,
044 parentContext.hasThisDescriptor() ? parentContext.getThisDescriptor() : null, null);
045 this.isInliningLambda = isInliningLambda;
046 }
047
048 @NotNull
049 @Override
050 public CodegenContext getParentContext() {
051 //noinspection ConstantConditions
052 return super.getParentContext();
053 }
054
055 public StackValue getReceiverExpression(JetTypeMapper typeMapper) {
056 assert getCallableDescriptorWithReceiver() != null;
057 @SuppressWarnings("ConstantConditions")
058 Type asmType = typeMapper.mapType(getCallableDescriptorWithReceiver().getExtensionReceiverParameter().getType());
059 return StackValue.local(AsmUtil.getReceiverIndex(this, getContextDescriptor()), asmType);
060 }
061
062 @Override
063 public StackValue lookupInContext(DeclarationDescriptor d, @Nullable StackValue result, GenerationState state, boolean ignoreNoOuter) {
064 if (getContextDescriptor() == d) {
065 return result != null ? result : StackValue.LOCAL_0;
066 }
067
068 return getParentContext().lookupInContext(d, result, state, ignoreNoOuter);
069 }
070
071 @Nullable
072 public StackValue generateReceiver(@NotNull CallableDescriptor descriptor, @NotNull GenerationState state, boolean ignoreNoOuter) {
073 if (getCallableDescriptorWithReceiver() == descriptor) {
074 return getReceiverExpression(state.getTypeMapper());
075 }
076 ReceiverParameterDescriptor parameter = descriptor.getExtensionReceiverParameter();
077 return lookupInContext(parameter, StackValue.LOCAL_0, state, ignoreNoOuter);
078 }
079
080 @Override
081 public boolean isStatic() {
082 return getParentContext().isStatic();
083 }
084
085 @Override
086 public StackValue getOuterExpression(StackValue prefix, boolean ignoreNoOuter) {
087 return getParentContext().getOuterExpression(prefix, false);
088 }
089
090 @Nullable
091 public Label getMethodStartLabel() {
092 return methodStartLabel;
093 }
094
095 public void setMethodStartLabel(@NotNull Label methodStartLabel) {
096 this.methodStartLabel = methodStartLabel;
097 }
098
099 @Override
100 public String toString() {
101 return "Method: " + getContextDescriptor();
102 }
103
104 public boolean isInlineFunction() {
105 DeclarationDescriptor descriptor = getContextDescriptor();
106 if (descriptor instanceof SimpleFunctionDescriptor) {
107 return ((SimpleFunctionDescriptor) descriptor).getInlineStrategy().isInline();
108 }
109 return false;
110 }
111
112 public boolean isInliningLambda() {
113 return isInliningLambda;
114 }
115
116 }