Skip to content

Commit 2c355de

Browse files
committed
RequirementMachine: Introduce RewriteStep::{Left,Right}ConcreteProjection
1 parent 00d226f commit 2c355de

File tree

4 files changed

+318
-19
lines changed

4 files changed

+318
-19
lines changed

lib/AST/RequirementMachine/HomotopyReduction.cpp

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ RewriteLoop::findRulesAppearingOnceInEmptyContext(
9999
case RewriteStep::Decompose:
100100
case RewriteStep::Relation:
101101
case RewriteStep::DecomposeConcrete:
102+
case RewriteStep::LeftConcreteProjection:
103+
case RewriteStep::RightConcreteProjection:
102104
break;
103105
}
104106

@@ -219,6 +221,8 @@ RewritePath RewritePath::splitCycleAtRule(unsigned ruleID) const {
219221
case RewriteStep::Decompose:
220222
case RewriteStep::Relation:
221223
case RewriteStep::DecomposeConcrete:
224+
case RewriteStep::LeftConcreteProjection:
225+
case RewriteStep::RightConcreteProjection:
222226
break;
223227
}
224228

@@ -280,34 +284,28 @@ bool RewritePath::replaceRuleWithPath(unsigned ruleID,
280284
// Replace this step with the provided path. If this rewrite step has
281285
// context, the path's own steps must be re-contextualized.
282286

283-
// Keep track of Decompose/DecomposeConcrete pairs. Any rewrite steps
284-
// in between do not need to be re-contextualized, since they operate
285-
// on new terms that were pushed on the stack by the Decompose or
286-
// DecomposeConcrete operation.
287-
unsigned decomposeCount = 0;
287+
// Keep track of rewrite step pairs which push and pop the stack. Any
288+
// rewrite steps enclosed with a push/pop are not re-contextualized.
289+
unsigned pushCount = 0;
288290

289291
auto recontextualizeStep = [&](RewriteStep newStep) {
290292
bool inverse = newStep.Inverse ^ step.Inverse;
291293

292-
if ((newStep.Kind == RewriteStep::Decompose ||
293-
newStep.Kind == RewriteStep::DecomposeConcrete) &&
294-
inverse) {
295-
assert(decomposeCount > 0);
296-
--decomposeCount;
294+
if (newStep.pushesTermsOnStack() && inverse) {
295+
assert(pushCount > 0);
296+
--pushCount;
297297
}
298298

299-
if (decomposeCount == 0) {
299+
if (pushCount == 0) {
300300
newStep.StartOffset += step.StartOffset;
301301
newStep.EndOffset += step.EndOffset;
302302
}
303303

304304
newStep.Inverse = inverse;
305305
newSteps.push_back(newStep);
306306

307-
if ((newStep.Kind == RewriteStep::Decompose ||
308-
newStep.Kind == RewriteStep::DecomposeConcrete) &&
309-
!inverse) {
310-
++decomposeCount;
307+
if (newStep.pushesTermsOnStack() && !inverse) {
308+
++pushCount;
311309
}
312310
};
313311

@@ -320,8 +318,8 @@ bool RewritePath::replaceRuleWithPath(unsigned ruleID,
320318
recontextualizeStep(newStep);
321319
}
322320

323-
// Decompose and DecomposeConcrete steps should come in balanced pairs.
324-
assert(decomposeCount == 0);
321+
// Rewrite steps which push and pop the stack must come in balanced pairs.
322+
assert(pushCount == 0);
325323

326324
break;
327325
}
@@ -330,6 +328,8 @@ bool RewritePath::replaceRuleWithPath(unsigned ruleID,
330328
case RewriteStep::Decompose:
331329
case RewriteStep::Relation:
332330
case RewriteStep::DecomposeConcrete:
331+
case RewriteStep::LeftConcreteProjection:
332+
case RewriteStep::RightConcreteProjection:
333333
newSteps.push_back(step);
334334
break;
335335
}

lib/AST/RequirementMachine/MinimalConformances.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ void RewriteLoop::findProtocolConformanceRules(
139139
case RewriteStep::Decompose:
140140
case RewriteStep::Relation:
141141
case RewriteStep::DecomposeConcrete:
142+
case RewriteStep::LeftConcreteProjection:
143+
case RewriteStep::RightConcreteProjection:
142144
break;
143145
}
144146
}

lib/AST/RequirementMachine/RewriteLoop.cpp

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,28 @@ void RewriteStep::dump(llvm::raw_ostream &out,
136136
out << difference.LHS << " : " << difference.RHS << ")";
137137
break;
138138
}
139+
case LeftConcreteProjection: {
140+
evaluator.applyLeftConcreteProjection(*this, system);
141+
142+
out << "LeftConcrete" << (Inverse ? "In" : "Pro") << "jection(";
143+
144+
const auto &difference = system.getTypeDifference(
145+
getTypeDifferenceID());
146+
147+
out << difference.LHS << " : " << difference.RHS << ")";
148+
break;
149+
}
150+
case RightConcreteProjection: {
151+
evaluator.applyRightConcreteProjection(*this, system);
152+
153+
out << "RightConcrete" << (Inverse ? "In" : "Pro") << "jection(";
154+
155+
const auto &difference = system.getTypeDifference(
156+
getTypeDifferenceID());
157+
158+
out << difference.LHS << " : " << difference.RHS << ")";
159+
break;
160+
}
139161
}
140162
}
141163

@@ -542,6 +564,139 @@ void RewritePathEvaluator::applyDecomposeConcrete(const RewriteStep &step,
542564
}
543565
}
544566

567+
void
568+
RewritePathEvaluator::applyLeftConcreteProjection(const RewriteStep &step,
569+
const RewriteSystem &system) {
570+
assert(step.Kind == RewriteStep::LeftConcreteProjection);
571+
572+
const auto &difference = system.getTypeDifference(step.getTypeDifferenceID());
573+
unsigned index = step.getSubstitutionIndex();
574+
575+
MutableTerm leftProjection(difference.LHS.getSubstitutions()[index]);
576+
577+
MutableTerm leftBaseTerm(difference.BaseTerm);
578+
leftBaseTerm.add(difference.LHS);
579+
580+
auto bug = [&](StringRef msg) {
581+
llvm::errs() << msg << "\n";
582+
llvm::errs() << "- StartOffset: " << step.StartOffset << "\n";
583+
llvm::errs() << "- EndOffset: " << step.EndOffset << "\n";
584+
llvm::errs() << "- SubstitutionIndex: " << index << "\n";
585+
llvm::errs() << "- LeftProjection: " << leftProjection << "\n";
586+
llvm::errs() << "- LeftBaseTerm: " << leftBaseTerm << "\n";
587+
llvm::errs() << "- DifferenceID: " << step.getTypeDifferenceID() << "\n";
588+
llvm::errs() << "\nType difference:\n";
589+
difference.dump(llvm::errs());
590+
llvm::errs() << ":\n";
591+
difference.dump(llvm::errs());
592+
llvm::errs() << "\nEvaluator state:\n";
593+
dump(llvm::errs());
594+
abort();
595+
};
596+
597+
if (!step.Inverse) {
598+
const auto &term = getCurrentTerm();
599+
600+
MutableTerm subTerm(term.begin() + step.StartOffset,
601+
term.end() - step.EndOffset);
602+
if (subTerm != MutableTerm(leftProjection))
603+
bug("Incorrect left projection term");
604+
605+
Primary.push_back(leftBaseTerm);
606+
} else {
607+
if (Primary.size() < 2)
608+
bug("Too few elements on the primary stack");
609+
610+
if (Primary.back() != leftBaseTerm)
611+
bug("Incorrect left base term");
612+
613+
Primary.pop_back();
614+
615+
const auto &term = getCurrentTerm();
616+
617+
MutableTerm subTerm(term.begin() + step.StartOffset,
618+
term.end() - step.EndOffset);
619+
if (subTerm != leftProjection)
620+
bug("Incorrect left projection term");
621+
}
622+
}
623+
624+
void
625+
RewritePathEvaluator::applyRightConcreteProjection(const RewriteStep &step,
626+
const RewriteSystem &system) {
627+
assert(step.Kind == RewriteStep::RightConcreteProjection);
628+
629+
const auto &difference = system.getTypeDifference(step.getTypeDifferenceID());
630+
unsigned index = step.getSubstitutionIndex();
631+
632+
MutableTerm leftProjection(difference.LHS.getSubstitutions()[index]);
633+
auto rightProjection = difference.getReplacementSubstitution(index);
634+
635+
MutableTerm leftBaseTerm(difference.BaseTerm);
636+
leftBaseTerm.add(difference.LHS);
637+
638+
MutableTerm rightBaseTerm(difference.BaseTerm);
639+
rightBaseTerm.add(difference.RHS);
640+
641+
auto bug = [&](StringRef msg) {
642+
llvm::errs() << msg << "\n";
643+
llvm::errs() << "- StartOffset: " << step.StartOffset << "\n";
644+
llvm::errs() << "- EndOffset: " << step.EndOffset << "\n";
645+
llvm::errs() << "- SubstitutionIndex: " << index << "\n";
646+
llvm::errs() << "- LeftProjection: " << leftProjection << "\n";
647+
llvm::errs() << "- RightProjection: " << rightProjection << "\n";
648+
llvm::errs() << "- LeftBaseTerm: " << leftBaseTerm << "\n";
649+
llvm::errs() << "- RightBaseTerm: " << rightBaseTerm << "\n";
650+
llvm::errs() << "- DifferenceID: " << step.getTypeDifferenceID() << "\n";
651+
llvm::errs() << "\nType difference:\n";
652+
difference.dump(llvm::errs());
653+
llvm::errs() << ":\n";
654+
difference.dump(llvm::errs());
655+
llvm::errs() << "\nEvaluator state:\n";
656+
dump(llvm::errs());
657+
abort();
658+
};
659+
660+
if (!step.Inverse) {
661+
auto &term = getCurrentTerm();
662+
663+
MutableTerm subTerm(term.begin() + step.StartOffset,
664+
term.end() - step.EndOffset);
665+
666+
if (subTerm != rightProjection)
667+
bug("Incorrect right projection term");
668+
669+
MutableTerm newTerm(term.begin(), term.begin() + step.StartOffset);
670+
newTerm.append(leftProjection);
671+
newTerm.append(term.end() - step.EndOffset, term.end());
672+
673+
term = newTerm;
674+
675+
Primary.push_back(rightBaseTerm);
676+
} else {
677+
if (Primary.size() < 2)
678+
bug("Too few elements on the primary stack");
679+
680+
if (Primary.back() != rightBaseTerm)
681+
bug("Incorrect right base term");
682+
683+
Primary.pop_back();
684+
685+
auto &term = getCurrentTerm();
686+
687+
MutableTerm subTerm(term.begin() + step.StartOffset,
688+
term.end() - step.EndOffset);
689+
if (subTerm != leftProjection)
690+
bug("Incorrect left projection term");
691+
692+
MutableTerm newTerm(term.begin(), term.begin() + step.StartOffset);
693+
newTerm.append(rightProjection);
694+
newTerm.append(term.end() - step.EndOffset, term.end());
695+
696+
term = newTerm;
697+
}
698+
}
699+
545700
void RewritePathEvaluator::apply(const RewriteStep &step,
546701
const RewriteSystem &system) {
547702
switch (step.Kind) {
@@ -568,5 +723,13 @@ void RewritePathEvaluator::apply(const RewriteStep &step,
568723
case RewriteStep::DecomposeConcrete:
569724
applyDecomposeConcrete(step, system);
570725
break;
726+
727+
case RewriteStep::LeftConcreteProjection:
728+
applyLeftConcreteProjection(step, system);
729+
break;
730+
731+
case RewriteStep::RightConcreteProjection:
732+
applyRightConcreteProjection(step, system);
733+
break;
571734
}
572735
}

0 commit comments

Comments
 (0)