Skip to content

Commit 3fbb7b3

Browse files
committed
Fix #471, implement auto ref lambdas
1 parent 71d64cf commit 3fbb7b3

File tree

6 files changed

+91
-28
lines changed

6 files changed

+91
-28
lines changed

src/dparse/ast.d

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1807,10 +1807,24 @@ final class FunctionLiteralExpression : ExpressionNode
18071807
/** */ Parameters parameters;
18081808
/** */ Token identifier;
18091809
/** */ Type returnType;
1810-
/** */ bool isReturnRef;
1810+
/** */ ReturnRefType returnRefType;
18111811
/** */ size_t line;
18121812
/** */ size_t column;
18131813
mixin OpEquals;
1814+
1815+
deprecated("Use returnRefType") bool isReturnRef() const
1816+
{
1817+
return returnRefType == ReturnRefType.ref_
1818+
|| returnRefType == ReturnRefType.autoRef;
1819+
}
1820+
}
1821+
1822+
///
1823+
enum ReturnRefType : ubyte
1824+
{
1825+
noRef = 0,
1826+
ref_ = 1,
1827+
autoRef = 2
18141828
}
18151829

18161830
///

src/dparse/astprinter.d

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -423,10 +423,25 @@ class XMLPrinter : ASTVisitor
423423

424424
override void visit(const FunctionLiteralExpression functionLiteralExpression)
425425
{
426-
output.writeln("<functionLiteralExpression type=\"", functionLiteralExpression.functionOrDelegate != tok!""
427-
? str(functionLiteralExpression.functionOrDelegate) : "auto", "\">");
428-
functionLiteralExpression.accept(this);
429-
output.writeln("</functionLiteralExpression>");
426+
with (functionLiteralExpression)
427+
{
428+
output.write("<functionLiteralExpression type=\"",
429+
functionOrDelegate != tok!"" ? str(functionOrDelegate) : "auto",
430+
"\"");
431+
if (identifier.type != tok!"")
432+
output.write(" identifier=\"", identifier, "\"");
433+
output.write(" line=\"", line, "\"");
434+
output.write(" column=\"", column, "\"");
435+
final switch (returnRefType) with (ReturnRefType)
436+
{
437+
case noRef: break;
438+
case ref_: output.write(" ref=\"ref\""); break;
439+
case autoRef: output.write(" ref=\"auto ref\""); break;
440+
}
441+
output.writeln(">");
442+
accept(this);
443+
output.writeln("</functionLiteralExpression>");
444+
}
430445
}
431446

432447
override void visit(const GotoStatement gotoStatement)

src/dparse/formatter.d

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1554,23 +1554,17 @@ class Formatter(Sink)
15541554
void format(const FunctionLiteralExpression functionLiteralExpression)
15551555
{
15561556
debug(verbose) writeln("FunctionLiteralExpression");
1557-
/**
1558-
ExpressionNode assignExpression;
1559-
FunctionAttribute[] functionAttributes;
1560-
SpecifiedFunctionBody specifiedFunctionBody;
1561-
IdType functionOrDelegate;
1562-
MemberFunctionAttribute[] memberFunctionAttributes;
1563-
Parameters parameters;
1564-
Token identifier;
1565-
Type returnType;
1566-
bool isReturnRef;
1567-
**/
15681557

15691558
with(functionLiteralExpression)
15701559
{
15711560
put(tokenRep(functionOrDelegate));
15721561

1573-
if (isReturnRef) put("ref ");
1562+
final switch (returnRefType)
1563+
{
1564+
case ReturnRefType.noRef: break;
1565+
case ReturnRefType.ref_: put("ref "); break;
1566+
case ReturnRefType.autoRef: put("auto ref "); break;
1567+
}
15741568
//if (returnType || parameters)
15751569
// space();
15761570

src/dparse/parser.d

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3581,14 +3581,14 @@ class Parser
35813581
* Parses a FunctionLiteralExpression
35823582
*
35833583
* $(GRAMMAR $(RULEDEF functionLiteralExpression):
3584-
* | $(LITERAL 'delegate') $(LITERAL 'ref')? $(RULE type)? ($(RULE parameters) $(RULE functionAttribute)*)? $(RULE specifiedFunctionBody)
3585-
* | $(LITERAL 'function') $(LITERAL 'ref')? $(RULE type)? ($(RULE parameters) $(RULE functionAttribute)*)? $(RULE specifiedFunctionBody)
3586-
* | $(LITERAL 'ref')? $(RULE parameters) $(RULE functionAttribute)* $(RULE specifiedFunctionBody)
3584+
* | $(LITERAL 'delegate') $($(LITERAL 'auto')? LITERAL 'ref')? $(RULE type)? ($(RULE parameters) $(RULE functionAttribute)*)? $(RULE specifiedFunctionBody)
3585+
* | $(LITERAL 'function') $($(LITERAL 'auto')? LITERAL 'ref')? $(RULE type)? ($(RULE parameters) $(RULE functionAttribute)*)? $(RULE specifiedFunctionBody)
3586+
* | $($(LITERAL 'auto')? LITERAL 'ref')? $(RULE parameters) $(RULE functionAttribute)* $(RULE specifiedFunctionBody)
35873587
* | $(RULE specifiedFunctionBody)
35883588
* | $(LITERAL Identifier) $(LITERAL '=>') $(RULE assignExpression)
3589-
* | $(LITERAL 'function') $(LITERAL 'ref')? $(RULE type)? $(RULE parameters) $(RULE functionAttribute)* $(LITERAL '=>') $(RULE assignExpression)
3590-
* | $(LITERAL 'delegate') $(LITERAL 'ref')? $(RULE type)? $(RULE parameters) $(RULE functionAttribute)* $(LITERAL '=>') $(RULE assignExpression)
3591-
* | $(LITERAL 'ref')? $(RULE parameters) $(RULE functionAttribute)* $(LITERAL '=>') $(RULE assignExpression)
3589+
* | $(LITERAL 'function') $($(LITERAL 'auto')? LITERAL 'ref')? $(RULE type)? $(RULE parameters) $(RULE functionAttribute)* $(LITERAL '=>') $(RULE assignExpression)
3590+
* | $(LITERAL 'delegate') $($(LITERAL 'auto')? LITERAL 'ref')? $(RULE type)? $(RULE parameters) $(RULE functionAttribute)* $(LITERAL '=>') $(RULE assignExpression)
3591+
* | $($(LITERAL 'auto')? LITERAL 'ref')? $(RULE parameters) $(RULE functionAttribute)* $(LITERAL '=>') $(RULE assignExpression)
35923592
* ;)
35933593
*/
35943594
FunctionLiteralExpression parseFunctionLiteralExpression()
@@ -3601,10 +3601,16 @@ class Parser
36013601
if (currentIsOneOf(tok!"function", tok!"delegate"))
36023602
{
36033603
node.functionOrDelegate = advance().type;
3604-
if (currentIs(tok!"ref"))
3604+
if (currentIs(tok!"auto"))
3605+
{
3606+
advance();
3607+
expect(tok!"ref");
3608+
node.returnRefType = ReturnRefType.autoRef;
3609+
}
3610+
else if (currentIs(tok!"ref"))
36053611
{
36063612
advance();
3607-
node.isReturnRef = true;
3613+
node.returnRefType = ReturnRefType.ref_;
36083614
}
36093615
if (!currentIsOneOf(tok!"(", tok!"in", tok!"do",
36103616
tok!"out", tok!"{", tok!"=>") && current.text != "body")
@@ -3618,12 +3624,20 @@ class Parser
36183624
node.tokens = tokens[startIndex .. index];
36193625
return node;
36203626
}
3621-
else if (currentIs(tok!"(") || currentIs(tok!"ref") && peekIs(tok!"("))
3627+
else if (currentIs(tok!"(")
3628+
|| (currentIs(tok!"ref") && peekIs(tok!"("))
3629+
|| (currentIs(tok!"auto") && peekAre(tok!"ref", tok!"(")))
36223630
{
3623-
if (currentIs(tok!"ref"))
3631+
if (currentIs(tok!"auto"))
3632+
{
3633+
advance();
3634+
expect(tok!"ref");
3635+
node.returnRefType = ReturnRefType.autoRef;
3636+
}
3637+
else if (currentIs(tok!"ref"))
36243638
{
36253639
advance();
3626-
node.isReturnRef = true;
3640+
node.returnRefType = ReturnRefType.ref_;
36273641
}
36283642
mixin(parseNodeQ!(`node.parameters`, `Parameters`));
36293643
StackBuffer memberFunctionAttributes;
@@ -5684,6 +5698,13 @@ class Parser
56845698
else
56855699
mixin(parseNodeQ!(`node.arrayLiteral`, `ArrayLiteral`));
56865700
break;
5701+
case tok!"auto":
5702+
if (peekAre(tok!"ref", tok!"("))
5703+
{
5704+
mixin(parseNodeQ!(`node.functionLiteralExpression`, `FunctionLiteralExpression`));
5705+
break;
5706+
}
5707+
else goto default;
56875708
case tok!"ref":
56885709
if (peekIs(tok!"("))
56895710
{

test/ast_checks/issue471.d

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
void foo()
2+
{
3+
auto bar1 = () => 4;
4+
auto bar2 = ref () => 4;
5+
auto bar3 = auto ref () => 4;
6+
auto bar4 = function () => 4;
7+
auto bar5 = function ref () => 4;
8+
auto bar6 = function auto ref () => 4;
9+
}

test/ast_checks/issue471.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//variableDeclaration//autoDeclarationPart//name[text()="bar1"]/../initializer//functionLiteralExpression
2+
not(//variableDeclaration//autoDeclarationPart//name[text()="bar1"]/../initializer//functionLiteralExpression[@ref])
3+
//variableDeclaration//autoDeclarationPart//name[text()="bar2"]/../initializer//functionLiteralExpression[@ref]
4+
//variableDeclaration//autoDeclarationPart//name[text()="bar2"]/../initializer//functionLiteralExpression[@ref="ref"]
5+
//variableDeclaration//autoDeclarationPart//name[text()="bar3"]/../initializer//functionLiteralExpression[@ref="auto ref"]
6+
//variableDeclaration//autoDeclarationPart//name[text()="bar4"]/../initializer//functionLiteralExpression
7+
not(//variableDeclaration//autoDeclarationPart//name[text()="bar4"]/../initializer//functionLiteralExpression[@ref])
8+
//variableDeclaration//autoDeclarationPart//name[text()="bar5"]/../initializer//functionLiteralExpression[@ref]
9+
//variableDeclaration//autoDeclarationPart//name[text()="bar5"]/../initializer//functionLiteralExpression[@ref="ref"]
10+
//variableDeclaration//autoDeclarationPart//name[text()="bar6"]/../initializer//functionLiteralExpression[@ref="auto ref"]

0 commit comments

Comments
 (0)