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

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

Issue 1234053002: Add SubclassNode to prepare for optimized queries on ClassWorld. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 5 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
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 library dart2js.world.class_set;
6
7 import 'dart:collection' show IterableBase;
8 import '../elements/elements.dart' show ClassElement;
9 import '../util/util.dart' show Link;
10
11 /// Node for [cls] in a tree forming the subclass relation of [ClassElement]s.
12 ///
13 /// This is used by the [ClassWorld] to perform queries on subclass and subtype
14 /// relations.
15 // TODO(johnniwinther): Use this for `ClassWorld.subtypesOf`.
16 class SubclassNode {
Siggi Cherem (dart-lang) 2015/07/14 23:51:07 This is a hard one name :) - Somehow SubclassNode
Johnni Winther 2015/07/15 08:55:08 ClassHierarchyNode or ClassHierarchyTreeNode it is
Johnni Winther 2015/07/21 12:11:01 Done.
17 final ClassElement cls;
18
19 /// `true` if [cls] has been directly instantiated.
20 ///
21 /// For instance `C` but _not_ `B` in:
22 /// class B {}
23 /// class C extends B {}
24 /// main() => new C();
25 ///
26 bool isDirectlyInstantiated = false;
27
28 /// `true` if [cls] has been instantiated through subclasses.
29 ///
30 /// For instance `B` and `C` but _not_ `A` in:
Siggi Cherem (dart-lang) 2015/07/14 23:51:07 I was expecting `A` would be true in this case (si
Johnni Winther 2015/07/15 08:55:08 It should have been: `A` and `B` but _not_ `C`
Johnni Winther 2015/07/21 12:11:00 Done.
31 /// class A {}
32 /// class B extends A {}
33 /// class C extends B {}
34 /// main() => [new B(), new C()];
35 ///
36 bool isIndirectlyInstantiated = false;
37
38 /// The node for the direct subclasses of [cls].
39 Link<SubclassNode> _directSubclasses = const Link<SubclassNode>();
40
41 SubclassNode(this.cls);
42
43 /// Adds [subclass] as a direct subclass of [cls].
44 void addDirectSubclass(SubclassNode subclass) {
45 assert(subclass.cls.superclass == cls);
46 assert(!_directSubclasses.contains(subclass));
47 _directSubclasses = _directSubclasses.prepend(subclass);
48 }
49
50 /// The nodes for the direct subclasses of [cls].
51 Link<SubclassNode> get directSubclasses => _directSubclasses;
52
53 /// `true` if [cls] has any direct subclasses.
54 bool get hasDirectSubclasses => !_directSubclasses.isEmpty;
55
56 /// `true` if [cls] has been directly or indirectly instantiated.
57 bool get isInstantiated => isDirectlyInstantiated || isIndirectlyInstantiated;
58
59 /// Returns an [Iterable] of the subclasses of [cls] possibly including [cls].
60 /// If [directlyInstantiated] is `true`, the iterable only returns the
61 /// directly instantiated subclasses of [cls].
62 Iterable<ClassElement> subclasses({bool directlyInstantiated: true}) {
63 return new SubclassNodeIterable(
64 this, directlyInstantiatedOnly: directlyInstantiated);
65 }
66
67 /// Returns an [Iterable] of the strict subclasses of [cls] _not_ including
68 /// [cls] itself. If [directlyInstantiated] is `true`, the iterable only
69 /// returns the directly instantiated subclasses of [cls].
70 Iterable<ClassElement> strictSubclasses(
71 {bool directlyInstantiated: true}) {
72 return new SubclassNodeIterable(this,
73 includeRoot: false, directlyInstantiatedOnly: directlyInstantiated);
74 }
75
76 String toString() => cls.toString();
77 }
78
79 /// Iterable for subclasses of a [SubclassNode].
80 class SubclassNodeIterable extends IterableBase<ClassElement> {
81 final SubclassNode root;
82 final bool includeRoot;
83 final bool directlyInstantiatedOnly;
84
85 SubclassNodeIterable(
86 this.root,
87 {this.includeRoot: true,
88 this.directlyInstantiatedOnly: false});
89
90 @override
91 Iterator<ClassElement> get iterator {
92 return new SubclassNodeIterator(this);
93 }
94 }
95
96 /// Iterator for subclasses of a [SubclassNode].
Siggi Cherem (dart-lang) 2015/07/14 23:51:07 it might be worth mentioning here or in the sublas
Johnni Winther 2015/07/15 08:55:08 The iterator is an intermediate step towards the i
97 class SubclassNodeIterator implements Iterator<ClassElement> {
98 final SubclassNodeIterable iterable;
99
100 /// The class node holding the [current] class.
101 ///
102 /// This is `null` before the first call to [moveNext] and at the end of
103 /// iteration, i.e. after [moveNext] has returned `false`.
104 SubclassNode currentNode;
105
106 /// Stack of list of pending class nodes.
107 ///
108 /// This is `null` before the first call to [moveNext].
109 Link<Link<SubclassNode>> stack;
110
111 SubclassNodeIterator(this.iterable);
112
113 SubclassNode get root => iterable.root;
114
115 bool get includeRoot => iterable.includeRoot;
116
117 bool get directlyInstantiatedOnly => iterable.directlyInstantiatedOnly;
118
119 @override
120 ClassElement get current {
121 return currentNode != null ? currentNode.cls : null;
122 }
123
124 @override
125 bool moveNext() {
126 if (stack == null) {
127 // Uninitialized state.
128 stack = const Link<Link<SubclassNode>>();
129 currentNode = root;
130 if (currentNode.hasDirectSubclasses) {
Siggi Cherem (dart-lang) 2015/07/14 23:51:07 it would be nice to only have this part of the log
Johnni Winther 2015/07/15 08:55:09 Good idea!
Johnni Winther 2015/07/21 12:11:00 Done.
131 stack = stack.prepend(currentNode.directSubclasses);
132 }
133 if (isValid(currentNode)) {
134 return true;
135 }
136 return findNext();
137 } else {
138 // Initialized state.
139 if (currentNode == null) return false;
140 return findNext();
141 }
142 }
143
144 /// Find the next class using the [stack].
145 bool findNext() {
Siggi Cherem (dart-lang) 2015/07/14 23:51:07 make private?
Johnni Winther 2015/07/21 12:11:00 Done.
146 while (true) {
147 if (stack.isEmpty) {
148 // No more classes. Set [currentNode] to `null` to signal the end of
149 // iteration.
150 currentNode = null;
151 return false;
152 }
153 Link<SubclassNode> pending = stack.head;
154 stack = stack.tail;
155 currentNode = pending.head;
156 pending = pending.tail;
157 if (!pending.isEmpty) {
158 stack = stack.prepend(pending);
159 }
160 if (currentNode.hasDirectSubclasses) {
161 stack = stack.prepend(currentNode.directSubclasses);
Siggi Cherem (dart-lang) 2015/07/14 23:51:07 What do you think about flattening the list here (
Johnni Winther 2015/07/15 08:55:08 I'll give it a try.
Johnni Winther 2015/07/21 12:11:00 Done.
162 }
163 if (isValid(currentNode)) {
164 return true;
165 }
166 }
167 }
168
169 /// Returns `true` if the class of [node] is a valid result for this iterator.
170 bool isValid(SubclassNode node) {
Siggi Cherem (dart-lang) 2015/07/14 23:51:07 make private too?
Johnni Winther 2015/07/15 08:55:08 Will do.
Johnni Winther 2015/07/21 12:11:00 Done.
171 if (!includeRoot && node == root) return false;
172 if (directlyInstantiatedOnly && !node.isDirectlyInstantiated) return false;
173 return true;
174 }
175 }
176
177
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698