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.lang.types.expressions;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.annotations.Nullable;
021 import org.jetbrains.jet.lang.psi.*;
022 import org.jetbrains.jet.lang.resolve.BindingContext;
023 import org.jetbrains.jet.lang.resolve.BindingContextUtils;
024 import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
025 import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
026 import org.jetbrains.jet.lang.types.DeferredType;
027 import org.jetbrains.jet.lang.types.ErrorUtils;
028 import org.jetbrains.jet.lang.types.JetTypeInfo;
029 import org.jetbrains.jet.util.lazy.ReenteringLazyValueComputationException;
030
031 import static org.jetbrains.jet.lang.diagnostics.Errors.TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM;
032
033 public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetTypeInfo, ExpressionTypingContext> implements ExpressionTypingInternals {
034
035 @Override
036 public JetTypeInfo visitIdeTemplate(JetIdeTemplate expression, ExpressionTypingContext data) {
037 return basic.visitIdeTemplate(expression, data);
038 }
039
040 @NotNull
041 public static ExpressionTypingFacade create() {
042 return new ExpressionTypingVisitorDispatcher(null);
043 }
044
045 @NotNull
046 public static ExpressionTypingInternals createForBlock(WritableScope writableScope) {
047 return new ExpressionTypingVisitorDispatcher(writableScope);
048 }
049
050 private final BasicExpressionTypingVisitor basic;
051 private final ExpressionTypingVisitorForStatements statements;
052 private final ClosureExpressionsTypingVisitor closures = new ClosureExpressionsTypingVisitor(this);
053 private final ControlStructureTypingVisitor controlStructures = new ControlStructureTypingVisitor(this);
054 private final PatternMatchingTypingVisitor patterns = new PatternMatchingTypingVisitor(this);
055
056 private ExpressionTypingVisitorDispatcher(WritableScope writableScope) {
057 this.basic = new BasicExpressionTypingVisitor(this);
058 if (writableScope != null) {
059 this.statements = new ExpressionTypingVisitorForStatements(this, writableScope, basic, controlStructures, patterns);
060 }
061 else {
062 this.statements = null;
063 }
064 }
065
066 @NotNull
067 @Override
068 public JetTypeInfo checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @Nullable JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context) {
069 return basic.checkInExpression(callElement, operationSign, left, right, context);
070 }
071
072 @Override
073 @NotNull
074 public final JetTypeInfo safeGetTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context) {
075 JetTypeInfo typeInfo = getTypeInfo(expression, context);
076 if (typeInfo.getType() != null) {
077 return typeInfo;
078 }
079 return JetTypeInfo.create(ErrorUtils.createErrorType("Type for " + expression.getText()), context.dataFlowInfo);
080 }
081
082 @Override
083 @NotNull
084 public final JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context) {
085 return getTypeInfo(expression, context, this);
086 }
087
088 @Override
089 @NotNull
090 public final JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context, boolean isStatement) {
091 if (!isStatement) return getTypeInfo(expression, context);
092 if (statements != null) {
093 return getTypeInfo(expression, context, statements);
094 }
095 return getTypeInfo(expression, context, createStatementVisitor(context));
096 }
097
098 private ExpressionTypingVisitorForStatements createStatementVisitor(ExpressionTypingContext context) {
099 return new ExpressionTypingVisitorForStatements(this, ExpressionTypingUtils.newWritableScopeImpl(context, "statement scope"), basic, controlStructures, patterns);
100 }
101
102 @Override
103 public void checkStatementType(@NotNull JetExpression expression, ExpressionTypingContext context) {
104 expression.accept(createStatementVisitor(context), context);
105 }
106
107 @NotNull
108 private JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context, JetVisitor<JetTypeInfo, ExpressionTypingContext> visitor) {
109 JetTypeInfo recordedTypeInfo = BindingContextUtils.getRecordedTypeInfo(expression, context.trace.getBindingContext());
110 if (recordedTypeInfo != null) {
111 return recordedTypeInfo;
112 }
113 JetTypeInfo result;
114 try {
115 result = expression.accept(visitor, context);
116 // Some recursive definitions (object expressions) must put their types in the cache manually:
117 if (context.trace.get(BindingContext.PROCESSED, expression)) {
118 return JetTypeInfo.create(context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression),
119 result.getDataFlowInfo());
120 }
121
122 if (result.getType() instanceof DeferredType) {
123 result = JetTypeInfo.create(((DeferredType) result.getType()).getActualType(), result.getDataFlowInfo());
124 }
125 if (result.getType() != null) {
126 context.trace.record(BindingContext.EXPRESSION_TYPE, expression, result.getType());
127 }
128
129 }
130 catch (ReenteringLazyValueComputationException e) {
131 context.trace.report(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM.on(expression));
132 result = JetTypeInfo.create(null, context.dataFlowInfo);
133 }
134
135 if (!context.trace.get(BindingContext.PROCESSED, expression) && !BindingContextUtils.isExpressionWithValidReference(expression, context.trace.getBindingContext())) {
136 context.trace.record(BindingContext.RESOLUTION_SCOPE, expression, context.scope);
137 }
138 context.trace.record(BindingContext.PROCESSED, expression);
139 if (result.getDataFlowInfo() != DataFlowInfo.EMPTY) {
140 context.trace.record(BindingContext.EXPRESSION_DATA_FLOW_INFO, expression, result.getDataFlowInfo());
141 }
142 return result;
143 }
144
145 //////////////////////////////////////////////////////////////////////////////////////////////
146
147 @Override
148 public JetTypeInfo visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, ExpressionTypingContext data) {
149 return expression.accept(closures, data);
150 }
151
152 @Override
153 public JetTypeInfo visitObjectLiteralExpression(JetObjectLiteralExpression expression, ExpressionTypingContext data) {
154 return expression.accept(closures, data);
155 }
156
157 //////////////////////////////////////////////////////////////////////////////////////////////
158
159 @Override
160 public JetTypeInfo visitThrowExpression(JetThrowExpression expression, ExpressionTypingContext data) {
161 return expression.accept(controlStructures, data);
162 }
163
164 @Override
165 public JetTypeInfo visitReturnExpression(JetReturnExpression expression, ExpressionTypingContext data) {
166 return expression.accept(controlStructures, data);
167 }
168
169 @Override
170 public JetTypeInfo visitContinueExpression(JetContinueExpression expression, ExpressionTypingContext data) {
171 return expression.accept(controlStructures, data);
172 }
173
174 @Override
175 public JetTypeInfo visitIfExpression(JetIfExpression expression, ExpressionTypingContext data) {
176 return expression.accept(controlStructures, data);
177 }
178
179 @Override
180 public JetTypeInfo visitTryExpression(JetTryExpression expression, ExpressionTypingContext data) {
181 return expression.accept(controlStructures, data);
182 }
183
184 @Override
185 public JetTypeInfo visitForExpression(JetForExpression expression, ExpressionTypingContext data) {
186 return expression.accept(controlStructures, data);
187 }
188
189 @Override
190 public JetTypeInfo visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext data) {
191 return expression.accept(controlStructures, data);
192 }
193
194 @Override
195 public JetTypeInfo visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext data) {
196 return expression.accept(controlStructures, data);
197 }
198
199 @Override
200 public JetTypeInfo visitBreakExpression(JetBreakExpression expression, ExpressionTypingContext data) {
201 return expression.accept(controlStructures, data);
202 }
203
204 //////////////////////////////////////////////////////////////////////////////////////////////
205
206 @Override
207 public JetTypeInfo visitIsExpression(JetIsExpression expression, ExpressionTypingContext data) {
208 return expression.accept(patterns, data);
209 }
210
211 @Override
212 public JetTypeInfo visitWhenExpression(JetWhenExpression expression, ExpressionTypingContext data) {
213 return expression.accept(patterns, data);
214 }
215
216 //////////////////////////////////////////////////////////////////////////////////////////////
217
218 @Override
219 public JetTypeInfo visitJetElement(JetElement element, ExpressionTypingContext data) {
220 return element.accept(basic, data);
221 }
222 }