Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(363)

Side by Side Diff: frog/leg/resolver.dart

Issue 8974014: Resolve initializers in constructors. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address 2nd round of comments. Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « frog/leg/elements/elements.dart ('k') | frog/leg/warnings.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « frog/leg/elements/elements.dart ('k') | frog/leg/warnings.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698