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 }