OLD | NEW |
---|---|
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 library kernel.incremental_class_hierarchy; | 4 library kernel.incremental_class_hierarchy; |
5 | 5 |
6 import 'dart:collection'; | 6 import 'dart:collection'; |
7 import 'dart:math'; | 7 import 'dart:math'; |
8 | 8 |
9 import 'package:kernel/ast.dart'; | 9 import 'package:kernel/ast.dart'; |
10 import 'package:kernel/class_hierarchy.dart'; | 10 import 'package:kernel/class_hierarchy.dart'; |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
208 | 208 |
209 @override | 209 @override |
210 Member getDispatchTarget(Class node, Name name, {bool setter: false}) { | 210 Member getDispatchTarget(Class node, Name name, {bool setter: false}) { |
211 _ClassInfo info = _getInfo(node); | 211 _ClassInfo info = _getInfo(node); |
212 List<Member> targets = | 212 List<Member> targets = |
213 setter ? info.implementedSetters : info.implementedGettersAndCalls; | 213 setter ? info.implementedSetters : info.implementedGettersAndCalls; |
214 return _findMemberByName(targets, name); | 214 return _findMemberByName(targets, name); |
215 } | 215 } |
216 | 216 |
217 @override | 217 @override |
218 Member getInterfaceMember(Class class_, Name name, {bool setter: false}) { | 218 Member getInterfaceMember(Class node, Name name, {bool setter: false}) { |
219 // TODO(scheglov): implement getInterfaceMember | 219 _ClassInfo info = _getInfo(node); |
220 throw new UnimplementedError(); | 220 List<Member> members = |
221 setter ? info.interfaceSetters : info.interfaceGettersAndCalls; | |
222 return _findMemberByName(members, name); | |
221 } | 223 } |
222 | 224 |
223 @override | 225 @override |
224 List<Class> getRankedSuperclasses(Class node) { | 226 List<Class> getRankedSuperclasses(Class node) { |
225 var info = _getInfo(node); | 227 var info = _getInfo(node); |
226 return _getRankedSuperclassList(info).map((info) => info.node).toList(); | 228 return _getRankedSuperclassList(info).map((info) => info.node).toList(); |
227 } | 229 } |
228 | 230 |
229 @override | 231 @override |
230 InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass) { | 232 InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass) { |
231 Supertype castedType = getClassAsInstanceOf(type.classNode, superclass); | 233 Supertype castedType = getClassAsInstanceOf(type.classNode, superclass); |
232 if (castedType == null) return null; | 234 if (castedType == null) return null; |
233 return Substitution | 235 return Substitution |
234 .fromInterfaceType(type) | 236 .fromInterfaceType(type) |
235 .substituteType(castedType.asInterfaceType); | 237 .substituteType(castedType.asInterfaceType); |
236 } | 238 } |
237 | 239 |
238 @override | 240 @override |
239 bool hasProperSubtypes(Class class_) { | 241 bool hasProperSubtypes(Class class_) { |
240 // TODO(scheglov): implement hasProperSubtypes | 242 // TODO(scheglov): implement hasProperSubtypes |
241 throw new UnimplementedError(); | 243 throw new UnimplementedError(); |
242 } | 244 } |
243 | 245 |
244 /// Fill the given [info] with declared methods and setters. | 246 /// Fill the given [info] with declared instance methods and setters. |
245 void _buildDeclaredMembers(_ClassInfo info) { | 247 void _buildDeclaredMembers(_ClassInfo info) { |
246 Class node = info.node; | 248 Class node = info.node; |
247 if (node.mixedInType != null) { | 249 if (node.mixedInType != null) { |
248 _ClassInfo mixedInfo = _getInfo(node.mixedInType.classNode); | 250 _ClassInfo mixedInfo = _getInfo(node.mixedInType.classNode); |
249 info.declaredGettersAndCalls = mixedInfo.declaredGettersAndCalls; | 251 info.declaredGettersAndCalls = mixedInfo.declaredGettersAndCalls; |
250 info.declaredSetters = mixedInfo.declaredSetters; | 252 info.declaredSetters = mixedInfo.declaredSetters; |
251 } else { | 253 } else { |
252 var members = info.declaredGettersAndCalls = <Member>[]; | 254 var members = info.declaredGettersAndCalls = <Member>[]; |
253 var setters = info.declaredSetters = <Member>[]; | 255 var setters = info.declaredSetters = <Member>[]; |
254 for (Procedure procedure in node.procedures) { | 256 for (Procedure procedure in node.procedures) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
286 inheritedSetters = superInfo.implementedSetters; | 288 inheritedSetters = superInfo.implementedSetters; |
287 } | 289 } |
288 info.implementedGettersAndCalls = _inheritMembers( | 290 info.implementedGettersAndCalls = _inheritMembers( |
289 info.declaredGettersAndCalls, inheritedMembers, | 291 info.declaredGettersAndCalls, inheritedMembers, |
290 skipAbstractMembers: true); | 292 skipAbstractMembers: true); |
291 info.implementedSetters = _inheritMembers( | 293 info.implementedSetters = _inheritMembers( |
292 info.declaredSetters, inheritedSetters, | 294 info.declaredSetters, inheritedSetters, |
293 skipAbstractMembers: true); | 295 skipAbstractMembers: true); |
294 } | 296 } |
295 | 297 |
298 /// Build interface methods or setters for the class described by [info]. | |
299 void _buildInterfaceMembers(_ClassInfo info) { | |
300 List<Member> declaredGetters = info.declaredGettersAndCalls; | |
301 List<Member> declaredSetters = info.declaredSetters; | |
302 List<Member> allInheritedGetters = <Member>[]; | |
303 List<Member> allInheritedSetters = <Member>[]; | |
304 | |
305 void inheritFrom(Supertype type) { | |
306 if (type == null) return; | |
307 var info = _getInfo(type.classNode); | |
308 // TODO(scheglov): Can we optimize this with yield? | |
309 | |
310 var inheritedGetters = _getUnshadowedInheritedMembers( | |
311 declaredGetters, info.interfaceGettersAndCalls); | |
312 allInheritedGetters = _merge(allInheritedGetters, inheritedGetters); | |
313 | |
314 var inheritedSetters = _getUnshadowedInheritedMembers( | |
315 declaredSetters, info.interfaceSetters); | |
316 allInheritedSetters = _merge(allInheritedSetters, inheritedSetters); | |
317 } | |
318 | |
319 Class node = info.node; | |
320 inheritFrom(node.supertype); | |
321 inheritFrom(node.mixedInType); | |
322 node.implementedTypes.forEach(inheritFrom); | |
323 | |
324 info.interfaceGettersAndCalls = | |
325 _inheritMembers(declaredGetters, allInheritedGetters); | |
326 info.interfaceSetters = | |
327 _inheritMembers(declaredSetters, allInheritedSetters); | |
328 } | |
329 | |
296 /// Return the [_ClassInfo] for the [node]. | 330 /// Return the [_ClassInfo] for the [node]. |
297 _ClassInfo _getInfo(Class node) { | 331 _ClassInfo _getInfo(Class node) { |
298 var info = _info[node]; | 332 var info = _info[node]; |
299 if (info == null) { | 333 if (info == null) { |
300 info = new _ClassInfo(_nextId++, node); | 334 info = new _ClassInfo(_nextId++, node); |
301 _info[node] = info; | 335 _info[node] = info; |
302 | 336 |
303 void addSupertypeIdentifiers(_ClassInfo superInfo) { | 337 void addSupertypeIdentifiers(_ClassInfo superInfo) { |
304 info.supertypeIdSet.add(superInfo.id); | 338 info.supertypeIdSet.add(superInfo.id); |
305 info.supertypeIdSet.addAll(superInfo.supertypeIdSet); | 339 info.supertypeIdSet.addAll(superInfo.supertypeIdSet); |
(...skipping 15 matching lines...) Expand all Loading... | |
321 for (var implementedType in node.implementedTypes) { | 355 for (var implementedType in node.implementedTypes) { |
322 var implementedInfo = _getInfo(implementedType.classNode); | 356 var implementedInfo = _getInfo(implementedType.classNode); |
323 superDepth = max(superDepth, implementedInfo.depth); | 357 superDepth = max(superDepth, implementedInfo.depth); |
324 addSupertypeIdentifiers(implementedInfo); | 358 addSupertypeIdentifiers(implementedInfo); |
325 _recordSuperTypes(info, implementedType, implementedInfo); | 359 _recordSuperTypes(info, implementedType, implementedInfo); |
326 } | 360 } |
327 info.depth = superDepth + 1; | 361 info.depth = superDepth + 1; |
328 | 362 |
329 _buildDeclaredMembers(info); | 363 _buildDeclaredMembers(info); |
330 _buildImplementedMembers(info); | 364 _buildImplementedMembers(info); |
365 _buildInterfaceMembers(info); | |
331 } | 366 } |
332 return info; | 367 return info; |
333 } | 368 } |
334 | 369 |
335 List<_ClassInfo> _getRankedSuperclassList(_ClassInfo info) { | 370 List<_ClassInfo> _getRankedSuperclassList(_ClassInfo info) { |
336 if (info.rankedSuperclassList != null) { | 371 if (info.rankedSuperclassList != null) { |
337 return info.rankedSuperclassList; | 372 return info.rankedSuperclassList; |
338 } | 373 } |
339 | 374 |
340 var heap = new _LubHeap()..add(info); | 375 var heap = new _LubHeap()..add(info); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
391 var substitution = Substitution.fromPairs( | 426 var substitution = Substitution.fromPairs( |
392 superclass.typeParameters, supertype.typeArguments); | 427 superclass.typeParameters, supertype.typeArguments); |
393 subInfo.genericSuperTypes ??= <Class, Supertype>{}; | 428 subInfo.genericSuperTypes ??= <Class, Supertype>{}; |
394 superInfo.genericSuperTypes?.forEach((Class key, Supertype type) { | 429 superInfo.genericSuperTypes?.forEach((Class key, Supertype type) { |
395 subInfo.genericSuperTypes[key] = substitution.substituteSupertype(type); | 430 subInfo.genericSuperTypes[key] = substitution.substituteSupertype(type); |
396 }); | 431 }); |
397 subInfo.genericSuperTypes[superclass] = supertype; | 432 subInfo.genericSuperTypes[superclass] = supertype; |
398 } | 433 } |
399 } | 434 } |
400 | 435 |
436 /// Returns the subset of members in [inherited] for which a member with the | |
437 /// same name does not occur in [declared]. | |
438 /// | |
439 /// The input lists must be sorted, and the returned list is sorted. | |
440 static List<Member> _getUnshadowedInheritedMembers( | |
441 List<Member> declared, List<Member> inherited) { | |
442 List<Member> result = <Member>[]..length = inherited.length; | |
Paul Berry
2017/06/03 13:27:34
Creating the list and then setting its length as t
scheglov
2017/06/04 00:47:47
Done.
| |
443 int storeIndex = 0; | |
444 int i = 0, j = 0; | |
445 while (i < declared.length && j < inherited.length) { | |
446 Member declaredMember = declared[i]; | |
447 Member inheritedMember = inherited[j]; | |
448 int comparison = _compareMembers(declaredMember, inheritedMember); | |
449 if (comparison < 0) { | |
450 ++i; | |
451 } else if (comparison > 0) { | |
452 result[storeIndex++] = inheritedMember; | |
453 ++j; | |
454 } else { | |
455 // Move past the shadowed member, but retain the declared member, as | |
456 // it may shadow multiple members. | |
457 ++j; | |
458 } | |
459 } | |
460 // If the list of declared members is exhausted, copy over the remains of | |
461 // the inherited members. | |
462 while (j < inherited.length) { | |
463 result[storeIndex++] = inherited[j++]; | |
464 } | |
465 result.length = storeIndex; | |
466 return result; | |
467 } | |
468 | |
401 /// Computes the list of implemented members, based on the declared instance | 469 /// Computes the list of implemented members, based on the declared instance |
402 /// members and inherited instance members. | 470 /// members and inherited instance members. |
403 /// | 471 /// |
404 /// Both lists must be sorted by name beforehand. | 472 /// Both lists must be sorted by name beforehand. |
405 static List<Member> _inheritMembers( | 473 static List<Member> _inheritMembers( |
406 List<Member> declared, List<Member> inherited, | 474 List<Member> declared, List<Member> inherited, |
407 {bool skipAbstractMembers: false}) { | 475 {bool skipAbstractMembers: false}) { |
408 List<Member> result = <Member>[]..length = | 476 List<Member> result = <Member>[]..length = |
409 declared.length + inherited.length; | 477 declared.length + inherited.length; |
410 // Since both lists are sorted, we can fuse them like in merge sort. | 478 // Since both lists are sorted, we can fuse them like in merge sort. |
(...skipping 30 matching lines...) Expand all Loading... | |
441 result[storeIndex++] = declaredMember; | 509 result[storeIndex++] = declaredMember; |
442 } | 510 } |
443 while (j < inherited.length) { | 511 while (j < inherited.length) { |
444 Member inheritedMember = inherited[j++]; | 512 Member inheritedMember = inherited[j++]; |
445 if (skipAbstractMembers && inheritedMember.isAbstract) continue; | 513 if (skipAbstractMembers && inheritedMember.isAbstract) continue; |
446 result[storeIndex++] = inheritedMember; | 514 result[storeIndex++] = inheritedMember; |
447 } | 515 } |
448 result.length = storeIndex; | 516 result.length = storeIndex; |
449 return result; | 517 return result; |
450 } | 518 } |
519 | |
520 /// Merges two sorted lists. | |
521 /// | |
522 /// If a given member occurs in both lists, the merge will attempt to exclude | |
523 /// the duplicate member, but is not strictly guaranteed to do so. | |
524 static List<Member> _merge(List<Member> first, List<Member> second) { | |
525 if (first.isEmpty) return second; | |
526 if (second.isEmpty) return first; | |
527 List<Member> result = <Member>[]..length = first.length + second.length; | |
528 int storeIndex = 0; | |
529 int i = 0, j = 0; | |
530 while (i < first.length && j < second.length) { | |
531 Member firstMember = first[i]; | |
532 Member secondMember = second[j]; | |
533 int compare = _compareMembers(firstMember, secondMember); | |
534 if (compare <= 0) { | |
535 result[storeIndex++] = firstMember; | |
536 ++i; | |
537 // If the same member occurs in both lists, skip the duplicate. | |
538 if (identical(firstMember, secondMember)) { | |
539 ++j; | |
540 } | |
541 } else { | |
542 result[storeIndex++] = secondMember; | |
543 ++j; | |
544 } | |
545 } | |
546 while (i < first.length) { | |
547 result[storeIndex++] = first[i++]; | |
548 } | |
549 while (j < second.length) { | |
550 result[storeIndex++] = second[j++]; | |
551 } | |
552 result.length = storeIndex; | |
553 return result; | |
554 } | |
451 } | 555 } |
452 | 556 |
453 /// Information about a [Class]. | 557 /// Information about a [Class]. |
454 class _ClassInfo { | 558 class _ClassInfo { |
455 /// The unique identifier of the [_ClassInfo]. | 559 /// The unique identifier of the [_ClassInfo]. |
456 final int id; | 560 final int id; |
457 | 561 |
458 /// The [Class] node described by this [_ClassInfo]. | 562 /// The [Class] node described by this [_ClassInfo]. |
459 final Class node; | 563 final Class node; |
460 | 564 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
508 List<Member> declaredSetters; | 612 List<Member> declaredSetters; |
509 | 613 |
510 /// Instance fields, getters, methods, and operators implemented by this class | 614 /// Instance fields, getters, methods, and operators implemented by this class |
511 /// (declared or inherited). | 615 /// (declared or inherited). |
512 List<Member> implementedGettersAndCalls; | 616 List<Member> implementedGettersAndCalls; |
513 | 617 |
514 /// Non-final instance fields and setters implemented by this class | 618 /// Non-final instance fields and setters implemented by this class |
515 /// (declared or inherited). | 619 /// (declared or inherited). |
516 List<Member> implementedSetters; | 620 List<Member> implementedSetters; |
517 | 621 |
622 /// Instance fields, getters, methods, and operators declared in this class, | |
623 /// or its supertype, or interfaces, sorted according to [_compareMembers], | |
624 /// or `null` if it has not been computed yet. | |
625 List<Member> interfaceGettersAndCalls; | |
626 | |
627 /// Non-final instance fields and setters declared in this class, or its | |
628 /// supertype, or interfaces, sorted according to [_compareMembers], or | |
629 /// `null` if it has not been computed yet. | |
630 List<Member> interfaceSetters; | |
631 | |
518 _ClassInfo(this.id, this.node); | 632 _ClassInfo(this.id, this.node); |
519 | 633 |
520 /// Return `true` if the [superInfo] corresponds to a supertype of this class. | 634 /// Return `true` if the [superInfo] corresponds to a supertype of this class. |
521 bool isSubtypeOf(_ClassInfo superInfo) { | 635 bool isSubtypeOf(_ClassInfo superInfo) { |
522 return supertypeIdSet.contains(superInfo.id); | 636 return supertypeIdSet.contains(superInfo.id); |
523 } | 637 } |
524 | 638 |
525 @override | 639 @override |
526 String toString() => node.toString(); | 640 String toString() => node.toString(); |
527 } | 641 } |
528 | 642 |
529 /// Heap for use in computing least upper bounds. | 643 /// Heap for use in computing least upper bounds. |
530 /// | 644 /// |
531 /// The heap is sorted such that classes that are deepest in the hierarchy | 645 /// The heap is sorted such that classes that are deepest in the hierarchy |
532 /// are removed first; in the case of ties, classes with lower unique | 646 /// are removed first; in the case of ties, classes with lower unique |
533 /// identifiers removed first. | 647 /// identifiers removed first. |
534 class _LubHeap extends Heap<_ClassInfo> { | 648 class _LubHeap extends Heap<_ClassInfo> { |
535 @override | 649 @override |
536 bool sortsBefore(_ClassInfo a, _ClassInfo b) => sortsBeforeStatic(a, b); | 650 bool sortsBefore(_ClassInfo a, _ClassInfo b) => sortsBeforeStatic(a, b); |
537 | 651 |
538 static bool sortsBeforeStatic(_ClassInfo a, _ClassInfo b) { | 652 static bool sortsBeforeStatic(_ClassInfo a, _ClassInfo b) { |
539 if (a.depth > b.depth) return true; | 653 if (a.depth > b.depth) return true; |
540 if (a.depth < b.depth) return false; | 654 if (a.depth < b.depth) return false; |
541 return a.id < b.id; | 655 return a.id < b.id; |
542 } | 656 } |
543 } | 657 } |
OLD | NEW |