Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 class TreeElements { | 5 class TreeElements { |
| 6 Map<Node, Element> map; | 6 Map<Node, Element> map; |
| 7 TreeElements() : map = new LinkedHashMap<Node, Element>(); | 7 TreeElements() : map = new LinkedHashMap<Node, Element>(); |
| 8 operator []=(Node node, Element element) => map[node] = element; | 8 operator []=(Node node, Element element) => map[node] = element; |
| 9 operator [](Node node) => map[node]; | 9 operator [](Node node) => map[node]; |
| 10 } | 10 } |
| 11 | 11 |
| 12 class ResolverTask extends CompilerTask { | 12 class ResolverTask extends CompilerTask { |
| 13 Queue<ClassElement> toResolve; | 13 Queue<ClassElement> toResolve; |
| 14 | 14 |
| 15 ResolverTask(Compiler compiler) | 15 ResolverTask(Compiler compiler) |
| 16 : super(compiler), toResolve = new Queue<ClassElement>(); | 16 : super(compiler), toResolve = new Queue<ClassElement>(); |
| 17 | 17 |
| 18 String get name() => 'Resolver'; | 18 String get name() => 'Resolver'; |
| 19 | 19 |
| 20 TreeElements resolve(FunctionElement element) { | 20 TreeElements resolve(FunctionElement element) { |
| 21 return measure(() { | 21 return measure(() { |
| 22 FunctionExpression tree = element.parseNode(compiler, compiler); | 22 FunctionExpression tree = element.parseNode(compiler, compiler); |
| 23 if (tree.initializers !== null) { | |
| 24 compiler.cancel('initializers are not implemented', | |
| 25 node: tree.initializers); | |
| 26 } | |
| 27 ResolverVisitor visitor = new SignatureResolverVisitor(compiler, element); | 23 ResolverVisitor visitor = new SignatureResolverVisitor(compiler, element); |
| 28 visitor.visit(tree); | 24 visitor.visit(tree); |
| 29 | 25 |
| 30 visitor = new FullResolverVisitor.from(visitor); | 26 visitor = new FullResolverVisitor.from(visitor); |
| 27 if (tree.initializers != null) { | |
| 28 resolveInitializers(element, tree, visitor); | |
| 29 } | |
| 31 visitor.visit(tree.body); | 30 visitor.visit(tree.body); |
| 32 | 31 |
| 33 // Resolve the type annotations encountered in the method. | 32 // Resolve the type annotations encountered in the method. |
| 34 while (!toResolve.isEmpty()) { | 33 while (!toResolve.isEmpty()) { |
| 35 toResolve.removeFirst().resolve(compiler); | 34 toResolve.removeFirst().resolve(compiler); |
| 36 } | 35 } |
| 37 return visitor.mapping; | 36 return visitor.mapping; |
| 38 }); | 37 }); |
| 39 } | 38 } |
| 40 | 39 |
| 40 bool isInitializer(SendSet node) { | |
| 41 if (node.selector.asIdentifier() == null) return false; | |
| 42 if (node.receiver == null) return true; | |
| 43 if (node.receiver.asIdentifier() == null) return false; | |
| 44 return node.receiver.asIdentifier().isThis(); | |
| 45 } | |
| 46 | |
| 47 SourceString getInitializerFieldName(SendSet node, onError(node)) { | |
| 48 if (!isInitializer(node)) onError(node); | |
| 49 return node.selector.asIdentifier().source; | |
| 50 } | |
| 51 | |
| 52 void resolveInitializers(Element element, FunctionExpression node, | |
| 53 ResolverVisitor visitor) { | |
| 54 void onError(node) { | |
| 55 visitor.error(node, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); | |
| 56 } | |
| 57 Map<SourceString, Node> initialized = new Map<SourceString, Node>(); | |
| 58 for (Link<Node> link = node.initializers.nodes; | |
| 59 !link.isEmpty(); | |
| 60 link = link.tail) { | |
| 61 if (link.head.asSendSet() != null) { | |
| 62 SendSet init = link.head; | |
| 63 SourceString name = getInitializerFieldName(init, onError); | |
|
ngeoffray
2011/12/21 16:44:08
If it's not an identifier, what do you get as a na
| |
| 64 ClassElement classElement = element.enclosingElement; | |
| 65 Element target = classElement.lookupLocalElement(name); | |
|
ngeoffray
2011/12/21 16:44:08
lookupLocalElement -> lookupLocalMember (after mer
| |
| 66 Node selector = init.selector; | |
| 67 if (target == null) { | |
| 68 visitor.error(selector, MessageKind.CANNOT_RESOLVE, [name]); | |
| 69 } else if (target.kind != ElementKind.FIELD) { | |
| 70 visitor.error(selector, MessageKind.NOT_A_FIELD, [name]); | |
| 71 } else if (!target.isInstanceMember()) { | |
| 72 visitor.error(selector, MessageKind.INIT_STATIC_FIELD, [name]); | |
| 73 } | |
| 74 visitor.useElement(init, target); | |
| 75 if (initialized.containsKey(name)) { | |
| 76 visitor.error(init, MessageKind.DUPLICATE_INITIALIZER, [name]); | |
| 77 visitor.warning(initialized[name], MessageKind.ALREADY_INITIALIZED, | |
| 78 [name]); | |
|
ngeoffray
2011/12/21 16:44:08
@ahe: not sure, but splitting the warning in two,
| |
| 79 } | |
| 80 initialized[name] = init; | |
| 81 Node value = init.arguments.head; | |
| 82 visitor.visitInStaticContext(value); | |
| 83 } else if (link.head.asSend() !== null) { | |
| 84 // TODO(karlklose): super(...), this(...). | |
| 85 compiler.cancel('uniplemented', node:link.head); | |
|
ngeoffray
2011/12/21 16:44:08
uniMplemented
| |
| 86 } else { | |
| 87 compiler.cancel('internal error: invalid initializer', | |
| 88 node: link.head); | |
| 89 } | |
| 90 } | |
| 91 } | |
| 92 | |
| 41 void resolveType(ClassElement element) { | 93 void resolveType(ClassElement element) { |
| 42 measure(() { | 94 measure(() { |
| 43 ClassNode tree = element.node; | 95 ClassNode tree = element.node; |
| 44 ClassResolverVisitor visitor = new ClassResolverVisitor(compiler); | 96 ClassResolverVisitor visitor = new ClassResolverVisitor(compiler); |
| 45 visitor.visit(tree); | 97 visitor.visit(tree); |
| 46 }); | 98 }); |
| 47 } | 99 } |
| 48 | 100 |
| 49 void resolveSignature(FunctionElement element) { | 101 void resolveSignature(FunctionElement element) { |
| 50 measure(() { | 102 measure(() { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 85 | 137 |
| 86 warning(Node node, MessageKind kind, [arguments = const []]) { | 138 warning(Node node, MessageKind kind, [arguments = const []]) { |
| 87 ResolutionWarning warning = new ResolutionWarning(kind, arguments); | 139 ResolutionWarning warning = new ResolutionWarning(kind, arguments); |
| 88 compiler.reportWarning(node, warning); | 140 compiler.reportWarning(node, warning); |
| 89 } | 141 } |
| 90 | 142 |
| 91 cancel(Node node, String message) { | 143 cancel(Node node, String message) { |
| 92 compiler.cancel(message); | 144 compiler.cancel(message); |
| 93 } | 145 } |
| 94 | 146 |
| 147 Element lookup(Node node, SourceString name) { | |
| 148 Element result = context.lookup(name); | |
| 149 if (!inInstanceContext && result != null && result.isInstanceMember()) { | |
| 150 error(node, MessageKind.NOT_STATIC, [node]); | |
| 151 } | |
| 152 return result; | |
| 153 } | |
| 154 | |
| 155 visitInStaticContext(Node node) { | |
| 156 bool wasInstanceContext = inInstanceContext; | |
| 157 inInstanceContext = false; | |
| 158 visit(node); | |
| 159 inInstanceContext = wasInstanceContext; | |
| 160 } | |
| 161 | |
| 95 visit(Node node) { | 162 visit(Node node) { |
| 96 if (node == null) return null; | 163 if (node == null) return null; |
| 97 return node.accept(this); | 164 return node.accept(this); |
| 98 } | 165 } |
| 99 | 166 |
| 100 visitIdentifier(Identifier node) { | 167 visitIdentifier(Identifier node) { |
| 101 if (node.isThis()) { | 168 if (node.isThis()) { |
| 102 if (!inInstanceContext) error(node, MessageKind.NO_THIS_IN_STATIC); | 169 if (!inInstanceContext) error(node, MessageKind.NO_THIS_IN_STATIC); |
| 103 return null; | 170 return null; |
| 104 } else { | 171 } else { |
| 105 Element element = context.lookup(node.source); | 172 Element element = lookup(node, node.source); |
| 106 if (element == null) { | 173 if (element == null) { |
| 107 error(node, MessageKind.CANNOT_RESOLVE, [node]); | 174 error(node, MessageKind.CANNOT_RESOLVE, [node]); |
| 108 } | 175 } |
| 109 return useElement(node, element); | 176 return useElement(node, element); |
| 110 } | 177 } |
| 111 } | 178 } |
| 112 | 179 |
| 113 visitTypeAnnotation(TypeAnnotation node) { | 180 visitTypeAnnotation(TypeAnnotation node) { |
| 114 Identifier name = node.typeName; | 181 Identifier name = node.typeName; |
| 115 if (name.source == const SourceString('var')) return null; | 182 if (name.source == const SourceString('var')) return null; |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 146 | 213 |
| 147 class SignatureResolverVisitor extends ResolverVisitor { | 214 class SignatureResolverVisitor extends ResolverVisitor { |
| 148 FunctionElement element; | 215 FunctionElement element; |
| 149 | 216 |
| 150 SignatureResolverVisitor(Compiler compiler, FunctionElement element) | 217 SignatureResolverVisitor(Compiler compiler, FunctionElement element) |
| 151 : super(compiler, element), this.element = element; | 218 : super(compiler, element), this.element = element; |
| 152 | 219 |
| 153 visitFunctionExpression(FunctionExpression node) { | 220 visitFunctionExpression(FunctionExpression node) { |
| 154 useElement(node, element); | 221 useElement(node, element); |
| 155 context = new MethodScope(context, element); | 222 context = new MethodScope(context, element); |
| 156 | |
| 157 if (element.parameters == null) { | 223 if (element.parameters == null) { |
| 158 ParametersVisitor visitor = new ParametersVisitor(this); | 224 ParametersVisitor visitor = new ParametersVisitor(this); |
| 159 visitor.visit(node.parameters); | 225 visitor.visit(node.parameters); |
| 160 element.parameters = visitor.elements.toLink(); | 226 element.parameters = visitor.elements.toLink(); |
| 161 } else { | 227 } else { |
| 162 Link<Node> parameterNodes = node.parameters.nodes; | 228 Link<Node> parameterNodes = node.parameters.nodes; |
| 163 for (Link<Element> link = element.parameters; | 229 for (Link<Element> link = element.parameters; |
| 164 !link.isEmpty() && !parameterNodes.isEmpty(); | 230 !link.isEmpty() && !parameterNodes.isEmpty(); |
| 165 link = link.tail, parameterNodes = parameterNodes.tail) { | 231 link = link.tail, parameterNodes = parameterNodes.tail) { |
| 166 defineElement(parameterNodes.head.definitions.nodes.head, link.head); | 232 defineElement(parameterNodes.head.definitions.nodes.head, link.head); |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 301 Identifier selector = node.selector; | 367 Identifier selector = node.selector; |
| 302 SourceString name = selector.source; | 368 SourceString name = selector.source; |
| 303 // No need to assign an element for a logical operation. | 369 // No need to assign an element for a logical operation. |
| 304 if (isLogicalOperator(selector)) return null; | 370 if (isLogicalOperator(selector)) return null; |
| 305 | 371 |
| 306 Element target = null; | 372 Element target = null; |
| 307 if (node.isOperator) { | 373 if (node.isOperator) { |
| 308 SourceString opName = mapOperatorToMethodName(name, node.isPrefix); | 374 SourceString opName = mapOperatorToMethodName(name, node.isPrefix); |
| 309 target = compiler.universe.find(opName); | 375 target = compiler.universe.find(opName); |
| 310 } else if (node.receiver === null) { | 376 } else if (node.receiver === null) { |
| 311 target = context.lookup(name); | 377 target = visit(node); |
| 312 if (target == null && !enclosingElement.isInstanceMember()) { | 378 if (target == null && !enclosingElement.isInstanceMember()) { |
| 313 error(node, MessageKind.CANNOT_RESOLVE, [name]); | 379 error(node, MessageKind.CANNOT_RESOLVE, [name]); |
| 314 } | 380 } |
| 315 } else if (receiver === null) { | 381 } else if (receiver === null) { |
| 316 return null; | 382 return null; |
| 317 } else if (receiver.kind === ElementKind.CLASS) { | 383 } else if (receiver.kind === ElementKind.CLASS) { |
| 318 ClassElement receiverClass = receiver; | 384 ClassElement receiverClass = receiver; |
| 319 target = receiverClass.resolve(compiler).lookupLocalElement(name); | 385 target = receiverClass.resolve(compiler).lookupLocalElement(name); |
| 320 if (target == null) { | 386 if (target == null) { |
| 321 error(node, MessageKind.METHOD_NOT_FOUND, [receiver, name]); | 387 error(node, MessageKind.METHOD_NOT_FOUND, [receiver, name]); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 345 SourceString name = mapAssignmentOperatorToMethodName(op.source); | 411 SourceString name = mapAssignmentOperatorToMethodName(op.source); |
| 346 Element operatorElement = compiler.universe.find(name); | 412 Element operatorElement = compiler.universe.find(name); |
| 347 useElement(op, operatorElement); | 413 useElement(op, operatorElement); |
| 348 // Resolve the getter for the lhs (receiver+selector). | 414 // Resolve the getter for the lhs (receiver+selector). |
| 349 // Currently this is the same as the setter. | 415 // Currently this is the same as the setter. |
| 350 // TODO(ngeoffray): Adapt for fields. | 416 // TODO(ngeoffray): Adapt for fields. |
| 351 Element getter; | 417 Element getter; |
| 352 if (node.isIndex) { | 418 if (node.isIndex) { |
| 353 getter = target; | 419 getter = target; |
| 354 } else { | 420 } else { |
| 355 getter = context.lookup(node.selector.asIdentifier().source); | 421 getter = visit(node); |
| 356 } | 422 } |
| 357 useElement(node.selector, getter); | 423 useElement(node.selector, getter); |
| 358 } | 424 } |
| 359 if (node.isIndex) { | 425 if (node.isIndex) { |
| 360 assert(target.name.stringValue === 'index'); | 426 assert(target.name.stringValue === 'index'); |
| 361 target = compiler.universe.find(const SourceString('indexSet')); | 427 target = compiler.universe.find(const SourceString('indexSet')); |
| 362 } | 428 } |
| 363 return useElement(node, target); | 429 return useElement(node, target); |
| 364 } | 430 } |
| 365 | 431 |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 562 | 628 |
| 563 visit(Node node) => node.accept(this); | 629 visit(Node node) => node.accept(this); |
| 564 } | 630 } |
| 565 | 631 |
| 566 class Scope { | 632 class Scope { |
| 567 final Element element; | 633 final Element element; |
| 568 final Scope parent; | 634 final Scope parent; |
| 569 | 635 |
| 570 Scope(this.parent, this.element); | 636 Scope(this.parent, this.element); |
| 571 abstract Element add(Element element); | 637 abstract Element add(Element element); |
| 572 abstract Element lookup(Element element); | 638 abstract Element lookup(SourceString name); |
| 573 } | 639 } |
| 574 | 640 |
| 575 class MethodScope extends Scope { | 641 class MethodScope extends Scope { |
| 576 final Map<SourceString, Element> elements; | 642 final Map<SourceString, Element> elements; |
| 577 | 643 |
| 578 MethodScope(Scope parent, Element element) | 644 MethodScope(Scope parent, Element element) |
| 579 : super(parent, element), this.elements = {}; | 645 : super(parent, element), this.elements = {}; |
| 580 | 646 |
| 581 Element lookup(SourceString name) { | 647 Element lookup(SourceString name) { |
| 582 Element element = elements[name]; | 648 Element element = elements[name]; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 619 class TopScope extends Scope { | 685 class TopScope extends Scope { |
| 620 Universe universe; | 686 Universe universe; |
| 621 | 687 |
| 622 TopScope(Universe this.universe) : super(null, null); | 688 TopScope(Universe this.universe) : super(null, null); |
| 623 Element lookup(SourceString name) => universe.find(name); | 689 Element lookup(SourceString name) => universe.find(name); |
| 624 | 690 |
| 625 Element add(Element element) { | 691 Element add(Element element) { |
| 626 throw "Cannot add an element in the top scope"; | 692 throw "Cannot add an element in the top scope"; |
| 627 } | 693 } |
| 628 } | 694 } |
| OLD | NEW |