| 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'; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 | 108 |
| 109 /** | 109 /** |
| 110 * Returns `true` if `selector` should be updated to reflect the new | 110 * Returns `true` if `selector` should be updated to reflect the new |
| 111 * `receiverType`. | 111 * `receiverType`. |
| 112 */ | 112 */ |
| 113 bool selectorNeedsUpdate(T receiverType, Selector selector); | 113 bool selectorNeedsUpdate(T receiverType, Selector selector); |
| 114 | 114 |
| 115 /** | 115 /** |
| 116 * Returns a new receiver type for this [selector] applied to | 116 * Returns a new receiver type for this [selector] applied to |
| 117 * [receiverType]. | 117 * [receiverType]. |
| 118 * |
| 119 * The option [isConditional] is true when [selector] was seen in a |
| 120 * conditional send (e.g. `a?.selector`), in which case the returned type may |
| 121 * be null. |
| 118 */ | 122 */ |
| 119 T refineReceiver(Selector selector, T receiverType); | 123 T refineReceiver(Selector selector, T receiverType, bool isConditional); |
| 120 | 124 |
| 121 /** | 125 /** |
| 122 * Returns the internal inferrer representation for [mask]. | 126 * Returns the internal inferrer representation for [mask]. |
| 123 */ | 127 */ |
| 124 T getConcreteTypeFor(TypeMask mask); | 128 T getConcreteTypeFor(TypeMask mask); |
| 125 } | 129 } |
| 126 | 130 |
| 127 /** | 131 /** |
| 128 * A variable scope holds types for variables. It has a link to a | 132 * A variable scope holds types for variables. It has a link to a |
| 129 * parent scope, but never changes the types in that parent. Instead, | 133 * parent scope, but never changes the types in that parent. Instead, |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 } | 438 } |
| 435 } | 439 } |
| 436 | 440 |
| 437 void update(LocalElement local, T type, Node node) { | 441 void update(LocalElement local, T type, Node node) { |
| 438 assert(type != null); | 442 assert(type != null); |
| 439 if (compiler.trustTypeAnnotations || compiler.enableTypeAssertions) { | 443 if (compiler.trustTypeAnnotations || compiler.enableTypeAssertions) { |
| 440 type = types.narrowType(type, local.type); | 444 type = types.narrowType(type, local.type); |
| 441 } | 445 } |
| 442 updateLocal() { | 446 updateLocal() { |
| 443 T currentType = locals[local]; | 447 T currentType = locals[local]; |
| 448 |
| 449 SendSet send = node != null ? node.asSendSet() : null; |
| 450 if (send != null && send.isIfNullAssignment && currentType != null) { |
| 451 // If-null assignments may return either the new or the original value. |
| 452 type = types.addPhiInput( |
| 453 local, types.allocatePhi(locals.block, local, currentType), type); |
| 454 } |
| 444 locals[local] = type; | 455 locals[local] = type; |
| 445 if (currentType != type) { | 456 if (currentType != type) { |
| 446 inferrer.recordLocalUpdate(local, type); | 457 inferrer.recordLocalUpdate(local, type); |
| 447 } | 458 } |
| 448 } | 459 } |
| 449 if (capturedAndBoxed.containsKey(local)) { | 460 if (capturedAndBoxed.containsKey(local)) { |
| 450 inferrer.recordTypeOfNonFinalField( | 461 inferrer.recordTypeOfNonFinalField( |
| 451 node, capturedAndBoxed[local], type); | 462 node, capturedAndBoxed[local], type); |
| 452 } else if (inTryBlock) { | 463 } else if (inTryBlock) { |
| 453 // We don't know if an assignment in a try block | 464 // We don't know if an assignment in a try block |
| (...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 981 T visitDynamicPropertyInvoke( | 992 T visitDynamicPropertyInvoke( |
| 982 Send node, | 993 Send node, |
| 983 Node receiver, | 994 Node receiver, |
| 984 NodeList arguments, | 995 NodeList arguments, |
| 985 Selector selector, | 996 Selector selector, |
| 986 _) { | 997 _) { |
| 987 return handleDynamicInvoke(node); | 998 return handleDynamicInvoke(node); |
| 988 } | 999 } |
| 989 | 1000 |
| 990 @override | 1001 @override |
| 1002 T visitIfNotNullDynamicPropertyInvoke( |
| 1003 Send node, |
| 1004 Node receiver, |
| 1005 NodeList arguments, |
| 1006 Selector selector, |
| 1007 _) { |
| 1008 return handleDynamicInvoke(node); |
| 1009 } |
| 1010 |
| 1011 @override |
| 991 T visitThisPropertyInvoke( | 1012 T visitThisPropertyInvoke( |
| 992 Send node, | 1013 Send node, |
| 993 NodeList arguments, | 1014 NodeList arguments, |
| 994 Selector selector, | 1015 Selector selector, |
| 995 _) { | 1016 _) { |
| 996 return handleDynamicInvoke(node); | 1017 return handleDynamicInvoke(node); |
| 997 } | 1018 } |
| 998 | 1019 |
| 999 @override | 1020 @override |
| 1021 T visitIfNull(Send node, Node left, Node right, _) { |
| 1022 T firstType = visit(left); |
| 1023 T secondType = visit(right); |
| 1024 return types.allocateDiamondPhi(firstType, secondType); |
| 1025 } |
| 1026 |
| 1027 @override |
| 1000 T visitLogicalAnd(Send node, Node left, Node right, _) { | 1028 T visitLogicalAnd(Send node, Node left, Node right, _) { |
| 1001 conditionIsSimple = false; | 1029 conditionIsSimple = false; |
| 1002 bool oldAccumulateIsChecks = accumulateIsChecks; | 1030 bool oldAccumulateIsChecks = accumulateIsChecks; |
| 1003 List<Send> oldIsChecks = isChecks; | 1031 List<Send> oldIsChecks = isChecks; |
| 1004 if (!accumulateIsChecks) { | 1032 if (!accumulateIsChecks) { |
| 1005 accumulateIsChecks = true; | 1033 accumulateIsChecks = true; |
| 1006 isChecks = <Send>[]; | 1034 isChecks = <Send>[]; |
| 1007 } | 1035 } |
| 1008 visit(left); | 1036 visit(left); |
| 1009 LocalsHandler<T> saved = locals; | 1037 LocalsHandler<T> saved = locals; |
| (...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1412 return type; | 1440 return type; |
| 1413 } | 1441 } |
| 1414 | 1442 |
| 1415 T visitCascade(Cascade node) { | 1443 T visitCascade(Cascade node) { |
| 1416 // Ignore the result of the cascade send and return the type of the cascade | 1444 // Ignore the result of the cascade send and return the type of the cascade |
| 1417 // receiver. | 1445 // receiver. |
| 1418 visit(node.expression); | 1446 visit(node.expression); |
| 1419 return cascadeReceiverStack.removeLast(); | 1447 return cascadeReceiverStack.removeLast(); |
| 1420 } | 1448 } |
| 1421 } | 1449 } |
| OLD | NEW |