OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library inferrer_visitor; | 5 library inferrer_visitor; |
6 | 6 |
7 import '../constants/constant_system.dart'; | 7 import '../constants/constant_system.dart'; |
8 import '../constants/expressions.dart'; | 8 import '../constants/expressions.dart'; |
9 import '../dart2jslib.dart' hide Selector, TypedSelector; | 9 import '../dart2jslib.dart' hide Selector, TypedSelector; |
10 import '../dart_types.dart'; | 10 import '../dart_types.dart'; |
11 import '../elements/elements.dart'; | 11 import '../elements/elements.dart'; |
| 12 import '../resolution/operators.dart'; |
12 import '../tree/tree.dart'; | 13 import '../tree/tree.dart'; |
13 import '../universe/universe.dart'; | 14 import '../universe/universe.dart'; |
14 import '../util/util.dart'; | 15 import '../util/util.dart'; |
15 import '../types/types.dart' show TypeMask; | 16 import '../types/types.dart' show TypeMask; |
16 import '../types/constants.dart' show computeTypeMask; | 17 import '../types/constants.dart' show computeTypeMask; |
17 import 'dart:collection' show IterableMixin; | 18 import 'dart:collection' show IterableMixin; |
18 | 19 |
19 /** | 20 /** |
20 * The interface [InferrerVisitor] will use when working on types. | 21 * The interface [InferrerVisitor] will use when working on types. |
21 */ | 22 */ |
(...skipping 954 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
976 narrow(receiverElement, objectType, node); | 977 narrow(receiverElement, objectType, node); |
977 } | 978 } |
978 if (Elements.isLocal(argumentElement)) { | 979 if (Elements.isLocal(argumentElement)) { |
979 narrow(argumentElement, objectType, node); | 980 narrow(argumentElement, objectType, node); |
980 } | 981 } |
981 } | 982 } |
982 } | 983 } |
983 } | 984 } |
984 } | 985 } |
985 | 986 |
986 T visitOperatorSend(Send node) { | 987 @override |
987 Operator op = node.selector; | 988 T visitIndex(Send node, Node receiver, Node index, _) { |
988 if ("[]" == op.source) { | 989 return visitDynamicSend(node); |
989 return visitDynamicSend(node); | 990 } |
990 } else if ("&&" == op.source) { | 991 |
991 conditionIsSimple = false; | 992 @override |
992 bool oldAccumulateIsChecks = accumulateIsChecks; | 993 T visitLogicalAnd(Send node, Node left, Node right, _) { |
993 List<Send> oldIsChecks = isChecks; | 994 conditionIsSimple = false; |
994 if (!accumulateIsChecks) { | 995 bool oldAccumulateIsChecks = accumulateIsChecks; |
995 accumulateIsChecks = true; | 996 List<Send> oldIsChecks = isChecks; |
996 isChecks = <Send>[]; | 997 if (!accumulateIsChecks) { |
| 998 accumulateIsChecks = true; |
| 999 isChecks = <Send>[]; |
| 1000 } |
| 1001 visit(left); |
| 1002 LocalsHandler<T> saved = locals; |
| 1003 locals = new LocalsHandler<T>.from(locals, node); |
| 1004 updateIsChecks(isChecks, usePositive: true); |
| 1005 LocalsHandler<T> narrowed; |
| 1006 if (oldAccumulateIsChecks) { |
| 1007 narrowed = new LocalsHandler<T>.topLevelCopyOf(locals); |
| 1008 } else { |
| 1009 accumulateIsChecks = false; |
| 1010 isChecks = oldIsChecks; |
| 1011 } |
| 1012 visit(right); |
| 1013 if (oldAccumulateIsChecks) { |
| 1014 |
| 1015 bool invalidatedInRightHandSide (Send test) { |
| 1016 Element receiver = elements[test.receiver]; |
| 1017 if (receiver is LocalElement) { |
| 1018 return narrowed.locals[receiver] != locals.locals[receiver]; |
| 1019 } |
| 1020 return false; |
997 } | 1021 } |
998 visit(node.receiver); | |
999 LocalsHandler<T> saved = locals; | |
1000 locals = new LocalsHandler<T>.from(locals, node); | |
1001 updateIsChecks(isChecks, usePositive: true); | |
1002 LocalsHandler<T> narrowed; | |
1003 if (oldAccumulateIsChecks) { | |
1004 narrowed = new LocalsHandler<T>.topLevelCopyOf(locals); | |
1005 } else { | |
1006 accumulateIsChecks = false; | |
1007 isChecks = oldIsChecks; | |
1008 } | |
1009 visit(node.arguments.head); | |
1010 if (oldAccumulateIsChecks) { | |
1011 | 1022 |
1012 bool invalidatedInRightHandSide (Send test) { | 1023 isChecks.removeWhere(invalidatedInRightHandSide); |
1013 Element receiver = elements[test.receiver]; | 1024 } |
1014 if (receiver is LocalElement) { | 1025 saved.mergeDiamondFlow(locals, null); |
1015 return narrowed.locals[receiver] != locals.locals[receiver]; | 1026 locals = saved; |
1016 } | 1027 return types.boolType; |
1017 return false; | 1028 } |
1018 } | |
1019 | 1029 |
1020 isChecks.removeWhere(invalidatedInRightHandSide); | 1030 @override |
1021 } | 1031 T visitLogicalOr(Send node, Node left, Node right, _) { |
1022 saved.mergeDiamondFlow(locals, null); | 1032 conditionIsSimple = false; |
1023 locals = saved; | 1033 List<Send> tests = <Send>[]; |
1024 return types.boolType; | 1034 bool isSimple = handleCondition(left, tests); |
1025 } else if ("||" == op.source) { | 1035 LocalsHandler<T> saved = locals; |
1026 conditionIsSimple = false; | 1036 locals = new LocalsHandler<T>.from(locals, node); |
1027 List<Send> tests = <Send>[]; | 1037 if (isSimple) updateIsChecks(tests, usePositive: false); |
1028 bool isSimple = handleCondition(node.receiver, tests); | 1038 bool oldAccumulateIsChecks = accumulateIsChecks; |
1029 LocalsHandler<T> saved = locals; | 1039 accumulateIsChecks = false; |
1030 locals = new LocalsHandler<T>.from(locals, node); | 1040 visit(right); |
1031 if (isSimple) updateIsChecks(tests, usePositive: false); | 1041 accumulateIsChecks = oldAccumulateIsChecks; |
1032 bool oldAccumulateIsChecks = accumulateIsChecks; | 1042 saved.mergeDiamondFlow(locals, null); |
1033 accumulateIsChecks = false; | 1043 locals = saved; |
1034 visit(node.arguments.head); | 1044 return types.boolType; |
1035 accumulateIsChecks = oldAccumulateIsChecks; | 1045 } |
1036 saved.mergeDiamondFlow(locals, null); | 1046 |
1037 locals = saved; | 1047 @override |
1038 return types.boolType; | 1048 T visitNot(Send node, Node expression, _) { |
1039 } else if ("!" == op.source) { | 1049 bool oldAccumulateIsChecks = accumulateIsChecks; |
1040 bool oldAccumulateIsChecks = accumulateIsChecks; | 1050 accumulateIsChecks = false; |
1041 accumulateIsChecks = false; | 1051 visit(expression); |
1042 node.visitChildren(this); | 1052 accumulateIsChecks = oldAccumulateIsChecks; |
1043 accumulateIsChecks = oldAccumulateIsChecks; | 1053 return types.boolType; |
1044 return types.boolType; | 1054 } |
1045 } else if ("is" == op.source) { | 1055 |
1046 potentiallyAddIsCheck(node); | 1056 @override |
1047 node.visitChildren(this); | 1057 T visitIs(Send node, Node expression, DartType type, _) { |
1048 return types.boolType; | 1058 potentiallyAddIsCheck(node); |
1049 } else if ("as" == op.source) { | 1059 visit(expression); |
1050 T receiverType = visit(node.receiver); | 1060 return types.boolType; |
1051 DartType type = elements.getType(node.arguments.head); | 1061 } |
1052 return types.narrowType(receiverType, type); | 1062 |
1053 } else if (node.argumentsNode is Prefix) { | 1063 @override |
1054 // Unary operator. | 1064 T visitIsNot(Send node, Node expression, DartType type, _) { |
1055 return visitDynamicSend(node); | 1065 potentiallyAddIsCheck(node); |
1056 } else if ('===' == op.source | 1066 visit(expression); |
1057 || '!==' == op.source) { | 1067 return types.boolType; |
1058 node.visitChildren(this); | 1068 } |
1059 return types.boolType; | 1069 |
1060 } else if ('!=' == op.source) { | 1070 @override |
1061 visitDynamicSend(node); | 1071 T visitAs(Send node, Node expression, DartType type, _) { |
1062 return types.boolType; | 1072 T receiverType = visit(expression); |
1063 } else { | 1073 return types.narrowType(receiverType, type); |
1064 // Binary operator. | 1074 } |
1065 return visitDynamicSend(node); | 1075 |
1066 } | 1076 @override |
| 1077 T visitUnary(Send node, UnaryOperator operator, Node expression, _) { |
| 1078 return visitDynamicSend(node); |
| 1079 } |
| 1080 |
| 1081 @override |
| 1082 T visitNotEquals(Send node, Node left, Node right, _) { |
| 1083 visitDynamicSend(node); |
| 1084 return types.boolType; |
| 1085 } |
| 1086 |
| 1087 @override |
| 1088 T visitEquals(Send node, Node left, Node right, _) { |
| 1089 return visitDynamicSend(node); |
| 1090 } |
| 1091 |
| 1092 @override |
| 1093 T visitBinary(Send node, Node left, BinaryOperator operator, Node right, _) { |
| 1094 return visitDynamicSend(node); |
1067 } | 1095 } |
1068 | 1096 |
1069 // Because some nodes just visit their children, we may end up | 1097 // Because some nodes just visit their children, we may end up |
1070 // visiting a type annotation, that may contain a send in case of a | 1098 // visiting a type annotation, that may contain a send in case of a |
1071 // prefixed type. Therefore we explicitly visit the type annotation | 1099 // prefixed type. Therefore we explicitly visit the type annotation |
1072 // to avoid confusing the [ResolvedVisitor]. | 1100 // to avoid confusing the [ResolvedVisitor]. |
1073 visitTypeAnnotation(TypeAnnotation node) {} | 1101 visitTypeAnnotation(TypeAnnotation node) {} |
1074 | 1102 |
1075 T visitConditional(Conditional node) { | 1103 T visitConditional(Conditional node) { |
1076 List<Send> tests = <Send>[]; | 1104 List<Send> tests = <Send>[]; |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1298 | 1326 |
1299 T visitContinueStatement(ContinueStatement node) { | 1327 T visitContinueStatement(ContinueStatement node) { |
1300 JumpTarget target = elements.getTargetOf(node); | 1328 JumpTarget target = elements.getTargetOf(node); |
1301 locals.seenBreakOrContinue = true; | 1329 locals.seenBreakOrContinue = true; |
1302 // Do a deep-copy of the locals, because the code following the | 1330 // Do a deep-copy of the locals, because the code following the |
1303 // continue will change them. | 1331 // continue will change them. |
1304 continuesFor[target].add(new LocalsHandler<T>.deepCopyOf(locals)); | 1332 continuesFor[target].add(new LocalsHandler<T>.deepCopyOf(locals)); |
1305 return null; | 1333 return null; |
1306 } | 1334 } |
1307 | 1335 |
1308 void internalError(Spannable node, String reason) { | 1336 internalError(Spannable node, String reason) { |
1309 compiler.internalError(node, reason); | 1337 compiler.internalError(node, reason); |
1310 } | 1338 } |
1311 | 1339 |
1312 T visitSwitchStatement(SwitchStatement node) { | 1340 T visitSwitchStatement(SwitchStatement node) { |
1313 visit(node.parenthesizedExpression); | 1341 visit(node.parenthesizedExpression); |
1314 | 1342 |
1315 setupBreaksAndContinues(elements.getTargetDefinition(node)); | 1343 setupBreaksAndContinues(elements.getTargetDefinition(node)); |
1316 if (Elements.switchStatementHasContinue(node, elements)) { | 1344 if (Elements.switchStatementHasContinue(node, elements)) { |
1317 void forEachLabeledCase(void action(JumpTarget target)) { | 1345 void forEachLabeledCase(void action(JumpTarget target)) { |
1318 for (SwitchCase switchCase in node.cases) { | 1346 for (SwitchCase switchCase in node.cases) { |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1377 return type; | 1405 return type; |
1378 } | 1406 } |
1379 | 1407 |
1380 T visitCascade(Cascade node) { | 1408 T visitCascade(Cascade node) { |
1381 // Ignore the result of the cascade send and return the type of the cascade | 1409 // Ignore the result of the cascade send and return the type of the cascade |
1382 // receiver. | 1410 // receiver. |
1383 visit(node.expression); | 1411 visit(node.expression); |
1384 return cascadeReceiverStack.removeLast(); | 1412 return cascadeReceiverStack.removeLast(); |
1385 } | 1413 } |
1386 } | 1414 } |
OLD | NEW |