23
23
using namespace swift ;
24
24
using namespace rewriting ;
25
25
26
+ void Rule::dump (llvm::raw_ostream &out) const {
27
+ out << LHS << " => " << RHS;
28
+ if (deleted)
29
+ out << " [deleted]" ;
30
+ }
31
+
32
+ void RewritePath::invert () {
33
+ std::reverse (Steps.begin (), Steps.end ());
34
+
35
+ for (auto &step : Steps)
36
+ step.invert ();
37
+ }
38
+
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 {
44
+ const auto &rule = system.getRule (RuleID);
45
+
46
+ auto lhs = (Inverse ? rule.getRHS () : rule.getLHS ());
47
+ auto rhs = (Inverse ? rule.getLHS () : rule.getRHS ());
48
+
49
+ assert (std::equal (term.begin () + Offset,
50
+ term.begin () + Offset + lhs.size (),
51
+ lhs.begin ()));
52
+
53
+ MutableTerm prefix (term.begin (), term.begin () + Offset);
54
+ MutableTerm suffix (term.begin () + Offset + lhs.size (), term.end ());
55
+
56
+ if (!prefix.empty ()) {
57
+ out << prefix;
58
+ out << " ." ;
59
+ }
60
+ out << " (" << rule.getLHS ();
61
+ out << (Inverse ? " <= " : " => " );
62
+ out << rule.getRHS () << " )" ;
63
+ if (!suffix.empty ()) {
64
+ out << " ." ;
65
+ out << suffix;
66
+ }
67
+
68
+ term = prefix;
69
+ term.append (rhs);
70
+ term.append (suffix);
71
+ }
72
+
73
+ // / Dumps a series of rewrite steps applied to \p term.
74
+ void RewritePath::dump (llvm::raw_ostream &out,
75
+ MutableTerm term,
76
+ const RewriteSystem &system) const {
77
+ bool first = true ;
78
+
79
+ for (const auto &step : Steps) {
80
+ if (!first) {
81
+ out << " ⊗ " ;
82
+ } else {
83
+ first = false ;
84
+ }
85
+
86
+ step.dump (out, term, system);
87
+ }
88
+ }
89
+
26
90
RewriteSystem::RewriteSystem (RewriteContext &ctx)
27
91
: Context(ctx), Debug(ctx.getDebugOptions()) {}
28
92
@@ -31,12 +95,6 @@ RewriteSystem::~RewriteSystem() {
31
95
Context.RuleTrieRootHistogram );
32
96
}
33
97
34
- void Rule::dump (llvm::raw_ostream &out) const {
35
- out << LHS << " => " << RHS;
36
- if (deleted)
37
- out << " [deleted]" ;
38
- }
39
-
40
98
void RewriteSystem::initialize (
41
99
std::vector<std::pair<MutableTerm, MutableTerm>> &&rules,
42
100
ProtocolGraph &&graph) {
@@ -89,16 +147,16 @@ bool RewriteSystem::addRule(MutableTerm lhs, MutableTerm rhs) {
89
147
llvm::dbgs () << " ## Simplified and oriented rule " << lhs << " => " << rhs << " \n\n " ;
90
148
}
91
149
92
- unsigned i = Rules.size ();
150
+ unsigned newRuleID = Rules.size ();
93
151
94
152
auto uniquedLHS = Term::get (lhs, Context);
95
153
auto uniquedRHS = Term::get (rhs, Context);
96
154
Rules.emplace_back (uniquedLHS, uniquedRHS);
97
155
98
- auto oldRuleID = Trie.insert (lhs.begin (), lhs.end (), i );
156
+ auto oldRuleID = Trie.insert (lhs.begin (), lhs.end (), newRuleID );
99
157
if (oldRuleID) {
100
158
llvm::errs () << " Duplicate rewrite rule!\n " ;
101
- const auto &oldRule = Rules[ *oldRuleID] ;
159
+ const auto &oldRule = getRule ( *oldRuleID) ;
102
160
llvm::errs () << " Old rule #" << *oldRuleID << " : " ;
103
161
oldRule.dump (llvm::errs ());
104
162
llvm::errs () << " \n Trying to replay what happened when I simplified this term:\n " ;
@@ -116,11 +174,18 @@ bool RewriteSystem::addRule(MutableTerm lhs, MutableTerm rhs) {
116
174
}
117
175
118
176
// / Reduce a term by applying all rewrite rules until fixed point.
119
- bool RewriteSystem::simplify (MutableTerm &term) const {
177
+ // /
178
+ // / If \p path is non-null, records the series of rewrite steps taken.
179
+ bool RewriteSystem::simplify (MutableTerm &term, RewritePath *path) const {
120
180
bool changed = false ;
121
181
182
+ MutableTerm original;
183
+ RewritePath forDebug;
122
184
if (Debug.contains (DebugFlags::Simplify)) {
123
- llvm::dbgs () << " = Term " << term << " \n " ;
185
+
186
+ original = term;
187
+ if (!path)
188
+ path = &forDebug;
124
189
}
125
190
126
191
while (true ) {
@@ -131,19 +196,16 @@ bool RewriteSystem::simplify(MutableTerm &term) const {
131
196
while (from < end) {
132
197
auto ruleID = Trie.find (from, end);
133
198
if (ruleID) {
134
- const auto &rule = Rules[ *ruleID] ;
199
+ const auto &rule = getRule ( *ruleID) ;
135
200
if (!rule.isDeleted ()) {
136
- if (Debug.contains (DebugFlags::Simplify)) {
137
- llvm::dbgs () << " == Rule #" << *ruleID << " : " << rule << " \n " ;
138
- }
139
-
140
201
auto to = from + rule.getLHS ().size ();
141
202
assert (std::equal (from, to, rule.getLHS ().begin ()));
142
203
143
204
term.rewriteSubTerm (from, to, rule.getRHS ());
144
205
145
- if (Debug.contains (DebugFlags::Simplify)) {
146
- llvm::dbgs () << " === Result " << term << " \n " ;
206
+ if (path) {
207
+ unsigned offset = (unsigned )(from - term.begin ());
208
+ path->add (RewriteStep (offset, *ruleID, /* inverse=*/ false ));
147
209
}
148
210
149
211
changed = true ;
@@ -159,6 +221,17 @@ bool RewriteSystem::simplify(MutableTerm &term) const {
159
221
break ;
160
222
}
161
223
224
+ if (Debug.contains (DebugFlags::Simplify)) {
225
+ if (changed) {
226
+ llvm::dbgs () << " = Simplified " << term << " : " ;
227
+ forDebug.dump (llvm::dbgs (), original, *this );
228
+ llvm::dbgs () << " \n " ;
229
+ } else {
230
+ llvm::dbgs () << " = Irreducible term: " << term << " \n " ;
231
+ }
232
+ }
233
+
234
+ assert (path == nullptr || changed != path->empty ());
162
235
return changed;
163
236
}
164
237
@@ -170,7 +243,7 @@ bool RewriteSystem::simplify(MutableTerm &term) const {
170
243
// / rules is only valid to perform if the rewrite system is confluent.
171
244
void RewriteSystem::simplifyRewriteSystem () {
172
245
for (auto ruleID : indices (Rules)) {
173
- auto &rule = Rules[ ruleID] ;
246
+ auto &rule = getRule ( ruleID) ;
174
247
if (rule.isDeleted ())
175
248
continue ;
176
249
@@ -186,11 +259,11 @@ void RewriteSystem::simplifyRewriteSystem() {
186
259
continue ;
187
260
188
261
// Ignore other deleted rules.
189
- if (Rules[ *otherRuleID] .isDeleted ())
262
+ if (getRule ( *otherRuleID) .isDeleted ())
190
263
continue ;
191
264
192
265
if (Debug.contains (DebugFlags::Completion)) {
193
- const auto &otherRule = Rules[ ruleID] ;
266
+ const auto &otherRule = getRule ( ruleID) ;
194
267
llvm::dbgs () << " $ Deleting rule " << rule << " because "
195
268
<< " its left hand side contains " << otherRule
196
269
<< " \n " ;
0 commit comments