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