@@ -626,12 +626,107 @@ class BuilderClosureVisitor
626
626
DeclNameLoc (endLoc), /* implicit=*/ true );
627
627
}
628
628
629
+ VarDecl *visitSwitchStmt (SwitchStmt *switchStmt) {
630
+ // Generate constraints for the subject expression, and capture its
631
+ // type for use in matching the various patterns.
632
+ Expr *subjectExpr = switchStmt->getSubjectExpr ();
633
+ if (cs) {
634
+ // Form a one-way constraint to prevent backward propagation.
635
+ subjectExpr = new (ctx) OneWayExpr (subjectExpr);
636
+
637
+ // FIXME: Add contextual type purpose for switch subjects?
638
+ SolutionApplicationTarget target (subjectExpr, dc, CTP_Unused, Type (),
639
+ /* isDiscarded=*/ false );
640
+ if (cs->generateConstraints (target, FreeTypeVariableBinding::Disallow)) {
641
+ hadError = true ;
642
+ return nullptr ;
643
+ }
644
+
645
+ cs->setSolutionApplicationTarget (switchStmt, target);
646
+ subjectExpr = target.getAsExpr ();
647
+ assert (subjectExpr && " Must have a subject expression here" );
648
+ }
649
+
650
+ // Generate constraints and capture variables for all of the cases.
651
+ SmallVector<std::pair<CaseStmt *, VarDecl *>, 4 > capturedCaseVars;
652
+ for (auto *caseStmt : switchStmt->getCases ()) {
653
+ if (auto capturedCaseVar = visitCaseStmt (caseStmt, subjectExpr)) {
654
+ capturedCaseVars.push_back ({caseStmt, capturedCaseVar});
655
+ }
656
+ }
657
+
658
+ if (!cs)
659
+ return nullptr ;
660
+
661
+ // Form the expressions that inject the result of each case into the
662
+ // appropriate
663
+ llvm::TinyPtrVector<Expr *> injectedCaseExprs;
664
+ SmallVector<std::pair<Type, ConstraintLocator *>, 4 > injectedCaseTerms;
665
+ for (unsigned idx : indices (capturedCaseVars)) {
666
+ auto caseStmt = capturedCaseVars[idx].first ;
667
+ auto caseVar = capturedCaseVars[idx].second ;
668
+
669
+ // Build the expression that injects the case variable into appropriate
670
+ // buildEither(first:)/buildEither(second:) chain.
671
+ Expr *caseVarRef = buildVarRef (caseVar, caseStmt->getEndLoc ());
672
+ Expr *injectedCaseExpr = buildWrappedChainPayload (
673
+ caseVarRef, idx, capturedCaseVars.size (), /* isOptional=*/ false );
674
+
675
+ // Generate constraints for this injected case result.
676
+ injectedCaseExpr = cs->generateConstraints (injectedCaseExpr, dc);
677
+ if (!injectedCaseExpr) {
678
+ hadError = true ;
679
+ return nullptr ;
680
+ }
681
+
682
+ // Record this injected case expression.
683
+ injectedCaseExprs.push_back (injectedCaseExpr);
684
+
685
+ // Record the type and locator for this injected case expression, to be
686
+ // used in the "join" constraint later.
687
+ injectedCaseTerms.push_back (
688
+ { cs->getType (injectedCaseExpr)->getRValueType (),
689
+ cs->getConstraintLocator (injectedCaseExpr) });
690
+ }
691
+
692
+ // Form the type of the switch itself.
693
+ // FIXME: Need a locator for the "switch" statement.
694
+ Type resultType = cs->addJoinConstraint (nullptr , injectedCaseTerms);
695
+ if (!resultType) {
696
+ hadError = true ;
697
+ return nullptr ;
698
+ }
699
+
700
+ // Create a variable to capture the result of evaluating the switch.
701
+ auto switchVar = buildVar (switchStmt->getStartLoc ());
702
+ cs->setType (switchVar, resultType);
703
+ applied.capturedStmts .insert (
704
+ {switchStmt, { switchVar, std::move (injectedCaseExprs) } });
705
+ return switchVar;
706
+ }
707
+
708
+ VarDecl *visitCaseStmt (CaseStmt *caseStmt, Expr *subjectExpr) {
709
+ // If needed, generate constraints for everything in the case statement.
710
+ if (cs) {
711
+ auto locator = cs->getConstraintLocator (
712
+ subjectExpr, LocatorPathElt::ContextualType ());
713
+ Type subjectType = cs->getType (subjectExpr);
714
+
715
+ if (cs->generateConstraints (caseStmt, dc, subjectType, locator)) {
716
+ hadError = true ;
717
+ return nullptr ;
718
+ }
719
+ }
720
+
721
+ // Translate the body.
722
+ return visit (caseStmt->getBody ());
723
+ }
724
+
629
725
CONTROL_FLOW_STMT (Guard)
630
726
CONTROL_FLOW_STMT (While)
631
727
CONTROL_FLOW_STMT (DoCatch)
632
728
CONTROL_FLOW_STMT (RepeatWhile)
633
729
CONTROL_FLOW_STMT (ForEach)
634
- CONTROL_FLOW_STMT (Switch)
635
730
CONTROL_FLOW_STMT (Case)
636
731
CONTROL_FLOW_STMT (Catch)
637
732
CONTROL_FLOW_STMT (Break)
@@ -1000,6 +1095,63 @@ class BuilderClosureRewriter
1000
1095
return doStmt;
1001
1096
}
1002
1097
1098
+ Stmt *visitSwitchStmt (SwitchStmt *switchStmt, FunctionBuilderTarget target) {
1099
+ // Translate the subject expression.
1100
+ ConstraintSystem &cs = solution.getConstraintSystem ();
1101
+ auto subjectTarget =
1102
+ rewriteTarget (*cs.getSolutionApplicationTarget (switchStmt));
1103
+ if (!subjectTarget)
1104
+ return nullptr ;
1105
+
1106
+ switchStmt->setSubjectExpr (subjectTarget->getAsExpr ());
1107
+
1108
+ // Handle any declaration nodes within the case list first; we'll
1109
+ // handle the cases in a second pass.
1110
+ for (auto child : switchStmt->getRawCases ()) {
1111
+ if (auto decl = child.dyn_cast <Decl *>()) {
1112
+ TypeChecker::typeCheckDecl (decl);
1113
+ }
1114
+ }
1115
+
1116
+ // Translate all of the cases.
1117
+ assert (target.kind == FunctionBuilderTarget::TemporaryVar);
1118
+ auto temporaryVar = target.captured .first ;
1119
+ unsigned caseIndex = 0 ;
1120
+ for (auto caseStmt : switchStmt->getCases ()) {
1121
+ if (!visitCaseStmt (
1122
+ caseStmt,
1123
+ FunctionBuilderTarget::forAssign (
1124
+ temporaryVar, {target.captured .second [caseIndex]})))
1125
+ return nullptr ;
1126
+
1127
+ ++caseIndex;
1128
+ }
1129
+
1130
+ return switchStmt;
1131
+ }
1132
+
1133
+ Stmt *visitCaseStmt (CaseStmt *caseStmt, FunctionBuilderTarget target) {
1134
+ // Translate the patterns and guard expressions for each case label item.
1135
+ for (auto &caseLabelItem : caseStmt->getMutableCaseLabelItems ()) {
1136
+ SolutionApplicationTarget caseLabelTarget (&caseLabelItem, dc);
1137
+ if (!rewriteTarget (caseLabelTarget))
1138
+ return nullptr ;
1139
+ }
1140
+
1141
+ // Transform the body of the case.
1142
+ auto body = cast<BraceStmt>(caseStmt->getBody ());
1143
+ auto captured = takeCapturedStmt (body);
1144
+ auto newInnerBody = cast<BraceStmt>(
1145
+ visitBraceStmt (
1146
+ body,
1147
+ target,
1148
+ FunctionBuilderTarget::forAssign (
1149
+ captured.first , {captured.second .front ()})));
1150
+ caseStmt->setBody (newInnerBody);
1151
+
1152
+ return caseStmt;
1153
+ }
1154
+
1003
1155
#define UNHANDLED_FUNCTION_BUILDER_STMT (STMT ) \
1004
1156
Stmt *visit##STMT##Stmt(STMT##Stmt *stmt, FunctionBuilderTarget target) { \
1005
1157
llvm_unreachable (" Function builders do not allow statement of kind " \
@@ -1014,8 +1166,6 @@ class BuilderClosureRewriter
1014
1166
UNHANDLED_FUNCTION_BUILDER_STMT (DoCatch)
1015
1167
UNHANDLED_FUNCTION_BUILDER_STMT (RepeatWhile)
1016
1168
UNHANDLED_FUNCTION_BUILDER_STMT (ForEach)
1017
- UNHANDLED_FUNCTION_BUILDER_STMT (Switch)
1018
- UNHANDLED_FUNCTION_BUILDER_STMT (Case)
1019
1169
UNHANDLED_FUNCTION_BUILDER_STMT (Catch)
1020
1170
UNHANDLED_FUNCTION_BUILDER_STMT (Break)
1021
1171
UNHANDLED_FUNCTION_BUILDER_STMT (Continue)
0 commit comments