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