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.world.registerStaticUse(element); | |
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 var send = node.asSend(); | |
814 if (send !== null) { | |
815 Selector selector = mapping.getSelector(send); | |
816 if (selector !== null) { | |
817 world.registerDynamicInvocation(element.name, selector); | |
818 } | |
819 } | |
820 } else { | |
821 if (!element.isPrefix() && | |
822 !element.isClass() && | |
823 !element.isTypedef() && | |
824 !element.isTypeVariable()) { | |
825 world.registerStaticUse(element); | |
826 } | |
827 } | |
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); | |
ngeoffray
2012/06/12 12:44:14
handleDynamicSend -> registerDynamicSend ?
ahe
2012/06/12 18:47:13
Done.
| |
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 '===': | |
1141 case '!==': | |
1142 case '!': | |
1143 case '&&': | |
1144 case '||': | |
1145 case 'is': | |
1146 case '>>>': | |
1147 return null; | |
1148 } | |
1149 name = Elements.constructOperatorName( | |
1150 const SourceString('operator'), | |
1151 name, | |
1152 node.argumentsNode is Prefix); | |
1153 } | |
1154 Selector selector = mapping.getSelector(node); | |
1155 if (Selector.GETTER === selector) { | |
1156 world.registerDynamicGetter(name, selector); | |
1157 } else if (Selector.SETTER === selector) { | |
1158 world.registerDynamicSetter(name, selector); | |
1159 // Also register the getter for compound assignments. | |
1160 world.registerDynamicGetter(name, Selector.GETTER); | |
1161 } else { | |
1162 world.registerDynamicInvocation(name, selector); | |
1163 } | |
1164 var interceptor = new Interceptors(compiler).getStaticInterceptor( | |
1165 name, | |
1166 node.argumentCount()); | |
1167 if (interceptor !== null) { | |
1168 world.registerStaticUse(interceptor); | |
1169 } | |
1170 } | |
1171 | |
1105 visitLiteralInt(LiteralInt node) { | 1172 visitLiteralInt(LiteralInt node) { |
1106 } | 1173 } |
1107 | 1174 |
1108 visitLiteralDouble(LiteralDouble node) { | 1175 visitLiteralDouble(LiteralDouble node) { |
1109 } | 1176 } |
1110 | 1177 |
1111 visitLiteralBool(LiteralBool node) { | 1178 visitLiteralBool(LiteralBool node) { |
1112 } | 1179 } |
1113 | 1180 |
1114 visitLiteralString(LiteralString node) { | 1181 visitLiteralString(LiteralString node) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1162 FunctionElement constructor = resolveConstructor(node); | 1229 FunctionElement constructor = resolveConstructor(node); |
1163 handleArguments(node.send); | 1230 handleArguments(node.send); |
1164 if (constructor === null) return null; | 1231 if (constructor === null) return null; |
1165 // TODO(karlklose): handle optional arguments. | 1232 // TODO(karlklose): handle optional arguments. |
1166 if (node.send.argumentCount() != constructor.parameterCount(compiler)) { | 1233 if (node.send.argumentCount() != constructor.parameterCount(compiler)) { |
1167 // TODO(ngeoffray): resolution error with wrong number of | 1234 // TODO(ngeoffray): resolution error with wrong number of |
1168 // parameters. We cannot do this rigth now because of the | 1235 // parameters. We cannot do this rigth now because of the |
1169 // List constructor. | 1236 // List constructor. |
1170 } | 1237 } |
1171 useElement(node.send, constructor); | 1238 useElement(node.send, constructor); |
1239 compiler.withCurrentElement(constructor, () { | |
1240 FunctionExpression tree = constructor.parseNode(compiler); | |
1241 compiler.resolver.resolveConstructorImplementation(constructor, tree); | |
1242 }); | |
1243 world.registerStaticUse(constructor.defaultImplementation); | |
1244 ClassElement cls = constructor.defaultImplementation.enclosingElement; | |
1245 world.registerInstantiatedClass(cls); | |
1246 cls.forEachInstanceField( | |
1247 includeBackendMembers: false, | |
1248 includeSuperMembers: true, | |
1249 f: (ClassElement enclosingClass, Element member) { | |
1250 world.addToWorkList(member); | |
1251 }); | |
1172 return null; | 1252 return null; |
1173 } | 1253 } |
1174 | 1254 |
1175 TypeAnnotation getTypeAnnotationFromSend(Send send) { | 1255 TypeAnnotation getTypeAnnotationFromSend(Send send) { |
1176 if (send.selector.asTypeAnnotation() !== null) { | 1256 if (send.selector.asTypeAnnotation() !== null) { |
1177 return send.selector; | 1257 return send.selector; |
1178 } else if (send.selector.asSend() !== null) { | 1258 } else if (send.selector.asSend() !== null) { |
1179 Send selector = send.selector; | 1259 Send selector = send.selector; |
1180 if (selector.receiver.asTypeAnnotation() !== null) { | 1260 if (selector.receiver.asTypeAnnotation() !== null) { |
1181 return selector.receiver; | 1261 return selector.receiver; |
(...skipping 831 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2013 | 2093 |
2014 TopScope(LibraryElement library) : super(null, library); | 2094 TopScope(LibraryElement library) : super(null, library); |
2015 Element lookup(SourceString name) { | 2095 Element lookup(SourceString name) { |
2016 return library.find(name); | 2096 return library.find(name); |
2017 } | 2097 } |
2018 | 2098 |
2019 Element add(Element newElement) { | 2099 Element add(Element newElement) { |
2020 throw "Cannot add an element in the top scope"; | 2100 throw "Cannot add an element in the top scope"; |
2021 } | 2101 } |
2022 } | 2102 } |
OLD | NEW |