Skip to content

Commit b317a5c

Browse files
committed
RequirementMachine: Verify homotopy generators
1 parent a75327e commit b317a5c

File tree

3 files changed

+73
-22
lines changed

3 files changed

+73
-22
lines changed

lib/AST/RequirementMachine/RequirementMachine.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,8 @@ void RequirementMachine::computeCompletion() {
413413
checkCompletionResult();
414414

415415
// Check invariants.
416-
System.verify();
416+
System.verifyRewriteRules();
417+
System.verifyHomotopyGenerators();
417418

418419
// Build the property map, which also performs concrete term
419420
// unification; if this added any new rules, run the completion

lib/AST/RequirementMachine/RewriteSystem.cpp

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,38 +36,49 @@ void RewritePath::invert() {
3636
step.invert();
3737
}
3838

39-
/// Dumps the rewrite step that was applied to \p term. Mutates \p term to
40-
/// reflect the application of the rule.
41-
void RewriteStep::dump(llvm::raw_ostream &out,
42-
MutableTerm &term,
43-
const RewriteSystem &system) const {
39+
AppliedRewriteStep RewriteStep::apply(MutableTerm &term,
40+
const RewriteSystem &system) const {
4441
const auto &rule = system.getRule(RuleID);
4542

4643
auto lhs = (Inverse ? rule.getRHS() : rule.getLHS());
4744
auto rhs = (Inverse ? rule.getLHS() : rule.getRHS());
4845

49-
assert(std::equal(term.begin() + Offset,
50-
term.begin() + Offset + lhs.size(),
51-
lhs.begin()));
46+
if (!std::equal(term.begin() + Offset,
47+
term.begin() + Offset + lhs.size(),
48+
lhs.begin())) {
49+
llvm::errs() << "Invalid rewrite path\n";
50+
llvm::errs() << "- Term: " << term << "\n";
51+
llvm::errs() << "- Offset: " << Offset << "\n";
52+
llvm::errs() << "- Expected subterm: " << lhs << "\n";
53+
abort();
54+
}
5255

5356
MutableTerm prefix(term.begin(), term.begin() + Offset);
5457
MutableTerm suffix(term.begin() + Offset + lhs.size(), term.end());
5558

56-
if (!prefix.empty()) {
57-
out << prefix;
59+
term = prefix;
60+
term.append(rhs);
61+
term.append(suffix);
62+
63+
return {lhs, rhs, prefix, suffix};
64+
}
65+
66+
/// Dumps the rewrite step that was applied to \p term. Mutates \p term to
67+
/// reflect the application of the rule.
68+
void RewriteStep::dump(llvm::raw_ostream &out,
69+
MutableTerm &term,
70+
const RewriteSystem &system) const {
71+
auto result = apply(term, system);
72+
73+
if (!result.prefix.empty()) {
74+
out << result.prefix;
5875
out << ".";
5976
}
60-
out << "(" << rule.getLHS();
61-
out << (Inverse ? " <= " : " => ");
62-
out << rule.getRHS() << ")";
63-
if (!suffix.empty()) {
77+
out << "(" << result.lhs << " => " << result.rhs << ")";
78+
if (!result.suffix.empty()) {
6479
out << ".";
65-
out << suffix;
80+
out << result.suffix;
6681
}
67-
68-
term = prefix;
69-
term.append(rhs);
70-
term.append(suffix);
7182
}
7283

7384
/// Dumps a series of rewrite steps applied to \p term.
@@ -377,7 +388,7 @@ void RewriteSystem::simplifyRewriteSystem() {
377388
}
378389
}
379390

380-
void RewriteSystem::verify() const {
391+
void RewriteSystem::verifyRewriteRules() const {
381392
#ifndef NDEBUG
382393

383394
#define ASSERT_RULE(expr) \
@@ -439,6 +450,25 @@ void RewriteSystem::verify() const {
439450
#endif
440451
}
441452

453+
void RewriteSystem::verifyHomotopyGenerators() const {
454+
#ifndef NDEBUG
455+
for (const auto &loop : HomotopyGenerators) {
456+
auto term = loop.first;
457+
458+
for (const auto &step : loop.second) {
459+
(void) step.apply(term, *this);
460+
}
461+
462+
if (term != loop.first) {
463+
llvm::errs() << "Not a loop: ";
464+
loop.second.dump(llvm::errs(), loop.first, *this);
465+
llvm::errs() << "\n";
466+
abort();
467+
}
468+
}
469+
#endif
470+
}
471+
442472
void RewriteSystem::dump(llvm::raw_ostream &out) const {
443473
out << "Rewrite system: {\n";
444474
for (const auto &rule : Rules) {

lib/AST/RequirementMachine/RewriteSystem.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,22 @@ class Rule final {
7979
}
8080
};
8181

82+
struct AppliedRewriteStep {
83+
Term lhs;
84+
Term rhs;
85+
MutableTerm prefix;
86+
MutableTerm suffix;
87+
};
88+
8289
/// Records the application of a rewrite rule to a term.
90+
///
91+
/// Formally, this is a whiskered, oriented rewrite rule. For example, given a
92+
/// rule (X => Y) and the term A.X.B, the application at offset 1 yields A.Y.B.
93+
///
94+
/// This can be represented as A.(X => Y).B.
95+
///
96+
/// Similarly, going in the other direction, if we start from A.Y.B and apply
97+
/// the inverse rule, we get A.(Y => X).B.
8398
struct RewriteStep {
8499
/// The position within the term where the rule is being applied.
85100
unsigned Offset : 16;
@@ -103,6 +118,9 @@ struct RewriteStep {
103118
Inverse = !Inverse;
104119
}
105120

121+
AppliedRewriteStep apply(MutableTerm &term,
122+
const RewriteSystem &system) const;
123+
106124
void dump(llvm::raw_ostream &out,
107125
MutableTerm &term,
108126
const RewriteSystem &system) const;
@@ -244,7 +262,9 @@ class RewriteSystem final {
244262

245263
void simplifyRewriteSystem();
246264

247-
void verify() const;
265+
void verifyRewriteRules() const;
266+
267+
void verifyHomotopyGenerators() const;
248268

249269
std::pair<CompletionResult, unsigned>
250270
buildPropertyMap(PropertyMap &map,

0 commit comments

Comments
 (0)