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 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 RegeneratedClassContext(this, expressionMap, state, generator, 087 newTypeMappings, reifedTypeInliner, isInliningLambda, anonymousObjectGeneration); 088 } 089 090 public InliningContext subInline(NameGenerator generator, Map<String, String> additionalTypeMappings, boolean isInliningLambda) { 091 return subInline(generator, additionalTypeMappings, isInliningLambda, classRegeneration); 092 } 093 094 private InliningContext subInline( 095 NameGenerator generator, 096 Map<String, String> additionalTypeMappings, 097 boolean isInliningLambda, 098 boolean isRegeneration 099 ) { 100 Map<String, String> newTypeMappings = new HashMap<String, String>(typeMapping); 101 newTypeMappings.putAll(additionalTypeMappings); 102 return new InliningContext(this, expressionMap, state, generator, 103 newTypeMappings, reifedTypeInliner, isInliningLambda, isRegeneration); 104 } 105 106 public boolean isRoot() { 107 return parent == null; 108 } 109 110 @NotNull 111 public RootInliningContext getRoot() { 112 if (isRoot()) { 113 return (RootInliningContext) this; 114 } 115 else { 116 return parent.getRoot(); 117 } 118 } 119 120 @Nullable 121 public InliningContext getParent() { 122 return parent; 123 } 124 125 public boolean isInliningLambdaRootContext() { 126 //noinspection ConstantConditions 127 return isInliningLambda && !getParent().isInliningLambda; 128 } 129 130 public String getClassNameToInline() { 131 assert parent != null : "At least root context should return proper value"; 132 return parent.getClassNameToInline(); 133 } 134 }