diff --git a/src/dmd/cli.d b/src/dmd/cli.d index 9a2886b80888..c34b07194e38 100644 --- a/src/dmd/cli.d +++ b/src/dmd/cli.d @@ -792,6 +792,8 @@ dmd -cov -unittest myprog.d "`in` on parameters means `scope const [ref]` and accepts rvalues"), Feature("inclusiveincontracts", "inclusiveInContracts", "'in' contracts of overridden methods must be a superset of parent contract"), + Feature("shortenedMethods", "shortenedMethods", + "allow use of => for methods and top-level functions in addition to lambdas"), // DEPRECATED previews // trigger deprecation message once D repositories don't use this flag anymore Feature("markdown", "markdown", "enable Markdown replacements in Ddoc", false, false), diff --git a/src/dmd/frontend.h b/src/dmd/frontend.h index 815131630e4e..58d7d143ed33 100644 --- a/src/dmd/frontend.h +++ b/src/dmd/frontend.h @@ -7033,6 +7033,7 @@ struct Param bool useExceptions; bool noSharedAccess; bool previewIn; + bool shortenedMethods; bool betterC; bool addMain; bool allInst; @@ -7173,6 +7174,7 @@ struct Param useExceptions(true), noSharedAccess(), previewIn(), + shortenedMethods(), betterC(), addMain(), allInst(), diff --git a/src/dmd/globals.d b/src/dmd/globals.d index f8e32b21e905..e3871659b163 100644 --- a/src/dmd/globals.d +++ b/src/dmd/globals.d @@ -190,6 +190,7 @@ extern (C++) struct Param bool useExceptions = true; // support exception handling bool noSharedAccess; // read/write access to shared memory objects bool previewIn; // `in` means `[ref] scope const`, accepts rvalues + bool shortenedMethods; // allow => in normal function declarations bool betterC; // be a "better C" compiler; no dependency on D runtime bool addMain; // add a default main() function bool allInst; // generate code for all template instantiations diff --git a/src/dmd/globals.h b/src/dmd/globals.h index 248847317bac..16ae5888be6e 100644 --- a/src/dmd/globals.h +++ b/src/dmd/globals.h @@ -170,6 +170,7 @@ struct Param bool useExceptions; // support exception handling bool noSharedAccess; // read/write access to shared memory objects bool previewIn; // `in` means `scope const`, perhaps `ref`, accepts rvalues + bool shortenedMethods; // allow => in normal function declarations bool betterC; // be a "better C" compiler; no dependency on D runtime bool addMain; // add a default main() function bool allInst; // generate code for all template instantiations diff --git a/src/dmd/parse.d b/src/dmd/parse.d index 5cfb77ec5891..62d835f5235a 100644 --- a/src/dmd/parse.d +++ b/src/dmd/parse.d @@ -848,7 +848,7 @@ final class Parser(AST) : Lexer Token* tk; if (token.value == TOK.identifier && skipParens(peek(&token), &tk) && skipAttributes(tk, &tk) && (tk.value == TOK.leftParentheses || tk.value == TOK.leftCurly || tk.value == TOK.in_ || - tk.value == TOK.out_ || tk.value == TOK.do_ || + tk.value == TOK.out_ || tk.value == TOK.do_ || tk.value == TOK.goesTo || tk.value == TOK.identifier && tk.ident == Id._body)) { version (none) @@ -4753,7 +4753,7 @@ final class Parser(AST) : Lexer Token* tk; if ((storage_class || udas) && token.value == TOK.identifier && skipParens(peek(&token), &tk) && skipAttributes(tk, &tk) && - (tk.value == TOK.leftParentheses || tk.value == TOK.leftCurly || tk.value == TOK.in_ || tk.value == TOK.out_ || + (tk.value == TOK.leftParentheses || tk.value == TOK.leftCurly || tk.value == TOK.in_ || tk.value == TOK.out_ || tk.value == TOK.goesTo || tk.value == TOK.do_ || tk.value == TOK.identifier && tk.ident == Id._body)) { version (none) @@ -5119,6 +5119,18 @@ final class Parser(AST) : Lexer L1: switch (token.value) { + case TOK.goesTo: + if (requireDo) + error("missing `do { ... }` after `in` or `out`"); + if (!global.params.shortenedMethods) + error("=> shortened method not enabled, compile with compiler switch `-preview=shortenedMethods`"); + const returnloc = token.loc; + nextToken(); + f.fbody = new AST.ReturnStatement(returnloc, parseExpression()); + f.endloc = token.loc; + check(TOK.semicolon); + break; + case TOK.leftCurly: if (requireDo) error("missing `do { ... }` after `in` or `out`"); diff --git a/test/compilable/previewhelp.d b/test/compilable/previewhelp.d index aa5c22a416d8..391adca8fc42 100644 --- a/test/compilable/previewhelp.d +++ b/test/compilable/previewhelp.d @@ -17,5 +17,6 @@ Upcoming language changes listed by -preview=name: =nosharedaccess disable access to shared memory objects =in `in` on parameters means `scope const [ref]` and accepts rvalues =inclusiveincontracts 'in' contracts of overridden methods must be a superset of parent contract + =shortenedMethods allow use of => for methods and top-level functions in addition to lambdas ---- */ diff --git a/test/compilable/shortened_methods.d b/test/compilable/shortened_methods.d new file mode 100644 index 000000000000..5a7ac8749d85 --- /dev/null +++ b/test/compilable/shortened_methods.d @@ -0,0 +1,33 @@ +// REQUIRED_ARGS: -preview=shortenedMethods +class A { + int _x = 34; + // short syntax works in all contexts + @property x() => _x; + @property x(int v) => _x = v; + + // including with contracts + @property y() in(true) => _x; + + // or other auto returns + auto foo() @safe => assert(0); + + // or normal method defintions + bool isNull() => this is null; +} + +class B : A{ + // short syntax also overrides the same as long syntax + override bool isNull() => this !is null; +} + +static assert((new A).x == 34); + +string test() => "hello"; // works at any scope + +static assert(test() == "hello"); // works normally +static assert(is(typeof(&test) == string function())); // same normal type + +void func() { + int a; + int nested() => a; // and at nested scopes too +}