Skip to content

Commit 33f94bc

Browse files
committed
Introduce do expressions
1 parent 20d2667 commit 33f94bc

21 files changed

+1103
-47
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,6 +1256,9 @@ ERROR(single_value_stmt_must_be_unlabeled,none,
12561256
ERROR(if_expr_must_be_syntactically_exhaustive,none,
12571257
"'if' must have an unconditional 'else' to be used as expression",
12581258
())
1259+
ERROR(do_catch_expr_must_be_syntactically_exhaustive,none,
1260+
"'do catch' must have an unconditional 'catch' to be used as expression",
1261+
())
12591262
ERROR(single_value_stmt_branch_empty,none,
12601263
"expected expression in branch of '%0' expression",
12611264
(StmtKind))
@@ -1269,8 +1272,8 @@ ERROR(cannot_jump_in_single_value_stmt,none,
12691272
ERROR(effect_marker_on_single_value_stmt,none,
12701273
"'%0' may not be used on '%1' expression", (StringRef, StmtKind))
12711274
ERROR(out_of_place_then_stmt,none,
1272-
"'then' may only appear as the last statement in an 'if' or 'switch' "
1273-
"expression", ())
1275+
"'then' may only appear as the last statement in an 'if', 'switch', or "
1276+
"'do' expression", ())
12741277

12751278
ERROR(did_not_call_function_value,none,
12761279
"function value was used as a property; add () to call it",

include/swift/AST/Expr.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6075,7 +6075,7 @@ class KeyPathDotExpr : public Expr {
60756075
class SingleValueStmtExpr : public Expr {
60766076
public:
60776077
enum class Kind {
6078-
If, Switch
6078+
If, Switch, Do, DoCatch
60796079
};
60806080

60816081
private:

include/swift/AST/Stmt.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,6 +1417,9 @@ class DoCatchStmt final
14171417
return {getTrailingObjects<CaseStmt *>(), Bits.DoCatchStmt.NumCatches};
14181418
}
14191419

1420+
/// Retrieve the complete set of branches for this do-catch statement.
1421+
ArrayRef<Stmt *> getBranches(SmallVectorImpl<Stmt *> &scratch) const;
1422+
14201423
/// Does this statement contain a syntactically exhaustive catch
14211424
/// clause?
14221425
///

include/swift/AST/TypeCheckRequests.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3947,6 +3947,10 @@ class IsSingleValueStmtResult {
39473947
/// The statement is an 'if' statement without an unconditional 'else'.
39483948
NonExhaustiveIf,
39493949

3950+
/// The statement is a 'do catch' statement without an unconditional
3951+
/// 'catch'.
3952+
NonExhaustiveDoCatch,
3953+
39503954
/// There is no branch that produces a resulting value.
39513955
NoResult,
39523956

@@ -4003,6 +4007,9 @@ class IsSingleValueStmtResult {
40034007
static IsSingleValueStmtResult nonExhaustiveIf() {
40044008
return IsSingleValueStmtResult(Kind::NonExhaustiveIf);
40054009
}
4010+
static IsSingleValueStmtResult nonExhaustiveDoCatch() {
4011+
return IsSingleValueStmtResult(Kind::NonExhaustiveDoCatch);
4012+
}
40064013
static IsSingleValueStmtResult noResult() {
40074014
return IsSingleValueStmtResult(Kind::NoResult);
40084015
}

include/swift/Basic/Features.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@ EXPERIMENTAL_FEATURE(PlaygroundExtendedCallbacks, true)
232232
/// Enable 'then' statements.
233233
EXPERIMENTAL_FEATURE(ThenStatements, false)
234234

235+
/// Enable 'do' expressions.
236+
EXPERIMENTAL_FEATURE(DoExpressions, false)
237+
235238
/// Enable the `@_rawLayout` attribute.
236239
EXPERIMENTAL_FEATURE(RawLayout, true)
237240

lib/AST/ASTPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3563,6 +3563,10 @@ static bool usesFeatureThenStatements(Decl *decl) {
35633563
return false;
35643564
}
35653565

3566+
static bool usesFeatureDoExpressions(Decl *decl) {
3567+
return false;
3568+
}
3569+
35663570
static bool usesFeatureNewCxxMethodSafetyHeuristics(Decl *decl) {
35673571
return decl->hasClangNode();
35683572
}

lib/AST/ASTVerifier.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,6 +1227,7 @@ class Verifier : public ASTWalker {
12271227
break;
12281228
case Kind::UnterminatedBranches:
12291229
case Kind::NonExhaustiveIf:
1230+
case Kind::NonExhaustiveDoCatch:
12301231
case Kind::UnhandledStmt:
12311232
case Kind::CircularReference:
12321233
case Kind::HasLabel:

lib/AST/Expr.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2477,6 +2477,8 @@ SingleValueStmtExpr *SingleValueStmtExpr::create(ASTContext &ctx, Stmt *S,
24772477

24782478
SingleValueStmtExpr *SingleValueStmtExpr::createWithWrappedBranches(
24792479
ASTContext &ctx, Stmt *S, DeclContext *DC, bool mustBeExpr) {
2480+
assert(!(isa<DoStmt>(S) || isa<DoCatchStmt>(S)) ||
2481+
ctx.LangOpts.hasFeature(Feature::DoExpressions));
24802482
auto *SVE = create(ctx, S, DC);
24812483

24822484
// Attempt to wrap any branches that can be wrapped.
@@ -2488,12 +2490,15 @@ SingleValueStmtExpr *SingleValueStmtExpr::createWithWrappedBranches(
24882490

24892491
if (auto *S = BS->getSingleActiveStatement()) {
24902492
if (mustBeExpr) {
2491-
// If this must be an expression, we can eagerly wrap any exhaustive if
2492-
// and switch branch.
2493+
// If this must be an expression, we can eagerly wrap any exhaustive if,
2494+
// switch, and do statement.
24932495
if (auto *IS = dyn_cast<IfStmt>(S)) {
24942496
if (!IS->isSyntacticallyExhaustive())
24952497
continue;
2496-
} else if (!isa<SwitchStmt>(S)) {
2498+
} else if (auto *DCS = dyn_cast<DoCatchStmt>(S)) {
2499+
if (!DCS->isSyntacticallyExhaustive())
2500+
continue;
2501+
} else if (!isa<SwitchStmt>(S) && !isa<DoStmt>(S)) {
24972502
continue;
24982503
}
24992504
} else {
@@ -2576,18 +2581,28 @@ SingleValueStmtExpr::Kind SingleValueStmtExpr::getStmtKind() const {
25762581
return Kind::If;
25772582
case StmtKind::Switch:
25782583
return Kind::Switch;
2584+
case StmtKind::Do:
2585+
return Kind::Do;
2586+
case StmtKind::DoCatch:
2587+
return Kind::DoCatch;
25792588
default:
25802589
llvm_unreachable("Unhandled kind!");
25812590
}
25822591
}
25832592

25842593
ArrayRef<Stmt *>
25852594
SingleValueStmtExpr::getBranches(SmallVectorImpl<Stmt *> &scratch) const {
2595+
assert(scratch.empty());
25862596
switch (getStmtKind()) {
25872597
case Kind::If:
25882598
return cast<IfStmt>(getStmt())->getBranches(scratch);
25892599
case Kind::Switch:
25902600
return cast<SwitchStmt>(getStmt())->getBranches(scratch);
2601+
case Kind::Do:
2602+
scratch.push_back(cast<DoStmt>(getStmt())->getBody());
2603+
return scratch;
2604+
case Kind::DoCatch:
2605+
return cast<DoCatchStmt>(getStmt())->getBranches(scratch);
25912606
}
25922607
llvm_unreachable("Unhandled case in switch!");
25932608
}

lib/AST/Stmt.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,15 @@ SwitchStmt::getBranches(SmallVectorImpl<Stmt *> &scratch) const {
859859
return scratch;
860860
}
861861

862+
ArrayRef<Stmt *>
863+
DoCatchStmt::getBranches(SmallVectorImpl<Stmt *> &scratch) const {
864+
assert(scratch.empty());
865+
scratch.push_back(getBody());
866+
for (auto *CS : getCatches())
867+
scratch.push_back(CS->getBody());
868+
return scratch;
869+
}
870+
862871
// See swift/Basic/Statistic.h for declaration: this enables tracing Stmts, is
863872
// defined here to avoid too much layering violation / circular linkage
864873
// dependency.

lib/ASTGen/Sources/ASTGen/SourceFile.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ extension Parser.ExperimentalFeatures {
3737
}
3838
mapFeature(.ThenStatements, to: .thenStatements)
3939
mapFeature(.TypedThrows, to: .typedThrows)
40+
mapFeature(.DoExpressions, to: .doExpressions)
4041
}
4142
}
4243

0 commit comments

Comments
 (0)