@@ -40,11 +40,14 @@ void RewriteStep::dump(llvm::raw_ostream &out,
40
40
break ;
41
41
}
42
42
case AdjustConcreteType: {
43
- auto result = evaluator.applyAdjustment (*this , system);
43
+ auto pair = evaluator.applyAdjustment (*this , system);
44
44
45
45
out << " (σ" ;
46
46
out << (Inverse ? " - " : " + " );
47
- out << result << " )" ;
47
+ out << pair.first << " )" ;
48
+
49
+ if (!pair.second .empty ())
50
+ out << " ." << pair.second ;
48
51
49
52
break ;
50
53
}
@@ -186,7 +189,7 @@ RewritePathEvaluator::applyRewriteRule(const RewriteStep &step,
186
189
return {lhs, rhs, prefix, suffix};
187
190
}
188
191
189
- MutableTerm
192
+ std::pair< MutableTerm, MutableTerm>
190
193
RewritePathEvaluator::applyAdjustment (const RewriteStep &step,
191
194
const RewriteSystem &system) {
192
195
auto &term = getCurrentTerm ();
@@ -196,9 +199,19 @@ RewritePathEvaluator::applyAdjustment(const RewriteStep &step,
196
199
auto &ctx = system.getRewriteContext ();
197
200
MutableTerm prefix (term.begin () + step.StartOffset ,
198
201
term.begin () + step.StartOffset + step.RuleID );
202
+ MutableTerm suffix (term.end () - step.EndOffset - 1 , term.end ());
199
203
200
204
// We're either adding or removing the prefix to each concrete substitution.
201
- term.back () = term.back ().transformConcreteSubstitutions (
205
+ Symbol &last = *(term.end () - step.EndOffset - 1 );
206
+ if (!last.hasSubstitutions ()) {
207
+ llvm::errs () << " Invalid rewrite path\n " ;
208
+ llvm::errs () << " - Term: " << term << " \n " ;
209
+ llvm::errs () << " - Start offset: " << step.StartOffset << " \n " ;
210
+ llvm::errs () << " - End offset: " << step.EndOffset << " \n " ;
211
+ abort ();
212
+ }
213
+
214
+ last = last.transformConcreteSubstitutions (
202
215
[&](Term t) -> Term {
203
216
if (step.Inverse ) {
204
217
if (!std::equal (t.begin (),
@@ -208,6 +221,7 @@ RewritePathEvaluator::applyAdjustment(const RewriteStep &step,
208
221
llvm::errs () << " - Term: " << term << " \n " ;
209
222
llvm::errs () << " - Substitution: " << t << " \n " ;
210
223
llvm::errs () << " - Start offset: " << step.StartOffset << " \n " ;
224
+ llvm::errs () << " - End offset: " << step.EndOffset << " \n " ;
211
225
llvm::errs () << " - Expected subterm: " << prefix << " \n " ;
212
226
abort ();
213
227
}
@@ -221,7 +235,7 @@ RewritePathEvaluator::applyAdjustment(const RewriteStep &step,
221
235
}
222
236
}, ctx);
223
237
224
- return prefix;
238
+ return std::make_pair ( prefix, suffix) ;
225
239
}
226
240
227
241
void RewritePathEvaluator::applyShift (const RewriteStep &step,
@@ -247,16 +261,15 @@ void RewritePathEvaluator::applyShift(const RewriteStep &step,
247
261
void RewritePathEvaluator::applyDecompose (const RewriteStep &step,
248
262
const RewriteSystem &system) {
249
263
assert (step.Kind == RewriteStep::Decompose);
250
- assert (step.EndOffset == 0 );
251
264
252
265
auto &ctx = system.getRewriteContext ();
253
266
unsigned numSubstitutions = step.RuleID ;
254
267
255
268
if (!step.Inverse ) {
256
- // The top of the A stack must be a term ending with a superclass or
257
- // concrete type symbol .
269
+ // The input term takes the form U.[concrete: C].V or U.[ superclass: C].V,
270
+ // where |V| == EndOffset .
258
271
const auto &term = getCurrentTerm ();
259
- auto symbol = term.back ( );
272
+ auto symbol = *( term.end () - step. EndOffset - 1 );
260
273
if (!symbol.hasSubstitutions ()) {
261
274
llvm::errs () << " Expected term with superclass or concrete type symbol"
262
275
<< " on A stack\n " ;
@@ -277,7 +290,8 @@ void RewritePathEvaluator::applyDecompose(const RewriteStep &step,
277
290
}
278
291
} else {
279
292
// The A stack must store the number of substitutions, together with a
280
- // term ending with a superclass or concrete type symbol.
293
+ // term that takes the form U.[concrete: C].V or U.[superclass: C].V,
294
+ // where |V| == EndOffset.
281
295
if (A.size () < numSubstitutions + 1 ) {
282
296
llvm::errs () << " Not enough terms on A stack\n " ;
283
297
dump (llvm::errs ());
@@ -287,7 +301,8 @@ void RewritePathEvaluator::applyDecompose(const RewriteStep &step,
287
301
// The term immediately underneath the substitutions is the one we're
288
302
// updating with new substitutions.
289
303
auto &term = *(A.end () - numSubstitutions - 1 );
290
- auto symbol = term.back ();
304
+
305
+ auto &symbol = *(term.end () - step.EndOffset - 1 );
291
306
if (!symbol.hasSubstitutions ()) {
292
307
llvm::errs () << " Expected term with superclass or concrete type symbol"
293
308
<< " on A stack\n " ;
@@ -312,7 +327,7 @@ void RewritePathEvaluator::applyDecompose(const RewriteStep &step,
312
327
}
313
328
314
329
// Build the new symbol with the new substitutions.
315
- term. back () = symbol.withConcreteSubstitutions (substitutions, ctx);
330
+ symbol = symbol.withConcreteSubstitutions (substitutions, ctx);
316
331
317
332
// Pop the substitutions from the A stack.
318
333
A.resize (A.size () - numSubstitutions);
@@ -324,16 +339,23 @@ RewritePathEvaluator::applyConcreteConformance(const RewriteStep &step,
324
339
const RewriteSystem &system) {
325
340
checkA ();
326
341
auto &term = A.back ();
342
+ Symbol *last = term.end () - step.EndOffset ;
327
343
328
344
auto &ctx = system.getRewriteContext ();
329
345
330
346
if (!step.Inverse ) {
331
- assert (term.size () > 2 );
332
- auto concreteType = *(term.end () - 2 );
333
- auto proto = *(term.end () - 1 );
347
+ // The input term takes one of the following forms, where |V| == EndOffset:
348
+ // - U.[concrete: C].[P].V
349
+ // - U.[superclass: C].[P].V
350
+ assert (term.size () > step.EndOffset + 2 );
351
+ auto concreteType = *(last - 2 );
352
+ auto proto = *(last - 1 );
334
353
assert (proto.getKind () == Symbol::Kind::Protocol);
335
354
336
- MutableTerm newTerm (term.begin (), term.end () - 2 );
355
+ // Get the prefix U.
356
+ MutableTerm newTerm (term.begin (), last - 2 );
357
+
358
+ // Build the term U.[concrete: C : P].
337
359
if (step.Kind == RewriteStep::ConcreteConformance) {
338
360
assert (concreteType.getKind () == Symbol::Kind::ConcreteType);
339
361
@@ -353,14 +375,21 @@ RewritePathEvaluator::applyConcreteConformance(const RewriteStep &step,
353
375
ctx));
354
376
}
355
377
378
+ // Add the suffix V to get the final term U.[concrete: C : P].V.
379
+ newTerm.append (last, term.end ());
356
380
term = newTerm;
357
381
} else {
358
- assert (term.size () > 1 );
359
- auto concreteConformance = term.back ();
382
+ // The input term takes the form U.[concrete: C : P].V, where
383
+ // |V| == EndOffset.
384
+ assert (term.size () > step.EndOffset + 1 );
385
+ auto concreteConformance = *(last - 1 );
360
386
assert (concreteConformance.getKind () == Symbol::Kind::ConcreteConformance);
361
387
362
- MutableTerm newTerm (term.begin (), term.end () - 1 );
388
+ // Build the term U.
389
+ MutableTerm newTerm (term.begin (), last - 1 );
363
390
391
+ // Add the symbol [concrete: C] or [superclass: C] to get the term
392
+ // U.[concrete: C] or U.[superclass: C].
364
393
if (step.Kind == RewriteStep::ConcreteConformance) {
365
394
newTerm.add (Symbol::forConcreteType (
366
395
concreteConformance.getConcreteType (),
@@ -374,10 +403,15 @@ RewritePathEvaluator::applyConcreteConformance(const RewriteStep &step,
374
403
ctx));
375
404
}
376
405
406
+ // Add the symbol [P] to get the term U.[concrete: C].[P] or
407
+ // U.[superclass: C].[P].
377
408
newTerm.add (Symbol::forProtocol (
378
409
concreteConformance.getProtocol (),
379
410
ctx));
380
411
412
+ // Add the suffix V to get the final term U.[concrete: C].[P].V or
413
+ // U.[superclass: C].[P].V.
414
+ newTerm.append (last, term.end ());
381
415
term = newTerm;
382
416
}
383
417
}
0 commit comments