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 void resolveInitializers(element, node, visitor) { | |
|
ngeoffray
2011/12/21 11:52:11
Types on parameters?
ahe
2011/12/21 12:01:58
I'd like a type on node.
karlklose
2011/12/21 16:33:46
Done.
karlklose
2011/12/21 16:33:46
Done.
| |
| 41 Map<SourceString, Node> initialized = new Map<SourceString, Node>(); | |
| 42 for (Link<Node> link = node.initializers.nodes; | |
| 43 !link.isEmpty(); | |
| 44 link = link.tail) { | |
| 45 if (link.head.asSendSet() != null) { | |
| 46 SendSet init = link.head; | |
| 47 SourceString name = init.getInitializerFieldName( | |
| 48 () => visitor.error(init, | |
| 49 MessageKind.INVALID_RECEIVER_IN_INITIALIZER)); | |
| 50 ClassElement classElement = element.enclosingElement; | |
| 51 Element target = classElement.lookupLocalElement(name); | |
| 52 Node selector = init.selector; | |
| 53 if (target == null) { | |
| 54 visitor.error(selector, MessageKind.CANNOT_RESOLVE, [name]); | |
| 55 } else if (target.kind != ElementKind.FIELD) { | |
| 56 visitor.error(selector, MessageKind.NOT_A_FIELD, [name]); | |
| 57 } else if (!target.isInstanceMember()) { | |
| 58 visitor.error(selector, MessageKind.INIT_STATIC_FIELD, [name]); | |
| 59 } | |
| 60 visitor.useElement(init, target); | |
| 61 if (initialized.containsKey(name)) { | |
| 62 visitor.warning(init, MessageKind.DUPLICATE_INITIALIZER, | |
|
ngeoffray
2011/12/21 11:52:11
The spec says it's a compile time error, so should
karlklose
2011/12/21 16:33:46
Done.
| |
| 63 [name, initialized[name]]); | |
| 64 } | |
| 65 initialized[name] = init; | |
| 66 Node value = init.arguments.head; | |
| 67 visitor.visitInStaticContext(value); | |
| 68 } else { | |
| 69 // TODO(karlklose): super(...), this(...). | |
| 70 compiler.cancel('internal error: invalid initializer', | |
|
ngeoffray
2011/12/21 11:52:11
invalid -> unimplemented
ahe
2011/12/21 12:01:58
This is not an internal error, and the initializer
karlklose
2011/12/21 16:33:46
Done.
karlklose
2011/12/21 16:33:46
Done.
| |
| 71 node: link.head); | |
| 72 } | |
| 73 } | |
| 74 } | |
| 75 | |
| 41 void resolveType(ClassElement element) { | 76 void resolveType(ClassElement element) { |
| 42 measure(() { | 77 measure(() { |
| 43 ClassNode tree = element.node; | 78 ClassNode tree = element.node; |
| 44 ClassResolverVisitor visitor = new ClassResolverVisitor(compiler); | 79 ClassResolverVisitor visitor = new ClassResolverVisitor(compiler); |
| 45 visitor.visit(tree); | 80 visitor.visit(tree); |
| 46 }); | 81 }); |
| 47 } | 82 } |
| 48 | 83 |
| 49 void resolveSignature(FunctionElement element) { | 84 void resolveSignature(FunctionElement element) { |
| 50 measure(() { | 85 measure(() { |
| 51 FunctionExpression node = element.node; | 86 FunctionExpression node = element.node; |
| 52 SignatureResolverVisitor visitor = | 87 SignatureResolverVisitor visitor = |
| 53 new SignatureResolverVisitor(compiler, element); | 88 new SignatureResolverVisitor(compiler, element); |
| 54 visitor.visitFunctionExpression(node); | 89 visitor.visitFunctionExpression(node); |
| 55 }); | 90 }); |
| 56 } | 91 } |
| 57 } | 92 } |
| 58 | 93 |
| 59 class ResolverVisitor implements Visitor<Element> { | 94 class ResolverVisitor implements Visitor<Element> { |
| 60 final Compiler compiler; | 95 final Compiler compiler; |
| 61 final TreeElements mapping; | 96 final TreeElements mapping; |
| 62 final Element enclosingElement; | 97 final Element enclosingElement; |
| 63 Scope context; | 98 Scope context; |
| 99 bool isStaticContext; | |
|
ngeoffray
2011/12/21 11:52:11
isStaticContext always looks weird to me (is it a
karlklose
2011/12/21 16:33:46
Done.
| |
| 64 | 100 |
| 65 ResolverVisitor(Compiler compiler, Element element) | 101 ResolverVisitor(Compiler compiler, Element element) |
| 66 : this.compiler = compiler, | 102 : this.compiler = compiler, |
| 67 this.mapping = new TreeElements(), | 103 this.mapping = new TreeElements(), |
| 68 this.enclosingElement = element, | 104 this.enclosingElement = element, |
| 69 this.context = element.isMember() | 105 this.context = element.isMember() |
| 70 ? new ClassScope(element.enclosingElement, compiler.universe) | 106 ? new ClassScope(element.enclosingElement, compiler.universe) |
| 71 : new TopScope(compiler.universe); | 107 : new TopScope(compiler.universe), |
| 108 this.isStaticContext = false; | |
| 72 | 109 |
| 73 ResolverVisitor.from(ResolverVisitor other) | 110 ResolverVisitor.from(ResolverVisitor other) |
| 74 : compiler = other.compiler, | 111 : compiler = other.compiler, |
| 75 mapping = other.mapping, | 112 mapping = other.mapping, |
| 76 enclosingElement = other.enclosingElement, | 113 enclosingElement = other.enclosingElement, |
| 77 context = other.context; | 114 context = other.context; |
| 78 | 115 |
| 79 error(Node node, MessageKind kind, [arguments = const []]) { | 116 error(Node node, MessageKind kind, [arguments = const []]) { |
| 80 ResolutionError error = new ResolutionError(kind, arguments); | 117 ResolutionError error = new ResolutionError(kind, arguments); |
| 81 compiler.reportError(node, error); | 118 compiler.reportError(node, error); |
| 82 } | 119 } |
| 83 | 120 |
| 84 warning(Node node, MessageKind kind, [arguments = const []]) { | 121 warning(Node node, MessageKind kind, [arguments = const []]) { |
| 85 ResolutionWarning warning = new ResolutionWarning(kind, arguments); | 122 ResolutionWarning warning = new ResolutionWarning(kind, arguments); |
| 86 compiler.reportWarning(node, warning); | 123 compiler.reportWarning(node, warning); |
| 87 } | 124 } |
| 88 | 125 |
| 89 cancel(Node node, String message) { | 126 cancel(Node node, String message) { |
| 90 compiler.cancel(message); | 127 compiler.cancel(message); |
| 91 } | 128 } |
| 92 | 129 |
| 130 Element lookup(Node node, SourceString name) { | |
| 131 Element result = context.lookup(name); | |
| 132 if (isStaticContext && result != null && result.isInstanceMember()) { | |
| 133 error(node, MessageKind.NOT_STATIC, [node]); | |
| 134 } | |
| 135 return result; | |
| 136 } | |
| 137 | |
| 138 visitInStaticContext(Node node) { | |
| 139 bool wasStaticContext = isStaticContext; | |
| 140 isStaticContext = true; | |
| 141 visit(node); | |
| 142 isStaticContext = wasStaticContext; | |
| 143 } | |
| 144 | |
| 93 visit(Node node) { | 145 visit(Node node) { |
| 94 if (node == null) return null; | 146 if (node == null) return null; |
| 95 return node.accept(this); | 147 return node.accept(this); |
| 96 } | 148 } |
| 97 | 149 |
| 98 visitIdentifier(Identifier node) { | 150 visitIdentifier(Identifier node) { |
| 99 Element element = context.lookup(node.source); | 151 Element element = lookup(node, node.source); |
| 100 if (element == null) { | 152 if (element == null) { |
| 101 error(node, MessageKind.CANNOT_RESOLVE, [node]); | 153 error(node, MessageKind.CANNOT_RESOLVE, [node]); |
| 102 } | 154 } |
| 103 return useElement(node, element); | 155 return useElement(node, element); |
| 104 } | 156 } |
| 105 | 157 |
| 106 visitTypeAnnotation(TypeAnnotation node) { | 158 visitTypeAnnotation(TypeAnnotation node) { |
| 107 Identifier name = node.typeName; | 159 Identifier name = node.typeName; |
| 108 if (name.source == const SourceString('var')) return null; | 160 if (name.source == const SourceString('var')) return null; |
| 109 if (name.source == const SourceString('void')) return null; | 161 if (name.source == const SourceString('void')) return null; |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 139 | 191 |
| 140 class SignatureResolverVisitor extends ResolverVisitor { | 192 class SignatureResolverVisitor extends ResolverVisitor { |
| 141 FunctionElement element; | 193 FunctionElement element; |
| 142 | 194 |
| 143 SignatureResolverVisitor(Compiler compiler, FunctionElement element) | 195 SignatureResolverVisitor(Compiler compiler, FunctionElement element) |
| 144 : super(compiler, element), this.element = element; | 196 : super(compiler, element), this.element = element; |
| 145 | 197 |
| 146 visitFunctionExpression(FunctionExpression node) { | 198 visitFunctionExpression(FunctionExpression node) { |
| 147 useElement(node, element); | 199 useElement(node, element); |
| 148 context = new MethodScope(context, element); | 200 context = new MethodScope(context, element); |
| 149 | |
| 150 if (element.parameters == null) { | 201 if (element.parameters == null) { |
| 151 ParametersVisitor visitor = new ParametersVisitor(this); | 202 ParametersVisitor visitor = new ParametersVisitor(this); |
| 152 visitor.visit(node.parameters); | 203 visitor.visit(node.parameters); |
| 153 element.parameters = visitor.elements.toLink(); | 204 element.parameters = visitor.elements.toLink(); |
| 154 } else { | 205 } else { |
| 155 Link<Node> parameterNodes = node.parameters.nodes; | 206 Link<Node> parameterNodes = node.parameters.nodes; |
| 156 for (Link<Element> link = element.parameters; | 207 for (Link<Element> link = element.parameters; |
| 157 !link.isEmpty() && !parameterNodes.isEmpty(); | 208 !link.isEmpty() && !parameterNodes.isEmpty(); |
| 158 link = link.tail, parameterNodes = parameterNodes.tail) { | 209 link = link.tail, parameterNodes = parameterNodes.tail) { |
| 159 defineElement(parameterNodes.head.definitions.nodes.head, link.head); | 210 defineElement(parameterNodes.head.definitions.nodes.head, link.head); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 293 Identifier selector = node.selector; | 344 Identifier selector = node.selector; |
| 294 SourceString name = selector.source; | 345 SourceString name = selector.source; |
| 295 // No need to assign an element for a logical operation. | 346 // No need to assign an element for a logical operation. |
| 296 if (isLogicalOperator(selector)) return null; | 347 if (isLogicalOperator(selector)) return null; |
| 297 | 348 |
| 298 Element target = null; | 349 Element target = null; |
| 299 if (node.isOperator) { | 350 if (node.isOperator) { |
| 300 SourceString opName = mapOperatorToMethodName(name, node.isPrefix); | 351 SourceString opName = mapOperatorToMethodName(name, node.isPrefix); |
| 301 target = compiler.universe.find(opName); | 352 target = compiler.universe.find(opName); |
| 302 } else if (node.receiver === null) { | 353 } else if (node.receiver === null) { |
| 303 target = context.lookup(name); | 354 target = lookup(node, name); |
|
ngeoffray
2011/12/21 11:52:11
I think this should be changed to target = visit(n
karlklose
2011/12/21 16:33:46
Done.
| |
| 304 if (target == null && !enclosingElement.isInstanceMember()) { | 355 if (target == null && !enclosingElement.isInstanceMember()) { |
| 305 error(node, MessageKind.CANNOT_RESOLVE, [name]); | 356 error(node, MessageKind.CANNOT_RESOLVE, [name]); |
| 306 } | 357 } |
| 307 } else if (receiver === null) { | 358 } else if (receiver === null) { |
| 308 return null; | 359 return null; |
| 309 } else if (receiver.kind === ElementKind.CLASS) { | 360 } else if (receiver.kind === ElementKind.CLASS) { |
| 310 ClassElement receiverClass = receiver; | 361 ClassElement receiverClass = receiver; |
| 311 target = receiverClass.lookupLocalElement(name); | 362 target = receiverClass.lookupLocalElement(name); |
| 312 if (target == null) { | 363 if (target == null) { |
| 313 error(node, MessageKind.METHOD_NOT_FOUND, [receiver, name]); | 364 error(node, MessageKind.METHOD_NOT_FOUND, [receiver, name]); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 337 SourceString name = mapAssignmentOperatorToMethodName(op.source); | 388 SourceString name = mapAssignmentOperatorToMethodName(op.source); |
| 338 Element operatorElement = compiler.universe.find(name); | 389 Element operatorElement = compiler.universe.find(name); |
| 339 useElement(op, operatorElement); | 390 useElement(op, operatorElement); |
| 340 // Resolve the getter for the lhs (receiver+selector). | 391 // Resolve the getter for the lhs (receiver+selector). |
| 341 // Currently this is the same as the setter. | 392 // Currently this is the same as the setter. |
| 342 // TODO(ngeoffray): Adapt for fields. | 393 // TODO(ngeoffray): Adapt for fields. |
| 343 Element getter; | 394 Element getter; |
| 344 if (node.isIndex) { | 395 if (node.isIndex) { |
| 345 getter = target; | 396 getter = target; |
| 346 } else { | 397 } else { |
| 347 getter = context.lookup(node.selector.asIdentifier().source); | 398 getter = lookup(node, node.selector.asIdentifier().source); |
|
ngeoffray
2011/12/21 11:52:11
ditto.
karlklose
2011/12/21 16:33:46
Done.
| |
| 348 } | 399 } |
| 349 useElement(node.selector, getter); | 400 useElement(node.selector, getter); |
| 350 } | 401 } |
| 351 if (node.isIndex) { | 402 if (node.isIndex) { |
| 352 assert(target.name.stringValue === 'index'); | 403 assert(target.name.stringValue === 'index'); |
| 353 target = compiler.universe.find(const SourceString('indexSet')); | 404 target = compiler.universe.find(const SourceString('indexSet')); |
| 354 } | 405 } |
| 355 return useElement(node, target); | 406 return useElement(node, target); |
| 356 } | 407 } |
| 357 | 408 |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 559 } | 610 } |
| 560 | 611 |
| 561 class Scope { | 612 class Scope { |
| 562 final Element element; | 613 final Element element; |
| 563 final Scope parent; | 614 final Scope parent; |
| 564 | 615 |
| 565 Map<SourceString, Element> get elements() => const {}; | 616 Map<SourceString, Element> get elements() => const {}; |
| 566 | 617 |
| 567 Scope(this.parent, this.element); | 618 Scope(this.parent, this.element); |
| 568 abstract Element add(Element element); | 619 abstract Element add(Element element); |
| 569 abstract Element lookup(Element element); | 620 abstract Element lookup(SourceString name); |
| 570 } | 621 } |
| 571 | 622 |
| 572 class MethodScope extends Scope { | 623 class MethodScope extends Scope { |
| 573 final Map<SourceString, Element> elements; | 624 final Map<SourceString, Element> elements; |
| 574 | 625 |
| 575 MethodScope(Scope parent, Element element) | 626 MethodScope(Scope parent, Element element) |
| 576 : super(parent, element), this.elements = {}; | 627 : super(parent, element), this.elements = {}; |
| 577 | 628 |
| 578 Element lookup(SourceString name) { | 629 Element lookup(SourceString name) { |
| 579 Element element = elements[name]; | 630 Element element = elements[name]; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 616 class TopScope extends Scope { | 667 class TopScope extends Scope { |
| 617 Universe universe; | 668 Universe universe; |
| 618 | 669 |
| 619 TopScope(Universe this.universe) : super(null, null); | 670 TopScope(Universe this.universe) : super(null, null); |
| 620 Element lookup(SourceString name) => universe.find(name); | 671 Element lookup(SourceString name) => universe.find(name); |
| 621 | 672 |
| 622 Element add(Element element) { | 673 Element add(Element element) { |
| 623 throw "Cannot add an element in the top scope"; | 674 throw "Cannot add an element in the top scope"; |
| 624 } | 675 } |
| 625 } | 676 } |
| OLD | NEW |