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.inline;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.annotations.Nullable;
021 import org.jetbrains.jet.codegen.state.GenerationState;
022
023 import java.util.Collections;
024 import java.util.HashMap;
025 import java.util.Map;
026
027 public class InliningContext {
028
029 @Nullable
030 private final InliningContext parent;
031
032 public final Map<Integer, LambdaInfo> expressionMap;
033
034 public final GenerationState state;
035
036 public final NameGenerator nameGenerator;
037
038 public final Map<String, String> typeMapping;
039
040 public final boolean isInliningLambda;
041
042 public final boolean classRegeneration;
043
044 protected InliningContext(
045 @Nullable InliningContext parent,
046 @NotNull Map<Integer, LambdaInfo> map,
047 @NotNull GenerationState state,
048 @NotNull NameGenerator nameGenerator,
049 @NotNull Map<String, String> typeMapping,
050 boolean isInliningLambda,
051 boolean classRegeneration
052 ) {
053 this.parent = parent;
054 expressionMap = map;
055 this.state = state;
056 this.nameGenerator = nameGenerator;
057 this.typeMapping = typeMapping;
058 this.isInliningLambda = isInliningLambda;
059 this.classRegeneration = classRegeneration;
060 }
061
062 public InliningContext subInline(NameGenerator generator) {
063 return subInline(generator, Collections.<String, String>emptyMap());
064 }
065
066 public InliningContext subInlineLambda(LambdaInfo lambdaInfo) {
067 Map<String, String> map = new HashMap<String, String>();
068 map.put(lambdaInfo.getLambdaClassType().getInternalName(), null); //mark lambda inlined
069 return subInline(nameGenerator.subGenerator("lambda"), map, true);
070 }
071
072 public InliningContext subInline(NameGenerator generator, Map<String, String> additionalTypeMappings) {
073 return subInline(generator, additionalTypeMappings, isInliningLambda);
074 }
075
076 public InliningContext subInlineWithClassRegeneration(@NotNull NameGenerator generator,
077 @NotNull Map<String, String> additionalTypeMappings,
078 @NotNull ConstructorInvocation constructorInvocation) {
079 Map<String, String> newTypeMappings = new HashMap<String, String>(typeMapping);
080 newTypeMappings.putAll(additionalTypeMappings);
081 return new RegenetedClassContext(this, expressionMap, state, generator,
082 newTypeMappings, isInliningLambda, constructorInvocation);
083
084 }
085
086 public InliningContext subInline(NameGenerator generator, Map<String, String> additionalTypeMappings, boolean isInliningLambda) {
087 return subInline(generator, additionalTypeMappings, isInliningLambda, classRegeneration);
088 }
089
090 private InliningContext subInline(
091 NameGenerator generator,
092 Map<String, String> additionalTypeMappings,
093 boolean isInliningLambda,
094 boolean isRegeneration
095 ) {
096 Map<String, String> newTypeMappings = new HashMap<String, String>(typeMapping);
097 newTypeMappings.putAll(additionalTypeMappings);
098 return new InliningContext(this, expressionMap, state, generator,
099 newTypeMappings, isInliningLambda, isRegeneration);
100 }
101
102 public boolean isRoot() {
103 return parent == null;
104 }
105
106 @NotNull
107 public RootInliningContext getRoot() {
108 if (isRoot()) {
109 return (RootInliningContext) this;
110 }
111 else {
112 return parent.getRoot();
113 }
114 }
115
116 @Nullable
117 public InliningContext getParent() {
118 return parent;
119 }
120
121 public boolean isInliningLambdaRootContext() {
122 //noinspection ConstantConditions
123 return isInliningLambda && !getParent().isInliningLambda;
124 }
125
126 public String getClassNameToInline() {
127 assert parent != null : "At least root context should return proper value";
128 return parent.getClassNameToInline();
129 }
130 }