|
61 | 61 | using namespace swift;
|
62 | 62 | using namespace rewriting;
|
63 | 63 |
|
64 |
| -void RewritePathEvaluator::dump(llvm::raw_ostream &out) const { |
65 |
| - out << "A stack:\n"; |
66 |
| - for (const auto &term : A) { |
67 |
| - out << term << "\n"; |
68 |
| - } |
69 |
| - out << "\nB stack:\n"; |
70 |
| - for (const auto &term : B) { |
71 |
| - out << term << "\n"; |
72 |
| - } |
73 |
| -} |
74 |
| - |
75 |
| -void RewritePathEvaluator::checkA() const { |
76 |
| - if (A.empty()) { |
77 |
| - llvm::errs() << "Empty A stack\n"; |
78 |
| - dump(llvm::errs()); |
79 |
| - abort(); |
80 |
| - } |
81 |
| -} |
82 |
| - |
83 |
| -void RewritePathEvaluator::checkB() const { |
84 |
| - if (B.empty()) { |
85 |
| - llvm::errs() << "Empty B stack\n"; |
86 |
| - dump(llvm::errs()); |
87 |
| - abort(); |
88 |
| - } |
89 |
| -} |
90 |
| - |
91 |
| -MutableTerm &RewritePathEvaluator::getCurrentTerm() { |
92 |
| - checkA(); |
93 |
| - return A.back(); |
94 |
| -} |
95 |
| - |
96 |
| -/// Invert a rewrite path, producing a path that rewrites the original path's |
97 |
| -/// destination back to the original path's source. |
98 |
| -void RewritePath::invert() { |
99 |
| - std::reverse(Steps.begin(), Steps.end()); |
100 |
| - |
101 |
| - for (auto &step : Steps) |
102 |
| - step.invert(); |
103 |
| -} |
104 |
| - |
105 |
| -AppliedRewriteStep |
106 |
| -RewriteStep::applyRewriteRule(RewritePathEvaluator &evaluator, |
107 |
| - const RewriteSystem &system) const { |
108 |
| - auto &term = evaluator.getCurrentTerm(); |
109 |
| - |
110 |
| - assert(Kind == ApplyRewriteRule); |
111 |
| - |
112 |
| - const auto &rule = system.getRule(RuleID); |
113 |
| - |
114 |
| - auto lhs = (Inverse ? rule.getRHS() : rule.getLHS()); |
115 |
| - auto rhs = (Inverse ? rule.getLHS() : rule.getRHS()); |
116 |
| - |
117 |
| - auto bug = [&](StringRef msg) { |
118 |
| - llvm::errs() << msg << "\n"; |
119 |
| - llvm::errs() << "- Term: " << term << "\n"; |
120 |
| - llvm::errs() << "- StartOffset: " << StartOffset << "\n"; |
121 |
| - llvm::errs() << "- EndOffset: " << EndOffset << "\n"; |
122 |
| - llvm::errs() << "- Expected subterm: " << lhs << "\n"; |
123 |
| - abort(); |
124 |
| - }; |
125 |
| - |
126 |
| - if (term.size() != StartOffset + lhs.size() + EndOffset) { |
127 |
| - bug("Invalid whiskering"); |
128 |
| - } |
129 |
| - |
130 |
| - if (!std::equal(term.begin() + StartOffset, |
131 |
| - term.begin() + StartOffset + lhs.size(), |
132 |
| - lhs.begin())) { |
133 |
| - bug("Invalid subterm"); |
134 |
| - } |
135 |
| - |
136 |
| - MutableTerm prefix(term.begin(), term.begin() + StartOffset); |
137 |
| - MutableTerm suffix(term.end() - EndOffset, term.end()); |
138 |
| - |
139 |
| - term = prefix; |
140 |
| - term.append(rhs); |
141 |
| - term.append(suffix); |
142 |
| - |
143 |
| - return {lhs, rhs, prefix, suffix}; |
144 |
| -} |
145 |
| - |
146 |
| -MutableTerm RewriteStep::applyAdjustment(RewritePathEvaluator &evaluator, |
147 |
| - const RewriteSystem &system) const { |
148 |
| - auto &term = evaluator.getCurrentTerm(); |
149 |
| - |
150 |
| - assert(Kind == AdjustConcreteType); |
151 |
| - assert(EndOffset == 0); |
152 |
| - assert(RuleID == 0); |
153 |
| - |
154 |
| - auto &ctx = system.getRewriteContext(); |
155 |
| - MutableTerm prefix(term.begin(), term.begin() + StartOffset); |
156 |
| - |
157 |
| - // We're either adding or removing the prefix to each concrete substitution. |
158 |
| - term.back() = term.back().transformConcreteSubstitutions( |
159 |
| - [&](Term t) -> Term { |
160 |
| - if (Inverse) { |
161 |
| - if (!std::equal(t.begin(), |
162 |
| - t.begin() + StartOffset, |
163 |
| - prefix.begin())) { |
164 |
| - llvm::errs() << "Invalid rewrite path\n"; |
165 |
| - llvm::errs() << "- Term: " << term << "\n"; |
166 |
| - llvm::errs() << "- Start offset: " << StartOffset << "\n"; |
167 |
| - llvm::errs() << "- Expected subterm: " << prefix << "\n"; |
168 |
| - abort(); |
169 |
| - } |
170 |
| - |
171 |
| - MutableTerm mutTerm(t.begin() + StartOffset, t.end()); |
172 |
| - return Term::get(mutTerm, ctx); |
173 |
| - } else { |
174 |
| - MutableTerm mutTerm(prefix); |
175 |
| - mutTerm.append(t); |
176 |
| - return Term::get(mutTerm, ctx); |
177 |
| - } |
178 |
| - }, ctx); |
179 |
| - |
180 |
| - return prefix; |
181 |
| -} |
182 |
| - |
183 |
| -void RewriteStep::applyShift(RewritePathEvaluator &evaluator, |
184 |
| - const RewriteSystem &system) const { |
185 |
| - assert(Kind == Shift); |
186 |
| - assert(StartOffset == 0); |
187 |
| - assert(EndOffset == 0); |
188 |
| - assert(RuleID == 0); |
189 |
| - |
190 |
| - if (!Inverse) { |
191 |
| - // Move top of A stack to B stack. |
192 |
| - evaluator.checkA(); |
193 |
| - evaluator.B.push_back(evaluator.A.back()); |
194 |
| - evaluator.A.pop_back(); |
195 |
| - } else { |
196 |
| - // Move top of B stack to A stack. |
197 |
| - evaluator.checkB(); |
198 |
| - evaluator.A.push_back(evaluator.B.back()); |
199 |
| - evaluator.B.pop_back(); |
200 |
| - } |
201 |
| -} |
202 |
| - |
203 |
| -void RewriteStep::applyDecompose(RewritePathEvaluator &evaluator, |
204 |
| - const RewriteSystem &system) const { |
205 |
| - assert(Kind == Decompose); |
206 |
| - assert(StartOffset == 0); |
207 |
| - assert(EndOffset == 0); |
208 |
| - |
209 |
| - auto &ctx = system.getRewriteContext(); |
210 |
| - unsigned numSubstitutions = RuleID; |
211 |
| - |
212 |
| - if (!Inverse) { |
213 |
| - // The top of the A stack must be a term ending with a superclass or |
214 |
| - // concrete type symbol. |
215 |
| - const auto &term = evaluator.getCurrentTerm(); |
216 |
| - auto symbol = term.back(); |
217 |
| - if (!symbol.isSuperclassOrConcreteType()) { |
218 |
| - llvm::errs() << "Expected term with superclass or concrete type symbol" |
219 |
| - << " on A stack\n"; |
220 |
| - evaluator.dump(llvm::errs()); |
221 |
| - abort(); |
222 |
| - } |
223 |
| - |
224 |
| - // The symbol must have the expected number of substitutions. |
225 |
| - if (symbol.getSubstitutions().size() != numSubstitutions) { |
226 |
| - llvm::errs() << "Expected " << numSubstitutions << " substitutions\n"; |
227 |
| - evaluator.dump(llvm::errs()); |
228 |
| - abort(); |
229 |
| - } |
230 |
| - |
231 |
| - // Push each substitution on the A stack. |
232 |
| - for (auto substitution : symbol.getSubstitutions()) { |
233 |
| - evaluator.A.push_back(MutableTerm(substitution)); |
234 |
| - } |
235 |
| - } else { |
236 |
| - // The A stack must store the number of substitutions, together with a |
237 |
| - // term ending with a superclass or concrete type symbol. |
238 |
| - if (evaluator.A.size() < numSubstitutions + 1) { |
239 |
| - llvm::errs() << "Not enough terms on A stack\n"; |
240 |
| - evaluator.dump(llvm::errs()); |
241 |
| - abort(); |
242 |
| - } |
243 |
| - |
244 |
| - // The term immediately underneath the substitutions is the one we're |
245 |
| - // updating with new substitutions. |
246 |
| - auto &term = *(evaluator.A.end() - numSubstitutions - 1); |
247 |
| - auto symbol = term.back(); |
248 |
| - if (!symbol.isSuperclassOrConcreteType()) { |
249 |
| - llvm::errs() << "Expected term with superclass or concrete type symbol" |
250 |
| - << " on A stack\n"; |
251 |
| - evaluator.dump(llvm::errs()); |
252 |
| - abort(); |
253 |
| - } |
254 |
| - |
255 |
| - // The symbol at the end of this term must have the expected number of |
256 |
| - // substitutions. |
257 |
| - if (symbol.getSubstitutions().size() != numSubstitutions) { |
258 |
| - llvm::errs() << "Expected " << numSubstitutions << " substitutions\n"; |
259 |
| - evaluator.dump(llvm::errs()); |
260 |
| - abort(); |
261 |
| - } |
262 |
| - |
263 |
| - // Collect the substitutions from the A stack. |
264 |
| - SmallVector<Term, 2> substitutions; |
265 |
| - substitutions.reserve(numSubstitutions); |
266 |
| - for (unsigned i = 0; i < numSubstitutions; ++i) { |
267 |
| - const auto &substitution = *(evaluator.A.end() - numSubstitutions + i); |
268 |
| - substitutions.push_back(Term::get(substitution, ctx)); |
269 |
| - } |
270 |
| - |
271 |
| - // Build the new symbol with the new substitutions. |
272 |
| - auto newSymbol = (symbol.getKind() == Symbol::Kind::Superclass |
273 |
| - ? Symbol::forSuperclass(symbol.getSuperclass(), |
274 |
| - substitutions, ctx) |
275 |
| - : Symbol::forConcreteType(symbol.getConcreteType(), |
276 |
| - substitutions, ctx)); |
277 |
| - |
278 |
| - // Update the term with the new symbol. |
279 |
| - term.back() = newSymbol; |
280 |
| - |
281 |
| - // Pop the substitutions from the A stack. |
282 |
| - evaluator.A.resize(evaluator.A.size() - numSubstitutions); |
283 |
| - } |
284 |
| -} |
285 |
| - |
286 |
| -void RewriteStep::apply(RewritePathEvaluator &evaluator, |
287 |
| - const RewriteSystem &system) const { |
288 |
| - switch (Kind) { |
289 |
| - case ApplyRewriteRule: |
290 |
| - (void) applyRewriteRule(evaluator, system); |
291 |
| - break; |
292 |
| - |
293 |
| - case AdjustConcreteType: |
294 |
| - (void) applyAdjustment(evaluator, system); |
295 |
| - break; |
296 |
| - |
297 |
| - case Shift: |
298 |
| - applyShift(evaluator, system); |
299 |
| - break; |
300 |
| - |
301 |
| - case Decompose: |
302 |
| - applyDecompose(evaluator, system); |
303 |
| - break; |
304 |
| - } |
305 |
| -} |
306 |
| - |
307 |
| -/// Dumps the rewrite step that was applied to \p term. Mutates \p term to |
308 |
| -/// reflect the application of the rule. |
309 |
| -void RewriteStep::dump(llvm::raw_ostream &out, |
310 |
| - RewritePathEvaluator &evaluator, |
311 |
| - const RewriteSystem &system) const { |
312 |
| - switch (Kind) { |
313 |
| - case ApplyRewriteRule: { |
314 |
| - auto result = applyRewriteRule(evaluator, system); |
315 |
| - |
316 |
| - if (!result.prefix.empty()) { |
317 |
| - out << result.prefix; |
318 |
| - out << "."; |
319 |
| - } |
320 |
| - out << "(" << result.lhs << " => " << result.rhs << ")"; |
321 |
| - if (!result.suffix.empty()) { |
322 |
| - out << "."; |
323 |
| - out << result.suffix; |
324 |
| - } |
325 |
| - |
326 |
| - break; |
327 |
| - } |
328 |
| - case AdjustConcreteType: { |
329 |
| - auto result = applyAdjustment(evaluator, system); |
330 |
| - |
331 |
| - out << "(σ"; |
332 |
| - out << (Inverse ? " - " : " + "); |
333 |
| - out << result << ")"; |
334 |
| - |
335 |
| - break; |
336 |
| - } |
337 |
| - case Shift: { |
338 |
| - applyShift(evaluator, system); |
339 |
| - |
340 |
| - out << (Inverse ? "B>A" : "A>B"); |
341 |
| - break; |
342 |
| - } |
343 |
| - case Decompose: { |
344 |
| - applyDecompose(evaluator, system); |
345 |
| - |
346 |
| - out << (Inverse ? "Compose(" : "Decompose("); |
347 |
| - out << RuleID << ")"; |
348 |
| - break; |
349 |
| - } |
350 |
| - } |
351 |
| -} |
352 |
| - |
353 | 64 | /// A rewrite rule is redundant if it appears exactly once in a loop
|
354 | 65 | /// without context.
|
355 | 66 | llvm::SmallVector<unsigned, 1>
|
@@ -699,24 +410,6 @@ bool RewritePath::computeLeftCanonicalForm(const RewriteSystem &system) {
|
699 | 410 | return changed;
|
700 | 411 | }
|
701 | 412 |
|
702 |
| -/// Dumps a series of rewrite steps applied to \p term. |
703 |
| -void RewritePath::dump(llvm::raw_ostream &out, |
704 |
| - MutableTerm term, |
705 |
| - const RewriteSystem &system) const { |
706 |
| - RewritePathEvaluator evaluator(term); |
707 |
| - bool first = true; |
708 |
| - |
709 |
| - for (const auto &step : Steps) { |
710 |
| - if (!first) { |
711 |
| - out << " ⊗ "; |
712 |
| - } else { |
713 |
| - first = false; |
714 |
| - } |
715 |
| - |
716 |
| - step.dump(out, evaluator, system); |
717 |
| - } |
718 |
| -} |
719 |
| - |
720 | 413 | /// Compute cyclically-reduced left-canonical normal form of a loop.
|
721 | 414 | void RewriteLoop::normalize(const RewriteSystem &system) {
|
722 | 415 | // FIXME: This can be more efficient.
|
@@ -760,14 +453,6 @@ bool RewriteLoop::isInContext(const RewriteSystem &system) const {
|
760 | 453 | return (minStartOffset > 0 || minEndOffset > 0);
|
761 | 454 | }
|
762 | 455 |
|
763 |
| -void RewriteLoop::dump(llvm::raw_ostream &out, |
764 |
| - const RewriteSystem &system) const { |
765 |
| - out << Basepoint << ": "; |
766 |
| - Path.dump(out, Basepoint, system); |
767 |
| - if (isDeleted()) |
768 |
| - out << " [deleted]"; |
769 |
| -} |
770 |
| - |
771 | 456 | /// Check if a rewrite rule is a candidate for deletion in this pass of the
|
772 | 457 | /// minimization algorithm.
|
773 | 458 | bool RewriteSystem::
|
|
0 commit comments