Skip to content

Commit 450c7c2

Browse files
committed
RequirementMachine: Split off RewriteLoop.cpp from HomotopyReduction.cpp
1 parent 1057b56 commit 450c7c2

File tree

5 files changed

+646
-586
lines changed

5 files changed

+646
-586
lines changed

lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ add_swift_host_library(swiftAST STATIC
8282
RequirementMachine/RequirementMachine.cpp
8383
RequirementMachine/RequirementMachineRequests.cpp
8484
RequirementMachine/RewriteContext.cpp
85+
RequirementMachine/RewriteLoop.cpp
8586
RequirementMachine/RewriteSystem.cpp
8687
RequirementMachine/RewriteSystemCompletion.cpp
8788
RequirementMachine/Symbol.cpp

lib/AST/RequirementMachine/HomotopyReduction.cpp

Lines changed: 0 additions & 315 deletions
Original file line numberDiff line numberDiff line change
@@ -61,295 +61,6 @@
6161
using namespace swift;
6262
using namespace rewriting;
6363

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-
35364
/// A rewrite rule is redundant if it appears exactly once in a loop
35465
/// without context.
35566
llvm::SmallVector<unsigned, 1>
@@ -699,24 +410,6 @@ bool RewritePath::computeLeftCanonicalForm(const RewriteSystem &system) {
699410
return changed;
700411
}
701412

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-
720413
/// Compute cyclically-reduced left-canonical normal form of a loop.
721414
void RewriteLoop::normalize(const RewriteSystem &system) {
722415
// FIXME: This can be more efficient.
@@ -760,14 +453,6 @@ bool RewriteLoop::isInContext(const RewriteSystem &system) const {
760453
return (minStartOffset > 0 || minEndOffset > 0);
761454
}
762455

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-
771456
/// Check if a rewrite rule is a candidate for deletion in this pass of the
772457
/// minimization algorithm.
773458
bool RewriteSystem::

0 commit comments

Comments
 (0)