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

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

Issue 9243011: Implement named constructors and resolving of redirecting constructors and super-initializers. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rename field. Created 8 years, 11 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) 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 }
(...skipping 24 matching lines...) Expand all
35 } 35 }
36 36
37 TreeElements resolveMethodElement(FunctionElement element) { 37 TreeElements resolveMethodElement(FunctionElement element) {
38 FunctionExpression tree = element.parseNode(compiler, compiler); 38 FunctionExpression tree = element.parseNode(compiler, compiler);
39 // TODO(ahe): Can this be cleaned up to use resolveSignature? 39 // TODO(ahe): Can this be cleaned up to use resolveSignature?
40 ResolverVisitor visitor = new SignatureResolverVisitor(compiler, element); 40 ResolverVisitor visitor = new SignatureResolverVisitor(compiler, element);
41 visitor.visit(tree); 41 visitor.visit(tree);
42 42
43 visitor = new FullResolverVisitor.from(visitor); 43 visitor = new FullResolverVisitor.from(visitor);
44 if (tree.initializers != null) { 44 if (tree.initializers != null) {
45 resolveInitializers(element, tree, visitor); 45 new InitializerResolver(visitor, element).resolveInitializers(tree);
46 } 46 }
47 visitor.visit(tree.body); 47 visitor.visit(tree.body);
48 48
49 // Resolve the type annotations encountered in the method. 49 // Resolve the type annotations encountered in the method.
50 while (!toResolve.isEmpty()) { 50 while (!toResolve.isEmpty()) {
51 toResolve.removeFirst().resolve(compiler); 51 toResolve.removeFirst().resolve(compiler);
52 } 52 }
53 return visitor.mapping; 53 return visitor.mapping;
54 } 54 }
55 55
56 TreeElements resolveFieldElement(Element element) { 56 TreeElements resolveFieldElement(Element element) {
57 Node tree = element.parseNode(compiler, compiler); 57 Node tree = element.parseNode(compiler, compiler);
58 ResolverVisitor visitor = new FullResolverVisitor(compiler, element); 58 ResolverVisitor visitor = new FullResolverVisitor(compiler, element);
59 if (tree is SendSet) { 59 if (tree is SendSet) {
60 compiler.unimplemented("Field initializers", node: tree); 60 compiler.unimplemented("Field initializers", node: tree);
61 SendSet send = tree; 61 SendSet send = tree;
62 visitor.visit(send.arguments.head); 62 visitor.visit(send.arguments.head);
63 } 63 }
64 return visitor.mapping; 64 return visitor.mapping;
65 } 65 }
66 66
67 bool isInitializer(SendSet node) {
68 if (node.selector.asIdentifier() == null) return false;
69 if (node.receiver == null) return true;
70 if (node.receiver.asIdentifier() == null) return false;
71 return node.receiver.asIdentifier().isThis();
72 }
73
74 SourceString getInitializerFieldName(SendSet node, onError(node)) {
75 if (!isInitializer(node)) onError(node);
76 return node.selector.asIdentifier().source;
77 }
78
79 void resolveInitializers(Element element, FunctionExpression node,
80 ResolverVisitor visitor) {
81 void onError(node) {
82 visitor.error(node, MessageKind.INVALID_RECEIVER_IN_INITIALIZER);
83 }
84 Map<SourceString, Node> initialized = new Map<SourceString, Node>();
85 for (Link<Node> link = node.initializers.nodes;
86 !link.isEmpty();
87 link = link.tail) {
88 if (link.head.asSendSet() != null) {
89 SendSet init = link.head;
90 SourceString name = getInitializerFieldName(init, onError);
91 ClassElement classElement = element.enclosingElement;
92 Element target = classElement.lookupLocalMember(name);
93 Node selector = init.selector;
94 if (target == null) {
95 visitor.error(selector, MessageKind.CANNOT_RESOLVE, [name]);
96 } else if (target.kind != ElementKind.FIELD) {
97 visitor.error(selector, MessageKind.NOT_A_FIELD, [name]);
98 } else if (!target.isInstanceMember()) {
99 visitor.error(selector, MessageKind.INIT_STATIC_FIELD, [name]);
100 }
101 visitor.useElement(init, target);
102 if (initialized.containsKey(name)) {
103 visitor.error(init, MessageKind.DUPLICATE_INITIALIZER, [name]);
104 visitor.warning(initialized[name], MessageKind.ALREADY_INITIALIZED,
105 [name]);
106 }
107 initialized[name] = init;
108 Node value = init.arguments.head;
109 visitor.visitInStaticContext(value);
110 } else if (link.head.asSend() !== null) {
111 // TODO(karlklose): super(...), this(...).
112 compiler.cancel('uniplemented', node:link.head);
113 } else {
114 compiler.cancel('internal error: invalid initializer',
115 node: link.head);
116 }
117 }
118 }
119
120 void resolveType(ClassElement element) { 67 void resolveType(ClassElement element) {
121 measure(() { 68 measure(() {
122 ClassNode tree = element.node; 69 ClassNode tree = element.node;
123 ClassResolverVisitor visitor = new ClassResolverVisitor(compiler); 70 ClassResolverVisitor visitor = new ClassResolverVisitor(compiler);
124 visitor.visit(tree); 71 visitor.visit(tree);
125 }); 72 });
126 } 73 }
127 74
128 void resolveSignature(FunctionElement element) { 75 void resolveSignature(FunctionElement element) {
129 measure(() { 76 measure(() {
130 FunctionExpression node = element.node; 77 FunctionExpression node = element.node;
131 SignatureResolverVisitor visitor = 78 SignatureResolverVisitor visitor =
132 new SignatureResolverVisitor(compiler, element); 79 new SignatureResolverVisitor(compiler, element);
133 visitor.visitFunctionExpression(node); 80 visitor.visitFunctionExpression(node);
134 }); 81 });
135 } 82 }
136 } 83 }
137 84
85
86 class InitializerResolver {
87 final ResolverVisitor visitor;
88 final FunctionElement constructor;
89 Map<SourceString, Node> initialized;
90 Node initializerOrSuper;
91 bool hasSuper;
92
93 InitializerResolver(this.visitor, this.constructor)
94 : initialized = new Map<SourceString, Node>(), hasSuper = false;
95
96 Universe get universe() => visitor.compiler.universe;
97
98 error(Node node, MessageKind kind, [arguments = const []]) {
99 visitor.error(node, kind, arguments);
100 }
101
102 warning(Node node, MessageKind kind, [arguments = const []]) {
103 visitor.warning(node, kind, arguments);
104 }
105
106 bool isFieldInitializer(SendSet node) {
107 if (node.selector.asIdentifier() == null) return false;
108 if (node.receiver == null) return true;
109 if (node.receiver.asIdentifier() == null) return false;
110 return node.receiver.asIdentifier().isThis();
111 }
112
113 void resolveFieldInitializer(SendSet init) {
114 // init is of the form [this.]field = value.
115 final Node selector = init.selector;
116 final SourceString name = selector.asIdentifier().source;
117 // Lookup target field.
118 Element target;
119 if (isFieldInitializer(init)) {
120 if (initializerOrSuper == null) initializerOrSuper = init;
floitsch 2012/01/18 15:22:14 initializerOrSuper is unconditionally reassigned b
karlklose 2012/01/18 16:36:09 Done, moved.
121 final ClassElement classElement = constructor.enclosingElement;
122 target = classElement.lookupLocalMember(name);
123 if (target === null) {
124 error(selector, MessageKind.CANNOT_RESOLVE, [name]);
125 } else if (target.kind != ElementKind.FIELD) {
126 error(selector, MessageKind.NOT_A_FIELD, [name]);
127 } else if (!target.isInstanceMember()) {
128 error(selector, MessageKind.INIT_STATIC_FIELD, [name]);
129 }
130 } else {
131 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER);
132 }
133 visitor.useElement(init, target);
134 // Check for duplicate initializers.
135 if (initialized.containsKey(name)) {
136 error(init, MessageKind.DUPLICATE_INITIALIZER, [name]);
137 warning(initialized[name], MessageKind.ALREADY_INITIALIZED, [name]);
138 }
139 initialized[name] = init;
140 // Resolve initializing value.
141 visitor.visitInStaticContext(init.arguments.head);
142 initializerOrSuper = init;
143 }
144
145 SourceString getConstructorName(ClassElement cls, Send node) {
146 SourceString constructor = node.selector.asIdentifier().source;
147 if (node.receiver !== null) {
148 return new SourceString('${cls.name}.$constructor');
149 } else {
150 return cls.name;
151 }
152 }
153
154 void resolveSuperOrThis(Send call, Node next) {
155 noConstructor(e) {
156 if (e !== null) error(call, MessageKind.NO_CONSTRUCTOR, [e.name, e.kind]);
157 }
158 ClassElement lookupTarget = constructor.enclosingElement;
floitsch 2012/01/18 15:22:14 new line after nested function.
karlklose 2012/01/18 16:36:09 Done.
159 if (call.isSuperConstructorCall) {
160 // Check for invalid initializers.
161 if (hasSuper) {
162 error(call, MessageKind.DUPLICATE_SUPER_INITIALIZER);
163 }
164 if (initializerOrSuper == null) initializerOrSuper = call;
165 hasSuper = true;
166 // Calculate correct lookup target and constructor name.
167 if (constructor.name === Types.OBJECT) {
168 error(call, MessageKind.SUPER_INITIALIZER_IN_OBJECT);
169 } else {
170 lookupTarget = lookupTarget.supertype.element;
171 }
172 } else if (call.isConstructorRedirect) {
173 // Check that there are no other initializers.
174 if (initializerOrSuper !== null || next !== null) {
175 Node diagnosticNode =
176 initializerOrSuper !== null ? initializerOrSuper
177 : next;
178 error(diagnosticNode,
179 MessageKind.REDIRECTING_CTOR_HAS_INITIALIZER);
180 }
181 } else {
182 visitor.error(call, MessageKind.CONSTRUCTOR_CALL_EXPECTED);
183 }
184
185 final SourceString name = getConstructorName(lookupTarget, call);
186 FunctionElement target =
187 lookupTarget.lookupConstructor(name, noConstructor);
188 if (target === null && call.arguments.isEmpty()) {
189 target = lookupTarget.getSynthesizedConstructor();
floitsch 2012/01/18 15:22:14 what if there is no synthesized constructor? The n
karlklose 2012/01/18 16:36:09 Done.
190 } else if (target === null) {
191 error(call, MessageKind.CANNOT_RESOLVE, ["constructor $name"]);
192 } else {
193 final Compiler compiler = visitor.compiler;
194 final FunctionExpression targetNode =
195 target.parseNode(compiler, compiler);
196 final int parameters = targetNode.parameterCount();
floitsch 2012/01/18 15:22:14 no need to create these intermediate variables. pa
karlklose 2012/01/18 16:36:09 Done.
197 final int arguments = call.argumentCount();
198 // TODO(karlklose): support optional arguments.
199 if (parameters != arguments) {
200 error(call, MessageKind.NO_MATCHING_CONSTRUCTOR);
201 }
202 }
203 visitor.compiler.enqueue(new WorkItem.toCompile(target));
204 visitor.useElement(call, target);
205 // Resolve the arguments of the call.
206 for (Link<Node> arguments = call.arguments;
207 !arguments.isEmpty();
208 arguments = arguments.tail) {
209 visitor.visitInStaticContext(arguments.head);
210 }
211 }
212
213 void resolveInitializers(FunctionExpression node) {
214 if (node.initializers === null) return;
215 Compiler compiler = visitor.compiler;
216 // TODO(karlklose): implement initializer parameters.
217 for (Link<Node> link = node.initializers.nodes;
218 !link.isEmpty();
219 link = link.tail) {
220 if (link.head.asSendSet() != null) {
221 final SendSet init = link.head.asSendSet();
222 resolveFieldInitializer(init);
223 } else if (link.head.asSend() !== null) {
224 final Send call = link.head.asSend();
225 resolveSuperOrThis(call, link.tail.isEmpty() ? null : link.tail.head);
226 } else {
227 visitor.compiler.cancel('internal error: invalid initializer',
228 node: link.head);
229 }
230 }
231 }
232 }
233
234
138 // TODO(ahe): Frog cannot handle generic types. 235 // TODO(ahe): Frog cannot handle generic types.
139 class ResolverVisitor extends AbstractVisitor/*<Element>*/ { 236 class ResolverVisitor extends AbstractVisitor/*<Element>*/ {
140 final Compiler compiler; 237 final Compiler compiler;
141 final TreeElements mapping; 238 final TreeElements mapping;
142 final Element enclosingElement; 239 final Element enclosingElement;
143 bool inInstanceContext; 240 bool inInstanceContext;
144 Scope context; 241 Scope context;
145 ClassElement currentClass; 242 ClassElement currentClass;
146 bool typeRequired = false; 243 bool typeRequired = false;
147 244
(...skipping 26 matching lines...) Expand all
174 compiler.reportWarning(node, warning); 271 compiler.reportWarning(node, warning);
175 } 272 }
176 273
177 cancel(Node node, String message) { 274 cancel(Node node, String message) {
178 compiler.cancel(message, node: node); 275 compiler.cancel(message, node: node);
179 } 276 }
180 277
181 Element lookup(Node node, SourceString name) { 278 Element lookup(Node node, SourceString name) {
182 Element result = context.lookup(name); 279 Element result = context.lookup(name);
183 if (!inInstanceContext && result != null && result.isInstanceMember()) { 280 if (!inInstanceContext && result != null && result.isInstanceMember()) {
184 error(node, MessageKind.NOT_STATIC, [node]); 281 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]);
185 } 282 }
186 return result; 283 return result;
187 } 284 }
188 285
189 visitInStaticContext(Node node) { 286 visitInStaticContext(Node node) {
190 bool wasInstanceContext = inInstanceContext; 287 bool wasInstanceContext = inInstanceContext;
191 inInstanceContext = false; 288 inInstanceContext = false;
192 visit(node); 289 visit(node);
193 inInstanceContext = wasInstanceContext; 290 inInstanceContext = wasInstanceContext;
194 } 291 }
195 292
196 visit(Node node) { 293 visit(Node node) {
197 if (node == null) return null; 294 if (node == null) return null;
198 return node.accept(this); 295 return node.accept(this);
199 } 296 }
200 297
201 visitIdentifier(Identifier node) { 298 visitIdentifier(Identifier node) {
202 if (node.isThis()) { 299 if (node.isThis() || node.isSuper()) {
203 if (!inInstanceContext) error(node, MessageKind.NO_THIS_IN_STATIC); 300 if (!inInstanceContext) {
301 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]);
302 }
204 return null; 303 return null;
205 } else if (node.isSuper()) { 304 } else if (node.isSuper()) {
206 if (!inInstanceContext) error(node, MessageKind.NO_SUPER_IN_STATIC); 305 if (!inInstanceContext) error(node, MessageKind.NO_SUPER_IN_STATIC);
207 return null; 306 return null;
208 } else { 307 } else {
209 Element element = lookup(node, node.source); 308 Element element = lookup(node, node.source);
210 if (element == null) { 309 if (element == null) {
211 error(node, MessageKind.CANNOT_RESOLVE, [node]); 310 error(node, MessageKind.CANNOT_RESOLVE, [node]);
212 } 311 }
213 return useElement(node, element); 312 return useElement(node, element);
214 } 313 }
215 } 314 }
216 315
217 visitTypeAnnotation(TypeAnnotation node) { 316 visitTypeAnnotation(TypeAnnotation node) {
218 Identifier name = node.typeName.asIdentifier(); 317 SourceString className;
219 if (name === null) { 318 if (node.typeName.asSend() !== null) {
floitsch 2012/01/18 15:22:14 add comment when this happen (for 'new' and 'const
karlklose 2012/01/18 16:36:09 Done.
220 // TODO(karlklose): In progress. 319 Send send = node.typeName.asSend();
221 cancel(node.typeName, "not implemented"); 320 className = send.receiver.asIdentifier().source;
321 } else {
322 className = node.typeName.asIdentifier().source;
222 } 323 }
223 if (name.source == const SourceString('var')) return null; 324 if (className == const SourceString('var')) return null;
224 if (name.source == const SourceString('void')) return null; 325 if (className == const SourceString('void')) return null;
225 Element element = context.lookup(name.source); 326 Element element = context.lookup(className);
226 if (element === null) { 327 if (element === null) {
227 if (typeRequired) { 328 if (typeRequired) {
228 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [name]); 329 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [className]);
229 } else { 330 } else {
230 warning(node, MessageKind.CANNOT_RESOLVE_TYPE, [name]); 331 warning(node, MessageKind.CANNOT_RESOLVE_TYPE, [className]);
231 } 332 }
232 } else if (element.kind !== ElementKind.CLASS) { 333 } else if (element.kind !== ElementKind.CLASS) {
233 if (typeRequired) { 334 if (typeRequired) {
234 error(node, MessageKind.NOT_A_TYPE, [name]); 335 error(node, MessageKind.NOT_A_TYPE, [className]);
235 } else { 336 } else {
236 warning(node, MessageKind.NOT_A_TYPE, [name]); 337 warning(node, MessageKind.NOT_A_TYPE, [className]);
237 } 338 }
238 } else { 339 } else {
239 ClassElement cls = element; 340 ClassElement cls = element;
240 compiler.resolver.toResolve.add(element); 341 compiler.resolver.toResolve.add(element);
241 // TODO(ahe): This should be a Type. 342 // TODO(ahe): This should be a Type.
242 useElement(node, element); 343 useElement(node, element);
243 } 344 }
244 return element; 345 return element;
245 } 346 }
246 347
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 visitFor(For node) { 428 visitFor(For node) {
328 Scope scope = new BlockScope(context); 429 Scope scope = new BlockScope(context);
329 visitIn(node.initializer, scope); 430 visitIn(node.initializer, scope);
330 visitIn(node.condition, scope); 431 visitIn(node.condition, scope);
331 visitIn(node.update, scope); 432 visitIn(node.update, scope);
332 visitIn(node.body, scope); 433 visitIn(node.body, scope);
333 } 434 }
334 435
335 visitFunctionExpression(FunctionExpression node) { 436 visitFunctionExpression(FunctionExpression node) {
336 visit(node.returnType); 437 visit(node.returnType);
438 SourceString name;
337 if (node.name === null) { 439 if (node.name === null) {
338 cancel(node, "anonymous functions are not implemented"); 440 cancel(node, "anonymous functions are not implemented");
339 } 441 } else if (node.name.asSend() != null) {
340 if (node.name.asIdentifier() === null) { 442 Identifier cls = node.asSend().receiver.asIdentifier();
341 cancel(node.name, "named constructors are not implemented"); 443 Identifier constructor = node.asSend().selector.asIdentifier();
floitsch 2012/01/18 15:22:14 something missing here?
karlklose 2012/01/18 16:36:09 Done.
444 } else {
445 name = node.name.asIdentifier().source;
342 } 446 }
343 FunctionElement enclosingElement = new FunctionElement.node( 447 FunctionElement enclosingElement = new FunctionElement.node(
344 node, ElementKind.FUNCTION, null, context.element); 448 name, node, ElementKind.FUNCTION, null, context.element);
345 defineElement(node, enclosingElement); 449 defineElement(node, enclosingElement);
346 context = new MethodScope(context, enclosingElement); 450 context = new MethodScope(context, enclosingElement);
347 451
348 // TODO(ahe): Can this be cleaned up to use resolveSignature? 452 // TODO(ahe): Can this be cleaned up to use resolveSignature?
349 ParametersVisitor visitor = new ParametersVisitor(this); 453 ParametersVisitor visitor = new ParametersVisitor(this);
350 visitor.visit(node.parameters); 454 visitor.visit(node.parameters);
351 enclosingElement.parameters = visitor.elements.toLink(); 455 enclosingElement.parameters = visitor.elements.toLink();
352 456
353 visit(node.body); 457 visit(node.body);
354 context = context.parent; 458 context = context.parent;
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 615
512 visitParenthesizedExpression(ParenthesizedExpression node) { 616 visitParenthesizedExpression(ParenthesizedExpression node) {
513 visit(node.expression); 617 visit(node.expression);
514 } 618 }
515 619
516 visitNewExpression(NewExpression node) { 620 visitNewExpression(NewExpression node) {
517 if (node.isConst()) cancel(node, 'const expressions are not implemented'); 621 if (node.isConst()) cancel(node, 'const expressions are not implemented');
518 622
519 visit(node.send.argumentsNode); 623 visit(node.send.argumentsNode);
520 624
625 SourceString constructorName;
626 Node typeName = node.send.selector.asTypeAnnotation().typeName;
627 if (typeName.asSend() !== null) {
628 Identifier receiver = typeName.asSend().receiver.asIdentifier();
629 Identifier selector = typeName.asSend().selector.asIdentifier();
630 SourceString className = receiver.source;
631 SourceString name = selector.source;
632 constructorName = new SourceString('$className.$name');
633 } else {
634 constructorName = typeName.asIdentifier().source;
635 }
521 ClassElement cls = resolveTypeRequired(node.send.selector); 636 ClassElement cls = resolveTypeRequired(node.send.selector);
522 Element constructor = null; 637 Element constructor = null;
523 if (cls !== null) { 638 if (cls !== null) {
524 // TODO(ngeoffray): set constructor-name correctly. 639 constructor = cls.resolve(compiler).lookupConstructor(constructorName);
525 SourceString name = cls.name; 640 if (constructorName == cls.name
526 constructor = cls.resolve(compiler).lookupConstructor(name);
527 if (name == cls.name
528 && constructor === null 641 && constructor === null
529 && node.send.argumentsNode.isEmpty()) { 642 && node.send.argumentsNode.isEmpty()) {
530 constructor = cls.getSynthesizedConstructor(); 643 constructor = cls.getSynthesizedConstructor();
531 } 644 }
532 if (constructor === null) { 645 if (constructor === null) {
533 error(node, MessageKind.CANNOT_FIND_CONSTRUCTOR, [node]); 646 error(node.send, MessageKind.CANNOT_FIND_CONSTRUCTOR, [node.send]);
647 } else {
648 FunctionExpression fun = constructor.parseNode(compiler, compiler);
649 int argumentCount = node.send.argumentCount();
650 int parameterCount = fun.parameterCount();
floitsch 2012/01/18 15:22:14 ditto. no need to have these intermediate variable
karlklose 2012/01/18 16:36:09 Done.
651 // TODO(karlklose): handle optional arguments.
652 if (argumentCount != parameterCount) {
653 error(node.send, MessageKind.CANNOT_FIND_CONSTRUCTOR, [node.send]);
654 }
534 } 655 }
656 } else {
657 Node selector = node.send.selector;
658 error(selector, MessageKind.CANNOT_RESOLVE_TYPE, [selector]);
535 } 659 }
536
537 useElement(node.send, constructor); 660 useElement(node.send, constructor);
538 return null; 661 return null;
539 } 662 }
540 663
541 ClassElement resolveTypeRequired(Node node) { 664 ClassElement resolveTypeRequired(Node node) {
542 bool old = typeRequired; 665 bool old = typeRequired;
543 typeRequired = true; 666 typeRequired = true;
544 ClassElement cls = visit(node); 667 ClassElement cls = visit(node);
545 typeRequired = old; 668 typeRequired = old;
546 return cls; 669 return cls;
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
828 class TopScope extends Scope { 951 class TopScope extends Scope {
829 Universe universe; 952 Universe universe;
830 953
831 TopScope(Universe this.universe) : super(null, null); 954 TopScope(Universe this.universe) : super(null, null);
832 Element lookup(SourceString name) => universe.find(name); 955 Element lookup(SourceString name) => universe.find(name);
833 956
834 Element add(Element element) { 957 Element add(Element element) {
835 throw "Cannot add an element in the top scope"; 958 throw "Cannot add an element in the top scope";
836 } 959 }
837 } 960 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698