001 /* 002 * Copyright 2010-2015 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.kotlin.codegen.inline; 018 019 import org.jetbrains.annotations.NotNull; 020 import org.jetbrains.annotations.Nullable; 021 import org.jetbrains.kotlin.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 TypeRemapper typeRemapper; 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 TypeRemapper typeRemapper, 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.typeRemapper = typeRemapper; 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> newTypeMappings, 082 @NotNull AnonymousObjectGeneration anonymousObjectGeneration 083 ) { 084 return new RegeneratedClassContext(this, expressionMap, state, generator, 085 new TypeRemapper(typeRemapper, newTypeMappings), 086 reifedTypeInliner, isInliningLambda, anonymousObjectGeneration); 087 } 088 089 public InliningContext subInline(NameGenerator generator, Map<String, String> additionalTypeMappings, boolean isInliningLambda) { 090 return subInline(generator, additionalTypeMappings, isInliningLambda, classRegeneration); 091 } 092 093 private InliningContext subInline( 094 NameGenerator generator, 095 Map<String, String> additionalTypeMappings, 096 boolean isInliningLambda, 097 boolean isRegeneration 098 ) { 099 return new InliningContext(this, expressionMap, state, generator, 100 new TypeRemapper(typeRemapper, additionalTypeMappings), reifedTypeInliner, isInliningLambda, isRegeneration); 101 } 102 103 public boolean isRoot() { 104 return parent == null; 105 } 106 107 @NotNull 108 public RootInliningContext getRoot() { 109 if (isRoot()) { 110 return (RootInliningContext) this; 111 } 112 else { 113 return parent.getRoot(); 114 } 115 } 116 117 @Nullable 118 public InliningContext getParent() { 119 return parent; 120 } 121 122 public boolean isInliningLambdaRootContext() { 123 //noinspection ConstantConditions 124 return isInliningLambda && !getParent().isInliningLambda; 125 } 126 127 public String getClassNameToInline() { 128 assert parent != null : "At least root context should return proper value"; 129 return parent.getClassNameToInline(); 130 } 131 }