| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2013, the Dart project authors. | 2 * Copyright (c) 2013, the Dart project authors. |
| 3 * | 3 * |
| 4 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not u
se this file except | 4 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not u
se this file except |
| 5 * in compliance with the License. You may obtain a copy of the License at | 5 * in compliance with the License. You may obtain a copy of the License at |
| 6 * | 6 * |
| 7 * http://www.eclipse.org/legal/epl-v10.html | 7 * http://www.eclipse.org/legal/epl-v10.html |
| 8 * | 8 * |
| 9 * Unless required by applicable law or agreed to in writing, software distribut
ed under the License | 9 * Unless required by applicable law or agreed to in writing, software distribut
ed under the License |
| 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY K
IND, either express | 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY K
IND, either express |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 safelyVisit(leftOperand); | 237 safelyVisit(leftOperand); |
| 238 if (rightOperand != null) { | 238 if (rightOperand != null) { |
| 239 try { | 239 try { |
| 240 overrideManager.enterScope(); | 240 overrideManager.enterScope(); |
| 241 promoteManager.enterScope(); | 241 promoteManager.enterScope(); |
| 242 propagateTrueState(leftOperand); | 242 propagateTrueState(leftOperand); |
| 243 // Type promotion. | 243 // Type promotion. |
| 244 promoteTypes(leftOperand); | 244 promoteTypes(leftOperand); |
| 245 clearTypePromotionsIfPotentiallyMutatedIn(leftOperand); | 245 clearTypePromotionsIfPotentiallyMutatedIn(leftOperand); |
| 246 clearTypePromotionsIfPotentiallyMutatedIn(rightOperand); | 246 clearTypePromotionsIfPotentiallyMutatedIn(rightOperand); |
| 247 clearTypePromotionsIfAccessedInScopeAndProtentiallyMutated(rightOperan
d); | 247 clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(rightOper
and); |
| 248 // Visit right operand. | 248 // Visit right operand. |
| 249 rightOperand.accept(this); | 249 rightOperand.accept(this); |
| 250 } finally { | 250 } finally { |
| 251 overrideManager.exitScope(); | 251 overrideManager.exitScope(); |
| 252 promoteManager.exitScope(); | 252 promoteManager.exitScope(); |
| 253 } | 253 } |
| 254 } | 254 } |
| 255 } else if (operatorType == TokenType.BAR_BAR) { | 255 } else if (operatorType == TokenType.BAR_BAR) { |
| 256 safelyVisit(leftOperand); | 256 safelyVisit(leftOperand); |
| 257 if (rightOperand != null) { | 257 if (rightOperand != null) { |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 safelyVisit(condition); | 357 safelyVisit(condition); |
| 358 Expression thenExpression = node.getThenExpression(); | 358 Expression thenExpression = node.getThenExpression(); |
| 359 if (thenExpression != null) { | 359 if (thenExpression != null) { |
| 360 try { | 360 try { |
| 361 overrideManager.enterScope(); | 361 overrideManager.enterScope(); |
| 362 promoteManager.enterScope(); | 362 promoteManager.enterScope(); |
| 363 propagateTrueState(condition); | 363 propagateTrueState(condition); |
| 364 // Type promotion. | 364 // Type promotion. |
| 365 promoteTypes(condition); | 365 promoteTypes(condition); |
| 366 clearTypePromotionsIfPotentiallyMutatedIn(thenExpression); | 366 clearTypePromotionsIfPotentiallyMutatedIn(thenExpression); |
| 367 clearTypePromotionsIfAccessedInScopeAndProtentiallyMutated(thenExpressio
n); | 367 clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(thenExpress
ion); |
| 368 // Visit "then" expression. | 368 // Visit "then" expression. |
| 369 thenExpression.accept(this); | 369 thenExpression.accept(this); |
| 370 } finally { | 370 } finally { |
| 371 overrideManager.exitScope(); | 371 overrideManager.exitScope(); |
| 372 promoteManager.exitScope(); | 372 promoteManager.exitScope(); |
| 373 } | 373 } |
| 374 } | 374 } |
| 375 Expression elseExpression = node.getElseExpression(); | 375 Expression elseExpression = node.getElseExpression(); |
| 376 if (elseExpression != null) { | 376 if (elseExpression != null) { |
| 377 try { | 377 try { |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 HashMap<Element, Type> thenOverrides = null; | 565 HashMap<Element, Type> thenOverrides = null; |
| 566 Statement thenStatement = node.getThenStatement(); | 566 Statement thenStatement = node.getThenStatement(); |
| 567 if (thenStatement != null) { | 567 if (thenStatement != null) { |
| 568 try { | 568 try { |
| 569 overrideManager.enterScope(); | 569 overrideManager.enterScope(); |
| 570 promoteManager.enterScope(); | 570 promoteManager.enterScope(); |
| 571 propagateTrueState(condition); | 571 propagateTrueState(condition); |
| 572 // Type promotion. | 572 // Type promotion. |
| 573 promoteTypes(condition); | 573 promoteTypes(condition); |
| 574 clearTypePromotionsIfPotentiallyMutatedIn(thenStatement); | 574 clearTypePromotionsIfPotentiallyMutatedIn(thenStatement); |
| 575 clearTypePromotionsIfAccessedInScopeAndProtentiallyMutated(thenStatement
); | 575 clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(thenStateme
nt); |
| 576 // Visit "then". | 576 // Visit "then". |
| 577 visitStatementInScope(thenStatement); | 577 visitStatementInScope(thenStatement); |
| 578 } finally { | 578 } finally { |
| 579 thenOverrides = overrideManager.captureLocalOverrides(); | 579 thenOverrides = overrideManager.captureLocalOverrides(); |
| 580 overrideManager.exitScope(); | 580 overrideManager.exitScope(); |
| 581 promoteManager.exitScope(); | 581 promoteManager.exitScope(); |
| 582 } | 582 } |
| 583 } | 583 } |
| 584 HashMap<Element, Type> elseOverrides = null; | 584 HashMap<Element, Type> elseOverrides = null; |
| 585 Statement elseStatement = node.getElseStatement(); | 585 Statement elseStatement = node.getElseStatement(); |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 916 return; | 916 return; |
| 917 } | 917 } |
| 918 } | 918 } |
| 919 Type currentType = getBestType(element); | 919 Type currentType = getBestType(element); |
| 920 if (currentType == null || !currentType.isMoreSpecificThan(potentialType)) { | 920 if (currentType == null || !currentType.isMoreSpecificThan(potentialType)) { |
| 921 overrideManager.setType(element, potentialType); | 921 overrideManager.setType(element, potentialType); |
| 922 } | 922 } |
| 923 } | 923 } |
| 924 | 924 |
| 925 /** | 925 /** |
| 926 * If it is appropriate to do so, promotes the current type of the static elem
ent associated with | |
| 927 * the given expression with the given type. Generally speaking, it is appropr
iate if the given | |
| 928 * type is more specific than the current type. | |
| 929 * | |
| 930 * @param expression the expression used to access the static element whose ty
pes might be | |
| 931 * promoted | |
| 932 * @param potentialType the potential type of the elements | |
| 933 */ | |
| 934 protected void promote(Expression expression, Type potentialType) { | |
| 935 VariableElement element = getPromotionStaticElement(expression); | |
| 936 if (element != null) { | |
| 937 // may be mutated somewhere in closure | |
| 938 if (((VariableElementImpl) element).isPotentiallyMutatedInClosure()) { | |
| 939 return; | |
| 940 } | |
| 941 // prepare current variable type | |
| 942 Type type = expression.getStaticType(); | |
| 943 // Declared type should not be "dynamic". | |
| 944 if (type == null || type.isDynamic()) { | |
| 945 return; | |
| 946 } | |
| 947 // Promoted type should not be "dynamic". | |
| 948 if (potentialType == null || potentialType.isDynamic()) { | |
| 949 return; | |
| 950 } | |
| 951 // Promoted type should be more specific than declared. | |
| 952 if (!potentialType.isMoreSpecificThan(type)) { | |
| 953 return; | |
| 954 } | |
| 955 // Do promote type of variable. | |
| 956 promoteManager.setType(element, potentialType); | |
| 957 } | |
| 958 } | |
| 959 | |
| 960 /** | |
| 961 * Report a conditional analysis error with the given error code and arguments
. | 926 * Report a conditional analysis error with the given error code and arguments
. |
| 962 * | 927 * |
| 963 * @param enclosingElement the enclosing element | 928 * @param enclosingElement the enclosing element |
| 964 * @param errorCode the error code of the error to be reported | 929 * @param errorCode the error code of the error to be reported |
| 965 * @param node the node specifying the location of the error | 930 * @param node the node specifying the location of the error |
| 966 * @param arguments the arguments to the error, used to compose the error mess
age | 931 * @param arguments the arguments to the error, used to compose the error mess
age |
| 967 */ | 932 */ |
| 968 protected void reportErrorProxyConditionalAnalysisError(Element enclosingEleme
nt, | 933 protected void reportErrorProxyConditionalAnalysisError(Element enclosingEleme
nt, |
| 969 ErrorCode errorCode, ASTNode node, Object... arguments) { | 934 ErrorCode errorCode, ASTNode node, Object... arguments) { |
| 970 proxyConditionalAnalysisErrors.add(new ProxyConditionalAnalysisError( | 935 proxyConditionalAnalysisErrors.add(new ProxyConditionalAnalysisError( |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1060 // propagateFalseState(condition); | 1025 // propagateFalseState(condition); |
| 1061 } | 1026 } |
| 1062 | 1027 |
| 1063 /** | 1028 /** |
| 1064 * Checks each promoted variable in the current scope for compliance with the
following | 1029 * Checks each promoted variable in the current scope for compliance with the
following |
| 1065 * specification statement: | 1030 * specification statement: |
| 1066 * <p> | 1031 * <p> |
| 1067 * If the variable <i>v</i> is accessed by a closure in <i>s<sub>1</sub></i> t
hen the variable | 1032 * If the variable <i>v</i> is accessed by a closure in <i>s<sub>1</sub></i> t
hen the variable |
| 1068 * <i>v</i> is not potentially mutated anywhere in the scope of <i>v</i>. | 1033 * <i>v</i> is not potentially mutated anywhere in the scope of <i>v</i>. |
| 1069 */ | 1034 */ |
| 1070 private void clearTypePromotionsIfAccessedInScopeAndProtentiallyMutated(ASTNod
e target) { | 1035 private void clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(ASTN
ode target) { |
| 1071 for (Element element : promoteManager.getPromotedElements()) { | 1036 for (Element element : promoteManager.getPromotedElements()) { |
| 1072 if (((VariableElementImpl) element).isPotentiallyMutatedInScope()) { | 1037 if (((VariableElementImpl) element).isPotentiallyMutatedInScope()) { |
| 1073 if (isVariableAccessedInClosure(element, target)) { | 1038 if (isVariableAccessedInClosure(element, target)) { |
| 1074 promoteManager.setType(element, null); | 1039 promoteManager.setType(element, null); |
| 1075 } | 1040 } |
| 1076 } | 1041 } |
| 1077 } | 1042 } |
| 1078 } | 1043 } |
| 1079 | 1044 |
| 1080 /** | 1045 /** |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1295 result[0] |= true; | 1260 result[0] |= true; |
| 1296 } | 1261 } |
| 1297 } | 1262 } |
| 1298 return null; | 1263 return null; |
| 1299 } | 1264 } |
| 1300 }); | 1265 }); |
| 1301 return result[0]; | 1266 return result[0]; |
| 1302 } | 1267 } |
| 1303 | 1268 |
| 1304 /** | 1269 /** |
| 1270 * If it is appropriate to do so, promotes the current type of the static elem
ent associated with |
| 1271 * the given expression with the given type. Generally speaking, it is appropr
iate if the given |
| 1272 * type is more specific than the current type. |
| 1273 * |
| 1274 * @param expression the expression used to access the static element whose ty
pes might be |
| 1275 * promoted |
| 1276 * @param potentialType the potential type of the elements |
| 1277 */ |
| 1278 private void promote(Expression expression, Type potentialType) { |
| 1279 VariableElement element = getPromotionStaticElement(expression); |
| 1280 if (element != null) { |
| 1281 // may be mutated somewhere in closure |
| 1282 if (((VariableElementImpl) element).isPotentiallyMutatedInClosure()) { |
| 1283 return; |
| 1284 } |
| 1285 // prepare current variable type |
| 1286 Type type = promoteManager.getType(element); |
| 1287 if (type == null) { |
| 1288 type = expression.getStaticType(); |
| 1289 } |
| 1290 // Declared type should not be "dynamic". |
| 1291 if (type == null || type.isDynamic()) { |
| 1292 return; |
| 1293 } |
| 1294 // Promoted type should not be "dynamic". |
| 1295 if (potentialType == null || potentialType.isDynamic()) { |
| 1296 return; |
| 1297 } |
| 1298 // Promoted type should be more specific than declared. |
| 1299 if (!potentialType.isMoreSpecificThan(type)) { |
| 1300 return; |
| 1301 } |
| 1302 // Do promote type of variable. |
| 1303 promoteManager.setType(element, potentialType); |
| 1304 } |
| 1305 } |
| 1306 |
| 1307 /** |
| 1305 * Promotes type information using given condition. | 1308 * Promotes type information using given condition. |
| 1306 */ | 1309 */ |
| 1307 private void promoteTypes(Expression condition) { | 1310 private void promoteTypes(Expression condition) { |
| 1308 if (condition instanceof BinaryExpression) { | 1311 if (condition instanceof BinaryExpression) { |
| 1309 BinaryExpression binary = (BinaryExpression) condition; | 1312 BinaryExpression binary = (BinaryExpression) condition; |
| 1310 if (binary.getOperator().getType() == TokenType.AMPERSAND_AMPERSAND) { | 1313 if (binary.getOperator().getType() == TokenType.AMPERSAND_AMPERSAND) { |
| 1311 Expression left = binary.getLeftOperand(); | 1314 Expression left = binary.getLeftOperand(); |
| 1312 Expression right = binary.getRightOperand(); | 1315 Expression right = binary.getRightOperand(); |
| 1313 promoteTypes(left); | 1316 promoteTypes(left); |
| 1314 promoteTypes(right); | 1317 promoteTypes(right); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1395 * | 1398 * |
| 1396 * @param expression the node whose type is to be recorded | 1399 * @param expression the node whose type is to be recorded |
| 1397 * @param type the propagated type of the node | 1400 * @param type the propagated type of the node |
| 1398 */ | 1401 */ |
| 1399 private void recordPropagatedType(Expression expression, Type type) { | 1402 private void recordPropagatedType(Expression expression, Type type) { |
| 1400 if (type != null && !type.isDynamic()) { | 1403 if (type != null && !type.isDynamic()) { |
| 1401 expression.setPropagatedType(type); | 1404 expression.setPropagatedType(type); |
| 1402 } | 1405 } |
| 1403 } | 1406 } |
| 1404 } | 1407 } |
| OLD | NEW |