| 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 } | 8 } |
| 9 | 9 |
| 10 class TreeElementMapping implements TreeElements { | 10 class TreeElementMapping implements TreeElements { |
| 11 Map<Node, Element> map; | 11 Map<Node, Element> map; |
| 12 Map<Send, Selector> selectors; | 12 Map<Send, Selector> selectors; |
| 13 TreeElementMapping() | 13 TreeElementMapping() |
| 14 : map = new LinkedHashMap<Node, Element>(), | 14 : map = new LinkedHashMap<Node, Element>(), |
| 15 selectors = new LinkedHashMap<Send, Selector>(); | 15 selectors = new LinkedHashMap<Send, Selector>(); |
| 16 | 16 |
| 17 operator []=(Node node, Element element) => map[node] = element; | 17 operator []=(Node node, Element element) => map[node] = element; |
| 18 operator [](Node node) => map[node]; | 18 operator [](Node node) => map[node]; |
| 19 | 19 |
| 20 void setSelector(Send send, Selector selector) { | 20 void setSelector(Send send, Selector selector) { |
| 21 selectors[send] = selector; | 21 selectors[send] = selector; |
| 22 } | 22 } |
| 23 | 23 |
| 24 Selector getSelector(Send send) => selectors[send]; | 24 Selector getSelector(Send send) => selectors[send]; |
| 25 } | 25 } |
| 26 | 26 |
| 27 class ResolverTask extends CompilerTask { | 27 class ResolverTask extends CompilerTask { |
| 28 Queue<ClassElement> toResolve; | 28 Queue<ClassElement> toResolve; |
| 29 | 29 |
| 30 // Caches the elements of analyzed constructors to make them available |
| 31 // for inlining in later tasks. |
| 32 Map<FunctionElement, TreeElements> constructorElements; |
| 33 |
| 30 ResolverTask(Compiler compiler) | 34 ResolverTask(Compiler compiler) |
| 31 : super(compiler), toResolve = new Queue<ClassElement>(); | 35 : super(compiler), toResolve = new Queue<ClassElement>(), |
| 36 constructorElements = new Map<FunctionElement, TreeElements>(); |
| 32 | 37 |
| 33 String get name() => 'Resolver'; | 38 String get name() => 'Resolver'; |
| 34 | 39 |
| 35 TreeElements resolve(Element element) { | 40 TreeElements resolve(Element element) { |
| 36 return measure(() { | 41 return measure(() { |
| 37 switch (element.kind) { | 42 switch (element.kind) { |
| 38 case ElementKind.GENERATIVE_CONSTRUCTOR: | 43 case ElementKind.GENERATIVE_CONSTRUCTOR: |
| 39 case ElementKind.FUNCTION: | 44 case ElementKind.FUNCTION: |
| 40 case ElementKind.GETTER: | 45 case ElementKind.GETTER: |
| 41 case ElementKind.SETTER: | 46 case ElementKind.SETTER: |
| 42 return resolveMethodElement(element); | 47 return resolveMethodElement(element); |
| 43 | 48 |
| 44 case ElementKind.FIELD: | 49 case ElementKind.FIELD: |
| 45 case ElementKind.PARAMETER: | 50 case ElementKind.PARAMETER: |
| 46 return resolveVariableElement(element); | 51 return resolveVariableElement(element); |
| 47 | 52 |
| 48 default: | 53 default: |
| 49 compiler.unimplemented( | 54 compiler.unimplemented( |
| 50 "resolver", node: element.parseNode(compiler)); | 55 "resolver", node: element.parseNode(compiler)); |
| 51 } | 56 } |
| 52 }); | 57 }); |
| 53 } | 58 } |
| 54 | 59 |
| 55 TreeElements resolveMethodElement(FunctionElement element) { | 60 TreeElements resolveMethodElement(FunctionElement element) { |
| 61 if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR && |
| 62 constructorElements[element] !== null) { |
| 63 return constructorElements[element]; |
| 64 } |
| 56 FunctionExpression tree = element.parseNode(compiler); | 65 FunctionExpression tree = element.parseNode(compiler); |
| 57 ResolverVisitor visitor = new ResolverVisitor(compiler, element); | 66 ResolverVisitor visitor = new ResolverVisitor(compiler, element); |
| 58 visitor.useElement(tree, element); | 67 visitor.useElement(tree, element); |
| 59 visitor.setupFunction(tree, element); | 68 visitor.setupFunction(tree, element); |
| 60 | 69 |
| 61 if (tree.initializers != null) { | 70 if (tree.initializers != null) { |
| 62 new InitializerResolver(visitor, element).resolveInitializers(tree); | 71 new InitializerResolver(visitor, element).resolveInitializers(tree); |
| 63 } | 72 } |
| 64 visitor.visit(tree.body); | 73 visitor.visit(tree.body); |
| 65 | 74 |
| 66 // Resolve the type annotations encountered in the method. | 75 // Resolve the type annotations encountered in the method. |
| 67 Link<ClassElement> newResolvedClasses = const EmptyLink<ClassElement>(); | 76 Link<ClassElement> newResolvedClasses = const EmptyLink<ClassElement>(); |
| 68 while (!toResolve.isEmpty()) { | 77 while (!toResolve.isEmpty()) { |
| 69 ClassElement classElement = toResolve.removeFirst(); | 78 ClassElement classElement = toResolve.removeFirst(); |
| 70 if (!classElement.isResolved) { | 79 if (!classElement.isResolved) { |
| 71 classElement.resolve(compiler); | 80 classElement.resolve(compiler); |
| 72 } | 81 } |
| 73 newResolvedClasses = newResolvedClasses.prepend(classElement); | 82 newResolvedClasses = newResolvedClasses.prepend(classElement); |
| 74 } | 83 } |
| 75 checkClassHierarchy(newResolvedClasses); | 84 checkClassHierarchy(newResolvedClasses); |
| 85 if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR) { |
| 86 constructorElements[element] = visitor.mapping; |
| 87 } |
| 76 return visitor.mapping; | 88 return visitor.mapping; |
| 77 } | 89 } |
| 78 | 90 |
| 79 TreeElements resolveVariableElement(Element element) { | 91 TreeElements resolveVariableElement(Element element) { |
| 80 Node tree = element.parseNode(compiler); | 92 Node tree = element.parseNode(compiler); |
| 81 ResolverVisitor visitor = new ResolverVisitor(compiler, element); | 93 ResolverVisitor visitor = new ResolverVisitor(compiler, element); |
| 82 if (tree is SendSet) { | 94 if (tree is SendSet) { |
| 83 SendSet send = tree; | 95 SendSet send = tree; |
| 84 visitor.visit(send.arguments.head); | 96 visitor.visit(send.arguments.head); |
| 85 } | 97 } |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 } | 166 } |
| 155 } | 167 } |
| 156 | 168 |
| 157 class InitializerResolver { | 169 class InitializerResolver { |
| 158 final ResolverVisitor visitor; | 170 final ResolverVisitor visitor; |
| 159 final FunctionElement constructor; | 171 final FunctionElement constructor; |
| 160 final Map<SourceString, Node> initialized; | 172 final Map<SourceString, Node> initialized; |
| 161 Link<Node> initializers; | 173 Link<Node> initializers; |
| 162 bool hasSuper; | 174 bool hasSuper; |
| 163 | 175 |
| 164 bool isSuperConstructorCall(Send node) { | |
| 165 return (node.receiver === null && | |
| 166 node.selector.asIdentifier() !== null && | |
| 167 node.selector.asIdentifier().isSuper()) || | |
| 168 (node.receiver !== null && | |
| 169 node.receiver.asIdentifier() !== null && | |
| 170 node.receiver.asIdentifier().isSuper() && | |
| 171 node.selector.asIdentifier() !== null); | |
| 172 } | |
| 173 | |
| 174 bool isConstructorRedirect(Send node) { | |
| 175 return (node.receiver === null && | |
| 176 node.selector.asIdentifier() !== null && | |
| 177 node.selector.asIdentifier().isThis()) || | |
| 178 (node.receiver !== null && | |
| 179 node.receiver.asIdentifier() !== null && | |
| 180 node.receiver.asIdentifier().isThis() && | |
| 181 node.selector.asIdentifier() !== null); | |
| 182 } | |
| 183 | |
| 184 InitializerResolver(this.visitor, this.constructor) | 176 InitializerResolver(this.visitor, this.constructor) |
| 185 : initialized = new Map<SourceString, Node>(), hasSuper = false; | 177 : initialized = new Map<SourceString, Node>(), hasSuper = false; |
| 186 | 178 |
| 187 error(Node node, MessageKind kind, [arguments = const []]) { | 179 error(Node node, MessageKind kind, [arguments = const []]) { |
| 188 visitor.error(node, kind, arguments); | 180 visitor.error(node, kind, arguments); |
| 189 } | 181 } |
| 190 | 182 |
| 191 warning(Node node, MessageKind kind, [arguments = const []]) { | 183 warning(Node node, MessageKind kind, [arguments = const []]) { |
| 192 visitor.warning(node, kind, arguments); | 184 visitor.warning(node, kind, arguments); |
| 193 } | 185 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 } | 229 } |
| 238 } | 230 } |
| 239 | 231 |
| 240 void resolveSuperOrThis(Send call) { | 232 void resolveSuperOrThis(Send call) { |
| 241 noConstructor(e) { | 233 noConstructor(e) { |
| 242 if (e !== null) error(call, MessageKind.NO_CONSTRUCTOR, [e.name, e.kind]); | 234 if (e !== null) error(call, MessageKind.NO_CONSTRUCTOR, [e.name, e.kind]); |
| 243 } | 235 } |
| 244 | 236 |
| 245 ClassElement lookupTarget = constructor.enclosingElement; | 237 ClassElement lookupTarget = constructor.enclosingElement; |
| 246 bool validTarget = true; | 238 bool validTarget = true; |
| 247 if (isSuperConstructorCall(call)) { | 239 if (Initializers.isSuperConstructorCall(call)) { |
| 248 // Check for invalid initializers. | 240 // Check for invalid initializers. |
| 249 if (hasSuper) { | 241 if (hasSuper) { |
| 250 error(call, MessageKind.DUPLICATE_SUPER_INITIALIZER); | 242 error(call, MessageKind.DUPLICATE_SUPER_INITIALIZER); |
| 251 } | 243 } |
| 252 hasSuper = true; | 244 hasSuper = true; |
| 253 // Calculate correct lookup target and constructor name. | 245 // Calculate correct lookup target and constructor name. |
| 254 if (lookupTarget.name == Types.OBJECT) { | 246 if (lookupTarget.name == Types.OBJECT) { |
| 255 error(call, MessageKind.SUPER_INITIALIZER_IN_OBJECT); | 247 error(call, MessageKind.SUPER_INITIALIZER_IN_OBJECT); |
| 256 } else { | 248 } else { |
| 257 lookupTarget = lookupTarget.supertype.element; | 249 lookupTarget = lookupTarget.supertype.element; |
| 258 } | 250 } |
| 259 } else if (isConstructorRedirect(call)) { | 251 } else if (Initializers.isConstructorRedirect(call)) { |
| 260 // Check that there are no other initializers. | 252 // Check that there are no other initializers. |
| 261 if (!initializers.tail.isEmpty()) { | 253 if (!initializers.tail.isEmpty()) { |
| 262 error(call, MessageKind.REDIRECTING_CTOR_HAS_INITIALIZER); | 254 error(call, MessageKind.REDIRECTING_CTOR_HAS_INITIALIZER); |
| 263 } | 255 } |
| 264 } else { | 256 } else { |
| 265 visitor.error(call, MessageKind.CONSTRUCTOR_CALL_EXPECTED); | 257 visitor.error(call, MessageKind.CONSTRUCTOR_CALL_EXPECTED); |
| 266 validTarget = false; | 258 validTarget = false; |
| 267 } | 259 } |
| 268 | 260 |
| 269 if (validTarget) { | 261 if (validTarget) { |
| (...skipping 894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1164 class TopScope extends Scope { | 1156 class TopScope extends Scope { |
| 1165 LibraryElement get library() => element; | 1157 LibraryElement get library() => element; |
| 1166 | 1158 |
| 1167 TopScope(LibraryElement library) : super(null, library); | 1159 TopScope(LibraryElement library) : super(null, library); |
| 1168 Element lookup(SourceString name) => library.find(name); | 1160 Element lookup(SourceString name) => library.find(name); |
| 1169 | 1161 |
| 1170 Element add(Element element) { | 1162 Element add(Element element) { |
| 1171 throw "Cannot add an element in the top scope"; | 1163 throw "Cannot add an element in the top scope"; |
| 1172 } | 1164 } |
| 1173 } | 1165 } |
| OLD | NEW |