| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 part of resolution; | 5 part of resolution; |
| 6 | 6 |
| 7 /// The state of constants in resolutions. | 7 /// The state of constants in resolutions. |
| 8 enum ConstantState { | 8 enum ConstantState { |
| 9 /// Expressions are not required to be constants. | 9 /// Expressions are not required to be constants. |
| 10 NON_CONSTANT, | 10 NON_CONSTANT, |
| (...skipping 856 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 867 // This is a hack for the case of prefix.Type, we need to store | 867 // This is a hack for the case of prefix.Type, we need to store |
| 868 // the element on the selector, so [analyzeConstant] can build | 868 // the element on the selector, so [analyzeConstant] can build |
| 869 // the type literal from the selector. | 869 // the type literal from the selector. |
| 870 registry.useElement(node.selector, target); | 870 registry.useElement(node.selector, target); |
| 871 } | 871 } |
| 872 analyzeConstantDeferred(node.selector, enforceConst: false); | 872 analyzeConstantDeferred(node.selector, enforceConst: false); |
| 873 } | 873 } |
| 874 } | 874 } |
| 875 } | 875 } |
| 876 | 876 |
| 877 /// Check that access to `super` is currently allowed. | 877 /// Check that access to `super` is currently allowed. Returns an |
| 878 bool checkSuperAccess(Send node) { | 878 /// [AccessSemantics] in case of an error, `null` otherwise. |
| 879 AccessSemantics checkSuperAccess(Send node) { |
| 879 if (!inInstanceContext) { | 880 if (!inInstanceContext) { |
| 880 compiler.reportError(node, MessageKind.NO_SUPER_IN_STATIC); | 881 return new StaticAccess.invalid( |
| 881 return false; | 882 reportAndCreateErroneousElement( |
| 883 node, 'super', |
| 884 MessageKind.NO_SUPER_IN_STATIC, {}, |
| 885 isError: true)); |
| 882 } | 886 } |
| 883 if (node.isConditional) { | 887 if (node.isConditional) { |
| 884 // `super?.foo` is not allowed. | 888 // `super?.foo` is not allowed. |
| 885 compiler.reportError(node, MessageKind.INVALID_USE_OF_SUPER); | 889 return new StaticAccess.invalid( |
| 886 return false; | 890 reportAndCreateErroneousElement( |
| 891 node, 'super', |
| 892 MessageKind.INVALID_USE_OF_SUPER, {}, |
| 893 isError: true)); |
| 887 } | 894 } |
| 888 if (currentClass.supertype == null) { | 895 if (currentClass.supertype == null) { |
| 889 // This is just to guard against internal errors, so no need | 896 // This is just to guard against internal errors, so no need |
| 890 // for a real error message. | 897 // for a real error message. |
| 891 compiler.reportError(node, MessageKind.GENERIC, | 898 return new StaticAccess.invalid( |
| 892 {'text': "Object has no superclass"}); | 899 reportAndCreateErroneousElement( |
| 893 return false; | 900 node, 'super', |
| 901 MessageKind.GENERIC, |
| 902 {'text': "Object has no superclass"}, |
| 903 isError: true)); |
| 894 } | 904 } |
| 895 registry.registerSuperUse(node); | 905 registry.registerSuperUse(node); |
| 896 return true; | 906 return null; |
| 897 } | 907 } |
| 898 | 908 |
| 899 /// Check that access to `this` is currently allowed. | 909 /// Check that access to `this` is currently allowed. |
| 900 bool checkThisAccess(Send node) { | 910 bool checkThisAccess(Send node) { |
| 901 if (!inInstanceContext) { | 911 if (!inInstanceContext) { |
| 902 compiler.reportError(node, MessageKind.NO_THIS_AVAILABLE); | 912 compiler.reportError(node, MessageKind.NO_THIS_AVAILABLE); |
| 903 return false; | 913 return false; |
| 904 } | 914 } |
| 905 return true; | 915 return true; |
| 906 } | 916 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 919 } else { | 929 } else { |
| 920 return new StaticAccess.superField(target); | 930 return new StaticAccess.superField(target); |
| 921 } | 931 } |
| 922 } else { | 932 } else { |
| 923 assert(invariant(node, target.isFunction, | 933 assert(invariant(node, target.isFunction, |
| 924 message: "Unexpected super target '$target'.")); | 934 message: "Unexpected super target '$target'.")); |
| 925 return new StaticAccess.superMethod(target); | 935 return new StaticAccess.superMethod(target); |
| 926 } | 936 } |
| 927 } | 937 } |
| 928 | 938 |
| 939 /// Compute the [AccessSemantics] corresponding to a compound super access |
| 940 /// reading from [getter] and writing to [setter]. |
| 941 AccessSemantics computeCompoundSuperAccessSemantics( |
| 942 Spannable node, |
| 943 Element getter, |
| 944 Element setter) { |
| 945 if (getter.isErroneous) { |
| 946 if (setter.isErroneous) { |
| 947 return new StaticAccess.unresolvedSuper(getter); |
| 948 } else if (setter.isFunction) { |
| 949 assert(invariant(node, setter.name == '[]=', |
| 950 message: "Unexpected super setter '$setter'.")); |
| 951 return new CompoundAccessSemantics( |
| 952 CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, setter); |
| 953 } else { |
| 954 assert(invariant(node, setter.isSetter, |
| 955 message: "Unexpected super setter '$setter'.")); |
| 956 return new CompoundAccessSemantics( |
| 957 CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, setter); |
| 958 } |
| 959 } else if (getter.isField) { |
| 960 if (setter.isField) { |
| 961 if (getter == setter) { |
| 962 return new StaticAccess.superField(getter); |
| 963 } else { |
| 964 return new CompoundAccessSemantics( |
| 965 CompoundAccessKind.SUPER_FIELD_FIELD, getter, setter); |
| 966 } |
| 967 } else { |
| 968 // Either the field is accessible directly, or a setter shadows the |
| 969 // setter access. If there was another instance member it would shadow |
| 970 // the field. |
| 971 assert(invariant(node, setter.isSetter, |
| 972 message: "Unexpected super setter '$setter'.")); |
| 973 return new CompoundAccessSemantics( |
| 974 CompoundAccessKind.SUPER_FIELD_SETTER, getter, setter); |
| 975 } |
| 976 } else if (getter.isGetter) { |
| 977 if (setter.isErroneous) { |
| 978 return new CompoundAccessSemantics( |
| 979 CompoundAccessKind.UNRESOLVED_SUPER_SETTER, getter, setter); |
| 980 } else if (setter.isField) { |
| 981 return new CompoundAccessSemantics( |
| 982 CompoundAccessKind.SUPER_GETTER_FIELD, getter, setter); |
| 983 } else { |
| 984 assert(invariant(node, setter.isSetter, |
| 985 message: "Unexpected super setter '$setter'.")); |
| 986 return new CompoundAccessSemantics( |
| 987 CompoundAccessKind.SUPER_GETTER_SETTER, getter, setter); |
| 988 } |
| 989 } else { |
| 990 assert(invariant(node, getter.isFunction, |
| 991 message: "Unexpected super getter '$getter'.")); |
| 992 if (setter.isErroneous) { |
| 993 return new CompoundAccessSemantics( |
| 994 CompoundAccessKind.UNRESOLVED_SUPER_SETTER, getter, setter); |
| 995 } else if (setter.isFunction) { |
| 996 assert(invariant(node, getter.name == '[]', |
| 997 message: "Unexpected super getter '$getter'.")); |
| 998 assert(invariant(node, setter.name == '[]=', |
| 999 message: "Unexpected super setter '$setter'.")); |
| 1000 return new CompoundAccessSemantics( |
| 1001 CompoundAccessKind.SUPER_GETTER_SETTER, getter, setter); |
| 1002 } else { |
| 1003 assert(invariant(node, setter.isSetter, |
| 1004 message: "Unexpected super setter '$setter'.")); |
| 1005 return new CompoundAccessSemantics( |
| 1006 CompoundAccessKind.SUPER_METHOD_SETTER, getter, setter); |
| 1007 } |
| 1008 } |
| 1009 } |
| 1010 |
| 929 /// Compute the [AccessSemantics] corresponding to a local access of [target]. | 1011 /// Compute the [AccessSemantics] corresponding to a local access of [target]. |
| 930 AccessSemantics computeLocalAccessSemantics(Spannable node, | 1012 AccessSemantics computeLocalAccessSemantics(Spannable node, |
| 931 LocalElement target) { | 1013 LocalElement target) { |
| 932 if (target.isParameter) { | 1014 if (target.isParameter) { |
| 933 if (target.isFinal || target.isConst) { | 1015 if (target.isFinal || target.isConst) { |
| 934 return new StaticAccess.finalParameter(target); | 1016 return new StaticAccess.finalParameter(target); |
| 935 } else { | 1017 } else { |
| 936 return new StaticAccess.parameter(target); | 1018 return new StaticAccess.parameter(target); |
| 937 } | 1019 } |
| 938 } else if (target.isVariable) { | 1020 } else if (target.isVariable) { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1036 target = error; | 1118 target = error; |
| 1037 } | 1119 } |
| 1038 // We still need to register the invocation, because we might | 1120 // We still need to register the invocation, because we might |
| 1039 // call [:super.noSuchMethod:] which calls [JSInvocationMirror._invokeOn]. | 1121 // call [:super.noSuchMethod:] which calls [JSInvocationMirror._invokeOn]. |
| 1040 registry.registerDynamicInvocation(new UniverseSelector(selector, null)); | 1122 registry.registerDynamicInvocation(new UniverseSelector(selector, null)); |
| 1041 registry.registerSuperNoSuchMethod(); | 1123 registry.registerSuperNoSuchMethod(); |
| 1042 } | 1124 } |
| 1043 return computeSuperAccessSemantics(node, target); | 1125 return computeSuperAccessSemantics(node, target); |
| 1044 } | 1126 } |
| 1045 | 1127 |
| 1128 /// Compute the [AccessSemantics] for accessing the name of [selector] on the |
| 1129 /// super class. |
| 1130 /// |
| 1131 /// If no matching super member is found and error is reported and |
| 1132 /// `noSuchMethod` on `super` is registered. Furthermore, if [alternateName] |
| 1133 /// is provided, the [AccessSemantics] corresponding to the alternate name is |
| 1134 /// returned. For instance, the access of a super setter for an unresolved |
| 1135 /// getter: |
| 1136 /// |
| 1137 /// class Super { |
| 1138 /// set name(_) {} |
| 1139 /// } |
| 1140 /// class Sub extends Super { |
| 1141 /// foo => super.name; // Access to the setter. |
| 1142 /// } |
| 1143 /// |
| 1144 AccessSemantics computeSuperAccessSemanticsForSelectors( |
| 1145 Spannable node, |
| 1146 Selector getterSelector, Selector setterSelector) { |
| 1147 |
| 1148 // TODO(johnniwinther): Ensure correct behavior if currentClass is a |
| 1149 // patch. |
| 1150 Element getter = currentClass.lookupSuperByName(getterSelector.memberName); |
| 1151 // [target] may be null which means invoking noSuchMethod on super. |
| 1152 if (getter == null) { |
| 1153 getter = reportAndCreateErroneousElement( |
| 1154 node, getterSelector.name, MessageKind.NO_SUCH_SUPER_MEMBER, |
| 1155 {'className': currentClass.name, 'memberName': getterSelector.name}); |
| 1156 // We still need to register the invocation, because we might |
| 1157 // call `super.noSuchMethod` which calls [JSInvocationMirror._invokeOn]. |
| 1158 registry.registerDynamicInvocation( |
| 1159 new UniverseSelector(getterSelector, null)); |
| 1160 registry.registerSuperNoSuchMethod(); |
| 1161 } |
| 1162 Element setter = currentClass.lookupSuperByName(setterSelector.memberName); |
| 1163 // [target] may be null which means invoking noSuchMethod on super. |
| 1164 if (setter == null) { |
| 1165 setter = reportAndCreateErroneousElement( |
| 1166 node, setterSelector.name, MessageKind.NO_SUCH_SUPER_MEMBER, |
| 1167 {'className': currentClass.name, 'memberName': setterSelector.name}); |
| 1168 // We still need to register the invocation, because we might |
| 1169 // call `super.noSuchMethod` which calls [JSInvocationMirror._invokeOn]. |
| 1170 registry.registerDynamicInvocation( |
| 1171 new UniverseSelector(setterSelector, null)); |
| 1172 registry.registerSuperNoSuchMethod(); |
| 1173 } |
| 1174 return computeCompoundSuperAccessSemantics(node, getter, setter); |
| 1175 } |
| 1176 |
| 1046 /// Resolve [node] as a subexpression that is _not_ the prefix of a member | 1177 /// Resolve [node] as a subexpression that is _not_ the prefix of a member |
| 1047 /// access. For instance `a` in `a + b`, as opposed to `a` in `a.b`. | 1178 /// access. For instance `a` in `a + b`, as opposed to `a` in `a.b`. |
| 1048 ResolutionResult visitExpression(Node node) { | 1179 ResolutionResult visitExpression(Node node) { |
| 1049 bool oldSendIsMemberAccess = sendIsMemberAccess; | 1180 bool oldSendIsMemberAccess = sendIsMemberAccess; |
| 1050 sendIsMemberAccess = false; | 1181 sendIsMemberAccess = false; |
| 1051 ResolutionResult result = visit(node); | 1182 ResolutionResult result = visit(node); |
| 1052 sendIsMemberAccess = oldSendIsMemberAccess; | 1183 sendIsMemberAccess = oldSendIsMemberAccess; |
| 1053 return result; | 1184 return result; |
| 1054 } | 1185 } |
| 1055 | 1186 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1144 ResolutionResult handleUserDefinableUnary(Send node, UnaryOperator operator) { | 1275 ResolutionResult handleUserDefinableUnary(Send node, UnaryOperator operator) { |
| 1145 ResolutionResult result = const NoneResult(); | 1276 ResolutionResult result = const NoneResult(); |
| 1146 Node expression = node.receiver; | 1277 Node expression = node.receiver; |
| 1147 Selector selector = operator.selector; | 1278 Selector selector = operator.selector; |
| 1148 // TODO(johnniwinther): Remove this when all information goes through the | 1279 // TODO(johnniwinther): Remove this when all information goes through the |
| 1149 // [SendStructure]. | 1280 // [SendStructure]. |
| 1150 registry.setSelector(node, selector); | 1281 registry.setSelector(node, selector); |
| 1151 | 1282 |
| 1152 AccessSemantics semantics; | 1283 AccessSemantics semantics; |
| 1153 if (node.isSuperCall) { | 1284 if (node.isSuperCall) { |
| 1154 if (checkSuperAccess(node)) { | 1285 semantics = checkSuperAccess(node); |
| 1286 if (semantics == null) { |
| 1155 semantics = computeSuperAccessSemanticsForSelector(node, selector); | 1287 semantics = computeSuperAccessSemanticsForSelector(node, selector); |
| 1156 // TODO(johnniwinther): Add information to [AccessSemantics] about | 1288 // TODO(johnniwinther): Add information to [AccessSemantics] about |
| 1157 // whether it is erroneous. | 1289 // whether it is erroneous. |
| 1158 if (semantics.kind == AccessKind.SUPER_METHOD) { | 1290 if (semantics.kind == AccessKind.SUPER_METHOD) { |
| 1159 registry.registerStaticUse(semantics.element.declaration); | 1291 registry.registerStaticUse(semantics.element.declaration); |
| 1160 } | 1292 } |
| 1161 // TODO(johnniwinther): Remove this when all information goes through | 1293 // TODO(johnniwinther): Remove this when all information goes through |
| 1162 // the [SendStructure]. | 1294 // the [SendStructure]. |
| 1163 registry.useElement(node, semantics.element); | 1295 registry.useElement(node, semantics.element); |
| 1164 } | 1296 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1190 // TODO(johnniwinther): Handle potentially invalid constant | 1322 // TODO(johnniwinther): Handle potentially invalid constant |
| 1191 // expressions. | 1323 // expressions. |
| 1192 ConstantExpression constant = | 1324 ConstantExpression constant = |
| 1193 new UnaryConstantExpression(operator, expressionConstant); | 1325 new UnaryConstantExpression(operator, expressionConstant); |
| 1194 registry.setConstant(node, constant); | 1326 registry.setConstant(node, constant); |
| 1195 result = new ConstantResult(node, constant); | 1327 result = new ConstantResult(node, constant); |
| 1196 } | 1328 } |
| 1197 } | 1329 } |
| 1198 } | 1330 } |
| 1199 if (semantics != null) { | 1331 if (semantics != null) { |
| 1200 // TODO(johnniwinther): Support invalid super access as an | |
| 1201 // [AccessSemantics]. | |
| 1202 registry.registerSendStructure(node, | 1332 registry.registerSendStructure(node, |
| 1203 new UnaryStructure(semantics, operator)); | 1333 new UnaryStructure(semantics, operator)); |
| 1204 } | 1334 } |
| 1205 return result; | 1335 return result; |
| 1206 } | 1336 } |
| 1207 | 1337 |
| 1208 /// Handle a not expression, like `!a`. | 1338 /// Handle a not expression, like `!a`. |
| 1209 ResolutionResult handleNot(Send node, UnaryOperator operator) { | 1339 ResolutionResult handleNot(Send node, UnaryOperator operator) { |
| 1210 assert(invariant(node, operator.kind == UnaryOperatorKind.NOT)); | 1340 assert(invariant(node, operator.kind == UnaryOperatorKind.NOT)); |
| 1211 | 1341 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1318 if (operator.kind == BinaryOperatorKind.INDEX) { | 1448 if (operator.kind == BinaryOperatorKind.INDEX) { |
| 1319 selector = new Selector.index(); | 1449 selector = new Selector.index(); |
| 1320 } else { | 1450 } else { |
| 1321 selector = new Selector.binaryOperator(operator.selectorName); | 1451 selector = new Selector.binaryOperator(operator.selectorName); |
| 1322 } | 1452 } |
| 1323 // TODO(johnniwinther): Remove this when all information goes through the | 1453 // TODO(johnniwinther): Remove this when all information goes through the |
| 1324 // [SendStructure]. | 1454 // [SendStructure]. |
| 1325 registry.setSelector(node, selector); | 1455 registry.setSelector(node, selector); |
| 1326 | 1456 |
| 1327 if (node.isSuperCall) { | 1457 if (node.isSuperCall) { |
| 1328 if (checkSuperAccess(node)) { | 1458 semantics = checkSuperAccess(node); |
| 1459 if (semantics == null) { |
| 1329 semantics = computeSuperAccessSemanticsForSelector(node, selector); | 1460 semantics = computeSuperAccessSemanticsForSelector(node, selector); |
| 1330 // TODO(johnniwinther): Add information to [AccessSemantics] about | 1461 // TODO(johnniwinther): Add information to [AccessSemantics] about |
| 1331 // whether it is erroneous. | 1462 // whether it is erroneous. |
| 1332 if (semantics.kind == AccessKind.SUPER_METHOD) { | 1463 if (semantics.kind == AccessKind.SUPER_METHOD) { |
| 1333 registry.registerStaticUse(semantics.element.declaration); | 1464 registry.registerStaticUse(semantics.element.declaration); |
| 1334 } | 1465 } |
| 1335 // TODO(johnniwinther): Remove this when all information goes through | 1466 // TODO(johnniwinther): Remove this when all information goes through |
| 1336 // the [SendStructure]. | 1467 // the [SendStructure]. |
| 1337 registry.useElement(node, semantics.element); | 1468 registry.useElement(node, semantics.element); |
| 1338 } | 1469 } |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1545 Element target; | 1676 Element target; |
| 1546 Selector selector; | 1677 Selector selector; |
| 1547 CallStructure callStructure = CallStructure.NO_ARGS; | 1678 CallStructure callStructure = CallStructure.NO_ARGS; |
| 1548 if (node.isCall) { | 1679 if (node.isCall) { |
| 1549 callStructure = | 1680 callStructure = |
| 1550 resolveArguments(node.argumentsNode).callStructure; | 1681 resolveArguments(node.argumentsNode).callStructure; |
| 1551 selector = new Selector(SelectorKind.CALL, name, callStructure); | 1682 selector = new Selector(SelectorKind.CALL, name, callStructure); |
| 1552 } else { | 1683 } else { |
| 1553 selector = new Selector(SelectorKind.GETTER, name, callStructure); | 1684 selector = new Selector(SelectorKind.GETTER, name, callStructure); |
| 1554 } | 1685 } |
| 1555 if (checkSuperAccess(node)) { | 1686 AccessSemantics semantics = checkSuperAccess(node); |
| 1556 AccessSemantics semantics = computeSuperAccessSemanticsForSelector( | 1687 if (semantics == null) { |
| 1688 semantics = computeSuperAccessSemanticsForSelector( |
| 1557 node, selector, alternateName: name.setter); | 1689 node, selector, alternateName: name.setter); |
| 1558 if (node.isCall) { | 1690 } |
| 1559 bool isIncompatibleInvoke = false; | 1691 if (node.isCall) { |
| 1560 switch (semantics.kind) { | 1692 bool isIncompatibleInvoke = false; |
| 1561 case AccessKind.SUPER_METHOD: | 1693 switch (semantics.kind) { |
| 1562 MethodElementX superMethod = semantics.element; | 1694 case AccessKind.SUPER_METHOD: |
| 1563 superMethod.computeSignature(compiler); | 1695 MethodElementX superMethod = semantics.element; |
| 1564 if (!callStructure.signatureApplies( | 1696 superMethod.computeSignature(compiler); |
| 1565 superMethod.functionSignature)) { | 1697 if (!callStructure.signatureApplies( |
| 1566 registry.registerThrowNoSuchMethod(); | 1698 superMethod.functionSignature)) { |
| 1567 registry.registerDynamicInvocation( | 1699 registry.registerThrowNoSuchMethod(); |
| 1568 new UniverseSelector(selector, null)); | |
| 1569 registry.registerSuperNoSuchMethod(); | |
| 1570 isIncompatibleInvoke = true; | |
| 1571 } else { | |
| 1572 registry.registerStaticInvocation(semantics.element); | |
| 1573 } | |
| 1574 break; | |
| 1575 case AccessKind.SUPER_FIELD: | |
| 1576 case AccessKind.SUPER_FINAL_FIELD: | |
| 1577 case AccessKind.SUPER_GETTER: | |
| 1578 registry.registerStaticUse(semantics.element); | |
| 1579 selector = callStructure.callSelector; | |
| 1580 registry.registerDynamicInvocation( | 1700 registry.registerDynamicInvocation( |
| 1581 new UniverseSelector(selector, null)); | 1701 new UniverseSelector(selector, null)); |
| 1582 break; | 1702 registry.registerSuperNoSuchMethod(); |
| 1583 case AccessKind.SUPER_SETTER: | 1703 isIncompatibleInvoke = true; |
| 1584 case AccessKind.UNRESOLVED_SUPER: | 1704 } else { |
| 1585 // NoSuchMethod registered in [computeSuperSemantics]. | 1705 registry.registerStaticInvocation(semantics.element); |
| 1586 break; | 1706 } |
| 1587 default: | 1707 break; |
| 1588 internalError(node, "Unexpected super property access $semantics."); | 1708 case AccessKind.SUPER_FIELD: |
| 1589 break; | 1709 case AccessKind.SUPER_FINAL_FIELD: |
| 1590 } | 1710 case AccessKind.SUPER_GETTER: |
| 1591 registry.registerSendStructure(node, | 1711 registry.registerStaticUse(semantics.element); |
| 1592 isIncompatibleInvoke | 1712 selector = callStructure.callSelector; |
| 1593 ? new IncompatibleInvokeStructure(semantics, selector) | 1713 registry.registerDynamicInvocation( |
| 1594 : new InvokeStructure(semantics, selector)); | 1714 new UniverseSelector(selector, null)); |
| 1595 } else { | 1715 break; |
| 1596 switch (semantics.kind) { | 1716 case AccessKind.SUPER_SETTER: |
| 1597 case AccessKind.SUPER_METHOD: | 1717 case AccessKind.UNRESOLVED_SUPER: |
| 1598 // TODO(johnniwinther): Method this should be registered as a | 1718 // NoSuchMethod registered in [computeSuperSemantics]. |
| 1599 // closurization. | 1719 break; |
| 1600 registry.registerStaticUse(semantics.element); | 1720 case AccessKind.INVALID: |
| 1601 break; | 1721 // 'super' is not allowed. |
| 1602 case AccessKind.SUPER_FIELD: | 1722 break; |
| 1603 case AccessKind.SUPER_FINAL_FIELD: | 1723 default: |
| 1604 case AccessKind.SUPER_GETTER: | 1724 internalError(node, "Unexpected super property access $semantics."); |
| 1605 registry.registerStaticUse(semantics.element); | 1725 break; |
| 1606 break; | |
| 1607 case AccessKind.SUPER_SETTER: | |
| 1608 case AccessKind.UNRESOLVED_SUPER: | |
| 1609 // NoSuchMethod registered in [computeSuperSemantics]. | |
| 1610 break; | |
| 1611 default: | |
| 1612 internalError(node, "Unexpected super property access $semantics."); | |
| 1613 break; | |
| 1614 } | |
| 1615 registry.registerSendStructure(node, | |
| 1616 new GetStructure(semantics, selector)); | |
| 1617 } | 1726 } |
| 1618 target = semantics.element; | 1727 registry.registerSendStructure(node, |
| 1728 isIncompatibleInvoke |
| 1729 ? new IncompatibleInvokeStructure(semantics, selector) |
| 1730 : new InvokeStructure(semantics, selector)); |
| 1731 } else { |
| 1732 switch (semantics.kind) { |
| 1733 case AccessKind.SUPER_METHOD: |
| 1734 // TODO(johnniwinther): Method this should be registered as a |
| 1735 // closurization. |
| 1736 registry.registerStaticUse(semantics.element); |
| 1737 break; |
| 1738 case AccessKind.SUPER_FIELD: |
| 1739 case AccessKind.SUPER_FINAL_FIELD: |
| 1740 case AccessKind.SUPER_GETTER: |
| 1741 registry.registerStaticUse(semantics.element); |
| 1742 break; |
| 1743 case AccessKind.SUPER_SETTER: |
| 1744 case AccessKind.UNRESOLVED_SUPER: |
| 1745 // NoSuchMethod registered in [computeSuperSemantics]. |
| 1746 break; |
| 1747 case AccessKind.INVALID: |
| 1748 // 'super' is not allowed. |
| 1749 break; |
| 1750 default: |
| 1751 internalError(node, "Unexpected super property access $semantics."); |
| 1752 break; |
| 1753 } |
| 1754 registry.registerSendStructure(node, |
| 1755 new GetStructure(semantics, selector)); |
| 1619 } | 1756 } |
| 1757 target = semantics.element; |
| 1620 | 1758 |
| 1621 // TODO(johnniwinther): Remove these when all information goes through | 1759 // TODO(johnniwinther): Remove these when all information goes through |
| 1622 // the [SendStructure]. | 1760 // the [SendStructure]. |
| 1623 registry.useElement(node, target); | 1761 registry.useElement(node, target); |
| 1624 registry.setSelector(node, selector); | 1762 registry.setSelector(node, selector); |
| 1625 return const NoneResult(); | 1763 return const NoneResult(); |
| 1626 } | 1764 } |
| 1627 | 1765 |
| 1628 /// Handle a [Send] whose selector is an [Operator], like `a && b`, `a is T`, | 1766 /// Handle a [Send] whose selector is an [Operator], like `a && b`, `a is T`, |
| 1629 /// `a + b`, and `~a`. | 1767 /// `a + b`, and `~a`. |
| (...skipping 984 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2614 new UniverseSelector(operatorSelector, null)); | 2752 new UniverseSelector(operatorSelector, null)); |
| 2615 | 2753 |
| 2616 SendStructure sendStructure = new CompoundIndexSetStructure( | 2754 SendStructure sendStructure = new CompoundIndexSetStructure( |
| 2617 semantics, operator, getterSelector, setterSelector); | 2755 semantics, operator, getterSelector, setterSelector); |
| 2618 registry.registerSendStructure(node, sendStructure); | 2756 registry.registerSendStructure(node, sendStructure); |
| 2619 return const NoneResult(); | 2757 return const NoneResult(); |
| 2620 } | 2758 } |
| 2621 } | 2759 } |
| 2622 } | 2760 } |
| 2623 | 2761 |
| 2762 /// Handle super index operations like `super[a] = b`, `super[a] += b`, and |
| 2763 /// `super[a]++`. |
| 2764 // TODO(johnniwinther): Share code with [handleIndexSendSet]. |
| 2765 ResolutionResult handleSuperIndexSendSet(SendSet node) { |
| 2766 String operatorText = node.assignmentOperator.source; |
| 2767 Node index = node.arguments.head; |
| 2768 visitExpression(index); |
| 2769 AccessSemantics semantics = checkSuperAccess(node); |
| 2770 if (node.isPrefix || node.isPostfix) { |
| 2771 // `super[a]++` or `++super[a]`. |
| 2772 IncDecOperator operator = IncDecOperator.parse(operatorText); |
| 2773 Selector getterSelector = new Selector.index(); |
| 2774 Selector setterSelector = new Selector.indexSet(); |
| 2775 Selector operatorSelector = |
| 2776 new Selector.binaryOperator(operator.selectorName); |
| 2777 |
| 2778 // TODO(johnniwinther): Remove these when selectors are only accessed |
| 2779 // through the send structure. |
| 2780 registry.setGetterSelectorInComplexSendSet(node, getterSelector); |
| 2781 registry.setSelector(node, setterSelector); |
| 2782 registry.setOperatorSelectorInComplexSendSet(node, operatorSelector); |
| 2783 |
| 2784 if (semantics == null) { |
| 2785 semantics = computeSuperAccessSemanticsForSelectors( |
| 2786 node, getterSelector, setterSelector); |
| 2787 |
| 2788 registry.registerStaticInvocation(semantics.getter); |
| 2789 registry.registerStaticInvocation(semantics.setter); |
| 2790 |
| 2791 // TODO(johnniwinther): Remove these when elements are only accessed |
| 2792 // through the send structure. |
| 2793 registry.useElement(node, semantics.setter); |
| 2794 registry.useElement(node.selector, semantics.getter); |
| 2795 } |
| 2796 registry.registerDynamicInvocation( |
| 2797 new UniverseSelector(operatorSelector, null)); |
| 2798 |
| 2799 SendStructure sendStructure = node.isPrefix |
| 2800 ? new IndexPrefixStructure( |
| 2801 semantics, operator, getterSelector, setterSelector) |
| 2802 : new IndexPostfixStructure( |
| 2803 semantics, operator, getterSelector, setterSelector); |
| 2804 registry.registerSendStructure(node, sendStructure); |
| 2805 return const NoneResult(); |
| 2806 } else { |
| 2807 Node rhs = node.arguments.tail.head; |
| 2808 visitExpression(rhs); |
| 2809 |
| 2810 AssignmentOperator operator = AssignmentOperator.parse(operatorText); |
| 2811 if (operator.kind == AssignmentOperatorKind.ASSIGN) { |
| 2812 // `super[a] = b`. |
| 2813 Selector setterSelector = new Selector.indexSet(); |
| 2814 if (semantics == null) { |
| 2815 semantics = |
| 2816 computeSuperAccessSemanticsForSelector(node, setterSelector); |
| 2817 |
| 2818 // TODO(johnniwinther): Remove these when elements are only accessed |
| 2819 // through the send structure. |
| 2820 registry.useElement(node, semantics.setter); |
| 2821 } |
| 2822 |
| 2823 // TODO(johnniwinther): Remove this when selectors are only accessed |
| 2824 // through the send structure. |
| 2825 registry.setSelector(node, setterSelector); |
| 2826 registry.registerStaticInvocation(semantics.setter); |
| 2827 |
| 2828 SendStructure sendStructure = |
| 2829 new IndexSetStructure(semantics, setterSelector); |
| 2830 registry.registerSendStructure(node, sendStructure); |
| 2831 return const NoneResult(); |
| 2832 } else { |
| 2833 // `super[a] += b`. |
| 2834 Selector getterSelector = new Selector.index(); |
| 2835 Selector setterSelector = new Selector.indexSet(); |
| 2836 Selector operatorSelector = |
| 2837 new Selector.binaryOperator(operator.selectorName); |
| 2838 if (semantics == null) { |
| 2839 semantics = computeSuperAccessSemanticsForSelectors( |
| 2840 node, getterSelector, setterSelector); |
| 2841 |
| 2842 registry.registerStaticInvocation(semantics.getter); |
| 2843 registry.registerStaticInvocation(semantics.setter); |
| 2844 |
| 2845 // TODO(johnniwinther): Remove these when elements are only accessed |
| 2846 // through the send structure. |
| 2847 registry.useElement(node, semantics.setter); |
| 2848 registry.useElement(node.selector, semantics.getter); |
| 2849 } |
| 2850 |
| 2851 // TODO(johnniwinther): Remove these when selectors are only accessed |
| 2852 // through the send structure. |
| 2853 registry.setGetterSelectorInComplexSendSet(node, getterSelector); |
| 2854 registry.setSelector(node, setterSelector); |
| 2855 registry.setOperatorSelectorInComplexSendSet(node, operatorSelector); |
| 2856 |
| 2857 registry.registerDynamicInvocation( |
| 2858 new UniverseSelector(operatorSelector, null)); |
| 2859 |
| 2860 SendStructure sendStructure = new CompoundIndexSetStructure( |
| 2861 semantics, operator, getterSelector, setterSelector); |
| 2862 registry.registerSendStructure(node, sendStructure); |
| 2863 return const NoneResult(); |
| 2864 } |
| 2865 } |
| 2866 } |
| 2867 |
| 2624 ResolutionResult visitSendSet(SendSet node) { | 2868 ResolutionResult visitSendSet(SendSet node) { |
| 2625 if (node.isIndex) { | 2869 if (node.isIndex) { |
| 2626 if (node.isSuperCall) { | 2870 if (node.isSuperCall) { |
| 2627 // TODO(johnniwinther): Refactor index operations on super. | 2871 return handleSuperIndexSendSet(node); |
| 2628 } else { | 2872 } else { |
| 2629 return handleIndexSendSet(node); | 2873 return handleIndexSendSet(node); |
| 2630 } | 2874 } |
| 2631 } | 2875 } |
| 2632 return oldVisitSendSet(node); | 2876 return oldVisitSendSet(node); |
| 2633 } | 2877 } |
| 2634 | 2878 |
| 2635 ResolutionResult oldVisitSendSet(SendSet node) { | 2879 ResolutionResult oldVisitSendSet(SendSet node) { |
| 2636 bool oldSendIsMemberAccess = sendIsMemberAccess; | 2880 bool oldSendIsMemberAccess = sendIsMemberAccess; |
| 2637 sendIsMemberAccess = node.isPropertyAccess || node.isCall; | 2881 sendIsMemberAccess = node.isPropertyAccess || node.isCall; |
| (...skipping 1279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3917 } | 4161 } |
| 3918 return const NoneResult(); | 4162 return const NoneResult(); |
| 3919 } | 4163 } |
| 3920 } | 4164 } |
| 3921 | 4165 |
| 3922 /// Looks up [name] in [scope] and unwraps the result. | 4166 /// Looks up [name] in [scope] and unwraps the result. |
| 3923 Element lookupInScope(Compiler compiler, Node node, | 4167 Element lookupInScope(Compiler compiler, Node node, |
| 3924 Scope scope, String name) { | 4168 Scope scope, String name) { |
| 3925 return Elements.unwrap(scope.lookup(name), compiler, node); | 4169 return Elements.unwrap(scope.lookup(name), compiler, node); |
| 3926 } | 4170 } |
| OLD | NEW |