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

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

Issue 9327001: Implement super initializers. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebase and update test expectations. Created 8 years, 10 months 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
OLDNEW
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698