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

Side by Side Diff: pkg/compiler/lib/src/universe/selector.dart

Issue 1346593002: Move Selector and CallStructure into parts. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 3 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) 2015, 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 part of universe;
6
7 import 'dart:collection';
8
9 import '../common/names.dart' show
10 Identifiers,
11 Names,
12 Selectors;
13 import '../compiler.dart' show
14 Compiler;
15 import '../diagnostics/invariant.dart' show
16 invariant;
17 import '../diagnostics/spannable.dart' show
18 SpannableAssertionFailure;
19 import '../elements/elements.dart';
20 import '../dart_types.dart';
21 import '../tree/tree.dart';
22 import '../types/types.dart';
23 import '../util/util.dart';
24 import '../world.dart' show
25 ClassWorld,
26 World;
27
28 part 'function_set.dart';
29 part 'side_effects.dart';
30
31 class UniverseSelector {
32 final Selector selector;
33 final ReceiverMask mask;
34
35 UniverseSelector(this.selector, this.mask);
36
37 bool appliesUnnamed(Element element, ClassWorld world) {
38 return selector.appliesUnnamed(element, world) &&
39 (mask == null || mask.canHit(element, selector, world));
40 }
41
42 String toString() => '$selector,$mask';
43 }
44
45 /// A potential receiver for a dynamic call site.
46 abstract class ReceiverMask {
47 /// Returns whether [element] is a potential target when being
48 /// invoked on this receiver mask. [selector] is used to ensure library
49 /// privacy is taken into account.
50 bool canHit(Element element, Selector selector, ClassWorld classWorld);
51 }
52
53 /// A set of potential receivers for the dynamic call sites of the same
54 /// selector.
55 ///
56 /// For instance for these calls
57 ///
58 /// new A().foo(a, b);
59 /// new B().foo(0, 42);
60 ///
61 /// the receiver mask set for dynamic calls to 'foo' with to positional
62 /// arguments will contain receiver masks abstracting `new A()` and `new B()`.
63 abstract class ReceiverMaskSet {
64 /// Returns `true` if [selector] applies to any of the potential receivers
65 /// in this set given the closed [world].
66 bool applies(Element element, Selector selector, ClassWorld world);
67
68 /// Returns `true` if any potential receivers in this set given the closed
69 /// [world] have no implementation matching [selector].
70 ///
71 /// For instance for this code snippet
72 ///
73 /// class A {}
74 /// class B { foo() {} }
75 /// m(b) => (b ? new A() : new B()).foo();
76 ///
77 /// the potential receiver `new A()` have no implementation of `foo` and thus
78 /// needs to handle the call though its `noSuchMethod` handler.
79 bool needsNoSuchMethodHandling(Selector selector, ClassWorld world);
80 }
81
82 /// A mutable [ReceiverMaskSet] used in [Universe].
83 abstract class UniverseReceiverMaskSet extends ReceiverMaskSet {
84 /// Adds [mask] to this set of potential receivers. Return `true` if the
85 /// set expanded due to the new mask.
86 bool addReceiverMask(ReceiverMask mask);
87 }
88
89 /// Strategy for computing potential receivers of dynamic call sites.
90 abstract class ReceiverMaskStrategy {
91 /// Create a [UniverseReceiverMaskSet] to represent the potential receiver for
92 /// a dynamic call site with [selector].
93 UniverseReceiverMaskSet createReceiverMaskSet(Selector selector);
94 }
95
96 class Universe {
97 /// The set of all directly instantiated classes, that is, classes with a
98 /// generative constructor that has been called directly and not only through
99 /// a super-call.
100 ///
101 /// Invariant: Elements are declaration elements.
102 // TODO(johnniwinther): [_directlyInstantiatedClasses] and
103 // [_instantiatedTypes] sets should be merged.
104 final Set<ClassElement> _directlyInstantiatedClasses =
105 new Set<ClassElement>();
106
107 /// The set of all directly instantiated types, that is, the types of the
108 /// directly instantiated classes.
109 ///
110 /// See [_directlyInstantiatedClasses].
111 final Set<DartType> _instantiatedTypes = new Set<DartType>();
112
113 /// The set of all instantiated classes, either directly, as superclasses or
114 /// as supertypes.
115 ///
116 /// Invariant: Elements are declaration elements.
117 final Set<ClassElement> _allInstantiatedClasses = new Set<ClassElement>();
118
119 /// The set of all referenced static fields.
120 ///
121 /// Invariant: Elements are declaration elements.
122 final Set<FieldElement> allReferencedStaticFields = new Set<FieldElement>();
123
124 /**
125 * Documentation wanted -- johnniwinther
126 *
127 * Invariant: Elements are declaration elements.
128 */
129 final Set<FunctionElement> staticFunctionsNeedingGetter =
130 new Set<FunctionElement>();
131 final Set<FunctionElement> methodsNeedingSuperGetter =
132 new Set<FunctionElement>();
133 final Map<String, Map<Selector, ReceiverMaskSet>> _invokedNames =
134 <String, Map<Selector, ReceiverMaskSet>>{};
135 final Map<String, Map<Selector, ReceiverMaskSet>> _invokedGetters =
136 <String, Map<Selector, ReceiverMaskSet>>{};
137 final Map<String, Map<Selector, ReceiverMaskSet>> _invokedSetters =
138 <String, Map<Selector, ReceiverMaskSet>>{};
139
140 /**
141 * Fields accessed. Currently only the codegen knows this
142 * information. The resolver is too conservative when seeing a
143 * getter and only registers an invoked getter.
144 */
145 final Set<Element> fieldGetters = new Set<Element>();
146
147 /**
148 * Fields set. See comment in [fieldGetters].
149 */
150 final Set<Element> fieldSetters = new Set<Element>();
151 final Set<DartType> isChecks = new Set<DartType>();
152
153 /**
154 * Set of (live) [:call:] methods whose signatures reference type variables.
155 *
156 * A live [:call:] method is one whose enclosing class has been instantiated.
157 */
158 final Set<Element> callMethodsWithFreeTypeVariables = new Set<Element>();
159
160 /**
161 * Set of (live) local functions (closures) whose signatures reference type
162 * variables.
163 *
164 * A live function is one whose enclosing member function has been enqueued.
165 */
166 final Set<Element> closuresWithFreeTypeVariables = new Set<Element>();
167
168 /**
169 * Set of all closures in the program. Used by the mirror tracking system
170 * to find all live closure instances.
171 */
172 final Set<LocalFunctionElement> allClosures = new Set<LocalFunctionElement>();
173
174 /**
175 * Set of methods in instantiated classes that are potentially
176 * closurized.
177 */
178 final Set<Element> closurizedMembers = new Set<Element>();
179
180 final ReceiverMaskStrategy receiverMaskStrategy;
181
182 Universe(this.receiverMaskStrategy);
183
184 /// All directly instantiated classes, that is, classes with a generative
185 /// constructor that has been called directly and not only through a
186 /// super-call.
187 // TODO(johnniwinther): Improve semantic precision.
188 Iterable<ClassElement> get directlyInstantiatedClasses {
189 return _directlyInstantiatedClasses;
190 }
191
192 /// All instantiated classes, either directly, as superclasses or as
193 /// supertypes.
194 // TODO(johnniwinther): Improve semantic precision.
195 Iterable<ClassElement> get allInstantiatedClasses {
196 return _allInstantiatedClasses;
197 }
198
199 /// All directly instantiated types, that is, the types of the directly
200 /// instantiated classes.
201 ///
202 /// See [directlyInstantiatedClasses].
203 // TODO(johnniwinther): Improve semantic precision.
204 Iterable<DartType> get instantiatedTypes => _instantiatedTypes;
205
206 /// Returns `true` if [cls] is considered to be instantiated, either directly,
207 /// through subclasses or through subtypes. The latter case only contains
208 /// spurious information from instatiations through factory constructors and
209 /// mixins.
210 // TODO(johnniwinther): Improve semantic precision.
211 bool isInstantiated(ClassElement cls) {
212 return _allInstantiatedClasses.contains(cls);
213 }
214
215 /// Register [type] as (directly) instantiated.
216 ///
217 /// If [byMirrors] is `true`, the instantiation is through mirrors.
218 // TODO(johnniwinther): Fully enforce the separation between exact, through
219 // subclass and through subtype instantiated types/classes.
220 // TODO(johnniwinther): Support unknown type arguments for generic types.
221 void registerTypeInstantiation(InterfaceType type,
222 {bool byMirrors: false}) {
223 _instantiatedTypes.add(type);
224 ClassElement cls = type.element;
225 if (!cls.isAbstract
226 // We can't use the closed-world assumption with native abstract
227 // classes; a native abstract class may have non-abstract subclasses
228 // not declared to the program. Instances of these classes are
229 // indistinguishable from the abstract class.
230 || cls.isNative
231 // Likewise, if this registration comes from the mirror system,
232 // all bets are off.
233 // TODO(herhut): Track classes required by mirrors seperately.
234 || byMirrors) {
235 _directlyInstantiatedClasses.add(cls);
236 }
237
238 // TODO(johnniwinther): Replace this by separate more specific mappings.
239 if (!_allInstantiatedClasses.add(cls)) return;
240 cls.allSupertypes.forEach((InterfaceType supertype) {
241 _allInstantiatedClasses.add(supertype.element);
242 });
243 }
244
245 bool _hasMatchingSelector(Map<Selector, ReceiverMaskSet> selectors,
246 Element member,
247 World world) {
248 if (selectors == null) return false;
249 for (Selector selector in selectors.keys) {
250 if (selector.appliesUnnamed(member, world)) {
251 ReceiverMaskSet masks = selectors[selector];
252 if (masks.applies(member, selector, world)) {
253 return true;
254 }
255 }
256 }
257 return false;
258 }
259
260 bool hasInvocation(Element member, World world) {
261 return _hasMatchingSelector(_invokedNames[member.name], member, world);
262 }
263
264 bool hasInvokedGetter(Element member, World world) {
265 return _hasMatchingSelector(_invokedGetters[member.name], member, world);
266 }
267
268 bool hasInvokedSetter(Element member, World world) {
269 return _hasMatchingSelector(_invokedSetters[member.name], member, world);
270 }
271
272 bool registerInvocation(UniverseSelector selector) {
273 return _registerNewSelector(selector, _invokedNames);
274 }
275
276 bool registerInvokedGetter(UniverseSelector selector) {
277 return _registerNewSelector(selector, _invokedGetters);
278 }
279
280 bool registerInvokedSetter(UniverseSelector selector) {
281 return _registerNewSelector(selector, _invokedSetters);
282 }
283
284 bool _registerNewSelector(
285 UniverseSelector universeSelector,
286 Map<String, Map<Selector, ReceiverMaskSet>> selectorMap) {
287 Selector selector = universeSelector.selector;
288 String name = selector.name;
289 ReceiverMask mask = universeSelector.mask;
290 Map<Selector, ReceiverMaskSet> selectors = selectorMap.putIfAbsent(
291 name, () => new Maplet<Selector, ReceiverMaskSet>());
292 UniverseReceiverMaskSet masks = selectors.putIfAbsent(
293 selector, () => receiverMaskStrategy.createReceiverMaskSet(selector));
294 return masks.addReceiverMask(mask);
295 }
296
297 Map<Selector, ReceiverMaskSet> _asUnmodifiable(
298 Map<Selector, ReceiverMaskSet> map) {
299 if (map == null) return null;
300 return new UnmodifiableMapView(map);
301 }
302
303 Map<Selector, ReceiverMaskSet> invocationsByName(String name) {
304 return _asUnmodifiable(_invokedNames[name]);
305 }
306
307 Map<Selector, ReceiverMaskSet> getterInvocationsByName(String name) {
308 return _asUnmodifiable(_invokedGetters[name]);
309 }
310
311 Map<Selector, ReceiverMaskSet> setterInvocationsByName(String name) {
312 return _asUnmodifiable(_invokedSetters[name]);
313 }
314
315 void forEachInvokedName(
316 f(String name, Map<Selector, ReceiverMaskSet> selectors)) {
317 _invokedNames.forEach(f);
318 }
319
320 void forEachInvokedGetter(
321 f(String name, Map<Selector, ReceiverMaskSet> selectors)) {
322 _invokedGetters.forEach(f);
323 }
324
325 void forEachInvokedSetter(
326 f(String name, Map<Selector, ReceiverMaskSet> selectors)) {
327 _invokedSetters.forEach(f);
328 }
329
330 DartType registerIsCheck(DartType type, Compiler compiler) {
331 type = type.unalias(compiler);
332 // Even in checked mode, type annotations for return type and argument
333 // types do not imply type checks, so there should never be a check
334 // against the type variable of a typedef.
335 isChecks.add(type);
336 return type;
337 }
338
339 void registerStaticFieldUse(FieldElement staticField) {
340 assert(Elements.isStaticOrTopLevel(staticField) && staticField.isField);
341 assert(staticField.isDeclaration);
342
343 allReferencedStaticFields.add(staticField);
344 }
345
346 void forgetElement(Element element, Compiler compiler) {
347 allClosures.remove(element);
348 slowDirectlyNestedClosures(element).forEach(compiler.forgetElement);
349 closurizedMembers.remove(element);
350 fieldSetters.remove(element);
351 fieldGetters.remove(element);
352 _directlyInstantiatedClasses.remove(element);
353 _allInstantiatedClasses.remove(element);
354 if (element is ClassElement) {
355 assert(invariant(
356 element, element.thisType.isRaw,
357 message: 'Generic classes not supported (${element.thisType}).'));
358 _instantiatedTypes
359 ..remove(element.rawType)
360 ..remove(element.thisType);
361 }
362 }
363
364 // TODO(ahe): Replace this method with something that is O(1), for example,
365 // by using a map.
366 List<LocalFunctionElement> slowDirectlyNestedClosures(Element element) {
367 // Return new list to guard against concurrent modifications.
368 return new List<LocalFunctionElement>.from(
369 allClosures.where((LocalFunctionElement closure) {
370 return closure.executableContext == element;
371 }));
372 }
373 }
374 6
375 class SelectorKind { 7 class SelectorKind {
376 final String name; 8 final String name;
377 final int hashCode; 9 final int hashCode;
378 const SelectorKind(this.name, this.hashCode); 10 const SelectorKind(this.name, this.hashCode);
379 11
380 static const SelectorKind GETTER = const SelectorKind('getter', 0); 12 static const SelectorKind GETTER = const SelectorKind('getter', 0);
381 static const SelectorKind SETTER = const SelectorKind('setter', 1); 13 static const SelectorKind SETTER = const SelectorKind('setter', 1);
382 static const SelectorKind CALL = const SelectorKind('call', 2); 14 static const SelectorKind CALL = const SelectorKind('call', 2);
383 static const SelectorKind OPERATOR = const SelectorKind('operator', 3); 15 static const SelectorKind OPERATOR = const SelectorKind('operator', 3);
384 static const SelectorKind INDEX = const SelectorKind('index', 4); 16 static const SelectorKind INDEX = const SelectorKind('index', 4);
385 17
386 String toString() => name; 18 String toString() => name;
387 } 19 }
388 20
389 /// The structure of the arguments at a call-site.
390 // TODO(johnniwinther): Should these be cached?
391 // TODO(johnniwinther): Should isGetter/isSetter be part of the call structure
392 // instead of the selector?
393 class CallStructure {
394 static const CallStructure NO_ARGS = const CallStructure.unnamed(0);
395 static const CallStructure ONE_ARG = const CallStructure.unnamed(1);
396 static const CallStructure TWO_ARGS = const CallStructure.unnamed(2);
397
398 /// The numbers of arguments of the call. Includes named arguments.
399 final int argumentCount;
400
401 /// The number of named arguments of the call.
402 int get namedArgumentCount => 0;
403
404 /// The number of positional argument of the call.
405 int get positionalArgumentCount => argumentCount;
406
407 const CallStructure.unnamed(this.argumentCount);
408
409 factory CallStructure(int argumentCount, [List<String> namedArguments]) {
410 if (namedArguments == null || namedArguments.isEmpty) {
411 return new CallStructure.unnamed(argumentCount);
412 }
413 return new NamedCallStructure(argumentCount, namedArguments);
414 }
415
416 /// `true` if this call has named arguments.
417 bool get isNamed => false;
418
419 /// `true` if this call has no named arguments.
420 bool get isUnnamed => true;
421
422 /// The names of the named arguments in call-site order.
423 List<String> get namedArguments => const <String>[];
424
425 /// The names of the named arguments in canonicalized order.
426 List<String> getOrderedNamedArguments() => const <String>[];
427
428 /// A description of the argument structure.
429 String structureToString() => 'arity=$argumentCount';
430
431 String toString() => 'CallStructure(${structureToString()})';
432
433 Selector get callSelector {
434 return new Selector(SelectorKind.CALL, Selector.CALL_NAME, this);
435 }
436
437 bool match(CallStructure other) {
438 if (identical(this, other)) return true;
439 return this.argumentCount == other.argumentCount
440 && this.namedArgumentCount == other.namedArgumentCount
441 && sameNames(this.namedArguments, other.namedArguments);
442 }
443
444 // TODO(johnniwinther): Cache hash code?
445 int get hashCode {
446 return Hashing.listHash(namedArguments,
447 Hashing.objectHash(argumentCount, namedArguments.length));
448 }
449
450 bool operator ==(other) {
451 if (other is! CallStructure) return false;
452 return match(other);
453 }
454
455 bool signatureApplies(FunctionSignature parameters) {
456 if (argumentCount > parameters.parameterCount) return false;
457 int requiredParameterCount = parameters.requiredParameterCount;
458 int optionalParameterCount = parameters.optionalParameterCount;
459 if (positionalArgumentCount < requiredParameterCount) return false;
460
461 if (!parameters.optionalParametersAreNamed) {
462 // We have already checked that the number of arguments are
463 // not greater than the number of parameters. Therefore the
464 // number of positional arguments are not greater than the
465 // number of parameters.
466 assert(positionalArgumentCount <= parameters.parameterCount);
467 return namedArguments.isEmpty;
468 } else {
469 if (positionalArgumentCount > requiredParameterCount) return false;
470 assert(positionalArgumentCount == requiredParameterCount);
471 if (namedArgumentCount > optionalParameterCount) return false;
472 Set<String> nameSet = new Set<String>();
473 parameters.optionalParameters.forEach((Element element) {
474 nameSet.add(element.name);
475 });
476 for (String name in namedArguments) {
477 if (!nameSet.contains(name)) return false;
478 // TODO(5213): By removing from the set we are checking
479 // that we are not passing the name twice. We should have this
480 // check in the resolver also.
481 nameSet.remove(name);
482 }
483 return true;
484 }
485 }
486
487 /**
488 * Returns a `List` with the evaluated arguments in the normalized order.
489 *
490 * [compileDefaultValue] is a function that returns a compiled constant
491 * of an optional argument that is not in [compiledArguments].
492 *
493 * Precondition: `this.applies(element, world)`.
494 *
495 * Invariant: [element] must be the implementation element.
496 */
497 /*<T>*/ List/*<T>*/ makeArgumentsList(
498 Link<Node> arguments,
499 FunctionElement element,
500 /*T*/ compileArgument(Node argument),
501 /*T*/ compileDefaultValue(ParameterElement element)) {
502 assert(invariant(element, element.isImplementation));
503 List/*<T>*/ result = new List();
504
505 FunctionSignature parameters = element.functionSignature;
506 parameters.forEachRequiredParameter((ParameterElement element) {
507 result.add(compileArgument(arguments.head));
508 arguments = arguments.tail;
509 });
510
511 if (!parameters.optionalParametersAreNamed) {
512 parameters.forEachOptionalParameter((ParameterElement element) {
513 if (!arguments.isEmpty) {
514 result.add(compileArgument(arguments.head));
515 arguments = arguments.tail;
516 } else {
517 result.add(compileDefaultValue(element));
518 }
519 });
520 } else {
521 // Visit named arguments and add them into a temporary list.
522 List compiledNamedArguments = [];
523 for (; !arguments.isEmpty; arguments = arguments.tail) {
524 NamedArgument namedArgument = arguments.head;
525 compiledNamedArguments.add(compileArgument(namedArgument.expression));
526 }
527 // Iterate over the optional parameters of the signature, and try to
528 // find them in [compiledNamedArguments]. If found, we use the
529 // value in the temporary list, otherwise the default value.
530 parameters.orderedOptionalParameters.forEach((ParameterElement element) {
531 int foundIndex = namedArguments.indexOf(element.name);
532 if (foundIndex != -1) {
533 result.add(compiledNamedArguments[foundIndex]);
534 } else {
535 result.add(compileDefaultValue(element));
536 }
537 });
538 }
539 return result;
540 }
541
542 /**
543 * Fills [list] with the arguments in the order expected by
544 * [callee], and where [caller] is a synthesized element
545 *
546 * [compileArgument] is a function that returns a compiled version
547 * of a parameter of [callee].
548 *
549 * [compileConstant] is a function that returns a compiled constant
550 * of an optional argument that is not in the parameters of [callee].
551 *
552 * Returns [:true:] if the signature of the [caller] matches the
553 * signature of the [callee], [:false:] otherwise.
554 */
555 static /*<T>*/ bool addForwardingElementArgumentsToList(
556 ConstructorElement caller,
557 List/*<T>*/ list,
558 ConstructorElement callee,
559 /*T*/ compileArgument(ParameterElement element),
560 /*T*/ compileConstant(ParameterElement element)) {
561 assert(invariant(caller, !callee.isErroneous,
562 message: "Cannot compute arguments to erroneous constructor: "
563 "$caller calling $callee."));
564
565 FunctionSignature signature = caller.functionSignature;
566 Map<Node, ParameterElement> mapping = <Node, ParameterElement>{};
567
568 // TODO(ngeoffray): This is a hack that fakes up AST nodes, so
569 // that we can call [addArgumentsToList].
570 Link<Node> computeCallNodesFromParameters() {
571 LinkBuilder<Node> builder = new LinkBuilder<Node>();
572 signature.forEachRequiredParameter((ParameterElement element) {
573 Node node = element.node;
574 mapping[node] = element;
575 builder.addLast(node);
576 });
577 if (signature.optionalParametersAreNamed) {
578 signature.forEachOptionalParameter((ParameterElement element) {
579 mapping[element.initializer] = element;
580 builder.addLast(new NamedArgument(null, null, element.initializer));
581 });
582 } else {
583 signature.forEachOptionalParameter((ParameterElement element) {
584 Node node = element.node;
585 mapping[node] = element;
586 builder.addLast(node);
587 });
588 }
589 return builder.toLink();
590 }
591
592 /*T*/ internalCompileArgument(Node node) {
593 return compileArgument(mapping[node]);
594 }
595
596 Link<Node> nodes = computeCallNodesFromParameters();
597
598 // Synthesize a structure for the call.
599 // TODO(ngeoffray): Should the resolver do it instead?
600 List<String> namedParameters;
601 if (signature.optionalParametersAreNamed) {
602 namedParameters =
603 signature.optionalParameters.map((e) => e.name).toList();
604 }
605 CallStructure callStructure =
606 new CallStructure(signature.parameterCount, namedParameters);
607 if (!callStructure.signatureApplies(signature)) {
608 return false;
609 }
610 list.addAll(callStructure.makeArgumentsList(
611 nodes,
612 callee,
613 internalCompileArgument,
614 compileConstant));
615
616 return true;
617 }
618
619 static bool sameNames(List<String> first, List<String> second) {
620 for (int i = 0; i < first.length; i++) {
621 if (first[i] != second[i]) return false;
622 }
623 return true;
624 }
625 }
626
627 ///
628 class NamedCallStructure extends CallStructure {
629 final List<String> namedArguments;
630 final List<String> _orderedNamedArguments = <String>[];
631
632 NamedCallStructure(int argumentCount, this.namedArguments)
633 : super.unnamed(argumentCount) {
634 assert(namedArguments.isNotEmpty);
635 }
636
637 @override
638 bool get isNamed => true;
639
640 @override
641 bool get isUnnamed => false;
642
643 @override
644 int get namedArgumentCount => namedArguments.length;
645
646 @override
647 int get positionalArgumentCount => argumentCount - namedArgumentCount;
648
649 @override
650 List<String> getOrderedNamedArguments() {
651 if (!_orderedNamedArguments.isEmpty) return _orderedNamedArguments;
652
653 _orderedNamedArguments.addAll(namedArguments);
654 _orderedNamedArguments.sort((String first, String second) {
655 return first.compareTo(second);
656 });
657 return _orderedNamedArguments;
658 }
659
660 @override
661 String structureToString() {
662 return 'arity=$argumentCount, named=[${namedArguments.join(', ')}]';
663 }
664 }
665
666 class Selector { 21 class Selector {
667 final SelectorKind kind; 22 final SelectorKind kind;
668 final Name memberName; 23 final Name memberName;
669 final CallStructure callStructure; 24 final CallStructure callStructure;
670 25
671 final int hashCode; 26 final int hashCode;
672 27
673 int get argumentCount => callStructure.argumentCount; 28 int get argumentCount => callStructure.argumentCount;
674 int get namedArgumentCount => callStructure.namedArgumentCount; 29 int get namedArgumentCount => callStructure.namedArgumentCount;
675 int get positionalArgumentCount => callStructure.positionalArgumentCount; 30 int get positionalArgumentCount => callStructure.positionalArgumentCount;
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
907 // Add bits from the call structure. 262 // Add bits from the call structure.
908 return Hashing.mixHashCodeBits(hash, callStructure.hashCode); 263 return Hashing.mixHashCodeBits(hash, callStructure.hashCode);
909 } 264 }
910 265
911 String toString() { 266 String toString() {
912 return 'Selector($kind, $name, ${callStructure.structureToString()})'; 267 return 'Selector($kind, $name, ${callStructure.structureToString()})';
913 } 268 }
914 269
915 Selector toCallSelector() => new Selector.callClosureFrom(this); 270 Selector toCallSelector() => new Selector.callClosureFrom(this);
916 } 271 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/universe/call_structure.dart ('k') | pkg/compiler/lib/src/universe/universe.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698