Chromium Code Reviews| 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: |
| 44 case ElementKind.GENERATIVE_CONSTRUCTOR_BODY: | |
|
ngeoffray
2012/02/07 14:25:59
Why are you adding this one? The generative constr
| |
| 39 case ElementKind.FUNCTION: | 45 case ElementKind.FUNCTION: |
| 40 case ElementKind.GETTER: | 46 case ElementKind.GETTER: |
| 41 case ElementKind.SETTER: | 47 case ElementKind.SETTER: |
| 42 return resolveMethodElement(element); | 48 return resolveMethodElement(element); |
| 43 | 49 |
| 44 case ElementKind.FIELD: | 50 case ElementKind.FIELD: |
| 45 case ElementKind.PARAMETER: | 51 case ElementKind.PARAMETER: |
| 46 return resolveVariableElement(element); | 52 return resolveVariableElement(element); |
| 47 | 53 |
| 48 default: | 54 default: |
| 49 compiler.unimplemented( | 55 compiler.unimplemented( |
| 50 "resolver", node: element.parseNode(compiler)); | 56 "resolver", node: element.parseNode(compiler)); |
| 51 } | 57 } |
| 52 }); | 58 }); |
| 53 } | 59 } |
| 54 | 60 |
| 55 TreeElements resolveMethodElement(FunctionElement element) { | 61 TreeElements resolveMethodElement(FunctionElement element) { |
| 62 if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR && | |
| 63 constructorElements[element] !== null) { | |
| 64 return constructorElements[element]; | |
| 65 } | |
| 56 FunctionExpression tree = element.parseNode(compiler); | 66 FunctionExpression tree = element.parseNode(compiler); |
| 57 ResolverVisitor visitor = new ResolverVisitor(compiler, element); | 67 ResolverVisitor visitor = new ResolverVisitor(compiler, element); |
| 58 visitor.useElement(tree, element); | 68 visitor.useElement(tree, element); |
| 59 visitor.setupFunction(tree, element); | 69 visitor.setupFunction(tree, element); |
| 60 | 70 |
| 61 if (tree.initializers != null) { | 71 if (tree.initializers != null) { |
| 62 new InitializerResolver(visitor, element).resolveInitializers(tree); | 72 new InitializerResolver(visitor, element).resolveInitializers(tree); |
| 63 } | 73 } |
| 64 visitor.visit(tree.body); | 74 visitor.visit(tree.body); |
| 65 | 75 |
| 66 // Resolve the type annotations encountered in the method. | 76 // Resolve the type annotations encountered in the method. |
| 67 Link<ClassElement> newResolvedClasses = const EmptyLink<ClassElement>(); | 77 Link<ClassElement> newResolvedClasses = const EmptyLink<ClassElement>(); |
| 68 while (!toResolve.isEmpty()) { | 78 while (!toResolve.isEmpty()) { |
| 69 ClassElement classElement = toResolve.removeFirst(); | 79 ClassElement classElement = toResolve.removeFirst(); |
| 70 if (!classElement.isResolved) { | 80 if (!classElement.isResolved) { |
| 71 classElement.resolve(compiler); | 81 classElement.resolve(compiler); |
| 72 } | 82 } |
| 73 newResolvedClasses = newResolvedClasses.prepend(classElement); | 83 newResolvedClasses = newResolvedClasses.prepend(classElement); |
| 74 } | 84 } |
| 75 checkClassHierarchy(newResolvedClasses); | 85 checkClassHierarchy(newResolvedClasses); |
| 86 if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR) { | |
| 87 constructorElements[element] = visitor.mapping; | |
| 88 } | |
| 76 return visitor.mapping; | 89 return visitor.mapping; |
| 77 } | 90 } |
| 78 | 91 |
| 79 TreeElements resolveVariableElement(Element element) { | 92 TreeElements resolveVariableElement(Element element) { |
| 80 Node tree = element.parseNode(compiler); | 93 Node tree = element.parseNode(compiler); |
| 81 ResolverVisitor visitor = new ResolverVisitor(compiler, element); | 94 ResolverVisitor visitor = new ResolverVisitor(compiler, element); |
| 82 if (tree is SendSet) { | 95 if (tree is SendSet) { |
| 83 SendSet send = tree; | 96 SendSet send = tree; |
| 84 visitor.visit(send.arguments.head); | 97 visitor.visit(send.arguments.head); |
| 85 } | 98 } |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 154 } | 167 } |
| 155 } | 168 } |
| 156 | 169 |
| 157 class InitializerResolver { | 170 class InitializerResolver { |
| 158 final ResolverVisitor visitor; | 171 final ResolverVisitor visitor; |
| 159 final FunctionElement constructor; | 172 final FunctionElement constructor; |
| 160 final Map<SourceString, Node> initialized; | 173 final Map<SourceString, Node> initialized; |
| 161 Link<Node> initializers; | 174 Link<Node> initializers; |
| 162 bool hasSuper; | 175 bool hasSuper; |
| 163 | 176 |
| 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) | 177 InitializerResolver(this.visitor, this.constructor) |
| 185 : initialized = new Map<SourceString, Node>(), hasSuper = false; | 178 : initialized = new Map<SourceString, Node>(), hasSuper = false; |
| 186 | 179 |
| 187 error(Node node, MessageKind kind, [arguments = const []]) { | 180 error(Node node, MessageKind kind, [arguments = const []]) { |
| 188 visitor.error(node, kind, arguments); | 181 visitor.error(node, kind, arguments); |
| 189 } | 182 } |
| 190 | 183 |
| 191 warning(Node node, MessageKind kind, [arguments = const []]) { | 184 warning(Node node, MessageKind kind, [arguments = const []]) { |
| 192 visitor.warning(node, kind, arguments); | 185 visitor.warning(node, kind, arguments); |
| 193 } | 186 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 237 } | 230 } |
| 238 } | 231 } |
| 239 | 232 |
| 240 void resolveSuperOrThis(Send call) { | 233 void resolveSuperOrThis(Send call) { |
| 241 noConstructor(e) { | 234 noConstructor(e) { |
| 242 if (e !== null) error(call, MessageKind.NO_CONSTRUCTOR, [e.name, e.kind]); | 235 if (e !== null) error(call, MessageKind.NO_CONSTRUCTOR, [e.name, e.kind]); |
| 243 } | 236 } |
| 244 | 237 |
| 245 ClassElement lookupTarget = constructor.enclosingElement; | 238 ClassElement lookupTarget = constructor.enclosingElement; |
| 246 bool validTarget = true; | 239 bool validTarget = true; |
| 247 if (isSuperConstructorCall(call)) { | 240 if (Initializers.isSuperConstructorCall(call)) { |
| 248 // Check for invalid initializers. | 241 // Check for invalid initializers. |
| 249 if (hasSuper) { | 242 if (hasSuper) { |
| 250 error(call, MessageKind.DUPLICATE_SUPER_INITIALIZER); | 243 error(call, MessageKind.DUPLICATE_SUPER_INITIALIZER); |
| 251 } | 244 } |
| 252 hasSuper = true; | 245 hasSuper = true; |
| 253 // Calculate correct lookup target and constructor name. | 246 // Calculate correct lookup target and constructor name. |
| 254 if (lookupTarget.name == Types.OBJECT) { | 247 if (lookupTarget.name == Types.OBJECT) { |
| 255 error(call, MessageKind.SUPER_INITIALIZER_IN_OBJECT); | 248 error(call, MessageKind.SUPER_INITIALIZER_IN_OBJECT); |
| 256 } else { | 249 } else { |
| 257 lookupTarget = lookupTarget.supertype.element; | 250 lookupTarget = lookupTarget.supertype.element; |
| 258 } | 251 } |
| 259 } else if (isConstructorRedirect(call)) { | 252 } else if (Initializers.isConstructorRedirect(call)) { |
| 260 // Check that there are no other initializers. | 253 // Check that there are no other initializers. |
| 261 if (!initializers.tail.isEmpty()) { | 254 if (!initializers.tail.isEmpty()) { |
| 262 error(call, MessageKind.REDIRECTING_CTOR_HAS_INITIALIZER); | 255 error(call, MessageKind.REDIRECTING_CTOR_HAS_INITIALIZER); |
| 263 } | 256 } |
| 264 } else { | 257 } else { |
| 265 visitor.error(call, MessageKind.CONSTRUCTOR_CALL_EXPECTED); | 258 visitor.error(call, MessageKind.CONSTRUCTOR_CALL_EXPECTED); |
| 266 validTarget = false; | 259 validTarget = false; |
| 267 } | 260 } |
| 268 | 261 |
| 269 if (validTarget) { | 262 if (validTarget) { |
| (...skipping 877 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1147 class TopScope extends Scope { | 1140 class TopScope extends Scope { |
| 1148 LibraryElement get library() => element; | 1141 LibraryElement get library() => element; |
| 1149 | 1142 |
| 1150 TopScope(LibraryElement library) : super(null, library); | 1143 TopScope(LibraryElement library) : super(null, library); |
| 1151 Element lookup(SourceString name) => library.find(name); | 1144 Element lookup(SourceString name) => library.find(name); |
| 1152 | 1145 |
| 1153 Element add(Element element) { | 1146 Element add(Element element) { |
| 1154 throw "Cannot add an element in the top scope"; | 1147 throw "Cannot add an element in the top scope"; |
| 1155 } | 1148 } |
| 1156 } | 1149 } |
| OLD | NEW |