Skip to content

Commit 96a42a2

Browse files
Add support for declarations in switch expressions (#505)
Co-authored-by: Jan Jurzitza <gh@webfreak.org>
1 parent 1065837 commit 96a42a2

6 files changed

Lines changed: 93 additions & 13 deletions

File tree

src/dparse/ast.d

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3147,11 +3147,18 @@ final class SwitchStatement : BaseNode
31473147
{
31483148
override void accept(ASTVisitor visitor) const
31493149
{
3150-
mixin (visitIfNotNull!(expression, statement));
3150+
mixin (visitIfNotNull!(condition, statement));
31513151
}
3152-
/** */ Expression expression;
3152+
/** */ IfCondition condition;
31533153
/** */ Statement statement;
31543154
mixin OpEquals;
3155+
3156+
deprecated("use condition.expression") inout(Expression) expression() inout @property @safe nothrow @nogc pure
3157+
{
3158+
if (!condition)
3159+
return null;
3160+
return condition.expression;
3161+
}
31553162
}
31563163

31573164
///

src/dparse/formatter.d

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2958,15 +2958,15 @@ class Formatter(Sink)
29582958
debug(verbose) writeln("SwitchStatement");
29592959

29602960
/**
2961-
Expression expression;
2961+
IfCondition condition;
29622962
Statement statement;
29632963
**/
29642964

29652965
with(switchStatement)
29662966
{
29672967
newThing(What.other);
29682968
isFinal ? put(" final switch(") : put("switch(");
2969-
format(expression);
2969+
format(condition);
29702970
put(")");
29712971

29722972
bool needBlock = statement.statementNoCaseNoDefault &&

src/dparse/parser.d

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6755,17 +6755,13 @@ class Parser
67556755
// DCD #453
67566756
// with just `switch(stuff` returns a non null node,
67576757
// which allows DCD to gives completion on `stuff`.
6758-
if (auto e = parseExpression())
6758+
mixin(parseNodeQ!(`node.condition`, `IfCondition`));
6759+
if (currentIs(tok!")"))
67596760
{
6760-
node.expression = e;
6761-
if (currentIs(tok!")"))
6762-
{
6763-
advance();
6764-
// returns null only from here.
6765-
mixin(parseNodeQ!(`node.statement`, `Statement`));
6766-
}
6761+
advance();
6762+
// returns null only from here.
6763+
mixin(parseNodeQ!(`node.statement`, `Statement`));
67676764
}
6768-
else error("Expression expected after `switch(`", false);
67696765
node.tokens = tokens[startIndex .. index];
67706766
return node;
67716767
}

test/ast_checks/switch_condition.d

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
void a()
2+
{
3+
switch (auto line = readln)
4+
{
5+
default:
6+
line.strip;
7+
}
8+
}
9+
10+
void b()
11+
{
12+
switch (scope line = readln)
13+
{
14+
default:
15+
line.strip;
16+
}
17+
}
18+
19+
void c()
20+
{
21+
switch (const line = readln)
22+
{
23+
default:
24+
line.strip;
25+
}
26+
}
27+
28+
void d()
29+
{
30+
switch (const inout string line = readln)
31+
{
32+
default:
33+
line.strip;
34+
}
35+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//functionDeclaration[name = 'a']//functionBody//switchStatement/condition/auto
2+
not(//functionDeclaration[name = 'a']//functionBody//switchStatement/condition/scope)
3+
//functionDeclaration[name = 'a']//functionBody//switchStatement/condition/identifier[text()='line']
4+
//functionDeclaration[name = 'a']//functionBody//switchStatement/condition/unaryExpression//identifier[text()='readln']
5+
//functionDeclaration[name = 'a']//functionBody//switchStatement/statement//defaultStatement//identifier[text()='line']
6+
//functionDeclaration[name = 'a']//functionBody//switchStatement/statement//defaultStatement//identifier[text()='strip']
7+
not(//functionDeclaration[name = 'b']//functionBody//switchStatement/condition/auto)
8+
//functionDeclaration[name = 'b']//functionBody//switchStatement/condition/scope
9+
//functionDeclaration[name = 'b']//functionBody//switchStatement/condition/identifier[text()='line']
10+
//functionDeclaration[name = 'b']//functionBody//switchStatement/condition/unaryExpression//identifier[text()='readln']
11+
//functionDeclaration[name = 'b']//functionBody//switchStatement/statement//defaultStatement//identifier[text()='line']
12+
//functionDeclaration[name = 'b']//functionBody//switchStatement/statement//defaultStatement//identifier[text()='strip']
13+
not(//functionDeclaration[name = 'c']//functionBody//switchStatement/condition/auto)
14+
not(//functionDeclaration[name = 'c']//functionBody//switchStatement/condition/scope)
15+
//functionDeclaration[name = 'c']//functionBody//switchStatement/condition/typeConstructor[text()='const']
16+
//functionDeclaration[name = 'c']//functionBody//switchStatement/condition/identifier[text()='line']
17+
//functionDeclaration[name = 'c']//functionBody//switchStatement/condition/unaryExpression//identifier[text()='readln']
18+
//functionDeclaration[name = 'c']//functionBody//switchStatement/statement//defaultStatement//identifier[text()='line']
19+
//functionDeclaration[name = 'c']//functionBody//switchStatement/statement//defaultStatement//identifier[text()='strip']
20+
not(//functionDeclaration[name = 'd']//functionBody//switchStatement/condition/auto)
21+
not(//functionDeclaration[name = 'd']//functionBody//switchStatement/condition/scope)
22+
//functionDeclaration[name = 'd']//functionBody//switchStatement/condition/typeConstructor[text()='const']
23+
//functionDeclaration[name = 'd']//functionBody//switchStatement/condition/typeConstructor[text()='inout']
24+
//functionDeclaration[name = 'd']//functionBody//switchStatement/condition/type[@pretty='string']
25+
//functionDeclaration[name = 'd']//functionBody//switchStatement/condition/identifier[text()='line']
26+
//functionDeclaration[name = 'd']//functionBody//switchStatement/condition/unaryExpression//identifier[text()='readln']
27+
//functionDeclaration[name = 'd']//functionBody//switchStatement/statement//defaultStatement//identifier[text()='line']
28+
//functionDeclaration[name = 'd']//functionBody//switchStatement/statement//defaultStatement//identifier[text()='strip']
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import std : writeln, format;
2+
3+
int get()
4+
{
5+
return 1;
6+
}
7+
8+
void main()
9+
{
10+
switch (auto x = get()) {
11+
default:
12+
writeln("inside switch: ", x);
13+
}
14+
}

0 commit comments

Comments
 (0)