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

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

Powered by Google App Engine
This is Rietveld 408576698