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

Side by Side Diff: pkg/compiler/lib/src/resolution/members.dart

Issue 1170673002: Begin to compute constant expressions in resolution. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Fix BinaryConstantExpression.getKnownType Created 5 years, 6 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
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 part of resolution; 5 part of resolution;
6 6
7 /** 7 /**
8 * Core implementation of resolution. 8 * Core implementation of resolution.
9 * 9 *
10 * Do not subclass or instantiate this class outside this library 10 * Do not subclass or instantiate this class outside this library
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 ? Scope.buildEnclosingScope(element) : element.buildScope(), 95 ? Scope.buildEnclosingScope(element) : element.buildScope(),
96 // The type annotations on a typedef do not imply type checks. 96 // The type annotations on a typedef do not imply type checks.
97 // TODO(karlklose): clean this up (dartbug.com/8870). 97 // TODO(karlklose): clean this up (dartbug.com/8870).
98 inCheckContext = compiler.enableTypeAssertions && 98 inCheckContext = compiler.enableTypeAssertions &&
99 !element.isLibrary && 99 !element.isLibrary &&
100 !element.isTypedef && 100 !element.isTypedef &&
101 !element.enclosingElement.isTypedef, 101 !element.enclosingElement.isTypedef,
102 inCatchBlock = false, 102 inCatchBlock = false,
103 super(compiler, registry); 103 super(compiler, registry);
104 104
105 CoreTypes get coreTypes => compiler.coreTypes;
106
105 AsyncMarker get currentAsyncMarker { 107 AsyncMarker get currentAsyncMarker {
106 if (enclosingElement is FunctionElement) { 108 if (enclosingElement is FunctionElement) {
107 FunctionElement function = enclosingElement; 109 FunctionElement function = enclosingElement;
108 return function.asyncMarker; 110 return function.asyncMarker;
109 } 111 }
110 return AsyncMarker.SYNC; 112 return AsyncMarker.SYNC;
111 } 113 }
112 114
113 Element reportLookupErrorIfAny(Element result, Node node, String name) { 115 Element reportLookupErrorIfAny(Element result, Node node, String name) {
114 if (!Elements.isUnresolved(result)) { 116 if (!Elements.isUnresolved(result)) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 return result; 161 return result;
160 } 162 }
161 163
162 doInPromotionScope(Node node, action()) { 164 doInPromotionScope(Node node, action()) {
163 promotionScope = promotionScope.prepend(node); 165 promotionScope = promotionScope.prepend(node);
164 var result = action(); 166 var result = action();
165 promotionScope = promotionScope.tail; 167 promotionScope = promotionScope.tail;
166 return result; 168 return result;
167 } 169 }
168 170
169 visitInStaticContext(Node node) { 171 ResolutionResult visitInStaticContext(Node node) {
170 inStaticContext(() => visit(node)); 172 return inStaticContext(() => visit(node));
171 } 173 }
172 174
173 ErroneousElement reportAndCreateErroneousElement( 175 ErroneousElement reportAndCreateErroneousElement(
174 Node node, 176 Node node,
175 String name, 177 String name,
176 MessageKind kind, 178 MessageKind kind,
177 Map arguments, 179 Map arguments,
178 {bool isError: false}) { 180 {bool isError: false}) {
179 if (isError) { 181 if (isError) {
180 compiler.reportError(node, kind, arguments); 182 compiler.reportError(node, kind, arguments);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 registry.registerThrowNoSuchMethod(); 225 registry.registerThrowNoSuchMethod();
224 return reportAndCreateErroneousElement( 226 return reportAndCreateErroneousElement(
225 node, name, kind, arguments, isError: inInitializer); 227 node, name, kind, arguments, isError: inInitializer);
226 } 228 }
227 229
228 ResolutionResult visitIdentifier(Identifier node) { 230 ResolutionResult visitIdentifier(Identifier node) {
229 if (node.isThis()) { 231 if (node.isThis()) {
230 if (!inInstanceContext) { 232 if (!inInstanceContext) {
231 error(node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': node}); 233 error(node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': node});
232 } 234 }
233 return null; 235 return const NoneResult();
234 } else if (node.isSuper()) { 236 } else if (node.isSuper()) {
235 if (!inInstanceContext) { 237 if (!inInstanceContext) {
236 error(node, MessageKind.NO_SUPER_IN_STATIC); 238 error(node, MessageKind.NO_SUPER_IN_STATIC);
237 } 239 }
238 if ((ElementCategory.SUPER & allowedCategory) == 0) { 240 if ((ElementCategory.SUPER & allowedCategory) == 0) {
239 error(node, MessageKind.INVALID_USE_OF_SUPER); 241 error(node, MessageKind.INVALID_USE_OF_SUPER);
240 } 242 }
241 return null; 243 return const NoneResult();
242 } else { 244 } else {
243 String name = node.source; 245 String name = node.source;
244 Element element = lookupInScope(compiler, node, scope, name); 246 Element element = lookupInScope(compiler, node, scope, name);
245 if (Elements.isUnresolved(element) && name == 'dynamic') { 247 if (Elements.isUnresolved(element) && name == 'dynamic') {
246 // TODO(johnniwinther): Remove this hack when we can return more complex 248 // TODO(johnniwinther): Remove this hack when we can return more complex
247 // objects than [Element] from this method. 249 // objects than [Element] from this method.
248 element = compiler.typeClass; 250 element = compiler.typeClass;
249 // Set the type to be `dynamic` to mark that this is a type literal. 251 // Set the type to be `dynamic` to mark that this is a type literal.
250 registry.setType(node, const DynamicType()); 252 registry.setType(node, const DynamicType());
251 } 253 }
(...skipping 13 matching lines...) Expand all
265 } 267 }
266 } 268 }
267 if (!Elements.isUnresolved(element) && element.isClass) { 269 if (!Elements.isUnresolved(element) && element.isClass) {
268 ClassElement classElement = element; 270 ClassElement classElement = element;
269 classElement.ensureResolved(compiler); 271 classElement.ensureResolved(compiler);
270 } 272 }
271 return new ElementResult(registry.useElement(node, element)); 273 return new ElementResult(registry.useElement(node, element));
272 } 274 }
273 } 275 }
274 276
275 ResolutionResult visitTypeAnnotation(TypeAnnotation node) { 277 TypeResult visitTypeAnnotation(TypeAnnotation node) {
276 DartType type = resolveTypeAnnotation(node); 278 DartType type = resolveTypeAnnotation(node);
277 if (inCheckContext) { 279 if (inCheckContext) {
278 registry.registerIsCheck(type); 280 registry.registerIsCheck(type);
279 } 281 }
280 return new TypeResult(type); 282 return new TypeResult(type);
281 } 283 }
282 284
283 bool isNamedConstructor(Send node) => node.receiver != null; 285 bool isNamedConstructor(Send node) => node.receiver != null;
284 286
285 Selector getRedirectingThisOrSuperConstructorSelector(Send node) { 287 Selector getRedirectingThisOrSuperConstructorSelector(Send node) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 compiler.resolver.constantCompiler.compileConstant(parameter); 353 compiler.resolver.constantCompiler.compileConstant(parameter);
352 }); 354 });
353 }); 355 });
354 if (inCheckContext) { 356 if (inCheckContext) {
355 functionParameters.forEachParameter((ParameterElement element) { 357 functionParameters.forEachParameter((ParameterElement element) {
356 registry.registerIsCheck(element.type); 358 registry.registerIsCheck(element.type);
357 }); 359 });
358 } 360 }
359 } 361 }
360 362
361 visitCascade(Cascade node) { 363 ResolutionResult visitCascade(Cascade node) {
362 visit(node.expression); 364 visit(node.expression);
365 return const NoneResult();
363 } 366 }
364 367
365 visitCascadeReceiver(CascadeReceiver node) { 368 ResolutionResult visitCascadeReceiver(CascadeReceiver node) {
366 visit(node.expression); 369 visit(node.expression);
370 return const NoneResult();
367 } 371 }
368 372
369 visitClassNode(ClassNode node) { 373 ResolutionResult visitIn(Node node, Scope nestedScope) {
370 internalError(node, "shouldn't be called");
371 }
372
373 visitIn(Node node, Scope nestedScope) {
374 Scope oldScope = scope; 374 Scope oldScope = scope;
375 scope = nestedScope; 375 scope = nestedScope;
376 ResolutionResult result = visit(node); 376 ResolutionResult result = visit(node);
377 scope = oldScope; 377 scope = oldScope;
378 return result; 378 return result;
379 } 379 }
380 380
381 /** 381 /**
382 * Introduces new default targets for break and continue 382 * Introduces new default targets for break and continue
383 * before visiting the body of the loop 383 * before visiting the body of the loop
384 */ 384 */
385 visitLoopBodyIn(Loop loop, Node body, Scope bodyScope) { 385 void visitLoopBodyIn(Loop loop, Node body, Scope bodyScope) {
386 JumpTarget element = getOrDefineTarget(loop); 386 JumpTarget element = getOrDefineTarget(loop);
387 statementScope.enterLoop(element); 387 statementScope.enterLoop(element);
388 visitIn(body, bodyScope); 388 visitIn(body, bodyScope);
389 statementScope.exitLoop(); 389 statementScope.exitLoop();
390 if (!element.isTarget) { 390 if (!element.isTarget) {
391 registry.undefineTarget(loop); 391 registry.undefineTarget(loop);
392 } 392 }
393 } 393 }
394 394
395 visitBlock(Block node) { 395 ResolutionResult visitBlock(Block node) {
396 visitIn(node.statements, new BlockScope(scope)); 396 visitIn(node.statements, new BlockScope(scope));
397 return const NoneResult();
397 } 398 }
398 399
399 visitDoWhile(DoWhile node) { 400 ResolutionResult visitDoWhile(DoWhile node) {
400 visitLoopBodyIn(node, node.body, new BlockScope(scope)); 401 visitLoopBodyIn(node, node.body, new BlockScope(scope));
401 visit(node.condition); 402 visit(node.condition);
403 return const NoneResult();
402 } 404 }
403 405
404 visitEmptyStatement(EmptyStatement node) { } 406 ResolutionResult visitEmptyStatement(EmptyStatement node) {
407 return const NoneResult();
408 }
405 409
406 visitExpressionStatement(ExpressionStatement node) { 410 ResolutionResult visitExpressionStatement(ExpressionStatement node) {
407 ExpressionStatement oldExpressionStatement = currentExpressionStatement; 411 ExpressionStatement oldExpressionStatement = currentExpressionStatement;
408 currentExpressionStatement = node; 412 currentExpressionStatement = node;
409 visit(node.expression); 413 visit(node.expression);
410 currentExpressionStatement = oldExpressionStatement; 414 currentExpressionStatement = oldExpressionStatement;
415 return const NoneResult();
411 } 416 }
412 417
413 visitFor(For node) { 418 ResolutionResult visitFor(For node) {
414 Scope blockScope = new BlockScope(scope); 419 Scope blockScope = new BlockScope(scope);
415 visitIn(node.initializer, blockScope); 420 visitIn(node.initializer, blockScope);
416 visitIn(node.condition, blockScope); 421 visitIn(node.condition, blockScope);
417 visitIn(node.update, blockScope); 422 visitIn(node.update, blockScope);
418 visitLoopBodyIn(node, node.body, blockScope); 423 visitLoopBodyIn(node, node.body, blockScope);
424 return const NoneResult();
419 } 425 }
420 426
421 visitFunctionDeclaration(FunctionDeclaration node) { 427 ResolutionResult visitFunctionDeclaration(FunctionDeclaration node) {
422 assert(node.function.name != null); 428 assert(node.function.name != null);
423 visitFunctionExpression(node.function, inFunctionDeclaration: true); 429 visitFunctionExpression(node.function, inFunctionDeclaration: true);
430 return const NoneResult();
424 } 431 }
425 432
426 433
427 /// Process a local function declaration or an anonymous function expression. 434 /// Process a local function declaration or an anonymous function expression.
428 /// 435 ///
429 /// [inFunctionDeclaration] is `true` when the current node is the immediate 436 /// [inFunctionDeclaration] is `true` when the current node is the immediate
430 /// child of a function declaration. 437 /// child of a function declaration.
431 /// 438 ///
432 /// This is used to distinguish local function declarations from anonymous 439 /// This is used to distinguish local function declarations from anonymous
433 /// function expressions. 440 /// function expressions.
434 visitFunctionExpression(FunctionExpression node, 441 ResolutionResult visitFunctionExpression(
435 {bool inFunctionDeclaration: false}) { 442 FunctionExpression node,
443 {bool inFunctionDeclaration: false}) {
436 bool doAddToScope = inFunctionDeclaration; 444 bool doAddToScope = inFunctionDeclaration;
437 if (!inFunctionDeclaration && node.name != null) { 445 if (!inFunctionDeclaration && node.name != null) {
438 compiler.reportError( 446 compiler.reportError(
439 node.name, 447 node.name,
440 MessageKind.NAMED_FUNCTION_EXPRESSION, 448 MessageKind.NAMED_FUNCTION_EXPRESSION,
441 {'name': node.name}); 449 {'name': node.name});
442 } 450 }
443 visit(node.returnType); 451 visit(node.returnType);
444 String name; 452 String name;
445 if (node.name == null) { 453 if (node.name == null) {
(...skipping 27 matching lines...) Expand all
473 StatementScope oldStatementScope = statementScope; 481 StatementScope oldStatementScope = statementScope;
474 statementScope = new StatementScope(); 482 statementScope = new StatementScope();
475 visit(node.body); 483 visit(node.body);
476 statementScope = oldStatementScope; 484 statementScope = oldStatementScope;
477 485
478 scope = oldScope; 486 scope = oldScope;
479 enclosingElement = previousEnclosingElement; 487 enclosingElement = previousEnclosingElement;
480 488
481 registry.registerClosure(function); 489 registry.registerClosure(function);
482 registry.registerInstantiatedClass(compiler.functionClass); 490 registry.registerInstantiatedClass(compiler.functionClass);
491 return const NoneResult();
483 } 492 }
484 493
485 visitIf(If node) { 494 ResolutionResult visitIf(If node) {
486 doInPromotionScope(node.condition.expression, () => visit(node.condition)); 495 doInPromotionScope(node.condition.expression, () => visit(node.condition));
487 doInPromotionScope(node.thenPart, 496 doInPromotionScope(node.thenPart,
488 () => visitIn(node.thenPart, new BlockScope(scope))); 497 () => visitIn(node.thenPart, new BlockScope(scope)));
489 visitIn(node.elsePart, new BlockScope(scope)); 498 visitIn(node.elsePart, new BlockScope(scope));
499 return const NoneResult();
490 } 500 }
491 501
492 ResolutionResult resolveSend(Send node) { 502 ResolutionResult resolveSend(Send node) {
493 Selector selector = resolveSelector(node, null); 503 Selector selector = resolveSelector(node, null);
494 if (node.isSuperCall) registry.registerSuperUse(node); 504 if (node.isSuperCall) registry.registerSuperUse(node);
495 505
496 if (node.receiver == null) { 506 if (node.receiver == null) {
497 // If this send is of the form "assert(expr);", then 507 // If this send is of the form "assert(expr);", then
498 // this is an assertion. 508 // this is an assertion.
499 if (selector.isAssert) { 509 if (selector.isAssert) {
(...skipping 26 matching lines...) Expand all
526 } 536 }
527 537
528 allowedCategory = oldCategory; 538 allowedCategory = oldCategory;
529 539
530 Element target; 540 Element target;
531 String name = node.selector.asIdentifier().source; 541 String name = node.selector.asIdentifier().source;
532 if (identical(name, 'this')) { 542 if (identical(name, 'this')) {
533 // TODO(ahe): Why is this using GENERIC? 543 // TODO(ahe): Why is this using GENERIC?
534 error(node.selector, MessageKind.GENERIC, 544 error(node.selector, MessageKind.GENERIC,
535 {'text': "expected an identifier"}); 545 {'text': "expected an identifier"});
536 return null; 546 return const NoneResult();
537 } else if (node.isSuperCall) { 547 } else if (node.isSuperCall) {
538 if (node.isOperator) { 548 if (node.isOperator) {
539 if (isUserDefinableOperator(name)) { 549 if (isUserDefinableOperator(name)) {
540 name = selector.name; 550 name = selector.name;
541 } else { 551 } else {
542 error(node.selector, MessageKind.ILLEGAL_SUPER_SEND, {'name': name}); 552 error(node.selector, MessageKind.ILLEGAL_SUPER_SEND, {'name': name});
543 return null; 553 return const NoneResult();
544 } 554 }
545 } 555 }
546 if (!inInstanceContext) { 556 if (!inInstanceContext) {
547 error(node.receiver, MessageKind.NO_INSTANCE_AVAILABLE, {'name': name}); 557 error(node.receiver, MessageKind.NO_INSTANCE_AVAILABLE, {'name': name});
548 return null; 558 return const NoneResult();
549 } 559 }
550 if (currentClass.supertype == null) { 560 if (currentClass.supertype == null) {
551 // This is just to guard against internal errors, so no need 561 // This is just to guard against internal errors, so no need
552 // for a real error message. 562 // for a real error message.
553 error(node.receiver, MessageKind.GENERIC, 563 error(node.receiver, MessageKind.GENERIC,
554 {'text': "Object has no superclass"}); 564 {'text': "Object has no superclass"});
555 return null; 565 return const NoneResult();
556 } 566 }
557 // TODO(johnniwinther): Ensure correct behavior if currentClass is a 567 // TODO(johnniwinther): Ensure correct behavior if currentClass is a
558 // patch. 568 // patch.
559 target = currentClass.lookupSuperByName(selector.memberName); 569 target = currentClass.lookupSuperByName(selector.memberName);
560 // [target] may be null which means invoking noSuchMethod on 570 // [target] may be null which means invoking noSuchMethod on
561 // super. 571 // super.
562 if (target == null) { 572 if (target == null) {
563 target = reportAndCreateErroneousElement( 573 target = reportAndCreateErroneousElement(
564 node, name, MessageKind.NO_SUCH_SUPER_MEMBER, 574 node, name, MessageKind.NO_SUCH_SUPER_MEMBER,
565 {'className': currentClass.name, 'memberName': name}); 575 {'className': currentClass.name, 'memberName': name});
566 // We still need to register the invocation, because we might 576 // We still need to register the invocation, because we might
567 // call [:super.noSuchMethod:] which calls 577 // call [:super.noSuchMethod:] which calls
568 // [JSInvocationMirror._invokeOn]. 578 // [JSInvocationMirror._invokeOn].
569 registry.registerDynamicInvocation(selector); 579 registry.registerDynamicInvocation(selector);
570 registry.registerSuperNoSuchMethod(); 580 registry.registerSuperNoSuchMethod();
571 } 581 }
572 } else if (resolvedReceiver == null || 582 } else if (Elements.isUnresolved(resolvedReceiver.element)) {
573 Elements.isUnresolved(resolvedReceiver.element)) { 583 return const NoneResult();
574 return null;
575 } else if (resolvedReceiver.element.isClass) { 584 } else if (resolvedReceiver.element.isClass) {
576 ClassElement receiverClass = resolvedReceiver.element; 585 ClassElement receiverClass = resolvedReceiver.element;
577 receiverClass.ensureResolved(compiler); 586 receiverClass.ensureResolved(compiler);
578 if (node.isOperator) { 587 if (node.isOperator) {
579 // When the resolved receiver is a class, we can have two cases: 588 // When the resolved receiver is a class, we can have two cases:
580 // 1) a static send: C.foo, or 589 // 1) a static send: C.foo, or
581 // 2) an operator send, where the receiver is a class literal: 'C + 1'. 590 // 2) an operator send, where the receiver is a class literal: 'C + 1'.
582 // The following code that looks up the selector on the resolved 591 // The following code that looks up the selector on the resolved
583 // receiver will treat the second as the invocation of a static operator 592 // receiver will treat the second as the invocation of a static operator
584 // if the resolved receiver is not null. 593 // if the resolved receiver is not null.
585 return null; 594 return const NoneResult();
586 } 595 }
587 MembersCreator.computeClassMembersByName( 596 MembersCreator.computeClassMembersByName(
588 compiler, receiverClass.declaration, name); 597 compiler, receiverClass.declaration, name);
589 target = receiverClass.lookupLocalMember(name); 598 target = receiverClass.lookupLocalMember(name);
590 if (target == null || target.isInstanceMember) { 599 if (target == null || target.isInstanceMember) {
591 registry.registerThrowNoSuchMethod(); 600 registry.registerThrowNoSuchMethod();
592 // TODO(johnniwinther): With the simplified [TreeElements] invariant, 601 // TODO(johnniwinther): With the simplified [TreeElements] invariant,
593 // try to resolve injected elements if [currentClass] is in the patch 602 // try to resolve injected elements if [currentClass] is in the patch
594 // library of [receiverClass]. 603 // library of [receiverClass].
595 604
(...skipping 27 matching lines...) Expand all
623 AmbiguousElement ambiguous = target; 632 AmbiguousElement ambiguous = target;
624 target = reportAndCreateErroneousElement( 633 target = reportAndCreateErroneousElement(
625 node, name, ambiguous.messageKind, ambiguous.messageArguments); 634 node, name, ambiguous.messageKind, ambiguous.messageArguments);
626 ambiguous.diagnose(enclosingElement, compiler); 635 ambiguous.diagnose(enclosingElement, compiler);
627 return new ElementResult(target); 636 return new ElementResult(target);
628 } else if (target.kind == ElementKind.CLASS) { 637 } else if (target.kind == ElementKind.CLASS) {
629 ClassElement classElement = target; 638 ClassElement classElement = target;
630 classElement.ensureResolved(compiler); 639 classElement.ensureResolved(compiler);
631 } 640 }
632 } 641 }
633 return new ElementResult(target); 642 return new ResolutionResult.forElement(target);
634 } 643 }
635 644
636 static Selector computeSendSelector(Send node, 645 static Selector computeSendSelector(Send node,
637 LibraryElement library, 646 LibraryElement library,
638 Element element) { 647 Element element) {
639 // First determine if this is part of an assignment. 648 // First determine if this is part of an assignment.
640 bool isSet = node.asSendSet() != null; 649 bool isSet = node.asSendSet() != null;
641 650
642 if (node.isIndex) { 651 if (node.isIndex) {
643 return isSet ? new Selector.indexSet() : new Selector.index(); 652 return isSet ? new Selector.indexSet() : new Selector.index();
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 type = resolveTypeAnnotation(typeNode); 899 type = resolveTypeAnnotation(typeNode);
891 sendStructure = new IsNotStructure(type); 900 sendStructure = new IsNotStructure(type);
892 } else { 901 } else {
893 // `e is T`. 902 // `e is T`.
894 Node typeNode = node.arguments.head; 903 Node typeNode = node.arguments.head;
895 type = resolveTypeAnnotation(typeNode); 904 type = resolveTypeAnnotation(typeNode);
896 sendStructure = new IsStructure(type); 905 sendStructure = new IsStructure(type);
897 } 906 }
898 registry.registerIsCheck(type); 907 registry.registerIsCheck(type);
899 registry.registerSendStructure(node, sendStructure); 908 registry.registerSendStructure(node, sendStructure);
900 return null; 909 return const NoneResult();
901 } 910 }
902 911
903 /// Handle a type cast expression, like `a as T`. 912 /// Handle a type cast expression, like `a as T`.
904 ResolutionResult handleAs(Send node) { 913 ResolutionResult handleAs(Send node) {
905 Node expression = node.receiver; 914 Node expression = node.receiver;
906 visitExpression(expression); 915 visitExpression(expression);
907 916
908 Node typeNode = node.arguments.head; 917 Node typeNode = node.arguments.head;
909 DartType type = resolveTypeAnnotation(typeNode); 918 DartType type = resolveTypeAnnotation(typeNode);
910 registry.registerAsCheck(type); 919 registry.registerAsCheck(type);
911 registry.registerSendStructure(node, new AsStructure(type)); 920 registry.registerSendStructure(node, new AsStructure(type));
912 return null; 921 return const NoneResult();
913 } 922 }
914 923
915 /// Handle the unary expression of an unresolved unary operator [text], like 924 /// Handle the unary expression of an unresolved unary operator [text], like
916 /// the no longer supported `+a`. 925 /// the no longer supported `+a`.
917 ResolutionResult handleUnresolvedUnary(Send node, String text) { 926 ResolutionResult handleUnresolvedUnary(Send node, String text) {
918 Node expression = node.receiver; 927 Node expression = node.receiver;
919 if (node.isSuperCall) { 928 if (node.isSuperCall) {
920 checkSuperAccess(node); 929 checkSuperAccess(node);
921 } else { 930 } else {
922 visitExpression(expression); 931 visitExpression(expression);
923 } 932 }
924 933
925 registry.registerSendStructure(node, const InvalidUnaryStructure()); 934 registry.registerSendStructure(node, const InvalidUnaryStructure());
926 return null; 935 return const NoneResult();
927 } 936 }
928 937
929 /// Handle the unary expression of a user definable unary [operator], like 938 /// Handle the unary expression of a user definable unary [operator], like
930 /// `-a`, and `-super`. 939 /// `-a`, and `-super`.
931 ResolutionResult handleUserDefinableUnary(Send node, UnaryOperator operator) { 940 ResolutionResult handleUserDefinableUnary(Send node, UnaryOperator operator) {
941 ResolutionResult result = const NoneResult();
932 Node expression = node.receiver; 942 Node expression = node.receiver;
933 Selector selector = operator.selector; 943 Selector selector = operator.selector;
934 // TODO(johnniwinther): Remove this when all information goes through the 944 // TODO(johnniwinther): Remove this when all information goes through the
935 // [SendStructure]. 945 // [SendStructure].
936 registry.setSelector(node, selector); 946 registry.setSelector(node, selector);
937 947
938 AccessSemantics semantics; 948 AccessSemantics semantics;
939 if (node.isSuperCall) { 949 if (node.isSuperCall) {
940 if (checkSuperAccess(node)) { 950 if (checkSuperAccess(node)) {
941 semantics = computeSuperSemantics(node, selector); 951 semantics = computeSuperSemantics(node, selector);
942 // TODO(johnniwinther): Add information to [AccessSemantics] about 952 // TODO(johnniwinther): Add information to [AccessSemantics] about
943 // whether it is erroneous. 953 // whether it is erroneous.
944 if (semantics.kind == AccessKind.SUPER_METHOD) { 954 if (semantics.kind == AccessKind.SUPER_METHOD) {
945 registry.registerStaticUse(semantics.element.declaration); 955 registry.registerStaticUse(semantics.element.declaration);
946 } 956 }
947 // TODO(johnniwinther): Remove this when all information goes through 957 // TODO(johnniwinther): Remove this when all information goes through
948 // the [SendStructure]. 958 // the [SendStructure].
949 registry.useElement(node, semantics.element); 959 registry.useElement(node, semantics.element);
950 } 960 }
951 } else { 961 } else {
952 visitExpression(expression); 962 ResolutionResult expressionResult = visitExpression(expression);
953 semantics = new DynamicAccess.dynamicProperty(expression); 963 semantics = new DynamicAccess.dynamicProperty(expression);
954 registry.registerDynamicInvocation(selector); 964 registry.registerDynamicInvocation(selector);
965
966 if (expressionResult.isConstant) {
967 bool isValidConstant;
968 ConstantExpression expressionConstant = expressionResult.constant;
969 DartType knownExpressionType =
970 expressionConstant.getKnownType(coreTypes);
971 switch (operator.kind) {
972 case UnaryOperatorKind.COMPLEMENT:
973 isValidConstant =
974 knownExpressionType == coreTypes.intType;
975 break;
976 case UnaryOperatorKind.NEGATE:
977 isValidConstant =
978 knownExpressionType == coreTypes.intType ||
979 knownExpressionType == coreTypes.doubleType;
980 break;
981 case UnaryOperatorKind.NOT:
982 internalError(node,
983 "Unexpected user definable unary operator: $operator");
984 }
985 if (isValidConstant) {
986 // TODO(johnniwinther): Handle potentially invalid constant
987 // expressions.
988 ConstantExpression constant =
989 new UnaryConstantExpression(operator, expressionConstant);
990 registry.setConstant(node, constant);
991 result = new ConstantResult(node, constant);
992 }
993 }
955 } 994 }
956 if (semantics != null) { 995 if (semantics != null) {
957 // TODO(johnniwinther): Support invalid super access as an 996 // TODO(johnniwinther): Support invalid super access as an
958 // [AccessSemantics]. 997 // [AccessSemantics].
959 registry.registerSendStructure(node, 998 registry.registerSendStructure(node,
960 new UnaryStructure(semantics, operator)); 999 new UnaryStructure(semantics, operator));
961 } 1000 }
962 return null; 1001 return result;
963 } 1002 }
964 1003
965 /// Handle a not expression, like `!a`. 1004 /// Handle a not expression, like `!a`.
966 ResolutionResult handleNot(Send node, UnaryOperator operator) { 1005 ResolutionResult handleNot(Send node, UnaryOperator operator) {
967 assert(invariant(node, operator.kind == UnaryOperatorKind.NOT)); 1006 assert(invariant(node, operator.kind == UnaryOperatorKind.NOT));
968 1007
969 Node expression = node.receiver; 1008 Node expression = node.receiver;
970 visitExpression(expression); 1009 ResolutionResult result = visitExpression(expression);
971 registry.registerSendStructure(node, 1010 registry.registerSendStructure(node,
972 new NotStructure(new DynamicAccess.dynamicProperty(expression))); 1011 new NotStructure(new DynamicAccess.dynamicProperty(expression)));
973 return null; 1012
1013 if (result.isConstant) {
1014 ConstantExpression expressionConstant = result.constant;
1015 if (expressionConstant.getKnownType(coreTypes) == coreTypes.boolType) {
1016 // TODO(johnniwinther): Handle potentially invalid constant expressions.
1017 ConstantExpression constant =
1018 new UnaryConstantExpression(operator, expressionConstant);
1019 registry.setConstant(node, constant);
1020 return new ConstantResult(node, constant);
1021 }
1022 }
1023
1024 return const NoneResult();
974 } 1025 }
975 1026
976 /// Handle a logical and expression, like `a && b`. 1027 /// Handle a logical and expression, like `a && b`.
977 ResolutionResult handleLogicalAnd(Send node) { 1028 ResolutionResult handleLogicalAnd(Send node) {
978 Node left = node.receiver; 1029 Node left = node.receiver;
979 Node right = node.arguments.head; 1030 Node right = node.arguments.head;
980 doInPromotionScope(left, () => visitExpression(left)); 1031 ResolutionResult leftResult =
981 doInPromotionScope(right, () => visitExpression(right)); 1032 doInPromotionScope(left, () => visitExpression(left));
1033 ResolutionResult rightResult =
1034 doInPromotionScope(right, () => visitExpression(right));
982 registry.registerSendStructure(node, const LogicalAndStructure()); 1035 registry.registerSendStructure(node, const LogicalAndStructure());
983 return null; 1036
1037 if (leftResult.isConstant && rightResult.isConstant) {
1038 ConstantExpression leftConstant = leftResult.constant;
1039 ConstantExpression rightConstant = rightResult.constant;
1040 if (leftConstant.getKnownType(coreTypes) == coreTypes.boolType &&
1041 rightConstant.getKnownType(coreTypes) == coreTypes.boolType) {
1042 // TODO(johnniwinther): Handle potentially invalid constant expressions.
1043 ConstantExpression constant = new BinaryConstantExpression(
1044 leftConstant,
1045 BinaryOperator.LOGICAL_AND,
1046 rightConstant);
1047 registry.setConstant(node, constant);
1048 return new ConstantResult(node, constant);
1049 }
1050 }
1051
1052 return const NoneResult();
984 } 1053 }
985 1054
986 /// Handle a logical or expression, like `a || b`. 1055 /// Handle a logical or expression, like `a || b`.
987 ResolutionResult handleLogicalOr(Send node) { 1056 ResolutionResult handleLogicalOr(Send node) {
988 Node left = node.receiver; 1057 Node left = node.receiver;
989 Node right = node.arguments.head; 1058 Node right = node.arguments.head;
990 visitExpression(left); 1059 ResolutionResult leftResult = visitExpression(left);
991 visitExpression(right); 1060 ResolutionResult rightResult = visitExpression(right);
992 registry.registerSendStructure(node, const LogicalOrStructure()); 1061 registry.registerSendStructure(node, const LogicalOrStructure());
993 return null; 1062
1063 if (leftResult.isConstant && rightResult.isConstant) {
1064 ConstantExpression leftConstant = leftResult.constant;
1065 ConstantExpression rightConstant = rightResult.constant;
1066 if (leftConstant.getKnownType(coreTypes) == coreTypes.boolType &&
1067 rightConstant.getKnownType(coreTypes) == coreTypes.boolType) {
1068 // TODO(johnniwinther): Handle potentially invalid constant expressions.
1069 ConstantExpression constant = new BinaryConstantExpression(
1070 leftConstant,
1071 BinaryOperator.LOGICAL_OR,
1072 rightConstant);
1073 registry.setConstant(node, constant);
1074 return new ConstantResult(node, constant);
1075 }
1076 }
1077 return const NoneResult();
994 } 1078 }
995 1079
996 /// Handle an if-null expression, like `a ?? b`. 1080 /// Handle an if-null expression, like `a ?? b`.
997 ResolutionResult handleIfNull(Send node) { 1081 ResolutionResult handleIfNull(Send node) {
998 Node left = node.receiver; 1082 Node left = node.receiver;
999 Node right = node.arguments.head; 1083 Node right = node.arguments.head;
1000 visitExpression(left); 1084 visitExpression(left);
1001 visitExpression(right); 1085 visitExpression(right);
1002 registry.registerSendStructure(node, const IfNullStructure()); 1086 registry.registerSendStructure(node, const IfNullStructure());
1003 return null; 1087 return const NoneResult();
1004 } 1088 }
1005 1089
1006 /// Handle the binary expression of an unresolved binary operator [text], like 1090 /// Handle the binary expression of an unresolved binary operator [text], like
1007 /// the no longer supported `a === b`. 1091 /// the no longer supported `a === b`.
1008 ResolutionResult handleUnresolvedBinary(Send node, String text) { 1092 ResolutionResult handleUnresolvedBinary(Send node, String text) {
1009 Node left = node.receiver; 1093 Node left = node.receiver;
1010 Node right = node.arguments.head; 1094 Node right = node.arguments.head;
1011 if (node.isSuperCall) { 1095 if (node.isSuperCall) {
1012 checkSuperAccess(node); 1096 checkSuperAccess(node);
1013 } else { 1097 } else {
1014 visitExpression(left); 1098 visitExpression(left);
1015 } 1099 }
1016 visitExpression(right); 1100 visitExpression(right);
1017 registry.registerSendStructure(node, const InvalidBinaryStructure()); 1101 registry.registerSendStructure(node, const InvalidBinaryStructure());
1018 return null; 1102 return const NoneResult();
1019 } 1103 }
1020 1104
1021 /// Handle the binary expression of a user definable binary [operator], like 1105 /// Handle the binary expression of a user definable binary [operator], like
1022 /// `a + b`, `super + b`, `a == b` and `a != b`. 1106 /// `a + b`, `super + b`, `a == b` and `a != b`.
1023 ResolutionResult handleUserDefinableBinary(Send node, 1107 ResolutionResult handleUserDefinableBinary(Send node,
1024 BinaryOperator operator) { 1108 BinaryOperator operator) {
1109 ResolutionResult result = const NoneResult();
1025 Node left = node.receiver; 1110 Node left = node.receiver;
1026 Node right = node.arguments.head; 1111 Node right = node.arguments.head;
1027 AccessSemantics semantics; 1112 AccessSemantics semantics;
1028 Selector selector; 1113 Selector selector;
1029 if (operator.kind == BinaryOperatorKind.INDEX) { 1114 if (operator.kind == BinaryOperatorKind.INDEX) {
1030 selector = new Selector.index(); 1115 selector = new Selector.index();
1031 } else { 1116 } else {
1032 selector = new Selector.binaryOperator(operator.selectorName); 1117 selector = new Selector.binaryOperator(operator.selectorName);
1033 } 1118 }
1034 // TODO(johnniwinther): Remove this when all information goes through the 1119 // TODO(johnniwinther): Remove this when all information goes through the
1035 // [SendStructure]. 1120 // [SendStructure].
1036 registry.setSelector(node, selector); 1121 registry.setSelector(node, selector);
1037 1122
1038 if (node.isSuperCall) { 1123 if (node.isSuperCall) {
1039 if (checkSuperAccess(node)) { 1124 if (checkSuperAccess(node)) {
1040 semantics = computeSuperSemantics(node, selector); 1125 semantics = computeSuperSemantics(node, selector);
1041 // TODO(johnniwinther): Add information to [AccessSemantics] about 1126 // TODO(johnniwinther): Add information to [AccessSemantics] about
1042 // whether it is erroneous. 1127 // whether it is erroneous.
1043 if (semantics.kind == AccessKind.SUPER_METHOD) { 1128 if (semantics.kind == AccessKind.SUPER_METHOD) {
1044 registry.registerStaticUse(semantics.element.declaration); 1129 registry.registerStaticUse(semantics.element.declaration);
1045 } 1130 }
1046 // TODO(johnniwinther): Remove this when all information goes through 1131 // TODO(johnniwinther): Remove this when all information goes through
1047 // the [SendStructure]. 1132 // the [SendStructure].
1048 registry.useElement(node, semantics.element); 1133 registry.useElement(node, semantics.element);
1049 } 1134 }
1135 visitExpression(right);
1050 } else { 1136 } else {
1051 visitExpression(left); 1137 ResolutionResult leftResult = visitExpression(left);
1138 ResolutionResult rightResult = visitExpression(right);
1052 registry.registerDynamicInvocation(selector); 1139 registry.registerDynamicInvocation(selector);
1053 semantics = new DynamicAccess.dynamicProperty(left); 1140 semantics = new DynamicAccess.dynamicProperty(left);
1141
1142 if (leftResult.isConstant && rightResult.isConstant) {
1143 bool isValidConstant;
1144 ConstantExpression leftConstant = leftResult.constant;
1145 ConstantExpression rightConstant = leftResult.constant;
1146 DartType knownLeftType = leftConstant.getKnownType(coreTypes);
1147 DartType knownRightType = rightConstant.getKnownType(coreTypes);
1148 switch (operator.kind) {
1149 case BinaryOperatorKind.EQ:
1150 case BinaryOperatorKind.NOT_EQ:
1151 isValidConstant =
1152 (knownLeftType == coreTypes.intType ||
1153 knownLeftType == coreTypes.doubleType ||
1154 knownLeftType == coreTypes.stringType ||
1155 knownLeftType == coreTypes.boolType ||
1156 knownLeftType == coreTypes.nullType) &&
1157 (knownRightType == coreTypes.intType ||
1158 knownRightType == coreTypes.doubleType ||
1159 knownRightType == coreTypes.stringType ||
1160 knownRightType == coreTypes.boolType ||
1161 knownRightType == coreTypes.nullType);
1162 break;
1163 case BinaryOperatorKind.ADD:
1164 isValidConstant =
1165 (knownLeftType == coreTypes.intType ||
1166 knownLeftType == coreTypes.doubleType ||
1167 knownLeftType == coreTypes.stringType) &&
1168 (knownRightType == coreTypes.intType ||
1169 knownRightType == coreTypes.doubleType ||
1170 knownRightType == coreTypes.stringType);
1171 break;
1172 case BinaryOperatorKind.SUB:
1173 case BinaryOperatorKind.MUL:
1174 case BinaryOperatorKind.DIV:
1175 case BinaryOperatorKind.IDIV:
1176 case BinaryOperatorKind.MOD:
1177 case BinaryOperatorKind.GTEQ:
1178 case BinaryOperatorKind.GT:
1179 case BinaryOperatorKind.LTEQ:
1180 case BinaryOperatorKind.LT:
1181 isValidConstant =
1182 (knownLeftType == coreTypes.intType ||
1183 knownLeftType == coreTypes.doubleType) &&
1184 (knownRightType == coreTypes.intType ||
1185 knownRightType == coreTypes.doubleType);
1186 break;
1187 case BinaryOperatorKind.SHL:
1188 case BinaryOperatorKind.SHR:
1189 case BinaryOperatorKind.AND:
1190 case BinaryOperatorKind.OR:
1191 case BinaryOperatorKind.XOR:
1192 isValidConstant =
1193 knownLeftType == coreTypes.intType &&
1194 knownRightType == coreTypes.intType;
1195 break;
1196 case BinaryOperatorKind.INDEX:
1197 isValidConstant = false;
1198 break;
1199 case BinaryOperatorKind.LOGICAL_AND:
1200 case BinaryOperatorKind.LOGICAL_OR:
1201 case BinaryOperatorKind.IF_NULL:
1202 internalError(node, "Unexpected binary operator '${operator}'.");
1203 break;
1204 }
1205 if (isValidConstant) {
1206 // TODO(johnniwinther): Handle potentially invalid constant
1207 // expressions.
1208 ConstantExpression constant = new BinaryConstantExpression(
1209 leftResult.constant,
1210 operator,
1211 rightResult.constant);
1212 registry.setConstant(node, constant);
1213 result = new ConstantResult(node, constant);
1214 }
1215 }
1054 } 1216 }
1055 visitExpression(right);
1056 1217
1057 if (semantics != null) { 1218 if (semantics != null) {
1058 // TODO(johnniwinther): Support invalid super access as an 1219 // TODO(johnniwinther): Support invalid super access as an
1059 // [AccessSemantics]. 1220 // [AccessSemantics].
1060 SendStructure sendStructure; 1221 SendStructure sendStructure;
1061 switch (operator.kind) { 1222 switch (operator.kind) {
1062 case BinaryOperatorKind.EQ: 1223 case BinaryOperatorKind.EQ:
1063 sendStructure = new EqualsStructure(semantics); 1224 sendStructure = new EqualsStructure(semantics);
1064 break; 1225 break;
1065 case BinaryOperatorKind.NOT_EQ: 1226 case BinaryOperatorKind.NOT_EQ:
(...skipping 20 matching lines...) Expand all
1086 sendStructure = new BinaryStructure(semantics, operator); 1247 sendStructure = new BinaryStructure(semantics, operator);
1087 break; 1248 break;
1088 case BinaryOperatorKind.LOGICAL_AND: 1249 case BinaryOperatorKind.LOGICAL_AND:
1089 case BinaryOperatorKind.LOGICAL_OR: 1250 case BinaryOperatorKind.LOGICAL_OR:
1090 case BinaryOperatorKind.IF_NULL: 1251 case BinaryOperatorKind.IF_NULL:
1091 internalError(node, "Unexpected binary operator '${operator}'."); 1252 internalError(node, "Unexpected binary operator '${operator}'.");
1092 break; 1253 break;
1093 } 1254 }
1094 registry.registerSendStructure(node, sendStructure); 1255 registry.registerSendStructure(node, sendStructure);
1095 } 1256 }
1096 return null; 1257 return result;
1097 } 1258 }
1098 1259
1099 /// Handle an invocation of an expression, like `(){}()` or `(foo)()`. 1260 /// Handle an invocation of an expression, like `(){}()` or `(foo)()`.
1100 ResolutionResult handleExpressionInvoke(Send node) { 1261 ResolutionResult handleExpressionInvoke(Send node) {
1101 assert(invariant(node, node.isCall, 1262 assert(invariant(node, node.isCall,
1102 message: "Unexpected expression: $node")); 1263 message: "Unexpected expression: $node"));
1103 Node expression = node.selector; 1264 Node expression = node.selector;
1104 visitExpression(expression); 1265 visitExpression(expression);
1105 CallStructure callStructure = resolveArguments(node.argumentsNode); 1266 CallStructure callStructure = resolveArguments(node.argumentsNode);
1106 Selector selector = callStructure.callSelector; 1267 Selector selector = callStructure.callSelector;
1107 // TODO(johnniwinther): Remove this when all information goes through the 1268 // TODO(johnniwinther): Remove this when all information goes through the
1108 // [SendStructure]. 1269 // [SendStructure].
1109 registry.setSelector(node, selector); 1270 registry.setSelector(node, selector);
1110 registry.registerDynamicInvocation(selector); 1271 registry.registerDynamicInvocation(selector);
1111 registry.registerSendStructure(node, 1272 registry.registerSendStructure(node,
1112 new InvokeStructure(new AccessSemantics.expression(), selector)); 1273 new InvokeStructure(new AccessSemantics.expression(), selector));
1113 return null; 1274 return const NoneResult();
1114 } 1275 }
1115 1276
1116 /// Handle a, possibly invalid, assertion, like `assert(cond)` or `assert()`. 1277 /// Handle a, possibly invalid, assertion, like `assert(cond)` or `assert()`.
1117 ResolutionResult handleAssert(Send node) { 1278 ResolutionResult handleAssert(Send node) {
1118 assert(invariant(node, node.isCall, 1279 assert(invariant(node, node.isCall,
1119 message: "Unexpected assert: $node")); 1280 message: "Unexpected assert: $node"));
1120 // If this send is of the form "assert(expr);", then 1281 // If this send is of the form "assert(expr);", then
1121 // this is an assertion. 1282 // this is an assertion.
1122 1283
1123 CallStructure callStructure = resolveArguments(node.argumentsNode); 1284 CallStructure callStructure = resolveArguments(node.argumentsNode);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1155 assert(invariant(node, node.isPropertyAccess)); 1316 assert(invariant(node, node.isPropertyAccess));
1156 selector = new Selector( 1317 selector = new Selector(
1157 SelectorKind.GETTER, name, CallStructure.NO_ARGS); 1318 SelectorKind.GETTER, name, CallStructure.NO_ARGS);
1158 registry.registerDynamicGetter(selector); 1319 registry.registerDynamicGetter(selector);
1159 sendStructure = new GetStructure(accessSemantics, selector); 1320 sendStructure = new GetStructure(accessSemantics, selector);
1160 } 1321 }
1161 registry.registerSendStructure(node, sendStructure); 1322 registry.registerSendStructure(node, sendStructure);
1162 // TODO(johnniwinther): Remove this when all information goes through 1323 // TODO(johnniwinther): Remove this when all information goes through
1163 // the [SendStructure]. 1324 // the [SendStructure].
1164 registry.setSelector(node, selector); 1325 registry.setSelector(node, selector);
1165 return null; 1326 return const NoneResult();
1166 } 1327 }
1167 1328
1168 /// Handle access on `this`, like `this()` and `this` when it is parsed as a 1329 /// Handle access on `this`, like `this()` and `this` when it is parsed as a
1169 /// [Send] node. 1330 /// [Send] node.
1170 ResolutionResult handleThisAccess(Send node) { 1331 ResolutionResult handleThisAccess(Send node) {
1171 AccessSemantics accessSemantics = new AccessSemantics.thisAccess(); 1332 AccessSemantics accessSemantics = new AccessSemantics.thisAccess();
1172 if (node.isCall) { 1333 if (node.isCall) {
1173 CallStructure callStructure = resolveArguments(node.argumentsNode); 1334 CallStructure callStructure = resolveArguments(node.argumentsNode);
1174 Selector selector = callStructure.callSelector; 1335 Selector selector = callStructure.callSelector;
1175 // TODO(johnniwinther): Handle invalid this access as an 1336 // TODO(johnniwinther): Handle invalid this access as an
1176 // [AccessSemantics]. 1337 // [AccessSemantics].
1177 if (checkThisAccess(node)) { 1338 if (checkThisAccess(node)) {
1178 registry.registerDynamicInvocation(selector); 1339 registry.registerDynamicInvocation(selector);
1179 registry.registerSendStructure(node, 1340 registry.registerSendStructure(node,
1180 new InvokeStructure(accessSemantics, selector)); 1341 new InvokeStructure(accessSemantics, selector));
1181 } 1342 }
1182 // TODO(johnniwinther): Remove this when all information goes through 1343 // TODO(johnniwinther): Remove this when all information goes through
1183 // the [SendStructure]. 1344 // the [SendStructure].
1184 registry.setSelector(node, selector); 1345 registry.setSelector(node, selector);
1185 } else { 1346 } else {
1186 // TODO(johnniwinther): Handle get of `this` when it is a [Send] node. 1347 // TODO(johnniwinther): Handle get of `this` when it is a [Send] node.
1187 internalError(node, "Unexpected node '$node'."); 1348 internalError(node, "Unexpected node '$node'.");
1188 } 1349 }
1189 return null; 1350 return const NoneResult();
1190 } 1351 }
1191 1352
1192 /// Handle access of a super property, like `super.foo` and `super.foo()`. 1353 /// Handle access of a super property, like `super.foo` and `super.foo()`.
1193 ResolutionResult handleSuperPropertyAccess(Send node, Name name) { 1354 ResolutionResult handleSuperPropertyAccess(Send node, Name name) {
1194 Element target; 1355 Element target;
1195 Selector selector; 1356 Selector selector;
1196 CallStructure callStructure = CallStructure.NO_ARGS; 1357 CallStructure callStructure = CallStructure.NO_ARGS;
1197 if (node.isCall) { 1358 if (node.isCall) {
1198 callStructure = resolveArguments(node.argumentsNode); 1359 callStructure = resolveArguments(node.argumentsNode);
1199 selector = new Selector(SelectorKind.CALL, name, callStructure); 1360 selector = new Selector(SelectorKind.CALL, name, callStructure);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1258 registry.registerSendStructure(node, 1419 registry.registerSendStructure(node,
1259 new GetStructure(semantics, selector)); 1420 new GetStructure(semantics, selector));
1260 } 1421 }
1261 target = semantics.element; 1422 target = semantics.element;
1262 } 1423 }
1263 1424
1264 // TODO(johnniwinther): Remove these when all information goes through 1425 // TODO(johnniwinther): Remove these when all information goes through
1265 // the [SendStructure]. 1426 // the [SendStructure].
1266 registry.useElement(node, target); 1427 registry.useElement(node, target);
1267 registry.setSelector(node, selector); 1428 registry.setSelector(node, selector);
1268 return null; 1429 return const NoneResult();
1269 } 1430 }
1270 1431
1271 /// Handle a [Send] whose selector is an [Operator], like `a && b`, `a is T`, 1432 /// Handle a [Send] whose selector is an [Operator], like `a && b`, `a is T`,
1272 /// `a + b`, and `~a`. 1433 /// `a + b`, and `~a`.
1273 ResolutionResult handleOperatorSend(Send node) { 1434 ResolutionResult handleOperatorSend(Send node) {
1274 String operatorText = node.selector.asOperator().source; 1435 String operatorText = node.selector.asOperator().source;
1275 if (operatorText == 'is') { 1436 if (operatorText == 'is') {
1276 return handleIs(node); 1437 return handleIs(node);
1277 } else if (operatorText == 'as') { 1438 } else if (operatorText == 'as') {
1278 return handleAs(node); 1439 return handleAs(node);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1334 Identifier selector = node.selector.asIdentifier(); 1495 Identifier selector = node.selector.asIdentifier();
1335 Name name = new Name(selector.source, enclosingElement.library); 1496 Name name = new Name(selector.source, enclosingElement.library);
1336 if (node.isSuperCall) { 1497 if (node.isSuperCall) {
1337 return handleSuperPropertyAccess(node, name); 1498 return handleSuperPropertyAccess(node, name);
1338 } else if (node.receiver.isThis()) { 1499 } else if (node.receiver.isThis()) {
1339 if (checkThisAccess(node)) { 1500 if (checkThisAccess(node)) {
1340 return handleThisPropertyAccess(node, name); 1501 return handleThisPropertyAccess(node, name);
1341 } 1502 }
1342 // TODO(johnniwinther): Handle invalid this access as an 1503 // TODO(johnniwinther): Handle invalid this access as an
1343 // [AccessSemantics]. 1504 // [AccessSemantics].
1344 return null; 1505 return const NoneResult();
1345 } 1506 }
1346 // TODO(johnniwinther): Handle remaining qualified sends. 1507 // TODO(johnniwinther): Handle remaining qualified sends.
1347 return oldVisitSend(node); 1508 return oldVisitSend(node);
1348 } 1509 }
1349 1510
1350 /// Handle access unresolved access to [name] in a non-instance context. 1511 /// Handle access unresolved access to [name] in a non-instance context.
1351 ResolutionResult handleUnresolvedAccess( 1512 ResolutionResult handleUnresolvedAccess(
1352 Send node, Name name, Element element) { 1513 Send node, Name name, Element element) {
1353 // TODO(johnniwinther): Support unresolved top level access as an 1514 // TODO(johnniwinther): Support unresolved top level access as an
1354 // [AccessSemantics]. 1515 // [AccessSemantics].
(...skipping 10 matching lines...) Expand all
1365 selector = new Selector( 1526 selector = new Selector(
1366 SelectorKind.GETTER, name, CallStructure.NO_ARGS); 1527 SelectorKind.GETTER, name, CallStructure.NO_ARGS);
1367 registry.registerDynamicGetter(selector); 1528 registry.registerDynamicGetter(selector);
1368 sendStructure = new GetStructure(accessSemantics, selector); 1529 sendStructure = new GetStructure(accessSemantics, selector);
1369 } 1530 }
1370 // TODO(johnniwinther): Remove this when all information goes through 1531 // TODO(johnniwinther): Remove this when all information goes through
1371 // the [SendStructure]. 1532 // the [SendStructure].
1372 registry.setSelector(node, selector); 1533 registry.setSelector(node, selector);
1373 registry.useElement(node, element); 1534 registry.useElement(node, element);
1374 registry.registerSendStructure(node, sendStructure); 1535 registry.registerSendStructure(node, sendStructure);
1375 return null; 1536 return const NoneResult();
1376 } 1537 }
1377 1538
1378 /// Handle an unqualified [Send], that is where the `node.receiver` is null, 1539 /// Handle an unqualified [Send], that is where the `node.receiver` is null,
1379 /// like `a`, `a()`, `this()`, `assert()`, and `(){}()`. 1540 /// like `a`, `a()`, `this()`, `assert()`, and `(){}()`.
1380 ResolutionResult handleUnqualifiedSend(Send node) { 1541 ResolutionResult handleUnqualifiedSend(Send node) {
1381 Identifier selector = node.selector.asIdentifier(); 1542 Identifier selector = node.selector.asIdentifier();
1382 if (selector == null) { 1543 if (selector == null) {
1383 // `(){}()` and `(foo)()`. 1544 // `(){}()` and `(foo)()`.
1384 return handleExpressionInvoke(node); 1545 return handleExpressionInvoke(node);
1385 } 1546 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1422 return oldVisitSend(node); 1583 return oldVisitSend(node);
1423 } 1584 }
1424 1585
1425 ResolutionResult oldVisitSend(Send node) { 1586 ResolutionResult oldVisitSend(Send node) {
1426 bool oldSendIsMemberAccess = sendIsMemberAccess; 1587 bool oldSendIsMemberAccess = sendIsMemberAccess;
1427 sendIsMemberAccess = node.isPropertyAccess || node.isCall; 1588 sendIsMemberAccess = node.isPropertyAccess || node.isCall;
1428 1589
1429 ResolutionResult result = resolveSend(node); 1590 ResolutionResult result = resolveSend(node);
1430 sendIsMemberAccess = oldSendIsMemberAccess; 1591 sendIsMemberAccess = oldSendIsMemberAccess;
1431 1592
1432 Element target = result != null ? result.element : null; 1593 Element target = result.element;
1433 1594
1434 if (target != null 1595 if (target != null
1435 && target == compiler.mirrorSystemGetNameFunction 1596 && target == compiler.mirrorSystemGetNameFunction
1436 && !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) { 1597 && !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) {
1437 compiler.reportHint( 1598 compiler.reportHint(
1438 node.selector, MessageKind.STATIC_FUNCTION_BLOAT, 1599 node.selector, MessageKind.STATIC_FUNCTION_BLOAT,
1439 {'class': compiler.mirrorSystemClass.name, 1600 {'class': compiler.mirrorSystemClass.name,
1440 'name': compiler.mirrorSystemGetNameFunction.name}); 1601 'name': compiler.mirrorSystemGetNameFunction.name});
1441 } 1602 }
1442 1603
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1475 } 1636 }
1476 } 1637 }
1477 } 1638 }
1478 1639
1479 bool resolvedArguments = false; 1640 bool resolvedArguments = false;
1480 resolveArguments(node.argumentsNode); 1641 resolveArguments(node.argumentsNode);
1481 1642
1482 // If the selector is null, it means that we will not be generating 1643 // If the selector is null, it means that we will not be generating
1483 // code for this as a send. 1644 // code for this as a send.
1484 Selector selector = registry.getSelector(node); 1645 Selector selector = registry.getSelector(node);
1485 if (selector == null) return null; 1646 if (selector == null) return const NoneResult();
1486 1647
1487 if (node.isCall) { 1648 if (node.isCall) {
1488 if (Elements.isUnresolved(target) || 1649 if (Elements.isUnresolved(target) ||
1489 target.isGetter || 1650 target.isGetter ||
1490 target.isField || 1651 target.isField ||
1491 Elements.isClosureSend(node, target)) { 1652 Elements.isClosureSend(node, target)) {
1492 // If we don't know what we're calling or if we are calling a getter, 1653 // If we don't know what we're calling or if we are calling a getter,
1493 // we need to register that fact that we may be calling a closure 1654 // we need to register that fact that we may be calling a closure
1494 // with the same arguments. 1655 // with the same arguments.
1495 Selector call = new Selector.callClosureFrom(selector); 1656 Selector call = new Selector.callClosureFrom(selector);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1528 } 1689 }
1529 } 1690 }
1530 } 1691 }
1531 } 1692 }
1532 1693
1533 registry.useElement(node, target); 1694 registry.useElement(node, target);
1534 registerSend(selector, target); 1695 registerSend(selector, target);
1535 if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) { 1696 if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) {
1536 registry.registerGetOfStaticFunction(target.declaration); 1697 registry.registerGetOfStaticFunction(target.declaration);
1537 } 1698 }
1538 return node.isPropertyAccess ? new ElementResult(target) : null; 1699 return node.isPropertyAccess
1700 ? new ResolutionResult.forElement(target) : const NoneResult();
1539 } 1701 }
1540 1702
1541 /// Callback for native enqueuer to parse a type. Returns [:null:] on error. 1703 /// Callback for native enqueuer to parse a type. Returns [:null:] on error.
1542 DartType resolveTypeFromString(Node node, String typeName) { 1704 DartType resolveTypeFromString(Node node, String typeName) {
1543 Element element = lookupInScope(compiler, node, scope, typeName); 1705 Element element = lookupInScope(compiler, node, scope, typeName);
1544 if (element == null) return null; 1706 if (element == null) return null;
1545 if (element is! ClassElement) return null; 1707 if (element is! ClassElement) return null;
1546 ClassElement cls = element; 1708 ClassElement cls = element;
1547 cls.ensureResolved(compiler); 1709 cls.ensureResolved(compiler);
1548 return cls.computeType(compiler); 1710 return cls.computeType(compiler);
1549 } 1711 }
1550 1712
1551 ResolutionResult visitSendSet(SendSet node) { 1713 ResolutionResult visitSendSet(SendSet node) {
1552 bool oldSendIsMemberAccess = sendIsMemberAccess; 1714 bool oldSendIsMemberAccess = sendIsMemberAccess;
1553 sendIsMemberAccess = node.isPropertyAccess || node.isCall; 1715 sendIsMemberAccess = node.isPropertyAccess || node.isCall;
1554 ResolutionResult result = resolveSend(node); 1716 ResolutionResult result = resolveSend(node);
1555 sendIsMemberAccess = oldSendIsMemberAccess; 1717 sendIsMemberAccess = oldSendIsMemberAccess;
1556 Element target = result != null ? result.element : null; 1718 Element target = result.element;
1557 Element setter = target; 1719 Element setter = target;
1558 Element getter = target; 1720 Element getter = target;
1559 String operatorName = node.assignmentOperator.source; 1721 String operatorName = node.assignmentOperator.source;
1560 String source = operatorName; 1722 String source = operatorName;
1561 bool isComplex = !identical(source, '='); 1723 bool isComplex = !identical(source, '=');
1562 if (!(result is AssertResult || Elements.isUnresolved(target))) { 1724 if (!(result is AssertResult || Elements.isUnresolved(target))) {
1563 if (target.isAbstractField) { 1725 if (target.isAbstractField) {
1564 AbstractFieldElement field = target; 1726 AbstractFieldElement field = target;
1565 setter = field.setter; 1727 setter = field.setter;
1566 getter = field.getter; 1728 getter = field.getter;
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1670 registry.registerInstantiatedClass(compiler.intClass); 1832 registry.registerInstantiatedClass(compiler.intClass);
1671 } else if (identical(source, '--')) { 1833 } else if (identical(source, '--')) {
1672 registerBinaryOperator('-'); 1834 registerBinaryOperator('-');
1673 registry.registerInstantiatedClass(compiler.intClass); 1835 registry.registerInstantiatedClass(compiler.intClass);
1674 } else if (source.endsWith('=')) { 1836 } else if (source.endsWith('=')) {
1675 registerBinaryOperator(Elements.mapToUserOperator(operatorName)); 1837 registerBinaryOperator(Elements.mapToUserOperator(operatorName));
1676 } 1838 }
1677 } 1839 }
1678 1840
1679 registerSend(selector, setter); 1841 registerSend(selector, setter);
1680 return new ElementResult(registry.useElement(node, setter)); 1842 return new ResolutionResult.forElement(registry.useElement(node, setter));
1681 } 1843 }
1682 1844
1683 void registerSend(Selector selector, Element target) { 1845 void registerSend(Selector selector, Element target) {
1684 if (target == null || target.isInstanceMember) { 1846 if (target == null || target.isInstanceMember) {
1685 if (selector.isGetter) { 1847 if (selector.isGetter) {
1686 registry.registerDynamicGetter(selector); 1848 registry.registerDynamicGetter(selector);
1687 } else if (selector.isSetter) { 1849 } else if (selector.isSetter) {
1688 registry.registerDynamicSetter(selector); 1850 registry.registerDynamicSetter(selector);
1689 } else { 1851 } else {
1690 registry.registerDynamicInvocation(selector); 1852 registry.registerDynamicInvocation(selector);
1691 } 1853 }
1692 } else if (Elements.isStaticOrTopLevel(target)) { 1854 } else if (Elements.isStaticOrTopLevel(target)) {
1693 // Avoid registration of type variables since they are not analyzable but 1855 // Avoid registration of type variables since they are not analyzable but
1694 // instead resolved through their enclosing type declaration. 1856 // instead resolved through their enclosing type declaration.
1695 if (!target.isTypeVariable) { 1857 if (!target.isTypeVariable) {
1696 // [target] might be the implementation element and only declaration 1858 // [target] might be the implementation element and only declaration
1697 // elements may be registered. 1859 // elements may be registered.
1698 registry.registerStaticUse(target.declaration); 1860 registry.registerStaticUse(target.declaration);
1699 } 1861 }
1700 } 1862 }
1701 } 1863 }
1702 1864
1703 visitLiteralInt(LiteralInt node) { 1865 ConstantResult visitLiteralInt(LiteralInt node) {
1704 registry.registerInstantiatedClass(compiler.intClass); 1866 registry.registerInstantiatedType(coreTypes.intType);
1867 ConstantExpression constant = new IntConstantExpression(node.value);
1868 registry.setConstant(node, constant);
1869 return new ConstantResult(node, constant);
1705 } 1870 }
1706 1871
1707 visitLiteralDouble(LiteralDouble node) { 1872 ConstantResult visitLiteralDouble(LiteralDouble node) {
1708 registry.registerInstantiatedClass(compiler.doubleClass); 1873 registry.registerInstantiatedType(coreTypes.doubleType);
1874 ConstantExpression constant = new DoubleConstantExpression(node.value);
1875 registry.setConstant(node, constant);
1876 return new ConstantResult(node, constant);
1709 } 1877 }
1710 1878
1711 visitLiteralBool(LiteralBool node) { 1879 ConstantResult visitLiteralBool(LiteralBool node) {
1712 registry.registerInstantiatedClass(compiler.boolClass); 1880 registry.registerInstantiatedType(coreTypes.boolType);
1881 ConstantExpression constant = new BoolConstantExpression(node.value);
1882 registry.setConstant(node, constant);
1883 return new ConstantResult(node, constant);
1713 } 1884 }
1714 1885
1715 visitLiteralString(LiteralString node) { 1886 ResolutionResult visitLiteralString(LiteralString node) {
1716 registry.registerInstantiatedClass(compiler.stringClass); 1887 registry.registerInstantiatedType(coreTypes.stringType);
1888 if (node.dartString != null) {
1889 // [dartString] might be null on parser errors.
1890 ConstantExpression constant =
1891 new StringConstantExpression(node.dartString.slowToString());
1892 registry.setConstant(node, constant);
1893 return new ConstantResult(node, constant);
1894 }
1895 return const NoneResult();
1717 } 1896 }
1718 1897
1719 visitLiteralNull(LiteralNull node) { 1898 ConstantResult visitLiteralNull(LiteralNull node) {
1720 registry.registerInstantiatedClass(compiler.nullClass); 1899 registry.registerInstantiatedType(coreTypes.nullType);
1900 ConstantExpression constant = new NullConstantExpression();
1901 registry.setConstant(node, constant);
1902 return new ConstantResult(node, constant);
1721 } 1903 }
1722 1904
1723 visitLiteralSymbol(LiteralSymbol node) { 1905 ConstantResult visitLiteralSymbol(LiteralSymbol node) {
1724 registry.registerInstantiatedClass(compiler.symbolClass); 1906 registry.registerInstantiatedClass(compiler.symbolClass);
1725 registry.registerStaticUse(compiler.symbolConstructor.declaration); 1907 registry.registerStaticUse(compiler.symbolConstructor.declaration);
1726 registry.registerConstSymbol(node.slowNameString); 1908 String name = node.slowNameString;
1727 if (!validateSymbol(node, node.slowNameString, reportError: false)) { 1909 registry.registerConstSymbol(name);
1910 if (!validateSymbol(node, name, reportError: false)) {
1728 compiler.reportError(node, 1911 compiler.reportError(node,
1729 MessageKind.UNSUPPORTED_LITERAL_SYMBOL, 1912 MessageKind.UNSUPPORTED_LITERAL_SYMBOL,
1730 {'value': node.slowNameString}); 1913 {'value': name});
1731 } 1914 }
1732 analyzeConstantDeferred(node); 1915 analyzeConstantDeferred(node);
1916 ConstantExpression constant = new SymbolConstantExpression(name);
1917 registry.setConstant(node, constant);
1918 return new ConstantResult(node, constant);
1733 } 1919 }
1734 1920
1735 visitStringJuxtaposition(StringJuxtaposition node) { 1921 ResolutionResult visitStringJuxtaposition(StringJuxtaposition node) {
1736 registry.registerInstantiatedClass(compiler.stringClass); 1922 registry.registerInstantiatedType(coreTypes.stringType);
1737 node.visitChildren(this); 1923 ResolutionResult first = visit(node.first);
1924 ResolutionResult second = visit(node.second);
1925 if (first.isConstant && second.isConstant) {
1926 ConstantExpression constant = new ConcatenateConstantExpression(
1927 <ConstantExpression>[first.constant, second.constant]);
1928 registry.setConstant(node, constant);
1929 return new ConstantResult(node, constant);
1930 }
1931 return const NoneResult();
1738 } 1932 }
1739 1933
1740 visitNodeList(NodeList node) { 1934 ResolutionResult visitNodeList(NodeList node) {
1741 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) { 1935 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) {
1742 visit(link.head); 1936 visit(link.head);
1743 } 1937 }
1938 return const NoneResult();
1744 } 1939 }
1745 1940
1746 visitOperator(Operator node) { 1941 ResolutionResult visitRethrow(Rethrow node) {
1747 internalError(node, 'operator');
1748 }
1749
1750 visitRethrow(Rethrow node) {
1751 if (!inCatchBlock) { 1942 if (!inCatchBlock) {
1752 error(node, MessageKind.THROW_WITHOUT_EXPRESSION); 1943 error(node, MessageKind.THROW_WITHOUT_EXPRESSION);
1753 } 1944 }
1945 return const NoneResult();
1754 } 1946 }
1755 1947
1756 visitReturn(Return node) { 1948 ResolutionResult visitReturn(Return node) {
1757 Node expression = node.expression; 1949 Node expression = node.expression;
1758 if (expression != null) { 1950 if (expression != null) {
1759 if (enclosingElement.isGenerativeConstructor) { 1951 if (enclosingElement.isGenerativeConstructor) {
1760 // It is a compile-time error if a return statement of the form 1952 // It is a compile-time error if a return statement of the form
1761 // `return e;` appears in a generative constructor. (Dart Language 1953 // `return e;` appears in a generative constructor. (Dart Language
1762 // Specification 13.12.) 1954 // Specification 13.12.)
1763 compiler.reportError(expression, 1955 compiler.reportError(expression,
1764 MessageKind.CANNOT_RETURN_FROM_CONSTRUCTOR); 1956 MessageKind.CANNOT_RETURN_FROM_CONSTRUCTOR);
1765 } else if (!node.isArrowBody && currentAsyncMarker.isYielding) { 1957 } else if (!node.isArrowBody && currentAsyncMarker.isYielding) {
1766 compiler.reportError( 1958 compiler.reportError(
1767 node, 1959 node,
1768 MessageKind.RETURN_IN_GENERATOR, 1960 MessageKind.RETURN_IN_GENERATOR,
1769 {'modifier': currentAsyncMarker}); 1961 {'modifier': currentAsyncMarker});
1770 } 1962 }
1771 } 1963 }
1772 visit(node.expression); 1964 visit(node.expression);
1965 return const NoneResult();
1773 } 1966 }
1774 1967
1775 visitYield(Yield node) { 1968 ResolutionResult visitYield(Yield node) {
1776 compiler.streamClass.ensureResolved(compiler); 1969 compiler.streamClass.ensureResolved(compiler);
1777 compiler.iterableClass.ensureResolved(compiler); 1970 compiler.iterableClass.ensureResolved(compiler);
1778 visit(node.expression); 1971 visit(node.expression);
1972 return const NoneResult();
1779 } 1973 }
1780 1974
1781 visitRedirectingFactoryBody(RedirectingFactoryBody node) { 1975 ResolutionResult visitRedirectingFactoryBody(RedirectingFactoryBody node) {
1782 final isSymbolConstructor = enclosingElement == compiler.symbolConstructor; 1976 final isSymbolConstructor = enclosingElement == compiler.symbolConstructor;
1783 if (!enclosingElement.isFactoryConstructor) { 1977 if (!enclosingElement.isFactoryConstructor) {
1784 compiler.reportError( 1978 compiler.reportError(
1785 node, MessageKind.FACTORY_REDIRECTION_IN_NON_FACTORY); 1979 node, MessageKind.FACTORY_REDIRECTION_IN_NON_FACTORY);
1786 compiler.reportHint( 1980 compiler.reportHint(
1787 enclosingElement, MessageKind.MISSING_FACTORY_KEYWORD); 1981 enclosingElement, MessageKind.MISSING_FACTORY_KEYWORD);
1788 } 1982 }
1789 ConstructorElementX constructor = enclosingElement; 1983 ConstructorElementX constructor = enclosingElement;
1790 bool isConstConstructor = constructor.isConst; 1984 bool isConstConstructor = constructor.isConst;
1791 ConstructorElement redirectionTarget = resolveRedirectingFactory( 1985 ConstructorElement redirectionTarget = resolveRedirectingFactory(
1792 node, inConstContext: isConstConstructor); 1986 node, inConstContext: isConstConstructor);
1793 constructor.immediateRedirectionTarget = redirectionTarget; 1987 constructor.immediateRedirectionTarget = redirectionTarget;
1794 1988
1795 Node constructorReference = node.constructorReference; 1989 Node constructorReference = node.constructorReference;
1796 if (constructorReference is Send) { 1990 if (constructorReference is Send) {
1797 constructor.redirectionDeferredPrefix = 1991 constructor.redirectionDeferredPrefix =
1798 compiler.deferredLoadTask.deferredPrefixElement(constructorReference, 1992 compiler.deferredLoadTask.deferredPrefixElement(constructorReference,
1799 registry.mapping); 1993 registry.mapping);
1800 } 1994 }
1801 1995
1802 registry.setRedirectingTargetConstructor(node, redirectionTarget); 1996 registry.setRedirectingTargetConstructor(node, redirectionTarget);
1803 if (Elements.isUnresolved(redirectionTarget)) { 1997 if (Elements.isUnresolved(redirectionTarget)) {
1804 registry.registerThrowNoSuchMethod(); 1998 registry.registerThrowNoSuchMethod();
1805 return; 1999 return const NoneResult();
1806 } else { 2000 } else {
1807 if (isConstConstructor && 2001 if (isConstConstructor &&
1808 !redirectionTarget.isConst) { 2002 !redirectionTarget.isConst) {
1809 compiler.reportError(node, MessageKind.CONSTRUCTOR_IS_NOT_CONST); 2003 compiler.reportError(node, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
1810 } 2004 }
1811 if (redirectionTarget == constructor) { 2005 if (redirectionTarget == constructor) {
1812 compiler.reportError(node, MessageKind.CYCLIC_REDIRECTING_FACTORY); 2006 compiler.reportError(node, MessageKind.CYCLIC_REDIRECTING_FACTORY);
1813 } 2007 }
1814 } 2008 }
1815 2009
(...skipping 25 matching lines...) Expand all
1841 compiler.resolver.resolveRedirectionChain(constructor, node); 2035 compiler.resolver.resolveRedirectionChain(constructor, node);
1842 }); 2036 });
1843 2037
1844 registry.registerStaticUse(redirectionTarget); 2038 registry.registerStaticUse(redirectionTarget);
1845 // TODO(johnniwinther): Register the effective target type instead. 2039 // TODO(johnniwinther): Register the effective target type instead.
1846 registry.registerInstantiatedClass( 2040 registry.registerInstantiatedClass(
1847 redirectionTarget.enclosingClass.declaration); 2041 redirectionTarget.enclosingClass.declaration);
1848 if (isSymbolConstructor) { 2042 if (isSymbolConstructor) {
1849 registry.registerSymbolConstructor(); 2043 registry.registerSymbolConstructor();
1850 } 2044 }
2045 return const NoneResult();
1851 } 2046 }
1852 2047
1853 visitThrow(Throw node) { 2048 ResolutionResult visitThrow(Throw node) {
1854 registry.registerThrowExpression(); 2049 registry.registerThrowExpression();
1855 visit(node.expression); 2050 visit(node.expression);
2051 return const NoneResult();
1856 } 2052 }
1857 2053
1858 visitAwait(Await node) { 2054 ResolutionResult visitAwait(Await node) {
1859 compiler.futureClass.ensureResolved(compiler); 2055 compiler.futureClass.ensureResolved(compiler);
1860 visit(node.expression); 2056 visit(node.expression);
2057 return const NoneResult();
1861 } 2058 }
1862 2059
1863 visitVariableDefinitions(VariableDefinitions node) { 2060 ResolutionResult visitVariableDefinitions(VariableDefinitions node) {
1864 DartType type; 2061 DartType type;
1865 if (node.type != null) { 2062 if (node.type != null) {
1866 type = resolveTypeAnnotation(node.type); 2063 type = resolveTypeAnnotation(node.type);
1867 } else { 2064 } else {
1868 type = const DynamicType(); 2065 type = const DynamicType();
1869 } 2066 }
1870 VariableList variables = new VariableList.node(node, type); 2067 VariableList variables = new VariableList.node(node, type);
1871 VariableDefinitionsVisitor visitor = 2068 VariableDefinitionsVisitor visitor =
1872 new VariableDefinitionsVisitor(compiler, node, this, variables); 2069 new VariableDefinitionsVisitor(compiler, node, this, variables);
1873 2070
(...skipping 24 matching lines...) Expand all
1898 } 2095 }
1899 if (modifiers.isStatic) { 2096 if (modifiers.isStatic) {
1900 reportExtraModifier('static'); 2097 reportExtraModifier('static');
1901 } 2098 }
1902 } 2099 }
1903 if (node.metadata != null) { 2100 if (node.metadata != null) {
1904 variables.metadata = 2101 variables.metadata =
1905 compiler.resolver.resolveMetadata(enclosingElement, node); 2102 compiler.resolver.resolveMetadata(enclosingElement, node);
1906 } 2103 }
1907 visitor.visit(node.definitions); 2104 visitor.visit(node.definitions);
2105 return const NoneResult();
1908 } 2106 }
1909 2107
1910 visitWhile(While node) { 2108 ResolutionResult visitWhile(While node) {
1911 visit(node.condition); 2109 visit(node.condition);
1912 visitLoopBodyIn(node, node.body, new BlockScope(scope)); 2110 visitLoopBodyIn(node, node.body, new BlockScope(scope));
2111 return const NoneResult();
1913 } 2112 }
1914 2113
1915 visitParenthesizedExpression(ParenthesizedExpression node) { 2114 ResolutionResult visitParenthesizedExpression(ParenthesizedExpression node) {
1916 bool oldSendIsMemberAccess = sendIsMemberAccess; 2115 bool oldSendIsMemberAccess = sendIsMemberAccess;
1917 sendIsMemberAccess = false; 2116 sendIsMemberAccess = false;
1918 var oldCategory = allowedCategory; 2117 var oldCategory = allowedCategory;
1919 allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION 2118 allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION
1920 | ElementCategory.IMPLIES_TYPE; 2119 | ElementCategory.IMPLIES_TYPE;
1921 visit(node.expression); 2120 ResolutionResult result = visit(node.expression);
1922 allowedCategory = oldCategory; 2121 allowedCategory = oldCategory;
1923 sendIsMemberAccess = oldSendIsMemberAccess; 2122 sendIsMemberAccess = oldSendIsMemberAccess;
2123 if (result.kind == ResultKind.CONSTANT) {
2124 return result;
2125 }
2126 return const NoneResult();
1924 } 2127 }
1925 2128
1926 ResolutionResult visitNewExpression(NewExpression node) { 2129 ResolutionResult visitNewExpression(NewExpression node) {
1927 Node selector = node.send.selector; 2130 Node selector = node.send.selector;
1928 FunctionElement constructor = resolveConstructor(node); 2131 FunctionElement constructor = resolveConstructor(node);
1929 final bool isSymbolConstructor = constructor == compiler.symbolConstructor; 2132 final bool isSymbolConstructor = constructor == compiler.symbolConstructor;
1930 final bool isMirrorsUsedConstant = 2133 final bool isMirrorsUsedConstant =
1931 node.isConst && (constructor == compiler.mirrorsUsedConstructor); 2134 node.isConst && (constructor == compiler.mirrorsUsedConstructor);
1932 Selector callSelector = resolveSelector(node.send, constructor); 2135 Selector callSelector = resolveSelector(node.send, constructor);
1933 resolveArguments(node.send.argumentsNode); 2136 resolveArguments(node.send.argumentsNode);
1934 registry.useElement(node.send, constructor); 2137 registry.useElement(node.send, constructor);
1935 if (Elements.isUnresolved(constructor)) { 2138 if (Elements.isUnresolved(constructor)) {
1936 return new ElementResult(constructor); 2139 return new ResolutionResult.forElement(constructor);
1937 } 2140 }
1938 constructor.computeSignature(compiler); 2141 constructor.computeSignature(compiler);
1939 if (!callSelector.applies(constructor, compiler.world)) { 2142 if (!callSelector.applies(constructor, compiler.world)) {
1940 registry.registerThrowNoSuchMethod(); 2143 registry.registerThrowNoSuchMethod();
1941 } 2144 }
1942 2145
1943 // [constructor] might be the implementation element 2146 // [constructor] might be the implementation element
1944 // and only declaration elements may be registered. 2147 // and only declaration elements may be registered.
1945 registry.registerStaticUse(constructor.declaration); 2148 registry.registerStaticUse(constructor.declaration);
1946 ClassElement cls = constructor.enclosingClass; 2149 ClassElement cls = constructor.enclosingClass;
(...skipping 17 matching lines...) Expand all
1964 } 2167 }
1965 2168
1966 if (isSymbolConstructor) { 2169 if (isSymbolConstructor) {
1967 if (node.isConst) { 2170 if (node.isConst) {
1968 Node argumentNode = node.send.arguments.head; 2171 Node argumentNode = node.send.arguments.head;
1969 ConstantExpression constant = 2172 ConstantExpression constant =
1970 compiler.resolver.constantCompiler.compileNode( 2173 compiler.resolver.constantCompiler.compileNode(
1971 argumentNode, registry.mapping); 2174 argumentNode, registry.mapping);
1972 ConstantValue name = compiler.constants.getConstantValue(constant); 2175 ConstantValue name = compiler.constants.getConstantValue(constant);
1973 if (!name.isString) { 2176 if (!name.isString) {
1974 DartType type = name.getType(compiler.coreTypes); 2177 DartType type = name.getType(coreTypes);
1975 compiler.reportError(argumentNode, MessageKind.STRING_EXPECTED, 2178 compiler.reportError(argumentNode, MessageKind.STRING_EXPECTED,
1976 {'type': type}); 2179 {'type': type});
1977 } else { 2180 } else {
1978 StringConstantValue stringConstant = name; 2181 StringConstantValue stringConstant = name;
1979 String nameString = stringConstant.toDartString().slowToString(); 2182 String nameString = stringConstant.toDartString().slowToString();
1980 if (validateSymbol(argumentNode, nameString)) { 2183 if (validateSymbol(argumentNode, nameString)) {
1981 registry.registerConstSymbol(nameString); 2184 registry.registerConstSymbol(nameString);
1982 } 2185 }
1983 } 2186 }
1984 } else { 2187 } else {
1985 if (!compiler.mirrorUsageAnalyzerTask.hasMirrorUsage( 2188 if (!compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(
1986 enclosingElement)) { 2189 enclosingElement)) {
1987 compiler.reportHint( 2190 compiler.reportHint(
1988 node.newToken, MessageKind.NON_CONST_BLOAT, 2191 node.newToken, MessageKind.NON_CONST_BLOAT,
1989 {'name': compiler.symbolClass.name}); 2192 {'name': compiler.symbolClass.name});
1990 } 2193 }
1991 registry.registerNewSymbol(); 2194 registry.registerNewSymbol();
1992 } 2195 }
1993 } else if (isMirrorsUsedConstant) { 2196 } else if (isMirrorsUsedConstant) {
1994 compiler.mirrorUsageAnalyzerTask.validate(node, registry.mapping); 2197 compiler.mirrorUsageAnalyzerTask.validate(node, registry.mapping);
1995 } 2198 }
1996 if (node.isConst) { 2199 if (node.isConst) {
1997 analyzeConstantDeferred(node); 2200 analyzeConstantDeferred(node);
1998 } 2201 }
1999 2202
2000 return null; 2203 return const NoneResult();
2001 } 2204 }
2002 2205
2003 void checkConstMapKeysDontOverrideEquals(Spannable spannable, 2206 void checkConstMapKeysDontOverrideEquals(Spannable spannable,
2004 MapConstantValue map) { 2207 MapConstantValue map) {
2005 for (ConstantValue key in map.keys) { 2208 for (ConstantValue key in map.keys) {
2006 if (!key.isObject) continue; 2209 if (!key.isObject) continue;
2007 ObjectConstantValue objectConstant = key; 2210 ObjectConstantValue objectConstant = key;
2008 DartType keyType = objectConstant.type; 2211 DartType keyType = objectConstant.type;
2009 ClassElement cls = keyType.element; 2212 ClassElement cls = keyType.element;
2010 if (cls == compiler.stringClass) continue; 2213 if (cls == compiler.stringClass) continue;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
2098 DartType type = typeResolver.resolveTypeAnnotation( 2301 DartType type = typeResolver.resolveTypeAnnotation(
2099 this, node, malformedIsError: malformedIsError, 2302 this, node, malformedIsError: malformedIsError,
2100 deferredIsMalformed: deferredIsMalformed); 2303 deferredIsMalformed: deferredIsMalformed);
2101 if (inCheckContext) { 2304 if (inCheckContext) {
2102 registry.registerIsCheck(type); 2305 registry.registerIsCheck(type);
2103 registry.registerRequiredType(type, enclosingElement); 2306 registry.registerRequiredType(type, enclosingElement);
2104 } 2307 }
2105 return type; 2308 return type;
2106 } 2309 }
2107 2310
2108 visitModifiers(Modifiers node) { 2311 ResolutionResult visitLiteralList(LiteralList node) {
2109 internalError(node, 'modifiers'); 2312 bool isValidAsConstant = true;
2110 }
2111
2112 visitLiteralList(LiteralList node) {
2113 bool oldSendIsMemberAccess = sendIsMemberAccess;
2114 sendIsMemberAccess = false; 2313 sendIsMemberAccess = false;
2115 2314
2116 NodeList arguments = node.typeArguments; 2315 NodeList arguments = node.typeArguments;
2117 DartType typeArgument; 2316 DartType typeArgument;
2118 if (arguments != null) { 2317 if (arguments != null) {
2119 Link<Node> nodes = arguments.nodes; 2318 Link<Node> nodes = arguments.nodes;
2120 if (nodes.isEmpty) { 2319 if (nodes.isEmpty) {
2121 // The syntax [: <>[] :] is not allowed. 2320 // The syntax [: <>[] :] is not allowed.
2122 error(arguments, MessageKind.MISSING_TYPE_ARGUMENT); 2321 error(arguments, MessageKind.MISSING_TYPE_ARGUMENT);
2322 isValidAsConstant = false;
2123 } else { 2323 } else {
2124 typeArgument = resolveTypeAnnotation(nodes.head); 2324 typeArgument = resolveTypeAnnotation(nodes.head);
2125 for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) { 2325 for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) {
2126 warning(nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); 2326 warning(nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT);
2127 resolveTypeAnnotation(nodes.head); 2327 resolveTypeAnnotation(nodes.head);
2128 } 2328 }
2129 } 2329 }
2130 } 2330 }
2131 DartType listType; 2331 DartType listType;
2132 if (typeArgument != null) { 2332 if (typeArgument != null) {
2133 if (node.isConst && typeArgument.containsTypeVariables) { 2333 if (node.isConst && typeArgument.containsTypeVariables) {
2134 compiler.reportError(arguments.nodes.head, 2334 compiler.reportError(arguments.nodes.head,
2135 MessageKind.TYPE_VARIABLE_IN_CONSTANT); 2335 MessageKind.TYPE_VARIABLE_IN_CONSTANT);
2336 isValidAsConstant = false;
2136 } 2337 }
2137 listType = new InterfaceType(compiler.listClass, [typeArgument]); 2338 listType = coreTypes.listType(typeArgument);
2138 } else { 2339 } else {
2139 compiler.listClass.computeType(compiler); 2340 listType = coreTypes.listType();
2140 listType = compiler.listClass.rawType;
2141 } 2341 }
2142 registry.setType(node, listType); 2342 registry.setType(node, listType);
2143 registry.registerInstantiatedType(listType); 2343 registry.registerInstantiatedType(listType);
2144 registry.registerRequiredType(listType, enclosingElement); 2344 registry.registerRequiredType(listType, enclosingElement);
2145 visit(node.elements);
2146 if (node.isConst) { 2345 if (node.isConst) {
2346 List<ConstantExpression> constantExpressions = <ConstantExpression>[];
2347 for (Node element in node.elements) {
2348 ResolutionResult elementResult = visit(element);
2349 if (isValidAsConstant && elementResult.isConstant) {
2350 constantExpressions.add(elementResult.constant);
2351 } else {
2352 isValidAsConstant = false;
2353 }
2354 }
2147 analyzeConstantDeferred(node); 2355 analyzeConstantDeferred(node);
2356 sendIsMemberAccess = false;
2357 if (isValidAsConstant) {
2358 ConstantExpression constant =
2359 new ListConstantExpression(listType, constantExpressions);
2360 registry.setConstant(node, constant);
2361 return new ConstantResult(node, constant);
2362 }
2363 } else {
2364 visit(node.elements);
2365 sendIsMemberAccess = false;
2366 }
2367 return const NoneResult();
2368
2369 }
2370
2371 ResolutionResult visitConditional(Conditional node) {
2372 ResolutionResult conditionResult =
2373 doInPromotionScope(node.condition, () => visit(node.condition));
2374 ResolutionResult thenResult =
2375 doInPromotionScope(node.thenExpression, () => visit(node.thenExpression) );
2376 ResolutionResult elseResult = visit(node.elseExpression);
2377 if (conditionResult.isConstant &&
2378 thenResult.isConstant &&
2379 elseResult.isConstant) {
2380 ConstantExpression constant = new ConditionalConstantExpression(
2381 conditionResult.constant,
2382 thenResult.constant,
2383 elseResult.constant);
2384 registry.setConstant(node, constant);
2385 return new ConstantResult(node, constant);
2386 }
2387 return const NoneResult();
2388 }
2389
2390 ResolutionResult visitStringInterpolation(StringInterpolation node) {
2391 registry.registerInstantiatedType(coreTypes.stringType);
2392 registry.registerStringInterpolation();
2393 registerImplicitInvocation('toString', 0);
2394
2395 bool isValidAsConstant = true;
2396 List<ConstantExpression> parts = <ConstantExpression>[];
2397
2398 void resolvePart(Node subnode) {
2399 ResolutionResult result = visit(subnode);
2400 if (isValidAsConstant && result.isConstant) {
2401 parts.add(result.constant);
2402 } else {
2403 isValidAsConstant = false;
2404 }
2148 } 2405 }
2149 2406
2150 sendIsMemberAccess = false; 2407 resolvePart(node.string);
2408 for (StringInterpolationPart part in node.parts) {
2409 resolvePart(part.expression);
2410 resolvePart(part.string);
2411 }
2412
2413 if (isValidAsConstant) {
2414 ConstantExpression constant = new ConcatenateConstantExpression(parts);
2415 registry.setConstant(node, constant);
2416 return new ConstantResult(node, constant);
2417 }
2418 return const NoneResult();
2151 } 2419 }
2152 2420
2153 visitConditional(Conditional node) { 2421 ResolutionResult visitBreakStatement(BreakStatement node) {
2154 doInPromotionScope(node.condition, () => visit(node.condition));
2155 doInPromotionScope(node.thenExpression, () => visit(node.thenExpression));
2156 visit(node.elseExpression);
2157 }
2158
2159 visitStringInterpolation(StringInterpolation node) {
2160 registry.registerInstantiatedClass(compiler.stringClass);
2161 registry.registerStringInterpolation();
2162 node.visitChildren(this);
2163 }
2164
2165 visitStringInterpolationPart(StringInterpolationPart node) {
2166 registerImplicitInvocation('toString', 0);
2167 node.visitChildren(this);
2168 }
2169
2170 visitBreakStatement(BreakStatement node) {
2171 JumpTarget target; 2422 JumpTarget target;
2172 if (node.target == null) { 2423 if (node.target == null) {
2173 target = statementScope.currentBreakTarget(); 2424 target = statementScope.currentBreakTarget();
2174 if (target == null) { 2425 if (target == null) {
2175 error(node, MessageKind.NO_BREAK_TARGET); 2426 error(node, MessageKind.NO_BREAK_TARGET);
2176 return; 2427 return const NoneResult();
2177 } 2428 }
2178 target.isBreakTarget = true; 2429 target.isBreakTarget = true;
2179 } else { 2430 } else {
2180 String labelName = node.target.source; 2431 String labelName = node.target.source;
2181 LabelDefinition label = statementScope.lookupLabel(labelName); 2432 LabelDefinition label = statementScope.lookupLabel(labelName);
2182 if (label == null) { 2433 if (label == null) {
2183 error(node.target, MessageKind.UNBOUND_LABEL, {'labelName': labelName}); 2434 error(node.target, MessageKind.UNBOUND_LABEL, {'labelName': labelName});
2184 return; 2435 return const NoneResult();
2185 } 2436 }
2186 target = label.target; 2437 target = label.target;
2187 if (!target.statement.isValidBreakTarget()) { 2438 if (!target.statement.isValidBreakTarget()) {
2188 error(node.target, MessageKind.INVALID_BREAK); 2439 error(node.target, MessageKind.INVALID_BREAK);
2189 return; 2440 return const NoneResult();
2190 } 2441 }
2191 label.setBreakTarget(); 2442 label.setBreakTarget();
2192 registry.useLabel(node, label); 2443 registry.useLabel(node, label);
2193 } 2444 }
2194 registry.registerTargetOf(node, target); 2445 registry.registerTargetOf(node, target);
2446 return const NoneResult();
2195 } 2447 }
2196 2448
2197 visitContinueStatement(ContinueStatement node) { 2449 ResolutionResult visitContinueStatement(ContinueStatement node) {
2198 JumpTarget target; 2450 JumpTarget target;
2199 if (node.target == null) { 2451 if (node.target == null) {
2200 target = statementScope.currentContinueTarget(); 2452 target = statementScope.currentContinueTarget();
2201 if (target == null) { 2453 if (target == null) {
2202 error(node, MessageKind.NO_CONTINUE_TARGET); 2454 error(node, MessageKind.NO_CONTINUE_TARGET);
2203 return; 2455 return const NoneResult();
2204 } 2456 }
2205 target.isContinueTarget = true; 2457 target.isContinueTarget = true;
2206 } else { 2458 } else {
2207 String labelName = node.target.source; 2459 String labelName = node.target.source;
2208 LabelDefinition label = statementScope.lookupLabel(labelName); 2460 LabelDefinition label = statementScope.lookupLabel(labelName);
2209 if (label == null) { 2461 if (label == null) {
2210 error(node.target, MessageKind.UNBOUND_LABEL, {'labelName': labelName}); 2462 error(node.target, MessageKind.UNBOUND_LABEL, {'labelName': labelName});
2211 return; 2463 return const NoneResult();
2212 } 2464 }
2213 target = label.target; 2465 target = label.target;
2214 if (!target.statement.isValidContinueTarget()) { 2466 if (!target.statement.isValidContinueTarget()) {
2215 error(node.target, MessageKind.INVALID_CONTINUE); 2467 error(node.target, MessageKind.INVALID_CONTINUE);
2216 } 2468 }
2217 label.setContinueTarget(); 2469 label.setContinueTarget();
2218 registry.useLabel(node, label); 2470 registry.useLabel(node, label);
2219 } 2471 }
2220 registry.registerTargetOf(node, target); 2472 registry.registerTargetOf(node, target);
2473 return const NoneResult();
2221 } 2474 }
2222 2475
2223 registerImplicitInvocation(String name, int arity) { 2476 registerImplicitInvocation(String name, int arity) {
2224 Selector selector = new Selector.call(name, null, arity); 2477 Selector selector = new Selector.call(name, null, arity);
2225 registry.registerDynamicInvocation(selector); 2478 registry.registerDynamicInvocation(selector);
2226 } 2479 }
2227 2480
2228 visitAsyncForIn(AsyncForIn node) { 2481 ResolutionResult visitAsyncForIn(AsyncForIn node) {
2229 registry.registerAsyncForIn(node); 2482 registry.registerAsyncForIn(node);
2230 registry.setCurrentSelector(node, compiler.currentSelector); 2483 registry.setCurrentSelector(node, compiler.currentSelector);
2231 registry.registerDynamicGetter(compiler.currentSelector); 2484 registry.registerDynamicGetter(compiler.currentSelector);
2232 registry.setMoveNextSelector(node, compiler.moveNextSelector); 2485 registry.setMoveNextSelector(node, compiler.moveNextSelector);
2233 registry.registerDynamicInvocation(compiler.moveNextSelector); 2486 registry.registerDynamicInvocation(compiler.moveNextSelector);
2234 2487
2235 visit(node.expression); 2488 visit(node.expression);
2236 2489
2237 Scope blockScope = new BlockScope(scope); 2490 Scope blockScope = new BlockScope(scope);
2238 visitForInDeclaredIdentifierIn(node.declaredIdentifier, node, blockScope); 2491 visitForInDeclaredIdentifierIn(node.declaredIdentifier, node, blockScope);
2239 visitLoopBodyIn(node, node.body, blockScope); 2492 visitLoopBodyIn(node, node.body, blockScope);
2493 return const NoneResult();
2240 } 2494 }
2241 2495
2242 visitSyncForIn(SyncForIn node) { 2496 ResolutionResult visitSyncForIn(SyncForIn node) {
2243 registry.registerSyncForIn(node); 2497 registry.registerSyncForIn(node);
2244 registry.setIteratorSelector(node, compiler.iteratorSelector); 2498 registry.setIteratorSelector(node, compiler.iteratorSelector);
2245 registry.registerDynamicGetter(compiler.iteratorSelector); 2499 registry.registerDynamicGetter(compiler.iteratorSelector);
2246 registry.setCurrentSelector(node, compiler.currentSelector); 2500 registry.setCurrentSelector(node, compiler.currentSelector);
2247 registry.registerDynamicGetter(compiler.currentSelector); 2501 registry.registerDynamicGetter(compiler.currentSelector);
2248 registry.setMoveNextSelector(node, compiler.moveNextSelector); 2502 registry.setMoveNextSelector(node, compiler.moveNextSelector);
2249 registry.registerDynamicInvocation(compiler.moveNextSelector); 2503 registry.registerDynamicInvocation(compiler.moveNextSelector);
2250 2504
2251 visit(node.expression); 2505 visit(node.expression);
2252 2506
2253 Scope blockScope = new BlockScope(scope); 2507 Scope blockScope = new BlockScope(scope);
2254 visitForInDeclaredIdentifierIn(node.declaredIdentifier, node, blockScope); 2508 visitForInDeclaredIdentifierIn(node.declaredIdentifier, node, blockScope);
2255 visitLoopBodyIn(node, node.body, blockScope); 2509 visitLoopBodyIn(node, node.body, blockScope);
2510 return const NoneResult();
2256 } 2511 }
2257 2512
2258 visitForInDeclaredIdentifierIn(Node declaration, ForIn node, 2513 void visitForInDeclaredIdentifierIn(
2259 Scope blockScope) { 2514 Node declaration,
2515 ForIn node,
2516 Scope blockScope) {
2260 LibraryElement library = enclosingElement.library; 2517 LibraryElement library = enclosingElement.library;
2261 2518
2262 bool oldAllowFinalWithoutInitializer = allowFinalWithoutInitializer; 2519 bool oldAllowFinalWithoutInitializer = allowFinalWithoutInitializer;
2263 allowFinalWithoutInitializer = true; 2520 allowFinalWithoutInitializer = true;
2264 visitIn(declaration, blockScope); 2521 visitIn(declaration, blockScope);
2265 allowFinalWithoutInitializer = oldAllowFinalWithoutInitializer; 2522 allowFinalWithoutInitializer = oldAllowFinalWithoutInitializer;
2266 2523
2267 Send send = declaration.asSend(); 2524 Send send = declaration.asSend();
2268 VariableDefinitions variableDefinitions = 2525 VariableDefinitions variableDefinitions =
2269 declaration.asVariableDefinitions(); 2526 declaration.asVariableDefinitions();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2306 if (loopVariable != null) { 2563 if (loopVariable != null) {
2307 // loopVariable may be null if it could not be resolved. 2564 // loopVariable may be null if it could not be resolved.
2308 registry.setForInVariable(node, loopVariable); 2565 registry.setForInVariable(node, loopVariable);
2309 } 2566 }
2310 } 2567 }
2311 2568
2312 visitLabel(Label node) { 2569 visitLabel(Label node) {
2313 // Labels are handled by their containing statements/cases. 2570 // Labels are handled by their containing statements/cases.
2314 } 2571 }
2315 2572
2316 visitLabeledStatement(LabeledStatement node) { 2573 ResolutionResult visitLabeledStatement(LabeledStatement node) {
2317 Statement body = node.statement; 2574 Statement body = node.statement;
2318 JumpTarget targetElement = getOrDefineTarget(body); 2575 JumpTarget targetElement = getOrDefineTarget(body);
2319 Map<String, LabelDefinition> labelElements = <String, LabelDefinition>{}; 2576 Map<String, LabelDefinition> labelElements = <String, LabelDefinition>{};
2320 for (Label label in node.labels) { 2577 for (Label label in node.labels) {
2321 String labelName = label.labelName; 2578 String labelName = label.labelName;
2322 if (labelElements.containsKey(labelName)) continue; 2579 if (labelElements.containsKey(labelName)) continue;
2323 LabelDefinition element = targetElement.addLabel(label, labelName); 2580 LabelDefinition element = targetElement.addLabel(label, labelName);
2324 labelElements[labelName] = element; 2581 labelElements[labelName] = element;
2325 } 2582 }
2326 statementScope.enterLabelScope(labelElements); 2583 statementScope.enterLabelScope(labelElements);
2327 visit(node.statement); 2584 visit(node.statement);
2328 statementScope.exitLabelScope(); 2585 statementScope.exitLabelScope();
2329 labelElements.forEach((String labelName, LabelDefinition element) { 2586 labelElements.forEach((String labelName, LabelDefinition element) {
2330 if (element.isTarget) { 2587 if (element.isTarget) {
2331 registry.defineLabel(element.label, element); 2588 registry.defineLabel(element.label, element);
2332 } else { 2589 } else {
2333 warning(element.label, MessageKind.UNUSED_LABEL, 2590 warning(element.label, MessageKind.UNUSED_LABEL,
2334 {'labelName': labelName}); 2591 {'labelName': labelName});
2335 } 2592 }
2336 }); 2593 });
2337 if (!targetElement.isTarget) { 2594 if (!targetElement.isTarget) {
2338 registry.undefineTarget(body); 2595 registry.undefineTarget(body);
2339 } 2596 }
2597 return const NoneResult();
2340 } 2598 }
2341 2599
2342 visitLiteralMap(LiteralMap node) { 2600 ResolutionResult visitLiteralMap(LiteralMap node) {
2601 bool isValidAsConstant = true;
2343 sendIsMemberAccess = false; 2602 sendIsMemberAccess = false;
2344 2603
2345 NodeList arguments = node.typeArguments; 2604 NodeList arguments = node.typeArguments;
2346 DartType keyTypeArgument; 2605 DartType keyTypeArgument;
2347 DartType valueTypeArgument; 2606 DartType valueTypeArgument;
2348 if (arguments != null) { 2607 if (arguments != null) {
2349 Link<Node> nodes = arguments.nodes; 2608 Link<Node> nodes = arguments.nodes;
2350 if (nodes.isEmpty) { 2609 if (nodes.isEmpty) {
2351 // The syntax [: <>{} :] is not allowed. 2610 // The syntax [: <>{} :] is not allowed.
2352 error(arguments, MessageKind.MISSING_TYPE_ARGUMENT); 2611 error(arguments, MessageKind.MISSING_TYPE_ARGUMENT);
2612 isValidAsConstant = false;
2353 } else { 2613 } else {
2354 keyTypeArgument = resolveTypeAnnotation(nodes.head); 2614 keyTypeArgument = resolveTypeAnnotation(nodes.head);
2355 nodes = nodes.tail; 2615 nodes = nodes.tail;
2356 if (nodes.isEmpty) { 2616 if (nodes.isEmpty) {
2357 warning(arguments, MessageKind.MISSING_TYPE_ARGUMENT); 2617 warning(arguments, MessageKind.MISSING_TYPE_ARGUMENT);
2358 } else { 2618 } else {
2359 valueTypeArgument = resolveTypeAnnotation(nodes.head); 2619 valueTypeArgument = resolveTypeAnnotation(nodes.head);
2360 for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) { 2620 for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) {
2361 warning(nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); 2621 warning(nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT);
2362 resolveTypeAnnotation(nodes.head); 2622 resolveTypeAnnotation(nodes.head);
2363 } 2623 }
2364 } 2624 }
2365 } 2625 }
2366 } 2626 }
2367 DartType mapType; 2627 DartType mapType;
2368 if (valueTypeArgument != null) { 2628 if (valueTypeArgument != null) {
2369 mapType = new InterfaceType(compiler.mapClass, 2629 mapType = coreTypes.mapType(keyTypeArgument, valueTypeArgument);
2370 [keyTypeArgument, valueTypeArgument]);
2371 } else { 2630 } else {
2372 compiler.mapClass.computeType(compiler); 2631 mapType = coreTypes.mapType();
2373 mapType = compiler.mapClass.rawType;
2374 } 2632 }
2375 if (node.isConst && mapType.containsTypeVariables) { 2633 if (node.isConst && mapType.containsTypeVariables) {
2376 compiler.reportError(arguments, 2634 compiler.reportError(arguments,
2377 MessageKind.TYPE_VARIABLE_IN_CONSTANT); 2635 MessageKind.TYPE_VARIABLE_IN_CONSTANT);
2636 isValidAsConstant = false;
2378 } 2637 }
2379 registry.registerMapLiteral(node, mapType, node.isConst); 2638 registry.registerMapLiteral(node, mapType, node.isConst);
2380 registry.registerRequiredType(mapType, enclosingElement); 2639 registry.registerRequiredType(mapType, enclosingElement);
2381 node.visitChildren(this);
2382 if (node.isConst) { 2640 if (node.isConst) {
2641 List<ConstantExpression> keyExpressions = <ConstantExpression>[];
2642 List<ConstantExpression> valueExpressions = <ConstantExpression>[];
2643 for (LiteralMapEntry entry in node.entries) {
2644 ResolutionResult keyResult = visit(entry.key);
2645 ResolutionResult valueResult = visit(entry.value);
2646 if (isValidAsConstant &&
2647 keyResult.isConstant &&
2648 valueResult.isConstant) {
2649 keyExpressions.add(keyResult.constant);
2650 valueExpressions.add(valueResult.constant);
2651 } else {
2652 isValidAsConstant = false;
2653 }
2654 }
2383 analyzeConstantDeferred(node); 2655 analyzeConstantDeferred(node);
2656 sendIsMemberAccess = false;
2657 if (isValidAsConstant) {
2658 ConstantExpression constant = new MapConstantExpression(
2659 mapType, keyExpressions, valueExpressions);
2660 registry.setConstant(node, constant);
2661 return new ConstantResult(node, constant);
2662 }
2663 } else {
2664 node.visitChildren(this);
2665 sendIsMemberAccess = false;
2384 } 2666 }
2385 2667 return const NoneResult();
2386 sendIsMemberAccess = false;
2387 } 2668 }
2388 2669
2389 visitLiteralMapEntry(LiteralMapEntry node) { 2670 ResolutionResult visitLiteralMapEntry(LiteralMapEntry node) {
2390 node.visitChildren(this); 2671 node.visitChildren(this);
2672 return const NoneResult();
2391 } 2673 }
2392 2674
2393 visitNamedArgument(NamedArgument node) { 2675 ResolutionResult visitNamedArgument(NamedArgument node) {
2394 visit(node.expression); 2676 return visit(node.expression);
2395 } 2677 }
2396 2678
2397 DartType typeOfConstant(ConstantValue constant) { 2679 DartType typeOfConstant(ConstantValue constant) {
2398 if (constant.isInt) return compiler.intClass.rawType; 2680 if (constant.isInt) return compiler.intClass.rawType;
2399 if (constant.isBool) return compiler.boolClass.rawType; 2681 if (constant.isBool) return compiler.boolClass.rawType;
2400 if (constant.isDouble) return compiler.doubleClass.rawType; 2682 if (constant.isDouble) return compiler.doubleClass.rawType;
2401 if (constant.isString) return compiler.stringClass.rawType; 2683 if (constant.isString) return compiler.stringClass.rawType;
2402 if (constant.isNull) return compiler.nullClass.rawType; 2684 if (constant.isNull) return compiler.nullClass.rawType;
2403 if (constant.isFunction) return compiler.functionClass.rawType; 2685 if (constant.isFunction) return compiler.functionClass.rawType;
2404 assert(constant.isObject); 2686 assert(constant.isObject);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
2469 compiler.reportInfo( 2751 compiler.reportInfo(
2470 caseMatch.expression, 2752 caseMatch.expression,
2471 MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE, 2753 MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE,
2472 {'type': caseType}); 2754 {'type': caseType});
2473 } 2755 }
2474 } 2756 }
2475 } 2757 }
2476 } 2758 }
2477 } 2759 }
2478 2760
2479 visitSwitchStatement(SwitchStatement node) { 2761 ResolutionResult visitSwitchStatement(SwitchStatement node) {
2480 node.expression.accept(this); 2762 node.expression.accept(this);
2481 2763
2482 JumpTarget breakElement = getOrDefineTarget(node); 2764 JumpTarget breakElement = getOrDefineTarget(node);
2483 Map<String, LabelDefinition> continueLabels = <String, LabelDefinition>{}; 2765 Map<String, LabelDefinition> continueLabels = <String, LabelDefinition>{};
2484 Link<Node> cases = node.cases.nodes; 2766 Link<Node> cases = node.cases.nodes;
2485 while (!cases.isEmpty) { 2767 while (!cases.isEmpty) {
2486 SwitchCase switchCase = cases.head; 2768 SwitchCase switchCase = cases.head;
2487 for (Node labelOrCase in switchCase.labelsAndCases) { 2769 for (Node labelOrCase in switchCase.labelsAndCases) {
2488 CaseMatch caseMatch = labelOrCase.asCaseMatch(); 2770 CaseMatch caseMatch = labelOrCase.asCaseMatch();
2489 if (caseMatch != null) { 2771 if (caseMatch != null) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2540 if (!label.isContinueTarget) { 2822 if (!label.isContinueTarget) {
2541 JumpTarget targetElement = label.target; 2823 JumpTarget targetElement = label.target;
2542 SwitchCase switchCase = targetElement.statement; 2824 SwitchCase switchCase = targetElement.statement;
2543 registry.undefineTarget(switchCase); 2825 registry.undefineTarget(switchCase);
2544 registry.undefineLabel(label.label); 2826 registry.undefineLabel(label.label);
2545 } 2827 }
2546 }); 2828 });
2547 // TODO(15575): We should warn if we can detect a fall through 2829 // TODO(15575): We should warn if we can detect a fall through
2548 // error. 2830 // error.
2549 registry.registerFallThroughError(); 2831 registry.registerFallThroughError();
2832 return const NoneResult();
2550 } 2833 }
2551 2834
2552 visitSwitchCase(SwitchCase node) { 2835 ResolutionResult visitSwitchCase(SwitchCase node) {
2553 node.labelsAndCases.accept(this); 2836 node.labelsAndCases.accept(this);
2554 visitIn(node.statements, new BlockScope(scope)); 2837 visitIn(node.statements, new BlockScope(scope));
2838 return const NoneResult();
2555 } 2839 }
2556 2840
2557 visitCaseMatch(CaseMatch node) { 2841 ResolutionResult visitCaseMatch(CaseMatch node) {
2558 visit(node.expression); 2842 visit(node.expression);
2843 return const NoneResult();
2559 } 2844 }
2560 2845
2561 visitTryStatement(TryStatement node) { 2846 ResolutionResult visitTryStatement(TryStatement node) {
2562 visit(node.tryBlock); 2847 visit(node.tryBlock);
2563 if (node.catchBlocks.isEmpty && node.finallyBlock == null) { 2848 if (node.catchBlocks.isEmpty && node.finallyBlock == null) {
2564 error(node.getEndToken().next, MessageKind.NO_CATCH_NOR_FINALLY); 2849 error(node.getEndToken().next, MessageKind.NO_CATCH_NOR_FINALLY);
2565 } 2850 }
2566 visit(node.catchBlocks); 2851 visit(node.catchBlocks);
2567 visit(node.finallyBlock); 2852 visit(node.finallyBlock);
2853 return const NoneResult();
2568 } 2854 }
2569 2855
2570 visitCatchBlock(CatchBlock node) { 2856 ResolutionResult visitCatchBlock(CatchBlock node) {
2571 registry.registerCatchStatement(); 2857 registry.registerCatchStatement();
2572 // Check that if catch part is present, then 2858 // Check that if catch part is present, then
2573 // it has one or two formal parameters. 2859 // it has one or two formal parameters.
2574 VariableDefinitions exceptionDefinition; 2860 VariableDefinitions exceptionDefinition;
2575 VariableDefinitions stackTraceDefinition; 2861 VariableDefinitions stackTraceDefinition;
2576 if (node.formals != null) { 2862 if (node.formals != null) {
2577 Link<Node> formalsToProcess = node.formals.nodes; 2863 Link<Node> formalsToProcess = node.formals.nodes;
2578 if (formalsToProcess.isEmpty) { 2864 if (formalsToProcess.isEmpty) {
2579 error(node, MessageKind.EMPTY_CATCH_DECLARATION); 2865 error(node, MessageKind.EMPTY_CATCH_DECLARATION);
2580 } else { 2866 } else {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
2630 registry.getDefinition(exceptionVariable); 2916 registry.getDefinition(exceptionVariable);
2631 exceptionElement.variables.type = exceptionType; 2917 exceptionElement.variables.type = exceptionType;
2632 } 2918 }
2633 if (stackTraceDefinition != null) { 2919 if (stackTraceDefinition != null) {
2634 Node stackTraceVariable = stackTraceDefinition.definitions.nodes.head; 2920 Node stackTraceVariable = stackTraceDefinition.definitions.nodes.head;
2635 VariableElementX stackTraceElement = 2921 VariableElementX stackTraceElement =
2636 registry.getDefinition(stackTraceVariable); 2922 registry.getDefinition(stackTraceVariable);
2637 registry.registerInstantiatedClass(compiler.stackTraceClass); 2923 registry.registerInstantiatedClass(compiler.stackTraceClass);
2638 stackTraceElement.variables.type = compiler.stackTraceClass.rawType; 2924 stackTraceElement.variables.type = compiler.stackTraceClass.rawType;
2639 } 2925 }
2640 } 2926 return const NoneResult();
2641
2642 visitTypedef(Typedef node) {
2643 internalError(node, 'typedef');
2644 } 2927 }
2645 } 2928 }
2646 2929
2647 /// Looks up [name] in [scope] and unwraps the result. 2930 /// Looks up [name] in [scope] and unwraps the result.
2648 Element lookupInScope(Compiler compiler, Node node, 2931 Element lookupInScope(Compiler compiler, Node node,
2649 Scope scope, String name) { 2932 Scope scope, String name) {
2650 return Elements.unwrap(scope.lookup(name), compiler, node); 2933 return Elements.unwrap(scope.lookup(name), compiler, node);
2651 } 2934 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/constant_handler_javascript.dart ('k') | pkg/compiler/lib/src/resolution/registry.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698