Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions changelog/dmd.with-colon.dd
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Adds the with-colon statement.

Like at the global declarations level, a `with (expression) :` can be used to create
a scope until a `}` is encountered.

---
{
with (E):
statement;
statement;
}
---

which is equivalent to:

---
{
with (E)
{
statement;
statement;
}
}
---
44 changes: 36 additions & 8 deletions compiler/src/dmd/parse.d
Original file line number Diff line number Diff line change
Expand Up @@ -5777,7 +5777,7 @@

/*****************************************
* Input:
* flags PSxxxx
* flags = ParseStatementFlags
* Output:
* pEndloc if { ... statements ... }, store location of closing brace, otherwise loc of last token of statement
*/
Expand Down Expand Up @@ -6585,20 +6585,48 @@
s = new AST.SynchronizedStatement(loc, exp, _body);
break;
}
case TOK.with_:
case TOK.with_: // https://dlang.org/spec/statement.html#with-statement
{
AST.Expression exp;
AST.Statement _body;
Loc endloc = loc;
Loc withLoc = loc;

nextToken();
check(TOK.leftParenthesis);
exp = parseExpression();
AST.Expression exp = parseExpression();
closeCondition("with", null, exp);
_body = parseStatement(ParseStatementFlags.scope_, null, &endloc);
s = new AST.WithStatement(loc, exp, _body, endloc);

if (token.value == TOK.colon) // with (Expression) : StatementList
{
nextToken();

const lookingForElseSave = lookingForElse;
lookingForElse = Loc.initial;

auto statements = new AST.Statements();
while (token.value != TOK.rightCurly && token.value != TOK.endOfFile)
{
statements.push(parseStatement(ParseStatementFlags.curlyScope | ParseStatementFlags.semiOk));
}

lookingForElse = lookingForElseSave;

s = new AST.CompoundStatement(loc, statements);
s = new AST.ScopeStatement(loc, s, token.loc);
s = new AST.WithStatement(loc, exp, s, withLoc);

if (token.value == TOK.endOfFile)
{
error(token.loc, "matching `}` expected following compound with statement, not `%s`",

Check warning on line 6618 in compiler/src/dmd/parse.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/parse.d#L6618

Added line #L6618 was not covered by tests
token.toChars());
eSink.errorSupplemental(withLoc, "unmatched `with (exp):`");
s = new AST.ErrorStatement();

Check warning on line 6621 in compiler/src/dmd/parse.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/parse.d#L6620-L6621

Added lines #L6620 - L6621 were not covered by tests
}
break;
}
AST.Statement _body = parseStatement(ParseStatementFlags.scope_, null, &withLoc);
s = new AST.WithStatement(loc, exp, _body, withLoc);
break;
}

case TOK.try_:
{
AST.Statement _body;
Expand Down
20 changes: 20 additions & 0 deletions compiler/test/compilable/scope.d
Original file line number Diff line number Diff line change
Expand Up @@ -375,3 +375,23 @@ struct Result
auto r = Result(&s);
r.save();
}

/********************************************/

void withOmatic()
{
enum E { A, B }
E e;

{
with (E):
int i;
if (A)
return;
}
{
with (e)
if (A)
return;
}
}
16 changes: 16 additions & 0 deletions compiler/test/fail_compilation/withspoon.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* TEST_OUTPUT:
---
fail_compilation/withspoon.d(17): Error: matching `}` expected following compound with statement, not `End of File`
fail_compilation/withspoon.d(15): unmatched `with (exp):`
fail_compilation/withspoon.d(17): Error: matching `}` expected following compound statement, not `End of File`
fail_compilation/withspoon.d(14): unmatched `{`
---
*/


enum E { A, B }

void test2()
{
with (E):
return;