authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2019-08-16 12:24:06+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-16 06:17:28-07:00
log2151f84d59f8af6e28570cb01a3a134c7b068fa2
tree8ad09e707b33b7f53ed7964aa24bd4fd426ba6a7
parent1e3b6816a8929bb141fb2157197077d74656e7ca

implement new async syntax in self-hosted compiler


8 files changed, 41 insertions(+), 145 deletions(-)

doc/langref.html.in+2-4
...@@ -9987,7 +9987,7 @@ TypeExpr &lt;- PrefixTypeOp* ErrorUnionExpr...@@ -9987,7 +9987,7 @@ TypeExpr &lt;- PrefixTypeOp* ErrorUnionExpr
9987ErrorUnionExpr &lt;- SuffixExpr (EXCLAMATIONMARK TypeExpr)?9987ErrorUnionExpr &lt;- SuffixExpr (EXCLAMATIONMARK TypeExpr)?
99889988
9989SuffixExpr9989SuffixExpr
9990 &lt;- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArguments9990 &lt;- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments
9991 / PrimaryTypeExpr (SuffixOp / FnCallArguments)*9991 / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
99929992
9993PrimaryTypeExpr9993PrimaryTypeExpr
...@@ -10063,7 +10063,7 @@ FnCC...@@ -10063,7 +10063,7 @@ FnCC
10063 &lt;- KEYWORD_nakedcc10063 &lt;- KEYWORD_nakedcc
10064 / KEYWORD_stdcallcc10064 / KEYWORD_stdcallcc
10065 / KEYWORD_extern10065 / KEYWORD_extern
10066 / KEYWORD_async (LARROW TypeExpr RARROW)?10066 / KEYWORD_async
1006710067
10068ParamDecl &lt;- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType10068ParamDecl &lt;- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType
1006910069
...@@ -10168,8 +10168,6 @@ SuffixOp...@@ -10168,8 +10168,6 @@ SuffixOp
10168 / DOTASTERISK10168 / DOTASTERISK
10169 / DOTQUESTIONMARK10169 / DOTQUESTIONMARK
1017010170
10171AsyncPrefix &lt;- KEYWORD_async (LARROW PrefixExpr RARROW)?
10172
10173FnCallArguments &lt;- LPAREN ExprList RPAREN10171FnCallArguments &lt;- LPAREN ExprList RPAREN
1017410172
10175# Ptr specific10173# Ptr specific
src-self-hosted/ir.zig-1
...@@ -1181,7 +1181,6 @@ pub const Builder = struct {...@@ -1181,7 +1181,6 @@ pub const Builder = struct {
1181 ast.Node.Id.ErrorTag => return error.Unimplemented,1181 ast.Node.Id.ErrorTag => return error.Unimplemented,
1182 ast.Node.Id.AsmInput => return error.Unimplemented,1182 ast.Node.Id.AsmInput => return error.Unimplemented,
1183 ast.Node.Id.AsmOutput => return error.Unimplemented,1183 ast.Node.Id.AsmOutput => return error.Unimplemented,
1184 ast.Node.Id.AsyncAttribute => return error.Unimplemented,
1185 ast.Node.Id.ParamDecl => return error.Unimplemented,1184 ast.Node.Id.ParamDecl => return error.Unimplemented,
1186 ast.Node.Id.FieldInitializer => return error.Unimplemented,1185 ast.Node.Id.FieldInitializer => return error.Unimplemented,
1187 ast.Node.Id.EnumLiteral => return error.Unimplemented,1186 ast.Node.Id.EnumLiteral => return error.Unimplemented,
src-self-hosted/translate_c.zig+1-2
...@@ -1037,7 +1037,7 @@ fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp {...@@ -1037,7 +1037,7 @@ fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node) !*ast.Node.SuffixOp {
1037 .op = ast.Node.SuffixOp.Op{1037 .op = ast.Node.SuffixOp.Op{
1038 .Call = ast.Node.SuffixOp.Op.Call{1038 .Call = ast.Node.SuffixOp.Op.Call{
1039 .params = ast.Node.SuffixOp.Op.Call.ParamList.init(c.a()),1039 .params = ast.Node.SuffixOp.Op.Call.ParamList.init(c.a()),
1040 .async_attr = null,1040 .async_token = null,
1041 },1041 },
1042 },1042 },
1043 .rtoken = undefined, // set after appending args1043 .rtoken = undefined, // set after appending args
...@@ -1355,7 +1355,6 @@ fn finishTransFnProto(...@@ -1355,7 +1355,6 @@ fn finishTransFnProto(
1355 .var_args_token = null, // TODO this field is broken in the AST data model1355 .var_args_token = null, // TODO this field is broken in the AST data model
1356 .extern_export_inline_token = extern_export_inline_tok,1356 .extern_export_inline_token = extern_export_inline_tok,
1357 .cc_token = cc_tok,1357 .cc_token = cc_tok,
1358 .async_attr = null,
1359 .body_node = null,1358 .body_node = null,
1360 .lib_name = null,1359 .lib_name = null,
1361 .align_expr = null,1360 .align_expr = null,
src/parser.cpp+15-29
...@@ -113,7 +113,6 @@ static AstNode *ast_parse_multiply_op(ParseContext *pc);...@@ -113,7 +113,6 @@ static AstNode *ast_parse_multiply_op(ParseContext *pc);
113static AstNode *ast_parse_prefix_op(ParseContext *pc);113static AstNode *ast_parse_prefix_op(ParseContext *pc);
114static AstNode *ast_parse_prefix_type_op(ParseContext *pc);114static AstNode *ast_parse_prefix_type_op(ParseContext *pc);
115static AstNode *ast_parse_suffix_op(ParseContext *pc);115static AstNode *ast_parse_suffix_op(ParseContext *pc);
116static AstNode *ast_parse_async_prefix(ParseContext *pc);
117static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc);116static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc);
118static AstNode *ast_parse_array_type_start(ParseContext *pc);117static AstNode *ast_parse_array_type_start(ParseContext *pc);
119static AstNode *ast_parse_ptr_type_start(ParseContext *pc);118static AstNode *ast_parse_ptr_type_start(ParseContext *pc);
...@@ -1389,22 +1388,18 @@ static AstNode *ast_parse_error_union_expr(ParseContext *pc) {...@@ -1389,22 +1388,18 @@ static AstNode *ast_parse_error_union_expr(ParseContext *pc) {
1389}1388}
13901389
1391// SuffixExpr1390// SuffixExpr
1392// <- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArguments1391// <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments
1393// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*1392// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
1394static AstNode *ast_parse_suffix_expr(ParseContext *pc) {1393static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
1395 AstNode *async_call = ast_parse_async_prefix(pc);1394 Token *async_token = eat_token_if(pc, TokenIdKeywordAsync);
1396 if (async_call != nullptr) {1395 if (async_token != nullptr) {
1397 if (eat_token_if(pc, TokenIdKeywordFn) != nullptr) {1396 if (eat_token_if(pc, TokenIdKeywordFn) != nullptr) {
1398 // HACK: If we see the keyword `fn`, then we assume that1397 // HACK: If we see the keyword `fn`, then we assume that
1399 // we are parsing an async fn proto, and not a call.1398 // we are parsing an async fn proto, and not a call.
1400 // We therefore put back all tokens consumed by the async1399 // We therefore put back all tokens consumed by the async
1401 // prefix...1400 // prefix...
1402 // HACK: This loop is not actually enough to put back all the1401 put_back_token(pc);
1403 // tokens. Let's hope this is fine for most code right now1402 put_back_token(pc);
1404 // and wait till we get the async rework for a syntax update.
1405 do {
1406 put_back_token(pc);
1407 } while (peek_token(pc)->id != TokenIdKeywordAsync);
14081403
1409 return ast_parse_primary_type_expr(pc);1404 return ast_parse_primary_type_expr(pc);
1410 }1405 }
...@@ -1446,10 +1441,14 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {...@@ -1446,10 +1441,14 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
1446 ast_invalid_token_error(pc, peek_token(pc));1441 ast_invalid_token_error(pc, peek_token(pc));
14471442
1448 assert(args->type == NodeTypeFnCallExpr);1443 assert(args->type == NodeTypeFnCallExpr);
1449 async_call->data.fn_call_expr.fn_ref_expr = child;1444
1450 async_call->data.fn_call_expr.params = args->data.fn_call_expr.params;1445 AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, async_token);
1451 async_call->data.fn_call_expr.is_builtin = false;1446 res->data.fn_call_expr.is_async = true;
1452 return async_call;1447 res->data.fn_call_expr.seen = false;
1448 res->data.fn_call_expr.fn_ref_expr = child;
1449 res->data.fn_call_expr.params = args->data.fn_call_expr.params;
1450 res->data.fn_call_expr.is_builtin = false;
1451 return res;
1453 }1452 }
14541453
1455 AstNode *res = ast_parse_primary_type_expr(pc);1454 AstNode *res = ast_parse_primary_type_expr(pc);
...@@ -1501,7 +1500,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {...@@ -1501,7 +1500,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
1501// <- BUILTINIDENTIFIER FnCallArguments1500// <- BUILTINIDENTIFIER FnCallArguments
1502// / CHAR_LITERAL1501// / CHAR_LITERAL
1503// / ContainerDecl1502// / ContainerDecl
1504// / DOT IDENTIFIER1503// / DOT IDENTIFIER
1505// / ErrorSetDecl1504// / ErrorSetDecl
1506// / FLOAT1505// / FLOAT
1507// / FnProto1506// / FnProto
...@@ -2016,7 +2015,7 @@ static AstNode *ast_parse_link_section(ParseContext *pc) {...@@ -2016,7 +2015,7 @@ static AstNode *ast_parse_link_section(ParseContext *pc) {
2016// <- KEYWORD_nakedcc2015// <- KEYWORD_nakedcc
2017// / KEYWORD_stdcallcc2016// / KEYWORD_stdcallcc
2018// / KEYWORD_extern2017// / KEYWORD_extern
2019// / KEYWORD_async (LARROW TypeExpr RARROW)?2018// / KEYWORD_async
2020static Optional<AstNodeFnProto> ast_parse_fn_cc(ParseContext *pc) {2019static Optional<AstNodeFnProto> ast_parse_fn_cc(ParseContext *pc) {
2021 AstNodeFnProto res = {};2020 AstNodeFnProto res = {};
2022 if (eat_token_if(pc, TokenIdKeywordNakedCC) != nullptr) {2021 if (eat_token_if(pc, TokenIdKeywordNakedCC) != nullptr) {
...@@ -2657,19 +2656,6 @@ static AstNode *ast_parse_suffix_op(ParseContext *pc) {...@@ -2657,19 +2656,6 @@ static AstNode *ast_parse_suffix_op(ParseContext *pc) {
2657 return nullptr;2656 return nullptr;
2658}2657}
26592658
2660// AsyncPrefix <- KEYWORD_async (LARROW PrefixExpr RARROW)?
2661static AstNode *ast_parse_async_prefix(ParseContext *pc) {
2662 Token *async = eat_token_if(pc, TokenIdKeywordAsync);
2663 if (async == nullptr)
2664 return nullptr;
2665
2666 AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, async);
2667 res->data.fn_call_expr.is_async = true;
2668 res->data.fn_call_expr.seen = false;
2669
2670 return res;
2671}
2672
2673// FnCallArguments <- LPAREN ExprList RPAREN2659// FnCallArguments <- LPAREN ExprList RPAREN
2674static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc) {2660static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc) {
2675 Token *paren = eat_token_if(pc, TokenIdLParen);2661 Token *paren = eat_token_if(pc, TokenIdLParen);
std/zig/ast.zig+2-35
...@@ -434,7 +434,6 @@ pub const Node = struct {...@@ -434,7 +434,6 @@ pub const Node = struct {
434 ErrorTag,434 ErrorTag,
435 AsmInput,435 AsmInput,
436 AsmOutput,436 AsmOutput,
437 AsyncAttribute,
438 ParamDecl,437 ParamDecl,
439 FieldInitializer,438 FieldInitializer,
440 };439 };
...@@ -838,36 +837,6 @@ pub const Node = struct {...@@ -838,36 +837,6 @@ pub const Node = struct {
838 }837 }
839 };838 };
840839
841 pub const AsyncAttribute = struct {
842 base: Node,
843 async_token: TokenIndex,
844 allocator_type: ?*Node,
845 rangle_bracket: ?TokenIndex,
846
847 pub fn iterate(self: *AsyncAttribute, index: usize) ?*Node {
848 var i = index;
849
850 if (self.allocator_type) |allocator_type| {
851 if (i < 1) return allocator_type;
852 i -= 1;
853 }
854
855 return null;
856 }
857
858 pub fn firstToken(self: *const AsyncAttribute) TokenIndex {
859 return self.async_token;
860 }
861
862 pub fn lastToken(self: *const AsyncAttribute) TokenIndex {
863 if (self.rangle_bracket) |rangle_bracket| {
864 return rangle_bracket;
865 }
866
867 return self.async_token;
868 }
869 };
870
871 pub const FnProto = struct {840 pub const FnProto = struct {
872 base: Node,841 base: Node,
873 doc_comments: ?*DocComment,842 doc_comments: ?*DocComment,
...@@ -879,7 +848,6 @@ pub const Node = struct {...@@ -879,7 +848,6 @@ pub const Node = struct {
879 var_args_token: ?TokenIndex,848 var_args_token: ?TokenIndex,
880 extern_export_inline_token: ?TokenIndex,849 extern_export_inline_token: ?TokenIndex,
881 cc_token: ?TokenIndex,850 cc_token: ?TokenIndex,
882 async_attr: ?*AsyncAttribute,
883 body_node: ?*Node,851 body_node: ?*Node,
884 lib_name: ?*Node, // populated if this is an extern declaration852 lib_name: ?*Node, // populated if this is an extern declaration
885 align_expr: ?*Node, // populated if align(A) is present853 align_expr: ?*Node, // populated if align(A) is present
...@@ -935,7 +903,6 @@ pub const Node = struct {...@@ -935,7 +903,6 @@ pub const Node = struct {
935903
936 pub fn firstToken(self: *const FnProto) TokenIndex {904 pub fn firstToken(self: *const FnProto) TokenIndex {
937 if (self.visib_token) |visib_token| return visib_token;905 if (self.visib_token) |visib_token| return visib_token;
938 if (self.async_attr) |async_attr| return async_attr.firstToken();
939 if (self.extern_export_inline_token) |extern_export_inline_token| return extern_export_inline_token;906 if (self.extern_export_inline_token) |extern_export_inline_token| return extern_export_inline_token;
940 assert(self.lib_name == null);907 assert(self.lib_name == null);
941 if (self.cc_token) |cc_token| return cc_token;908 if (self.cc_token) |cc_token| return cc_token;
...@@ -1699,7 +1666,7 @@ pub const Node = struct {...@@ -1699,7 +1666,7 @@ pub const Node = struct {
16991666
1700 pub const Call = struct {1667 pub const Call = struct {
1701 params: ParamList,1668 params: ParamList,
1702 async_attr: ?*AsyncAttribute,1669 async_token: ?TokenIndex,
17031670
1704 pub const ParamList = SegmentedList(*Node, 2);1671 pub const ParamList = SegmentedList(*Node, 2);
1705 };1672 };
...@@ -1752,7 +1719,7 @@ pub const Node = struct {...@@ -1752,7 +1719,7 @@ pub const Node = struct {
17521719
1753 pub fn firstToken(self: *const SuffixOp) TokenIndex {1720 pub fn firstToken(self: *const SuffixOp) TokenIndex {
1754 switch (self.op) {1721 switch (self.op) {
1755 .Call => |*call_info| if (call_info.async_attr) |async_attr| return async_attr.firstToken(),1722 .Call => |*call_info| if (call_info.async_token) |async_token| return async_token,
1756 else => {},1723 else => {},
1757 }1724 }
1758 return self.lhs.firstToken();1725 return self.lhs.firstToken();
std/zig/parse.zig+17-52
...@@ -277,7 +277,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -277,7 +277,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
277277
278/// FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)278/// FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)
279fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {279fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
280 const cc = try parseFnCC(arena, it, tree);280 const cc = parseFnCC(arena, it, tree);
281 const fn_token = eatToken(it, .Keyword_fn) orelse {281 const fn_token = eatToken(it, .Keyword_fn) orelse {
282 if (cc == null) return null else return error.ParseError;282 if (cc == null) return null else return error.ParseError;
283 };283 };
...@@ -320,7 +320,6 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -320,7 +320,6 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
320 .var_args_token = var_args_token,320 .var_args_token = var_args_token,
321 .extern_export_inline_token = null,321 .extern_export_inline_token = null,
322 .cc_token = null,322 .cc_token = null,
323 .async_attr = null,
324 .body_node = null,323 .body_node = null,
325 .lib_name = null,324 .lib_name = null,
326 .align_expr = align_expr,325 .align_expr = align_expr,
...@@ -331,7 +330,6 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -331,7 +330,6 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
331 switch (kind) {330 switch (kind) {
332 .CC => |token| fn_proto_node.cc_token = token,331 .CC => |token| fn_proto_node.cc_token = token,
333 .Extern => |token| fn_proto_node.extern_export_inline_token = token,332 .Extern => |token| fn_proto_node.extern_export_inline_token = token,
334 .Async => |node| fn_proto_node.async_attr = node,
335 }333 }
336 }334 }
337335
...@@ -1092,10 +1090,19 @@ fn parseErrorUnionExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No...@@ -1092,10 +1090,19 @@ fn parseErrorUnionExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
1092}1090}
10931091
1094/// SuffixExpr1092/// SuffixExpr
1095/// <- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArguments1093/// <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments
1096/// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*1094/// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
1097fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {1095fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1098 if (try parseAsyncPrefix(arena, it, tree)) |async_node| {1096 if (eatToken(it, .Keyword_async)) |async_token| {
1097 if (eatToken(it, .Keyword_fn)) |token_fn| {
1098 // HACK: If we see the keyword `fn`, then we assume that
1099 // we are parsing an async fn proto, and not a call.
1100 // We therefore put back all tokens consumed by the async
1101 // prefix...
1102 putBackToken(it, token_fn);
1103 putBackToken(it, async_token);
1104 return parsePrimaryTypeExpr(arena, it, tree);
1105 }
1099 // TODO: Implement hack for parsing `async fn ...` in ast_parse_suffix_expr1106 // TODO: Implement hack for parsing `async fn ...` in ast_parse_suffix_expr
1100 var res = try expectNode(arena, it, tree, parsePrimaryTypeExpr, AstError{1107 var res = try expectNode(arena, it, tree, parsePrimaryTypeExpr, AstError{
1101 .ExpectedPrimaryTypeExpr = AstError.ExpectedPrimaryTypeExpr{ .token = it.index },1108 .ExpectedPrimaryTypeExpr = AstError.ExpectedPrimaryTypeExpr{ .token = it.index },
...@@ -1116,7 +1123,6 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1116,7 +1123,6 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1116 });1123 });
1117 return null;1124 return null;
1118 };1125 };
1119
1120 const node = try arena.create(Node.SuffixOp);1126 const node = try arena.create(Node.SuffixOp);
1121 node.* = Node.SuffixOp{1127 node.* = Node.SuffixOp{
1122 .base = Node{ .id = .SuffixOp },1128 .base = Node{ .id = .SuffixOp },
...@@ -1124,14 +1130,13 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1124,14 +1130,13 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1124 .op = Node.SuffixOp.Op{1130 .op = Node.SuffixOp.Op{
1125 .Call = Node.SuffixOp.Op.Call{1131 .Call = Node.SuffixOp.Op.Call{
1126 .params = params.list,1132 .params = params.list,
1127 .async_attr = async_node.cast(Node.AsyncAttribute).?,1133 .async_token = async_token,
1128 },1134 },
1129 },1135 },
1130 .rtoken = params.rparen,1136 .rtoken = params.rparen,
1131 };1137 };
1132 return &node.base;1138 return &node.base;
1133 }1139 }
1134
1135 if (try parsePrimaryTypeExpr(arena, it, tree)) |expr| {1140 if (try parsePrimaryTypeExpr(arena, it, tree)) |expr| {
1136 var res = expr;1141 var res = expr;
11371142
...@@ -1153,7 +1158,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1153,7 +1158,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1153 .op = Node.SuffixOp.Op{1158 .op = Node.SuffixOp.Op{
1154 .Call = Node.SuffixOp.Op.Call{1159 .Call = Node.SuffixOp.Op.Call{
1155 .params = params.list,1160 .params = params.list,
1156 .async_attr = null,1161 .async_token = null,
1157 },1162 },
1158 },1163 },
1159 .rtoken = params.rparen,1164 .rtoken = params.rparen,
...@@ -1653,36 +1658,18 @@ fn parseLinkSection(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -1653,36 +1658,18 @@ fn parseLinkSection(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
1653/// <- KEYWORD_nakedcc1658/// <- KEYWORD_nakedcc
1654/// / KEYWORD_stdcallcc1659/// / KEYWORD_stdcallcc
1655/// / KEYWORD_extern1660/// / KEYWORD_extern
1656/// / KEYWORD_async (LARROW TypeExpr RARROW)?1661/// / KEYWORD_async
1657fn parseFnCC(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?FnCC {1662fn parseFnCC(arena: *Allocator, it: *TokenIterator, tree: *Tree) ?FnCC {
1658 if (eatToken(it, .Keyword_nakedcc)) |token| return FnCC{ .CC = token };1663 if (eatToken(it, .Keyword_nakedcc)) |token| return FnCC{ .CC = token };
1659 if (eatToken(it, .Keyword_stdcallcc)) |token| return FnCC{ .CC = token };1664 if (eatToken(it, .Keyword_stdcallcc)) |token| return FnCC{ .CC = token };
1660 if (eatToken(it, .Keyword_extern)) |token| return FnCC{ .Extern = token };1665 if (eatToken(it, .Keyword_extern)) |token| return FnCC{ .Extern = token };
1661 if (eatToken(it, .Keyword_async)) |token| {1666 if (eatToken(it, .Keyword_async)) |token| return FnCC{ .CC = token };
1662 const node = try arena.create(Node.AsyncAttribute);
1663 node.* = Node.AsyncAttribute{
1664 .base = Node{ .id = .AsyncAttribute },
1665 .async_token = token,
1666 .allocator_type = null,
1667 .rangle_bracket = null,
1668 };
1669 if (eatToken(it, .AngleBracketLeft)) |_| {
1670 const type_expr = try expectNode(arena, it, tree, parseTypeExpr, AstError{
1671 .ExpectedTypeExpr = AstError.ExpectedTypeExpr{ .token = it.index },
1672 });
1673 const rarrow = try expectToken(it, tree, .AngleBracketRight);
1674 node.allocator_type = type_expr;
1675 node.rangle_bracket = rarrow;
1676 }
1677 return FnCC{ .Async = node };
1678 }
1679 return null;1667 return null;
1680}1668}
16811669
1682const FnCC = union(enum) {1670const FnCC = union(enum) {
1683 CC: TokenIndex,1671 CC: TokenIndex,
1684 Extern: TokenIndex,1672 Extern: TokenIndex,
1685 Async: *Node.AsyncAttribute,
1686};1673};
16871674
1688/// ParamDecl <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType1675/// ParamDecl <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType
...@@ -2409,28 +2396,6 @@ fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2409,28 +2396,6 @@ fn parseSuffixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2409 return &node.base;2396 return &node.base;
2410}2397}
24112398
2412/// AsyncPrefix <- KEYWORD_async (LARROW PrefixExpr RARROW)?
2413fn parseAsyncPrefix(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2414 const async_token = eatToken(it, .Keyword_async) orelse return null;
2415 var rangle_bracket: ?TokenIndex = null;
2416 const expr_node = if (eatToken(it, .AngleBracketLeft)) |_| blk: {
2417 const prefix_expr = try expectNode(arena, it, tree, parsePrefixExpr, AstError{
2418 .ExpectedPrefixExpr = AstError.ExpectedPrefixExpr{ .token = it.index },
2419 });
2420 rangle_bracket = try expectToken(it, tree, .AngleBracketRight);
2421 break :blk prefix_expr;
2422 } else null;
2423
2424 const node = try arena.create(Node.AsyncAttribute);
2425 node.* = Node.AsyncAttribute{
2426 .base = Node{ .id = .AsyncAttribute },
2427 .async_token = async_token,
2428 .allocator_type = expr_node,
2429 .rangle_bracket = rangle_bracket,
2430 };
2431 return &node.base;
2432}
2433
2434/// FnCallArguments <- LPAREN ExprList RPAREN2399/// FnCallArguments <- LPAREN ExprList RPAREN
2435/// ExprList <- (Expr COMMA)* Expr?2400/// ExprList <- (Expr COMMA)* Expr?
2436fn parseFnCallArguments(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?AnnotatedParamList {2401fn parseFnCallArguments(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?AnnotatedParamList {
std/zig/parser_test.zig+2-2
...@@ -210,7 +210,7 @@ test "zig fmt: spaces around slice operator" {...@@ -210,7 +210,7 @@ test "zig fmt: spaces around slice operator" {
210test "zig fmt: async call in if condition" {210test "zig fmt: async call in if condition" {
211 try testCanonical(211 try testCanonical(
212 \\comptime {212 \\comptime {
213 \\ if (async<a> b()) {213 \\ if (async b()) {
214 \\ a();214 \\ a();
215 \\ }215 \\ }
216 \\}216 \\}
...@@ -1118,7 +1118,7 @@ test "zig fmt: first line comment in struct initializer" {...@@ -1118,7 +1118,7 @@ test "zig fmt: first line comment in struct initializer" {
1118 \\pub async fn acquire(self: *Self) HeldLock {1118 \\pub async fn acquire(self: *Self) HeldLock {
1119 \\ return HeldLock{1119 \\ return HeldLock{
1120 \\ // guaranteed allocation elision1120 \\ // guaranteed allocation elision
1121 \\ .held = await (async self.lock.acquire() catch unreachable),1121 \\ .held = self.lock.acquire(),
1122 \\ .value = &self.private_data,1122 \\ .value = &self.private_data,
1123 \\ };1123 \\ };
1124 \\}1124 \\}
std/zig/render.zig+2-20
...@@ -284,20 +284,6 @@ fn renderExpression(...@@ -284,20 +284,6 @@ fn renderExpression(
284 return renderExpression(allocator, stream, tree, indent, start_col, comptime_node.expr, space);284 return renderExpression(allocator, stream, tree, indent, start_col, comptime_node.expr, space);
285 },285 },
286286
287 ast.Node.Id.AsyncAttribute => {
288 const async_attr = @fieldParentPtr(ast.Node.AsyncAttribute, "base", base);
289
290 if (async_attr.allocator_type) |allocator_type| {
291 try renderToken(tree, stream, async_attr.async_token, indent, start_col, Space.None); // async
292
293 try renderToken(tree, stream, tree.nextToken(async_attr.async_token), indent, start_col, Space.None); // <
294 try renderExpression(allocator, stream, tree, indent, start_col, allocator_type, Space.None); // allocator
295 return renderToken(tree, stream, tree.nextToken(allocator_type.lastToken()), indent, start_col, space); // >
296 } else {
297 return renderToken(tree, stream, async_attr.async_token, indent, start_col, space); // async
298 }
299 },
300
301 ast.Node.Id.Suspend => {287 ast.Node.Id.Suspend => {
302 const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base);288 const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base);
303289
...@@ -459,8 +445,8 @@ fn renderExpression(...@@ -459,8 +445,8 @@ fn renderExpression(
459445
460 switch (suffix_op.op) {446 switch (suffix_op.op) {
461 @TagType(ast.Node.SuffixOp.Op).Call => |*call_info| {447 @TagType(ast.Node.SuffixOp.Op).Call => |*call_info| {
462 if (call_info.async_attr) |async_attr| {448 if (call_info.async_token) |async_token| {
463 try renderExpression(allocator, stream, tree, indent, start_col, &async_attr.base, Space.Space);449 try renderToken(tree, stream, async_token, indent, start_col, Space.Space);
464 }450 }
465451
466 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);452 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
...@@ -1121,10 +1107,6 @@ fn renderExpression(...@@ -1121,10 +1107,6 @@ fn renderExpression(
1121 try renderToken(tree, stream, cc_token, indent, start_col, Space.Space); // stdcallcc1107 try renderToken(tree, stream, cc_token, indent, start_col, Space.Space); // stdcallcc
1122 }1108 }
11231109
1124 if (fn_proto.async_attr) |async_attr| {
1125 try renderExpression(allocator, stream, tree, indent, start_col, &async_attr.base, Space.Space);
1126 }
1127
1128 const lparen = if (fn_proto.name_token) |name_token| blk: {1110 const lparen = if (fn_proto.name_token) |name_token| blk: {
1129 try renderToken(tree, stream, fn_proto.fn_token, indent, start_col, Space.Space); // fn1111 try renderToken(tree, stream, fn_proto.fn_token, indent, start_col, Space.Space); // fn
1130 try renderToken(tree, stream, name_token, indent, start_col, Space.None); // name1112 try renderToken(tree, stream, name_token, indent, start_col, Space.None); // name