Skip to content

Commit f8e72ca

Browse files
committed
[CS] Factor out brace element handling in a couple of cases
Split out brace element handling for a couple of walkers into a new function. The diff for this is best viewed without whitespace changes. This should be NFC.
1 parent 35ae385 commit f8e72ca

File tree

1 file changed

+135
-127
lines changed

1 file changed

+135
-127
lines changed

lib/Sema/BuilderTransform.cpp

Lines changed: 135 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -364,68 +364,70 @@ class BuilderClosureVisitor
364364
}
365365
}
366366

367-
VarDecl *visitBraceStmt(BraceStmt *braceStmt) {
368-
SmallVector<Expr *, 4> expressions;
367+
void visitBraceElement(ASTNode node, SmallVectorImpl<Expr *> &expressions) {
369368
auto addChild = [&](VarDecl *childVar) {
370369
if (!childVar)
371370
return;
372371

373372
expressions.push_back(builder.buildVarRef(childVar, childVar->getLoc()));
374373
};
375374

376-
for (auto node : braceStmt->getElements()) {
377-
// Implicit returns in single-expression function bodies are treated
378-
// as the expression.
379-
if (auto returnStmt =
380-
dyn_cast_or_null<ReturnStmt>(node.dyn_cast<Stmt *>())) {
381-
assert(returnStmt->isImplicit());
382-
node = returnStmt->getResult();
383-
}
384-
385-
if (auto stmt = node.dyn_cast<Stmt *>()) {
386-
addChild(visit(stmt));
387-
continue;
388-
}
375+
// Implicit returns in single-expression function bodies are treated
376+
// as the expression.
377+
if (auto returnStmt =
378+
dyn_cast_or_null<ReturnStmt>(node.dyn_cast<Stmt *>())) {
379+
assert(returnStmt->isImplicit());
380+
node = returnStmt->getResult();
381+
}
389382

390-
if (auto decl = node.dyn_cast<Decl *>()) {
391-
// Just ignore #if; the chosen children should appear in the
392-
// surrounding context. This isn't good for source tools but it
393-
// at least works.
394-
if (isa<IfConfigDecl>(decl))
395-
continue;
383+
if (auto stmt = node.dyn_cast<Stmt *>()) {
384+
addChild(visit(stmt));
385+
return;
386+
}
396387

397-
// Skip #warning/#error; we'll handle them when applying the builder.
398-
if (isa<PoundDiagnosticDecl>(decl)) {
399-
continue;
400-
}
388+
if (auto decl = node.dyn_cast<Decl *>()) {
389+
// Just ignore #if; the chosen children should appear in the
390+
// surrounding context. This isn't good for source tools but it
391+
// at least works.
392+
if (isa<IfConfigDecl>(decl))
393+
return;
401394

402-
// Pattern bindings are okay so long as all of the entries are
403-
// initialized.
404-
if (auto patternBinding = dyn_cast<PatternBindingDecl>(decl)) {
405-
visitPatternBindingDecl(patternBinding);
406-
continue;
407-
}
395+
// Skip #warning/#error; we'll handle them when applying the builder.
396+
if (isa<PoundDiagnosticDecl>(decl))
397+
return;
408398

409-
// Ignore variable declarations, because they're always handled within
410-
// their enclosing pattern bindings.
411-
if (isa<VarDecl>(decl))
412-
continue;
399+
// Pattern bindings are okay so long as all of the entries are
400+
// initialized.
401+
if (auto patternBinding = dyn_cast<PatternBindingDecl>(decl)) {
402+
visitPatternBindingDecl(patternBinding);
403+
return;
404+
}
413405

414-
if (!unhandledNode)
415-
unhandledNode = decl;
406+
// Ignore variable declarations, because they're always handled within
407+
// their enclosing pattern bindings.
408+
if (isa<VarDecl>(decl))
409+
return;
416410

417-
continue;
418-
}
411+
if (!unhandledNode)
412+
unhandledNode = decl;
419413

420-
auto expr = node.get<Expr *>();
421-
if (cs && builder.supports(ctx.Id_buildExpression)) {
422-
expr = buildCallIfWanted(expr->getLoc(), ctx.Id_buildExpression,
423-
{ expr }, { Identifier() });
424-
}
414+
return;
415+
}
425416

426-
addChild(captureExpr(expr, /*oneWay=*/true, node.get<Expr *>()));
417+
auto expr = node.get<Expr *>();
418+
if (cs && builder.supports(ctx.Id_buildExpression)) {
419+
expr = buildCallIfWanted(expr->getLoc(), ctx.Id_buildExpression,
420+
{expr}, {Identifier()});
427421
}
428422

423+
addChild(captureExpr(expr, /*oneWay=*/true, node.get<Expr *>()));
424+
}
425+
426+
VarDecl *visitBraceStmt(BraceStmt *braceStmt) {
427+
SmallVector<Expr *, 4> expressions;
428+
for (auto node : braceStmt->getElements())
429+
visitBraceElement(node, expressions);
430+
429431
if (!cs || hadError)
430432
return nullptr;
431433

@@ -1769,107 +1771,113 @@ class BuilderClosureRewriter
17691771
solution(solution), dc(dc), builderTransform(builderTransform),
17701772
rewriteTarget(rewriteTarget) { }
17711773

1772-
NullablePtr<Stmt>
1773-
visitBraceStmt(BraceStmt *braceStmt, ResultBuilderTarget target,
1774-
Optional<ResultBuilderTarget> innerTarget = None) {
1775-
std::vector<ASTNode> newElements;
1776-
1777-
// If there is an "inner" target corresponding to this brace, declare
1778-
// it's temporary variable if needed.
1779-
if (innerTarget) {
1780-
declareTemporaryVariable(innerTarget->captured.first, newElements);
1774+
/// Visit the element of a brace statement, returning \c false if the element
1775+
/// was rewritten successfully, or \c true if there was an error.
1776+
bool visitBraceElement(ASTNode node, std::vector<ASTNode> &newElements) {
1777+
// Implicit returns in single-expression function bodies are treated
1778+
// as the expression.
1779+
if (auto returnStmt =
1780+
dyn_cast_or_null<ReturnStmt>(node.dyn_cast<Stmt *>())) {
1781+
assert(returnStmt->isImplicit());
1782+
node = returnStmt->getResult();
17811783
}
17821784

1783-
for (auto node : braceStmt->getElements()) {
1784-
// Implicit returns in single-expression function bodies are treated
1785-
// as the expression.
1786-
if (auto returnStmt =
1787-
dyn_cast_or_null<ReturnStmt>(node.dyn_cast<Stmt *>())) {
1788-
assert(returnStmt->isImplicit());
1789-
node = returnStmt->getResult();
1790-
}
1785+
if (auto expr = node.dyn_cast<Expr *>()) {
1786+
// Skip error expressions.
1787+
if (isa<ErrorExpr>(expr))
1788+
return false;
17911789

1792-
if (auto expr = node.dyn_cast<Expr *>()) {
1793-
// Skip error expressions.
1794-
if (isa<ErrorExpr>(expr))
1795-
continue;
1790+
// Each expression turns into a 'let' that captures the value of
1791+
// the expression.
1792+
auto recorded = takeCapturedExpr(expr);
17961793

1797-
// Each expression turns into a 'let' that captures the value of
1798-
// the expression.
1799-
auto recorded = takeCapturedExpr(expr);
1794+
// Rewrite the expression
1795+
Expr *finalExpr = rewriteExpr(recorded.generatedExpr);
18001796

1801-
// Rewrite the expression
1802-
Expr *finalExpr = rewriteExpr(recorded.generatedExpr);
1797+
// Form a new pattern binding to bind the temporary variable to the
1798+
// transformed expression.
1799+
declareTemporaryVariable(recorded.temporaryVar, newElements, finalExpr);
1800+
return false;
1801+
}
18031802

1804-
// Form a new pattern binding to bind the temporary variable to the
1805-
// transformed expression.
1806-
declareTemporaryVariable(recorded.temporaryVar, newElements, finalExpr);
1807-
continue;
1803+
if (auto stmt = node.dyn_cast<Stmt *>()) {
1804+
// "throw" statements produce no value. Transform them directly.
1805+
if (auto throwStmt = dyn_cast<ThrowStmt>(stmt)) {
1806+
if (auto newStmt = visitThrowStmt(throwStmt)) {
1807+
newElements.push_back(newStmt.get());
1808+
}
1809+
return false;
18081810
}
18091811

1810-
if (auto stmt = node.dyn_cast<Stmt *>()) {
1811-
// "throw" statements produce no value. Transform them directly.
1812-
if (auto throwStmt = dyn_cast<ThrowStmt>(stmt)) {
1813-
if (auto newStmt = visitThrowStmt(throwStmt)) {
1814-
newElements.push_back(newStmt.get());
1815-
}
1816-
continue;
1817-
}
1812+
// Each statement turns into a (potential) temporary variable
1813+
// binding followed by the statement itself.
1814+
auto captured = takeCapturedStmt(stmt);
18181815

1819-
// Each statement turns into a (potential) temporary variable
1820-
// binding followed by the statement itself.
1821-
auto captured = takeCapturedStmt(stmt);
1816+
declareTemporaryVariable(captured.first, newElements);
18221817

1823-
declareTemporaryVariable(captured.first, newElements);
1818+
auto finalStmt =
1819+
visit(stmt, ResultBuilderTarget{ResultBuilderTarget::TemporaryVar,
1820+
std::move(captured)});
18241821

1825-
auto finalStmt = visit(
1826-
stmt,
1827-
ResultBuilderTarget{ResultBuilderTarget::TemporaryVar,
1828-
std::move(captured)});
1822+
// Re-write of statements that envolve type-checking
1823+
// could fail, such a failure terminates the walk.
1824+
if (!finalStmt)
1825+
return true;
18291826

1830-
// Re-write of statements that envolve type-checking
1831-
// could fail, such a failure terminates the walk.
1832-
if (!finalStmt)
1833-
return nullptr;
1827+
newElements.push_back(finalStmt.get());
1828+
return false;
1829+
}
18341830

1835-
newElements.push_back(finalStmt.get());
1836-
continue;
1837-
}
1831+
auto decl = node.get<Decl *>();
18381832

1839-
auto decl = node.get<Decl *>();
1833+
// Skip #if declarations.
1834+
if (isa<IfConfigDecl>(decl)) {
1835+
newElements.push_back(decl);
1836+
return false;
1837+
}
18401838

1841-
// Skip #if declarations.
1842-
if (isa<IfConfigDecl>(decl)) {
1843-
newElements.push_back(decl);
1844-
continue;
1845-
}
1839+
// Diagnose #warning / #error during application.
1840+
if (auto poundDiag = dyn_cast<PoundDiagnosticDecl>(decl)) {
1841+
TypeChecker::typeCheckDecl(poundDiag);
1842+
newElements.push_back(decl);
1843+
return false;
1844+
}
18461845

1847-
// Diagnose #warning / #error during application.
1848-
if (auto poundDiag = dyn_cast<PoundDiagnosticDecl>(decl)) {
1849-
TypeChecker::typeCheckDecl(poundDiag);
1850-
newElements.push_back(decl);
1851-
continue;
1852-
}
1846+
// Skip variable declarations; they're always part of a pattern
1847+
// binding.
1848+
if (isa<VarDecl>(decl)) {
1849+
TypeChecker::typeCheckDecl(decl);
1850+
newElements.push_back(decl);
1851+
return false;
1852+
}
18531853

1854-
// Skip variable declarations; they're always part of a pattern
1855-
// binding.
1856-
if (isa<VarDecl>(decl)) {
1857-
TypeChecker::typeCheckDecl(decl);
1858-
newElements.push_back(decl);
1859-
continue;
1860-
}
1854+
// Handle pattern bindings.
1855+
if (auto patternBinding = dyn_cast<PatternBindingDecl>(decl)) {
1856+
auto resultTarget =
1857+
rewriteTarget(SolutionApplicationTarget{patternBinding});
1858+
assert(resultTarget.has_value() &&
1859+
"Could not rewrite pattern binding entries!");
1860+
TypeChecker::typeCheckDecl(resultTarget->getAsPatternBinding());
1861+
newElements.push_back(resultTarget->getAsPatternBinding());
1862+
return false;
1863+
}
18611864

1862-
// Handle pattern bindings.
1863-
if (auto patternBinding = dyn_cast<PatternBindingDecl>(decl)) {
1864-
auto resultTarget = rewriteTarget(SolutionApplicationTarget{patternBinding});
1865-
assert(resultTarget.has_value()
1866-
&& "Could not rewrite pattern binding entries!");
1867-
TypeChecker::typeCheckDecl(resultTarget->getAsPatternBinding());
1868-
newElements.push_back(resultTarget->getAsPatternBinding());
1869-
continue;
1870-
}
1865+
llvm_unreachable("Cannot yet handle declarations");
1866+
}
18711867

1872-
llvm_unreachable("Cannot yet handle declarations");
1868+
NullablePtr<Stmt>
1869+
visitBraceStmt(BraceStmt *braceStmt, ResultBuilderTarget target,
1870+
Optional<ResultBuilderTarget> innerTarget = None) {
1871+
std::vector<ASTNode> newElements;
1872+
1873+
// If there is an "inner" target corresponding to this brace, declare
1874+
// it's temporary variable if needed.
1875+
if (innerTarget)
1876+
declareTemporaryVariable(innerTarget->captured.first, newElements);
1877+
1878+
for (auto node : braceStmt->getElements()) {
1879+
if (visitBraceElement(node, newElements))
1880+
return nullptr;
18731881
}
18741882

18751883
// If there is an "inner" target corresponding to this brace, initialize

0 commit comments

Comments
 (0)