@@ -251,14 +251,13 @@ bool RewriteSystem::simplify(MutableTerm &term, RewritePath *path) const {
251251
252252// / Simplify terms appearing in the substitutions of the last symbol of \p term,
253253// / which must be a superclass or concrete type symbol.
254- void RewriteSystem::simplifySubstitutions (MutableTerm &term ,
254+ bool RewriteSystem::simplifySubstitutions (Symbol &symbol ,
255255 RewritePath &path) const {
256- auto symbol = term.back ();
257256 assert (symbol.hasSubstitutions ());
258257
259258 auto substitutions = symbol.getSubstitutions ();
260259 if (substitutions.empty ())
261- return ;
260+ return false ;
262261
263262 // Save the original rewrite path length so that we can reset if if we don't
264263 // find anything to simplify.
@@ -307,11 +306,12 @@ void RewriteSystem::simplifySubstitutions(MutableTerm &term,
307306#endif
308307
309308 path.resize (oldSize);
310- return ;
309+ return false ;
311310 }
312311
313312 // Build the new symbol with simplified substitutions.
314- term.back () = symbol.withConcreteSubstitutions (newSubstitutions, Context);
313+ symbol = symbol.withConcreteSubstitutions (newSubstitutions, Context);
314+ return true ;
315315}
316316
317317// / Adds a rewrite rule, returning true if the new rule was non-trivial.
@@ -341,12 +341,6 @@ bool RewriteSystem::addRule(MutableTerm lhs, MutableTerm rhs,
341341 RewritePath lhsPath;
342342 RewritePath rhsPath;
343343
344- if (lhs.back ().hasSubstitutions ())
345- simplifySubstitutions (lhs, lhsPath);
346-
347- if (rhs.back ().hasSubstitutions ())
348- simplifySubstitutions (rhs, rhsPath);
349-
350344 simplify (lhs, &lhsPath);
351345 simplify (rhs, &rhsPath);
352346
@@ -460,13 +454,11 @@ bool RewriteSystem::addExplicitRule(MutableTerm lhs, MutableTerm rhs) {
460454 return added;
461455}
462456
463- // / Delete any rules whose left hand sides can be reduced by other rules,
464- // / and reduce the right hand sides of all remaining rules as much as
465- // / possible.
457+ // / Delete any rules whose left hand sides can be reduced by other rules.
466458// /
467459// / Must be run after the completion procedure, since the deletion of
468460// / rules is only valid to perform if the rewrite system is confluent.
469- void RewriteSystem::simplifyRewriteSystem () {
461+ void RewriteSystem::simplifyLeftHandSides () {
470462 assert (Complete);
471463
472464 for (unsigned ruleID = 0 , e = Rules.size (); ruleID < e; ++ruleID) {
@@ -500,8 +492,19 @@ void RewriteSystem::simplifyRewriteSystem() {
500492 break ;
501493 }
502494 }
495+ }
496+ }
497+
498+ // / Reduce the right hand sides of all remaining rules as much as
499+ // / possible.
500+ // /
501+ // / Must be run after the completion procedure, since the deletion of
502+ // / rules is only valid to perform if the rewrite system is confluent.
503+ void RewriteSystem::simplifyRightHandSidesAndSubstitutions () {
504+ assert (Complete);
503505
504- // If the rule was deleted above, skip the rest.
506+ for (unsigned ruleID = 0 , e = Rules.size (); ruleID < e; ++ruleID) {
507+ auto &rule = getRule (ruleID);
505508 if (rule.isSimplified ())
506509 continue ;
507510
@@ -511,6 +514,8 @@ void RewriteSystem::simplifyRewriteSystem() {
511514 if (!simplify (rhs, &rhsPath))
512515 continue ;
513516
517+ auto lhs = rule.getLHS ();
518+
514519 // We're adding a new rule, so the old rule won't apply anymore.
515520 rule.markSimplified ();
516521
@@ -544,6 +549,41 @@ void RewriteSystem::simplifyRewriteSystem() {
544549
545550 recordRewriteLoop (MutableTerm (lhs), loop);
546551 }
552+
553+ // Finally try to simplify substitutions in superclass, concrete type and
554+ // concrete conformance symbols.
555+ for (unsigned ruleID = 0 , e = Rules.size (); ruleID < e; ++ruleID) {
556+ auto &rule = getRule (ruleID);
557+ if (rule.isSimplified ())
558+ continue ;
559+
560+ auto lhs = rule.getLHS ();
561+ auto symbol = lhs.back ();
562+ if (!symbol.hasSubstitutions ())
563+ continue ;
564+
565+ RewritePath path;
566+
567+ // (1) First, apply the original rule to produce the original lhs.
568+ path.add (RewriteStep::forRewriteRule (/* startOffset=*/ 0 , /* endOffset=*/ 0 ,
569+ ruleID, /* inverse=*/ true ));
570+
571+ // (2) Now, simplify the substitutions to get the new lhs.
572+ if (!simplifySubstitutions (symbol, path))
573+ continue ;
574+
575+ // We're either going to add a new rule or record an identity, so
576+ // mark the old rule as simplified.
577+ rule.markSimplified ();
578+
579+ MutableTerm newLHS (lhs.begin (), lhs.end () - 1 );
580+ newLHS.add (symbol);
581+
582+ // Invert the path to get a path from the new lhs to the old rhs.
583+ path.invert ();
584+
585+ addRule (newLHS, MutableTerm (rule.getRHS ()), &path);
586+ }
547587}
548588
549589void RewriteSystem::verifyRewriteRules (ValidityPolicy policy) const {
0 commit comments