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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/universe/universe.dart

Issue 12207081: Add a type kind to TypedSelector. A typed selector can either be (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library universe; 5 library universe;
6 6
7 import '../closure.dart'; 7 import '../closure.dart';
8 import '../elements/elements.dart'; 8 import '../elements/elements.dart';
9 import '../dart2jslib.dart'; 9 import '../dart2jslib.dart';
10 import '../dart_types.dart'; 10 import '../dart_types.dart';
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 class SelectorKind { 93 class SelectorKind {
94 final String name; 94 final String name;
95 const SelectorKind(this.name); 95 const SelectorKind(this.name);
96 96
97 static const SelectorKind GETTER = const SelectorKind('getter'); 97 static const SelectorKind GETTER = const SelectorKind('getter');
98 static const SelectorKind SETTER = const SelectorKind('setter'); 98 static const SelectorKind SETTER = const SelectorKind('setter');
99 static const SelectorKind CALL = const SelectorKind('call'); 99 static const SelectorKind CALL = const SelectorKind('call');
100 static const SelectorKind OPERATOR = const SelectorKind('operator'); 100 static const SelectorKind OPERATOR = const SelectorKind('operator');
101 static const SelectorKind INDEX = const SelectorKind('index'); 101 static const SelectorKind INDEX = const SelectorKind('index');
102 102
103 toString() => name; 103 String toString() => name;
104 }
105
106 class TypedSelectorKind {
107 final String name;
108 const TypedSelectorKind(this.name);
109
110 /// Unknown type: used for untyped selector.
111 static const TypedSelectorKind UNKNOWN = const TypedSelectorKind('unknown');
112
113 // Exact type: the selector knows the exact type of the receiver.
114 // For example [:new Map():].
115 static const TypedSelectorKind EXACT = const TypedSelectorKind('exact');
116
117 // Subclass type: the receiver type is in a subclass hierarchy.
118 // For example [:this:].
119 static const TypedSelectorKind SUBCLASS = const TypedSelectorKind('subclass');
120
121 // Interface type: any type that implements the receiver type.
122 // For example [(foo as Foo).bar()], or any type annotation in
123 // checked mode.
124 static const TypedSelectorKind INTERFACE =
125 const TypedSelectorKind('interface');
126
127 String toString() => name;
104 } 128 }
105 129
106 class Selector { 130 class Selector {
107 final SelectorKind kind; 131 final SelectorKind kind;
108 final SourceString name; 132 final SourceString name;
109 final LibraryElement library; // Library is null for non-private selectors. 133 final LibraryElement library; // Library is null for non-private selectors.
110 134
111 // The numbers of arguments of the selector. Includes named arguments. 135 // The numbers of arguments of the selector. Includes named arguments.
112 final int argumentCount; 136 final int argumentCount;
113 final List<SourceString> namedArguments; 137 final List<SourceString> namedArguments;
114 final List<SourceString> orderedNamedArguments; 138 final List<SourceString> orderedNamedArguments;
139 TypedSelectorKind get typeKind => TypedSelectorKind.UNKNOWN;
115 140
116 Selector( 141 Selector(
117 this.kind, 142 this.kind,
118 SourceString name, 143 SourceString name,
119 LibraryElement library, 144 LibraryElement library,
120 this.argumentCount, 145 this.argumentCount,
121 [List<SourceString> namedArguments = const <SourceString>[]]) 146 [List<SourceString> namedArguments = const <SourceString>[]])
122 : this.name = name, 147 : this.name = name,
123 this.library = name.isPrivate() ? library : null, 148 this.library = name.isPrivate() ? library : null,
124 this.namedArguments = namedArguments, 149 this.namedArguments = namedArguments,
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 386
362 bool operator ==(other) { 387 bool operator ==(other) {
363 if (other is !Selector) return false; 388 if (other is !Selector) return false;
364 return identical(receiverType, other.receiverType) 389 return identical(receiverType, other.receiverType)
365 && equalsUntyped(other); 390 && equalsUntyped(other);
366 } 391 }
367 392
368 bool equalsUntyped(Selector other) { 393 bool equalsUntyped(Selector other) {
369 return name == other.name 394 return name == other.name
370 && kind == other.kind 395 && kind == other.kind
396 && typeKind == other.typeKind
371 && identical(library, other.library) 397 && identical(library, other.library)
372 && argumentCount == other.argumentCount 398 && argumentCount == other.argumentCount
373 && namedArguments.length == other.namedArguments.length 399 && namedArguments.length == other.namedArguments.length
374 && sameNames(namedArguments, other.namedArguments); 400 && sameNames(namedArguments, other.namedArguments);
375 } 401 }
376 402
377 List<SourceString> getOrderedNamedArguments() { 403 List<SourceString> getOrderedNamedArguments() {
378 if (namedArguments.isEmpty) return namedArguments; 404 if (namedArguments.isEmpty) return namedArguments;
379 if (!orderedNamedArguments.isEmpty) return orderedNamedArguments; 405 if (!orderedNamedArguments.isEmpty) return orderedNamedArguments;
380 406
(...skipping 21 matching lines...) Expand all
402 String type = ''; 428 String type = '';
403 if (namedArgumentCount > 0) named = ', named=${namedArgumentsToString()}'; 429 if (namedArgumentCount > 0) named = ', named=${namedArgumentsToString()}';
404 if (receiverType != null) type = ', type=$receiverType'; 430 if (receiverType != null) type = ', type=$receiverType';
405 return 'Selector($kind, ${name.slowToString()}, ' 431 return 'Selector($kind, ${name.slowToString()}, '
406 'arity=$argumentCount$named$type)'; 432 'arity=$argumentCount$named$type)';
407 } 433 }
408 } 434 }
409 435
410 class TypedSelector extends Selector { 436 class TypedSelector extends Selector {
411 /** 437 /**
412 * The type of the receiver. Any subtype of that type can be the 438 * The type of the receiver.
413 * target of the invocation.
414 */ 439 */
415 final DartType receiverType; 440 final DartType receiverType;
441 final TypedSelectorKind typeKind;
416 442
417 final Selector asUntyped; 443 final Selector asUntyped;
418 444
419 TypedSelector(DartType this.receiverType, Selector selector) 445 TypedSelector(DartType this.receiverType, this.typeKind, Selector selector)
420 : asUntyped = selector.asUntyped, 446 : asUntyped = selector.asUntyped,
421 super(selector.kind, 447 super(selector.kind,
422 selector.name, 448 selector.name,
423 selector.library, 449 selector.library,
424 selector.argumentCount, 450 selector.argumentCount,
425 selector.namedArguments) { 451 selector.namedArguments) {
426 // Invariant: Typed selector can not be based on a malformed type. 452 // Invariant: Typed selector can not be based on a malformed type.
427 assert(!identical(receiverType.kind, TypeKind.MALFORMED_TYPE)); 453 assert(!identical(receiverType.kind, TypeKind.MALFORMED_TYPE));
kasperl 2013/02/11 08:18:12 Assert that typeKind isn't unknown?
ngeoffray 2013/02/11 10:20:55 Done.
428 assert(asUntyped.receiverType == null); 454 assert(asUntyped.receiverType == null);
429 } 455 }
430 456
431 /** 457 /**
432 * Check if [element] will be the one used at runtime when being 458 * Check if [element] will be the one used at runtime when being
433 * invoked on an instance of [cls]. 459 * invoked on an instance of [cls].
434 */ 460 */
435 bool hasElementIn(ClassElement cls, Element element) { 461 bool hasElementIn(ClassElement cls, Element element) {
436 // Use the selector for the lookup instead of [:element.name:] 462 // Use the selector for the lookup instead of [:element.name:]
437 // because the selector has the right privacy information. 463 // because the selector has the right privacy information.
438 Element resolved = cls.lookupSelector(this); 464 Element resolved = cls.lookupSelector(this);
439 if (resolved == element) return true; 465 if (resolved == element) return true;
440 if (resolved == null) return false; 466 if (resolved == null) return false;
441 if (resolved.isAbstractField()) { 467 if (resolved.isAbstractField()) {
442 AbstractFieldElement field = resolved; 468 AbstractFieldElement field = resolved;
443 if (element == field.getter || element == field.setter) { 469 if (element == field.getter || element == field.setter) {
444 return true; 470 return true;
445 } else { 471 } else {
446 ClassElement otherCls = field.getEnclosingClass();
447 // We have not found a match, but another class higher in the 472 // We have not found a match, but another class higher in the
448 // hierarchy may define the getter or the setter. 473 // hierarchy may define the getter or the setter.
449 return hasElementIn(otherCls.superclass, element); 474 ClassElement otherCls = field.getEnclosingClass().superclass;
475 if (otherCls == null) return false;
476 return hasElementIn(otherCls, element);
450 } 477 }
451 } 478 }
452 return false; 479 return false;
453 } 480 }
454 481
455 bool appliesUnnamed(Element element, Compiler compiler) { 482 bool appliesUnnamed(Element element, Compiler compiler) {
456 assert(sameNameHack(element, compiler)); 483 assert(sameNameHack(element, compiler));
457 // [TypedSelector] are only used when compiling. 484 // [TypedSelector] are only used when compiling.
458 assert(compiler.phase == Compiler.PHASE_COMPILING); 485 assert(compiler.phase == Compiler.PHASE_COMPILING);
459 if (!element.isMember()) return false; 486 if (!element.isMember()) return false;
460 487
461 // A closure can be called through any typed selector: 488 // A closure can be called through any typed selector:
462 // class A { 489 // class A {
463 // get foo => () => 42; 490 // get foo => () => 42;
464 // bar() => foo(); // The call to 'foo' is a typed selector. 491 // bar() => foo(); // The call to 'foo' is a typed selector.
465 // } 492 // }
466 ClassElement other = element.getEnclosingClass(); 493 ClassElement other = element.getEnclosingClass();
467 if (identical(other.superclass, compiler.closureClass)) { 494 if (identical(other.superclass, compiler.closureClass)) {
468 return appliesUntyped(element, compiler); 495 return appliesUntyped(element, compiler);
469 } 496 }
470 497
471 Element self = receiverType.element; 498 Element self = receiverType.element;
472 if (self.isTypedef()) { 499 if (self.isTypedef()) {
473 // A typedef is a function type that doesn't have any 500 // A typedef is a function type that doesn't have any
474 // user-defined members. 501 // user-defined members.
475 return false; 502 return false;
476 } 503 }
477 504
478 if (other.implementsInterface(self) 505 if (typeKind == TypedSelectorKind.EXACT) {
479 || other.isSubclassOf(self) 506 return hasElementIn(self, element) && appliesUntyped(element, compiler);
480 || compiler.world.hasAnySubclassThatImplements(other, receiverType)) { 507 } else if (typeKind == TypedSelectorKind.SUBCLASS) {
481 return appliesUntyped(element, compiler); 508 return (hasElementIn(self, element) || other.isSubclassOf(self))
482 } 509 && appliesUntyped(element, compiler);
510 } else {
511 assert(typeKind == TypedSelectorKind.INTERFACE);
512 if (other.implementsInterface(self)
513 || other.isSubclassOf(self)
514 || compiler.world.hasAnySubclassThatImplements(other, receiverType)) {
515 return appliesUntyped(element, compiler);
516 }
483 517
484 // If [self] is a subclass of [other], it inherits the 518 // If [self] is a subclass of [other], it inherits the
485 // implementation of [element]. 519 // implementation of [element].
486 ClassElement cls = self; 520 ClassElement cls = self;
487 if (cls.isSubclassOf(other)) { 521 if (cls.isSubclassOf(other)) {
488 // Resolve an invocation of [element.name] on [self]. If it 522 // Resolve an invocation of [element.name] on [self]. If it
489 // is found, this selector is a candidate. 523 // is found, this selector is a candidate.
490 return hasElementIn(self, element) && appliesUntyped(element, compiler); 524 return hasElementIn(self, element) && appliesUntyped(element, compiler);
525 }
491 } 526 }
492 527
493 return false; 528 return false;
494 } 529 }
495 } 530 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698