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 interface TreeElements { | 5 interface TreeElements { |
6 Element operator[](Node node); | 6 Element operator[](Node node); |
7 Selector getSelector(Send send); | 7 Selector getSelector(Send send); |
8 Type getType(TypeAnnotation annotation); | 8 Type getType(TypeAnnotation annotation); |
9 } | 9 } |
10 | 10 |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
342 } | 342 } |
343 | 343 |
344 void resolveImplicitSuperConstructorSend(FunctionElement constructor, | 344 void resolveImplicitSuperConstructorSend(FunctionElement constructor, |
345 FunctionExpression functionNode) { | 345 FunctionExpression functionNode) { |
346 // If the class has a super resolve the implicit super call. | 346 // If the class has a super resolve the implicit super call. |
347 ClassElement classElement = constructor.enclosingElement; | 347 ClassElement classElement = constructor.enclosingElement; |
348 ClassElement superClass = classElement.superclass; | 348 ClassElement superClass = classElement.superclass; |
349 if (classElement != visitor.compiler.objectClass) { | 349 if (classElement != visitor.compiler.objectClass) { |
350 assert(superClass !== null); | 350 assert(superClass !== null); |
351 assert(superClass.isResolved); | 351 assert(superClass.isResolved); |
352 resolveSuperOrThis(constructor, true, true, const SourceString(''), | 352 var element = resolveSuperOrThis(constructor, true, true, |
353 Selector.INVOCATION_0, functionNode); | 353 const SourceString(''), |
354 Selector.INVOCATION_0, functionNode); | |
355 visitor.compiler.enqueuer.resolution.registerStaticUse(element); | |
kasperl
2012/06/12 05:50:12
Would visitor.world work?
ahe
2012/06/12 06:22:49
visitor.world.
ahe
2012/06/12 10:56:11
Done.
ahe
2012/06/12 10:56:11
Done.
| |
354 } | 356 } |
355 } | 357 } |
356 | 358 |
357 Element resolveSuperOrThis(FunctionElement constructor, | 359 Element resolveSuperOrThis(FunctionElement constructor, |
358 bool isSuperCall, | 360 bool isSuperCall, |
359 bool isImplicitSuperCall, | 361 bool isImplicitSuperCall, |
360 SourceString constructorName, | 362 SourceString constructorName, |
361 Selector selector, | 363 Selector selector, |
362 Node diagnosticNode) { | 364 Node diagnosticNode) { |
363 ClassElement lookupTarget = constructor.enclosingElement; | 365 ClassElement lookupTarget = constructor.enclosingElement; |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
717 super(compiler) { | 719 super(compiler) { |
718 LibraryElement library = element.getLibrary(); | 720 LibraryElement library = element.getLibrary(); |
719 element = element.getEnclosingMember(); | 721 element = element.getEnclosingMember(); |
720 if (element !== null) { | 722 if (element !== null) { |
721 context = new ClassScope(element.enclosingElement, library); | 723 context = new ClassScope(element.enclosingElement, library); |
722 } else { | 724 } else { |
723 this.context = new TopScope(library); | 725 this.context = new TopScope(library); |
724 } | 726 } |
725 } | 727 } |
726 | 728 |
729 Enqueuer get world() => compiler.enqueuer.resolution; | |
730 | |
727 Element lookup(Node node, SourceString name) { | 731 Element lookup(Node node, SourceString name) { |
728 Element result = context.lookup(name); | 732 Element result = context.lookup(name); |
729 if (!inInstanceContext && result != null && result.isInstanceMember()) { | 733 if (!inInstanceContext && result != null && result.isInstanceMember()) { |
730 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]); | 734 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]); |
731 } | 735 } |
732 return result; | 736 return result; |
733 } | 737 } |
734 | 738 |
735 // Create, or reuse an already created, statement element for a statement. | 739 // Create, or reuse an already created, statement element for a statement. |
736 TargetElement getOrCreateTargetElement(Node statement) { | 740 TargetElement getOrCreateTargetElement(Node statement) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
796 Element existing = context.add(element); | 800 Element existing = context.add(element); |
797 if (existing != element) { | 801 if (existing != element) { |
798 error(node, MessageKind.DUPLICATE_DEFINITION, [node]); | 802 error(node, MessageKind.DUPLICATE_DEFINITION, [node]); |
799 } | 803 } |
800 } | 804 } |
801 return element; | 805 return element; |
802 } | 806 } |
803 | 807 |
804 Element useElement(Node node, Element element) { | 808 Element useElement(Node node, Element element) { |
805 if (element === null) return null; | 809 if (element === null) return null; |
806 return mapping[node] = element; | 810 mapping[node] = element; |
811 if (element.isTopLevel() || element.isMember()) { | |
812 if (element.isInstanceMember()) { | |
813 Selector selector = mapping.getSelector(node); | |
814 if (selector !== null) { | |
815 world.registerDynamicInvocation(element.name, selector); | |
816 } | |
817 } else { | |
818 if (!element.isPrefix() && | |
819 !element.isClass() && | |
820 !element.isTypedef() && | |
821 !element.isTypeVariable()) { | |
822 world.registerStaticUse(element); | |
823 } | |
824 } | |
825 } else { | |
826 assert(enclosingElement === | |
827 element.getOutermostEnclosingMemberOrTopLevel()); | |
828 } | |
829 return element; | |
807 } | 830 } |
808 | 831 |
809 Type useType(TypeAnnotation annotation, Type type) { | 832 Type useType(TypeAnnotation annotation, Type type) { |
810 if (type !== null) { | 833 if (type !== null) { |
811 mapping.setType(annotation, type); | 834 mapping.setType(annotation, type); |
812 useElement(annotation, type.element); | 835 useElement(annotation, type.element); |
813 } | 836 } |
814 return type; | 837 return type; |
815 } | 838 } |
816 | 839 |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1057 if (target === compiler.assertMethod && !node.isCall) { | 1080 if (target === compiler.assertMethod && !node.isCall) { |
1058 // We can only use assert by calling it. | 1081 // We can only use assert by calling it. |
1059 if (!inInstanceContext) { | 1082 if (!inInstanceContext) { |
1060 error(node, MessageKind.MISSING_ARGUMENTS_TO_ASSERT, [node]); | 1083 error(node, MessageKind.MISSING_ARGUMENTS_TO_ASSERT, [node]); |
1061 } | 1084 } |
1062 target = null; | 1085 target = null; |
1063 } | 1086 } |
1064 // TODO(ngeoffray): Warn if target is null and the send is | 1087 // TODO(ngeoffray): Warn if target is null and the send is |
1065 // unqualified. | 1088 // unqualified. |
1066 useElement(node, target); | 1089 useElement(node, target); |
1090 if (target === null) handleDynamicSend(node); | |
1067 if (node.isPropertyAccess) return target; | 1091 if (node.isPropertyAccess) return target; |
1068 } | 1092 } |
1069 | 1093 |
1070 visitSendSet(SendSet node) { | 1094 visitSendSet(SendSet node) { |
1071 Element target = resolveSend(node); | 1095 Element target = resolveSend(node); |
1072 Element setter = null; | 1096 Element setter = null; |
1073 Element getter = null; | 1097 Element getter = null; |
1074 if (target != null && target.kind == ElementKind.ABSTRACT_FIELD) { | 1098 if (target != null && target.kind == ElementKind.ABSTRACT_FIELD) { |
1075 AbstractFieldElement field = target; | 1099 AbstractFieldElement field = target; |
1076 setter = field.setter; | 1100 setter = field.setter; |
(...skipping 15 matching lines...) Expand all Loading... | |
1092 useElement(node.selector, getter); | 1116 useElement(node.selector, getter); |
1093 } else if (node.isIndex) { | 1117 } else if (node.isIndex) { |
1094 selector = Selector.INDEX_SET; | 1118 selector = Selector.INDEX_SET; |
1095 } else { | 1119 } else { |
1096 selector = Selector.SETTER; | 1120 selector = Selector.SETTER; |
1097 } | 1121 } |
1098 visit(node.argumentsNode); | 1122 visit(node.argumentsNode); |
1099 mapping.setSelector(node, selector); | 1123 mapping.setSelector(node, selector); |
1100 // TODO(ngeoffray): Warn if target is null and the send is | 1124 // TODO(ngeoffray): Warn if target is null and the send is |
1101 // unqualified. | 1125 // unqualified. |
1126 handleDynamicSend(node); | |
1102 return useElement(node, setter); | 1127 return useElement(node, setter); |
1103 } | 1128 } |
1104 | 1129 |
1130 handleDynamicSend(Send node) { | |
1131 Identifier id = node.selector.asIdentifier(); | |
1132 if (id === null) return; | |
1133 SourceString name = node.selector.asIdentifier().source; | |
1134 if (node.isIndex && !node.arguments.tail.isEmpty()) { | |
1135 name = Elements.constructOperatorName( | |
1136 const SourceString('operator'), | |
1137 const SourceString('[]=')); | |
1138 } else if (node.selector.asOperator() != null) { | |
1139 switch (name.stringValue) { | |
1140 case "===": | |
kasperl
2012/06/12 05:50:12
Use ' for string literals for consistency?
ahe
2012/06/12 10:56:11
Done.
| |
1141 case "!==": | |
1142 case "!": | |
1143 case "&&": | |
1144 case "||": | |
1145 case "is": | |
1146 case ">>>": | |
1147 return null; | |
1148 } | |
1149 if (name === null) return; | |
kasperl
2012/06/12 05:50:12
Check for name === null before switching on name.s
ahe
2012/06/12 10:56:11
Removed.
| |
1150 name = Elements.constructOperatorName( | |
1151 const SourceString('operator'), | |
1152 name, | |
1153 node.argumentsNode is Prefix); | |
1154 } | |
1155 Selector selector = mapping.getSelector(node); | |
1156 if (Selector.GETTER === selector) { | |
1157 world.registerDynamicGetter(name, selector); | |
1158 } else if (Selector.SETTER === selector) { | |
1159 world.registerDynamicSetter(name, selector); | |
1160 // Also register the getter for compound assignments. | |
1161 world.registerDynamicGetter(name, Selector.GETTER); | |
1162 } else { | |
1163 world.registerDynamicInvocation(name, selector); | |
1164 } | |
1165 var interceptor = new Interceptors(compiler).getStaticInterceptor( | |
1166 name, | |
1167 node.argumentCount()); | |
1168 if (interceptor !== null) { | |
1169 world.registerStaticUse(interceptor); | |
1170 } | |
1171 } | |
1172 | |
1105 visitLiteralInt(LiteralInt node) { | 1173 visitLiteralInt(LiteralInt node) { |
1106 } | 1174 } |
1107 | 1175 |
1108 visitLiteralDouble(LiteralDouble node) { | 1176 visitLiteralDouble(LiteralDouble node) { |
1109 } | 1177 } |
1110 | 1178 |
1111 visitLiteralBool(LiteralBool node) { | 1179 visitLiteralBool(LiteralBool node) { |
1112 } | 1180 } |
1113 | 1181 |
1114 visitLiteralString(LiteralString node) { | 1182 visitLiteralString(LiteralString node) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1162 FunctionElement constructor = resolveConstructor(node); | 1230 FunctionElement constructor = resolveConstructor(node); |
1163 handleArguments(node.send); | 1231 handleArguments(node.send); |
1164 if (constructor === null) return null; | 1232 if (constructor === null) return null; |
1165 // TODO(karlklose): handle optional arguments. | 1233 // TODO(karlklose): handle optional arguments. |
1166 if (node.send.argumentCount() != constructor.parameterCount(compiler)) { | 1234 if (node.send.argumentCount() != constructor.parameterCount(compiler)) { |
1167 // TODO(ngeoffray): resolution error with wrong number of | 1235 // TODO(ngeoffray): resolution error with wrong number of |
1168 // parameters. We cannot do this rigth now because of the | 1236 // parameters. We cannot do this rigth now because of the |
1169 // List constructor. | 1237 // List constructor. |
1170 } | 1238 } |
1171 useElement(node.send, constructor); | 1239 useElement(node.send, constructor); |
1240 compiler.withCurrentElement(constructor, () { | |
1241 FunctionExpression tree = constructor.parseNode(compiler); | |
1242 compiler.resolver.resolveConstructorImplementation(constructor, tree); | |
1243 }); | |
1244 world.registerStaticUse(constructor.defaultImplementation); | |
1245 world.registerInstantiatedClass( | |
1246 constructor.defaultImplementation.enclosingElement); | |
1247 constructor.defaultImplementation.enclosingElement.forEachInstanceField( | |
1248 includeBackendMembers: false, | |
1249 includeSuperMembers: true, | |
1250 f: (ClassElement enclosingClass, Element member) { | |
1251 world.addToWorkList(member); | |
1252 }); | |
1172 return null; | 1253 return null; |
1173 } | 1254 } |
1174 | 1255 |
1175 TypeAnnotation getTypeAnnotationFromSend(Send send) { | 1256 TypeAnnotation getTypeAnnotationFromSend(Send send) { |
1176 if (send.selector.asTypeAnnotation() !== null) { | 1257 if (send.selector.asTypeAnnotation() !== null) { |
1177 return send.selector; | 1258 return send.selector; |
1178 } else if (send.selector.asSend() !== null) { | 1259 } else if (send.selector.asSend() !== null) { |
1179 Send selector = send.selector; | 1260 Send selector = send.selector; |
1180 if (selector.receiver.asTypeAnnotation() !== null) { | 1261 if (selector.receiver.asTypeAnnotation() !== null) { |
1181 return selector.receiver; | 1262 return selector.receiver; |
(...skipping 831 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2013 | 2094 |
2014 TopScope(LibraryElement library) : super(null, library); | 2095 TopScope(LibraryElement library) : super(null, library); |
2015 Element lookup(SourceString name) { | 2096 Element lookup(SourceString name) { |
2016 return library.find(name); | 2097 return library.find(name); |
2017 } | 2098 } |
2018 | 2099 |
2019 Element add(Element newElement) { | 2100 Element add(Element newElement) { |
2020 throw "Cannot add an element in the top scope"; | 2101 throw "Cannot add an element in the top scope"; |
2021 } | 2102 } |
2022 } | 2103 } |
OLD | NEW |