@@ -36,11 +36,6 @@ void ProtocolGraph::visitProtocols(ArrayRef<const ProtocolDecl *> protos) {
36
36
}
37
37
}
38
38
39
- // / Return true if we know about this protocol.
40
- bool ProtocolGraph::isKnownProtocol (const ProtocolDecl *proto) const {
41
- return Info.count (proto) > 0 ;
42
- }
43
-
44
39
// / Look up information about a known protocol.
45
40
const ProtocolInfo &ProtocolGraph::getProtocolInfo (
46
41
const ProtocolDecl *proto) const {
@@ -49,223 +44,23 @@ const ProtocolInfo &ProtocolGraph::getProtocolInfo(
49
44
return found->second ;
50
45
}
51
46
52
- // / The "support" of a protocol P is the size of the transitive closure of
53
- // / the singleton set {P} under protocol inheritance.
54
- unsigned ProtocolGraph::getProtocolSupport (
55
- const ProtocolDecl *proto) const {
56
- return getProtocolInfo (proto).AllInherited .size () + 1 ;
57
- }
58
-
59
- // / The "support" of a set S of protocols is the size of the transitive
60
- // / closure of S under protocol inheritance. For example, if you start
61
- // / with
62
- // /
63
- // / protocol P1 : P3 {}
64
- // / protocol P2 : P3 {}
65
- // / protocol P3 {}
66
- // /
67
- // / Then the "support" of P1 & P2 is 3 because |P1 & P2 & P3| = 3.
68
- // /
69
- // / The \p protos array must be sorted in canonical order and
70
- // / permanently-allocated; one safe choice is to use the return value of
71
- // / Symbol::getProtocols().
72
- unsigned ProtocolGraph::getProtocolSupport (
73
- ArrayRef<const ProtocolDecl *> protos) const {
74
- auto found = Support.find (protos);
75
- if (found != Support.end ())
76
- return found->second ;
77
-
78
- unsigned result;
79
- if (protos.size () == 1 ) {
80
- result = getProtocolSupport (protos[0 ]);
81
- } else {
82
- llvm::DenseSet<const ProtocolDecl *> visited;
83
- for (const auto *proto : protos) {
84
- visited.insert (proto);
85
- for (const auto *inheritedProto : getProtocolInfo (proto).AllInherited )
86
- visited.insert (inheritedProto);
87
- }
88
-
89
- result = visited.size ();
90
- }
91
-
92
- const_cast <ProtocolGraph *>(this )->Support [protos] = result;
93
- return result;
94
- }
95
-
96
47
// / Record information about a protocol if we have no seen it yet.
97
48
void ProtocolGraph::addProtocol (const ProtocolDecl *proto,
98
49
bool initialComponent) {
99
50
if (Info.count (proto) > 0 )
100
51
return ;
101
52
102
- Info[proto] = {proto->getInheritedProtocols (),
103
- proto->getAssociatedTypeMembers (),
104
- proto->getProtocolDependencies (),
105
- initialComponent};
53
+ Info[proto] = {initialComponent};
106
54
Protocols.push_back (proto);
107
55
}
108
56
109
- // / Record information about all protocols transtively referenced
110
- // / from protocol requirement signatures.
111
- void ProtocolGraph::computeTransitiveClosure () {
57
+ // / Compute everything in the right order.
58
+ void ProtocolGraph::compute () {
112
59
unsigned i = 0 ;
113
60
while (i < Protocols.size ()) {
114
61
auto *proto = Protocols[i++];
115
- for (auto *proto : getProtocolInfo (proto).Dependencies ) {
116
- addProtocol (proto, /* initialComponent=*/ false );
117
- }
118
- }
119
- }
120
-
121
- // / See ProtocolGraph::compareProtocols() for the definition of this linear
122
- // / order.
123
- void ProtocolGraph::computeLinearOrder () {
124
- for (const auto *proto : Protocols) {
125
- (void ) computeProtocolDepth (proto);
126
- }
127
-
128
- std::sort (
129
- Protocols.begin (), Protocols.end (),
130
- [&](const ProtocolDecl *lhs,
131
- const ProtocolDecl *rhs) -> bool {
132
- const auto &lhsInfo = getProtocolInfo (lhs);
133
- const auto &rhsInfo = getProtocolInfo (rhs);
134
-
135
- // protocol Base {} // depth 1
136
- // protocol Derived : Base {} // depth 2
137
- //
138
- // Derived < Base in the linear order.
139
- if (lhsInfo.Depth != rhsInfo.Depth )
140
- return lhsInfo.Depth > rhsInfo.Depth ;
141
-
142
- return TypeDecl::compare (lhs, rhs) < 0 ;
143
- });
144
-
145
- for (unsigned i : indices (Protocols)) {
146
- Info[Protocols[i]].Index = i;
147
- }
148
-
149
- if (Debug) {
150
- for (const auto *proto : Protocols) {
151
- const auto &info = getProtocolInfo (proto);
152
- llvm::dbgs () << " @ Protocol " << proto->getName ()
153
- << " Depth=" << info.Depth
154
- << " Index=" << info.Index << " \n " ;
155
- }
156
- }
157
- }
158
-
159
- // / Update each ProtocolInfo's AssociatedTypes vector to add all associated
160
- // / types from all transitively inherited protocols.
161
- void ProtocolGraph::computeInheritedAssociatedTypes () {
162
- // Visit protocols in reverse order, so that if P inherits from Q and
163
- // Q inherits from R, we first visit R, then Q, then P, ensuring that
164
- // R's associated types are added to P's list, etc.
165
- for (const auto *proto : llvm::reverse (Protocols)) {
166
- auto &info = Info[proto];
167
-
168
- for (const auto *inherited : info.AllInherited ) {
169
- for (auto *inheritedType : getProtocolInfo (inherited).AssociatedTypes ) {
170
- info.InheritedAssociatedTypes .push_back (inheritedType);
171
- }
62
+ for (auto *depProto : proto->getProtocolDependencies ()) {
63
+ addProtocol (depProto, /* initialComponent=*/ false );
172
64
}
173
65
}
174
- }
175
-
176
- // Update each protocol's AllInherited vector to add all transitively
177
- // inherited protocols.
178
- void ProtocolGraph::computeInheritedProtocols () {
179
- // Visit protocols in reverse order, so that if P inherits from Q and
180
- // Q inherits from R, we first visit R, then Q, then P, ensuring that
181
- // R's inherited protocols are added to P's list, etc.
182
- for (const auto *proto : llvm::reverse (Protocols)) {
183
- auto &info = Info[proto];
184
-
185
- // We might inherit the same protocol multiple times due to diamond
186
- // inheritance, so make sure we only add each protocol once.
187
- llvm::SmallDenseSet<const ProtocolDecl *, 4 > visited;
188
- visited.insert (proto);
189
-
190
- for (const auto *inherited : info.Inherited ) {
191
- // Add directly-inherited protocols.
192
- if (!visited.insert (inherited).second )
193
- continue ;
194
- info.AllInherited .push_back (inherited);
195
-
196
- // Add indirectly-inherited protocols.
197
- for (auto *inheritedType : getProtocolInfo (inherited).AllInherited ) {
198
- if (!visited.insert (inheritedType).second )
199
- continue ;
200
-
201
- info.AllInherited .push_back (inheritedType);
202
- }
203
- }
204
- }
205
- }
206
-
207
- // / Recursively compute the 'depth' of a protocol, which is inductively defined
208
- // / as one greater than the depth of all inherited protocols, with a protocol
209
- // / that does not inherit any other protocol having a depth of one.
210
- unsigned ProtocolGraph::computeProtocolDepth (const ProtocolDecl *proto) {
211
- auto &info = Info[proto];
212
-
213
- if (info.Mark ) {
214
- // Already computed, or we have a cycle. Cycles are diagnosed
215
- // elsewhere in the type checker, so we don't have to do
216
- // anything here.
217
- return info.Depth ;
218
- }
219
-
220
- info.Mark = true ;
221
- unsigned depth = 0 ;
222
-
223
- for (auto *inherited : info.Inherited ) {
224
- unsigned inheritedDepth = computeProtocolDepth (inherited);
225
- depth = std::max (inheritedDepth, depth);
226
- }
227
-
228
- depth++;
229
-
230
- info.Depth = depth;
231
- return depth;
232
- }
233
-
234
- // / Compute everything in the right order.
235
- void ProtocolGraph::compute () {
236
- computeTransitiveClosure ();
237
- computeLinearOrder ();
238
- computeInheritedProtocols ();
239
- computeInheritedAssociatedTypes ();
240
- }
241
-
242
- // / Defines a linear order with the property that if a protocol P inherits
243
- // / from another protocol Q, then P < Q. (The converse cannot be true, since
244
- // / this is a linear order.)
245
- // /
246
- // / We first compare the 'support' of a protocol, which is defined in
247
- // / ProtocolGraph::getProtocolSupport() above.
248
- // /
249
- // / If two protocols have the same support, the tie is broken by the standard
250
- // / TypeDecl::compare().
251
- int ProtocolGraph::compareProtocols (const ProtocolDecl *lhs,
252
- const ProtocolDecl *rhs) const {
253
- unsigned lhsSupport = getProtocolSupport (lhs);
254
- unsigned rhsSupport = getProtocolSupport (rhs);
255
-
256
- if (lhsSupport != rhsSupport)
257
- return rhsSupport - lhsSupport;
258
-
259
- return TypeDecl::compare (lhs, rhs);
260
- }
261
-
262
- // / Returns if \p thisProto transitively inherits from \p otherProto.
263
- // /
264
- // / The result is false if the two protocols are equal.
265
- bool ProtocolGraph::inheritsFrom (const ProtocolDecl *thisProto,
266
- const ProtocolDecl *otherProto) const {
267
- const auto &info = getProtocolInfo (thisProto);
268
- return std::find (info.AllInherited .begin (),
269
- info.AllInherited .end (),
270
- otherProto) != info.AllInherited .end ();
271
- }
66
+ }
0 commit comments