authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-09 18:36:01-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-03-09 18:36:01-04:00
log638d5c3aca7ce1e4fd10060079caa0acb66144c0
tree7001b05a51eea62061ad9dfcba8b99d904ea1be5
parent52c01840ce36f6ed6528fc62c6f3c1426bdce914
parent3fd2cd43678d52ca2f737d991edaddfd8b73c2a4
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #4700 from Vexu/noasync

Implement new noasync syntax

12 files changed, 224 insertions(+), 46 deletions(-)

lib/std/zig/ast.zig+25-3
...@@ -431,6 +431,7 @@ pub const Node = struct {...@@ -431,6 +431,7 @@ pub const Node = struct {
431 ContainerDecl,431 ContainerDecl,
432 Asm,432 Asm,
433 Comptime,433 Comptime,
434 Noasync,
434 Block,435 Block,
435436
436 // Misc437 // Misc
...@@ -1078,6 +1079,29 @@ pub const Node = struct {...@@ -1078,6 +1079,29 @@ pub const Node = struct {
1078 }1079 }
1079 };1080 };
10801081
1082 pub const Noasync = struct {
1083 base: Node = Node{ .id = .Noasync },
1084 noasync_token: TokenIndex,
1085 expr: *Node,
1086
1087 pub fn iterate(self: *Noasync, index: usize) ?*Node {
1088 var i = index;
1089
1090 if (i < 1) return self.expr;
1091 i -= 1;
1092
1093 return null;
1094 }
1095
1096 pub fn firstToken(self: *const Noasync) TokenIndex {
1097 return self.noasync_token;
1098 }
1099
1100 pub fn lastToken(self: *const Noasync) TokenIndex {
1101 return self.expr.lastToken();
1102 }
1103 };
1104
1081 pub const Payload = struct {1105 pub const Payload = struct {
1082 base: Node = Node{ .id = .Payload },1106 base: Node = Node{ .id = .Payload },
1083 lpipe: TokenIndex,1107 lpipe: TokenIndex,
...@@ -1560,9 +1584,7 @@ pub const Node = struct {...@@ -1560,9 +1584,7 @@ pub const Node = struct {
1560 pub const Op = union(enum) {1584 pub const Op = union(enum) {
1561 AddressOf,1585 AddressOf,
1562 ArrayType: ArrayInfo,1586 ArrayType: ArrayInfo,
1563 Await: struct {1587 Await,
1564 noasync_token: ?TokenIndex = null,
1565 },
1566 BitNot,1588 BitNot,
1567 BoolNot,1589 BoolNot,
1568 Cancel,1590 Cancel,
lib/std/zig/parse.zig+49-25
...@@ -462,6 +462,7 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No...@@ -462,6 +462,7 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
462/// Statement462/// Statement
463/// <- KEYWORD_comptime? VarDecl463/// <- KEYWORD_comptime? VarDecl
464/// / KEYWORD_comptime BlockExprStatement464/// / KEYWORD_comptime BlockExprStatement
465/// / KEYWORD_noasync BlockExprStatement
465/// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)466/// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)
466/// / KEYWORD_defer BlockExprStatement467/// / KEYWORD_defer BlockExprStatement
467/// / KEYWORD_errdefer BlockExprStatement468/// / KEYWORD_errdefer BlockExprStatement
...@@ -493,6 +494,19 @@ fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*No...@@ -493,6 +494,19 @@ fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*No
493 return &node.base;494 return &node.base;
494 }495 }
495496
497 if (eatToken(it, .Keyword_noasync)) |noasync_token| {
498 const block_expr = try expectNode(arena, it, tree, parseBlockExprStatement, .{
499 .ExpectedBlockOrAssignment = .{ .token = it.index },
500 });
501
502 const node = try arena.create(Node.Noasync);
503 node.* = .{
504 .noasync_token = noasync_token,
505 .expr = block_expr,
506 };
507 return &node.base;
508 }
509
496 if (eatToken(it, .Keyword_suspend)) |suspend_token| {510 if (eatToken(it, .Keyword_suspend)) |suspend_token| {
497 const semicolon = eatToken(it, .Semicolon);511 const semicolon = eatToken(it, .Semicolon);
498512
...@@ -856,6 +870,7 @@ fn parsePrefixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -856,6 +870,7 @@ fn parsePrefixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
856/// / IfExpr870/// / IfExpr
857/// / KEYWORD_break BreakLabel? Expr?871/// / KEYWORD_break BreakLabel? Expr?
858/// / KEYWORD_comptime Expr872/// / KEYWORD_comptime Expr
873/// / KEYWORD_noasync Expr
859/// / KEYWORD_continue BreakLabel?874/// / KEYWORD_continue BreakLabel?
860/// / KEYWORD_resume Expr875/// / KEYWORD_resume Expr
861/// / KEYWORD_return Expr?876/// / KEYWORD_return Expr?
...@@ -870,7 +885,7 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -870,7 +885,7 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
870 const label = try parseBreakLabel(arena, it, tree);885 const label = try parseBreakLabel(arena, it, tree);
871 const expr_node = try parseExpr(arena, it, tree);886 const expr_node = try parseExpr(arena, it, tree);
872 const node = try arena.create(Node.ControlFlowExpression);887 const node = try arena.create(Node.ControlFlowExpression);
873 node.* = Node.ControlFlowExpression{888 node.* = .{
874 .ltoken = token,889 .ltoken = token,
875 .kind = Node.ControlFlowExpression.Kind{ .Break = label },890 .kind = Node.ControlFlowExpression.Kind{ .Break = label },
876 .rhs = expr_node,891 .rhs = expr_node,
...@@ -883,7 +898,7 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -883,7 +898,7 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
883 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },898 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
884 });899 });
885 const node = try arena.create(Node.Comptime);900 const node = try arena.create(Node.Comptime);
886 node.* = Node.Comptime{901 node.* = .{
887 .doc_comments = null,902 .doc_comments = null,
888 .comptime_token = token,903 .comptime_token = token,
889 .expr = expr_node,904 .expr = expr_node,
...@@ -891,10 +906,22 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -891,10 +906,22 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
891 return &node.base;906 return &node.base;
892 }907 }
893908
909 if (eatToken(it, .Keyword_noasync)) |token| {
910 const expr_node = try expectNode(arena, it, tree, parseExpr, AstError{
911 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
912 });
913 const node = try arena.create(Node.Noasync);
914 node.* = .{
915 .noasync_token = token,
916 .expr = expr_node,
917 };
918 return &node.base;
919 }
920
894 if (eatToken(it, .Keyword_continue)) |token| {921 if (eatToken(it, .Keyword_continue)) |token| {
895 const label = try parseBreakLabel(arena, it, tree);922 const label = try parseBreakLabel(arena, it, tree);
896 const node = try arena.create(Node.ControlFlowExpression);923 const node = try arena.create(Node.ControlFlowExpression);
897 node.* = Node.ControlFlowExpression{924 node.* = .{
898 .ltoken = token,925 .ltoken = token,
899 .kind = Node.ControlFlowExpression.Kind{ .Continue = label },926 .kind = Node.ControlFlowExpression.Kind{ .Continue = label },
900 .rhs = null,927 .rhs = null,
...@@ -907,7 +934,7 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -907,7 +934,7 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
907 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },934 .ExpectedExpr = AstError.ExpectedExpr{ .token = it.index },
908 });935 });
909 const node = try arena.create(Node.PrefixOp);936 const node = try arena.create(Node.PrefixOp);
910 node.* = Node.PrefixOp{937 node.* = .{
911 .op_token = token,938 .op_token = token,
912 .op = Node.PrefixOp.Op.Resume,939 .op = Node.PrefixOp.Op.Resume,
913 .rhs = expr_node,940 .rhs = expr_node,
...@@ -918,7 +945,7 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -918,7 +945,7 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
918 if (eatToken(it, .Keyword_return)) |token| {945 if (eatToken(it, .Keyword_return)) |token| {
919 const expr_node = try parseExpr(arena, it, tree);946 const expr_node = try parseExpr(arena, it, tree);
920 const node = try arena.create(Node.ControlFlowExpression);947 const node = try arena.create(Node.ControlFlowExpression);
921 node.* = Node.ControlFlowExpression{948 node.* = .{
922 .ltoken = token,949 .ltoken = token,
923 .kind = Node.ControlFlowExpression.Kind.Return,950 .kind = Node.ControlFlowExpression.Kind.Return,
924 .rhs = expr_node,951 .rhs = expr_node,
...@@ -1126,19 +1153,18 @@ fn parseErrorUnionExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No...@@ -1126,19 +1153,18 @@ fn parseErrorUnionExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
11261153
1127/// SuffixExpr1154/// SuffixExpr
1128/// <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments1155/// <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments
1129/// / KEYWORD_noasync PrimaryTypeExpr SuffixOp* FnCallArguments
1130/// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*1156/// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
1131fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {1157fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1132 const maybe_async = eatAnnotatedToken(it, .Keyword_async) orelse eatAnnotatedToken(it, .Keyword_noasync);1158 const maybe_async = eatToken(it, .Keyword_async);
1133 if (maybe_async) |async_token| {1159 if (maybe_async) |async_token| {
1134 const token_fn = eatToken(it, .Keyword_fn);1160 const token_fn = eatToken(it, .Keyword_fn);
1135 if (async_token.ptr.id == .Keyword_async and token_fn != null) {1161 if (token_fn != null) {
1136 // HACK: If we see the keyword `fn`, then we assume that1162 // HACK: If we see the keyword `fn`, then we assume that
1137 // we are parsing an async fn proto, and not a call.1163 // we are parsing an async fn proto, and not a call.
1138 // We therefore put back all tokens consumed by the async1164 // We therefore put back all tokens consumed by the async
1139 // prefix...1165 // prefix...
1140 putBackToken(it, token_fn.?);1166 putBackToken(it, token_fn.?);
1141 putBackToken(it, async_token.index);1167 putBackToken(it, async_token);
1142 return parsePrimaryTypeExpr(arena, it, tree);1168 return parsePrimaryTypeExpr(arena, it, tree);
1143 }1169 }
1144 // TODO: Implement hack for parsing `async fn ...` in ast_parse_suffix_expr1170 // TODO: Implement hack for parsing `async fn ...` in ast_parse_suffix_expr
...@@ -1167,7 +1193,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1167,7 +1193,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1167 .op = Node.SuffixOp.Op{1193 .op = Node.SuffixOp.Op{
1168 .Call = Node.SuffixOp.Op.Call{1194 .Call = Node.SuffixOp.Op.Call{
1169 .params = params.list,1195 .params = params.list,
1170 .async_token = async_token.index,1196 .async_token = async_token,
1171 },1197 },
1172 },1198 },
1173 .rtoken = params.rparen,1199 .rtoken = params.rparen,
...@@ -1224,6 +1250,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1224,6 +1250,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1224/// / IfTypeExpr1250/// / IfTypeExpr
1225/// / INTEGER1251/// / INTEGER
1226/// / KEYWORD_comptime TypeExpr1252/// / KEYWORD_comptime TypeExpr
1253/// / KEYWORD_noasync TypeExpr
1227/// / KEYWORD_error DOT IDENTIFIER1254/// / KEYWORD_error DOT IDENTIFIER
1228/// / KEYWORD_false1255/// / KEYWORD_false
1229/// / KEYWORD_null1256/// / KEYWORD_null
...@@ -1255,13 +1282,22 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N...@@ -1255,13 +1282,22 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
1255 if (eatToken(it, .Keyword_comptime)) |token| {1282 if (eatToken(it, .Keyword_comptime)) |token| {
1256 const expr = (try parseTypeExpr(arena, it, tree)) orelse return null;1283 const expr = (try parseTypeExpr(arena, it, tree)) orelse return null;
1257 const node = try arena.create(Node.Comptime);1284 const node = try arena.create(Node.Comptime);
1258 node.* = Node.Comptime{1285 node.* = .{
1259 .doc_comments = null,1286 .doc_comments = null,
1260 .comptime_token = token,1287 .comptime_token = token,
1261 .expr = expr,1288 .expr = expr,
1262 };1289 };
1263 return &node.base;1290 return &node.base;
1264 }1291 }
1292 if (eatToken(it, .Keyword_noasync)) |token| {
1293 const expr = (try parseTypeExpr(arena, it, tree)) orelse return null;
1294 const node = try arena.create(Node.Noasync);
1295 node.* = .{
1296 .noasync_token = token,
1297 .expr = expr,
1298 };
1299 return &node.base;
1300 }
1265 if (eatToken(it, .Keyword_error)) |token| {1301 if (eatToken(it, .Keyword_error)) |token| {
1266 const period = try expectToken(it, tree, .Period);1302 const period = try expectToken(it, tree, .Period);
1267 const identifier = try expectNode(arena, it, tree, parseIdentifier, AstError{1303 const identifier = try expectNode(arena, it, tree, parseIdentifier, AstError{
...@@ -1269,7 +1305,7 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N...@@ -1269,7 +1305,7 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
1269 });1305 });
1270 const global_error_set = try createLiteral(arena, Node.ErrorType, token);1306 const global_error_set = try createLiteral(arena, Node.ErrorType, token);
1271 const node = try arena.create(Node.InfixOp);1307 const node = try arena.create(Node.InfixOp);
1272 node.* = Node.InfixOp{1308 node.* = .{
1273 .op_token = period,1309 .op_token = period,
1274 .lhs = global_error_set,1310 .lhs = global_error_set,
1275 .op = Node.InfixOp.Op.Period,1311 .op = Node.InfixOp.Op.Period,
...@@ -1281,7 +1317,7 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N...@@ -1281,7 +1317,7 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
1281 if (eatToken(it, .Keyword_null)) |token| return createLiteral(arena, Node.NullLiteral, token);1317 if (eatToken(it, .Keyword_null)) |token| return createLiteral(arena, Node.NullLiteral, token);
1282 if (eatToken(it, .Keyword_anyframe)) |token| {1318 if (eatToken(it, .Keyword_anyframe)) |token| {
1283 const node = try arena.create(Node.AnyFrameType);1319 const node = try arena.create(Node.AnyFrameType);
1284 node.* = Node.AnyFrameType{1320 node.* = .{
1285 .anyframe_token = token,1321 .anyframe_token = token,
1286 .result = null,1322 .result = null,
1287 };1323 };
...@@ -2180,18 +2216,6 @@ fn parsePrefixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -2180,18 +2216,6 @@ fn parsePrefixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2180 .Ampersand => ops{ .AddressOf = {} },2216 .Ampersand => ops{ .AddressOf = {} },
2181 .Keyword_try => ops{ .Try = {} },2217 .Keyword_try => ops{ .Try = {} },
2182 .Keyword_await => ops{ .Await = .{} },2218 .Keyword_await => ops{ .Await = .{} },
2183 .Keyword_noasync => if (eatToken(it, .Keyword_await)) |await_tok| {
2184 const node = try arena.create(Node.PrefixOp);
2185 node.* = Node.PrefixOp{
2186 .op_token = await_tok,
2187 .op = .{ .Await = .{ .noasync_token = token.index } },
2188 .rhs = undefined, // set by caller
2189 };
2190 return &node.base;
2191 } else {
2192 putBackToken(it, token.index);
2193 return null;
2194 },
2195 else => {2219 else => {
2196 putBackToken(it, token.index);2220 putBackToken(it, token.index);
2197 return null;2221 return null;
lib/std/zig/render.zig+6-3
...@@ -390,6 +390,12 @@ fn renderExpression(...@@ -390,6 +390,12 @@ fn renderExpression(
390 try renderToken(tree, stream, comptime_node.comptime_token, indent, start_col, Space.Space);390 try renderToken(tree, stream, comptime_node.comptime_token, indent, start_col, Space.Space);
391 return renderExpression(allocator, stream, tree, indent, start_col, comptime_node.expr, space);391 return renderExpression(allocator, stream, tree, indent, start_col, comptime_node.expr, space);
392 },392 },
393 .Noasync => {
394 const noasync_node = @fieldParentPtr(ast.Node.Noasync, "base", base);
395
396 try renderToken(tree, stream, noasync_node.noasync_token, indent, start_col, Space.Space);
397 return renderExpression(allocator, stream, tree, indent, start_col, noasync_node.expr, space);
398 },
393399
394 .Suspend => {400 .Suspend => {
395 const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base);401 const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base);
...@@ -590,9 +596,6 @@ fn renderExpression(...@@ -590,9 +596,6 @@ fn renderExpression(
590 },596 },
591597
592 .Await => |await_info| {598 .Await => |await_info| {
593 if (await_info.noasync_token) |tok| {
594 try renderToken(tree, stream, tok, indent, start_col, Space.Space);
595 }
596 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.Space);599 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.Space);
597 },600 },
598 }601 }
src/all_types.hpp+12-1
...@@ -651,6 +651,7 @@ enum NodeType {...@@ -651,6 +651,7 @@ enum NodeType {
651 NodeTypeSwitchProng,651 NodeTypeSwitchProng,
652 NodeTypeSwitchRange,652 NodeTypeSwitchRange,
653 NodeTypeCompTime,653 NodeTypeCompTime,
654 NodeTypeNoAsync,
654 NodeTypeBreak,655 NodeTypeBreak,
655 NodeTypeContinue,656 NodeTypeContinue,
656 NodeTypeAsmExpr,657 NodeTypeAsmExpr,
...@@ -991,6 +992,10 @@ struct AstNodeCompTime {...@@ -991,6 +992,10 @@ struct AstNodeCompTime {
991 AstNode *expr;992 AstNode *expr;
992};993};
993994
995struct AstNodeNoAsync {
996 AstNode *expr;
997};
998
994struct AsmOutput {999struct AsmOutput {
995 Buf *asm_symbolic_name;1000 Buf *asm_symbolic_name;
996 Buf *constraint;1001 Buf *constraint;
...@@ -1148,7 +1153,6 @@ struct AstNodeErrorType {...@@ -1148,7 +1153,6 @@ struct AstNodeErrorType {
1148};1153};
11491154
1150struct AstNodeAwaitExpr {1155struct AstNodeAwaitExpr {
1151 Token *noasync_token;
1152 AstNode *expr;1156 AstNode *expr;
1153};1157};
11541158
...@@ -1199,6 +1203,7 @@ struct AstNode {...@@ -1199,6 +1203,7 @@ struct AstNode {
1199 AstNodeSwitchProng switch_prong;1203 AstNodeSwitchProng switch_prong;
1200 AstNodeSwitchRange switch_range;1204 AstNodeSwitchRange switch_range;
1201 AstNodeCompTime comptime_expr;1205 AstNodeCompTime comptime_expr;
1206 AstNodeNoAsync noasync_expr;
1202 AstNodeAsmExpr asm_expr;1207 AstNodeAsmExpr asm_expr;
1203 AstNodeFieldAccessExpr field_access_expr;1208 AstNodeFieldAccessExpr field_access_expr;
1204 AstNodePtrDerefExpr ptr_deref_expr;1209 AstNodePtrDerefExpr ptr_deref_expr;
...@@ -2325,6 +2330,7 @@ enum ScopeId {...@@ -2325,6 +2330,7 @@ enum ScopeId {
2325 ScopeIdRuntime,2330 ScopeIdRuntime,
2326 ScopeIdTypeOf,2331 ScopeIdTypeOf,
2327 ScopeIdExpr,2332 ScopeIdExpr,
2333 ScopeIdNoAsync,
2328};2334};
23292335
2330struct Scope {2336struct Scope {
...@@ -2457,6 +2463,11 @@ struct ScopeCompTime {...@@ -2457,6 +2463,11 @@ struct ScopeCompTime {
2457 Scope base;2463 Scope base;
2458};2464};
24592465
2466// This scope is created for a noasync expression.
2467// NodeTypeNoAsync
2468struct ScopeNoAsync {
2469 Scope base;
2470};
24602471
2461// This scope is created for a function definition.2472// This scope is created for a function definition.
2462// NodeTypeFnDef2473// NodeTypeFnDef
src/analyze.cpp+9
...@@ -106,6 +106,7 @@ static ScopeExpr *find_expr_scope(Scope *scope) {...@@ -106,6 +106,7 @@ static ScopeExpr *find_expr_scope(Scope *scope) {
106 case ScopeIdDecls:106 case ScopeIdDecls:
107 case ScopeIdFnDef:107 case ScopeIdFnDef:
108 case ScopeIdCompTime:108 case ScopeIdCompTime:
109 case ScopeIdNoAsync:
109 case ScopeIdVarDecl:110 case ScopeIdVarDecl:
110 case ScopeIdCImport:111 case ScopeIdCImport:
111 case ScopeIdSuspend:112 case ScopeIdSuspend:
...@@ -226,6 +227,12 @@ Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent) {...@@ -226,6 +227,12 @@ Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent) {
226 return &scope->base;227 return &scope->base;
227}228}
228229
230Scope *create_noasync_scope(CodeGen *g, AstNode *node, Scope *parent) {
231 ScopeNoAsync *scope = heap::c_allocator.create<ScopeNoAsync>();
232 init_scope(g, &scope->base, ScopeIdNoAsync, node, parent);
233 return &scope->base;
234}
235
229Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent) {236Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent) {
230 ScopeTypeOf *scope = heap::c_allocator.create<ScopeTypeOf>();237 ScopeTypeOf *scope = heap::c_allocator.create<ScopeTypeOf>();
231 init_scope(g, &scope->base, ScopeIdTypeOf, node, parent);238 init_scope(g, &scope->base, ScopeIdTypeOf, node, parent);
...@@ -3755,6 +3762,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {...@@ -3755,6 +3762,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
3755 case NodeTypeCompTime:3762 case NodeTypeCompTime:
3756 preview_comptime_decl(g, node, decls_scope);3763 preview_comptime_decl(g, node, decls_scope);
3757 break;3764 break;
3765 case NodeTypeNoAsync:
3758 case NodeTypeParamDecl:3766 case NodeTypeParamDecl:
3759 case NodeTypeReturnExpr:3767 case NodeTypeReturnExpr:
3760 case NodeTypeDefer:3768 case NodeTypeDefer:
...@@ -6176,6 +6184,7 @@ static void mark_suspension_point(Scope *scope) {...@@ -6176,6 +6184,7 @@ static void mark_suspension_point(Scope *scope) {
6176 case ScopeIdDecls:6184 case ScopeIdDecls:
6177 case ScopeIdFnDef:6185 case ScopeIdFnDef:
6178 case ScopeIdCompTime:6186 case ScopeIdCompTime:
6187 case ScopeIdNoAsync:
6179 case ScopeIdCImport:6188 case ScopeIdCImport:
6180 case ScopeIdSuspend:6189 case ScopeIdSuspend:
6181 case ScopeIdTypeOf:6190 case ScopeIdTypeOf:
src/analyze.hpp+1
...@@ -125,6 +125,7 @@ ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent);...@@ -125,6 +125,7 @@ ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent);
125ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent);125ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent);
126ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *fn_entry);126ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *fn_entry);
127Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent);127Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent);
128Scope *create_noasync_scope(CodeGen *g, AstNode *node, Scope *parent);
128Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstSrc *is_comptime);129Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstSrc *is_comptime);
129Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent);130Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent);
130ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent);131ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent);
src/ast_render.cpp+8
...@@ -220,6 +220,8 @@ static const char *node_type_str(NodeType node_type) {...@@ -220,6 +220,8 @@ static const char *node_type_str(NodeType node_type) {
220 return "SwitchRange";220 return "SwitchRange";
221 case NodeTypeCompTime:221 case NodeTypeCompTime:
222 return "CompTime";222 return "CompTime";
223 case NodeTypeNoAsync:
224 return "NoAsync";
223 case NodeTypeBreak:225 case NodeTypeBreak:
224 return "Break";226 return "Break";
225 case NodeTypeContinue:227 case NodeTypeContinue:
...@@ -1091,6 +1093,12 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -1091,6 +1093,12 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
1091 render_node_grouped(ar, node->data.comptime_expr.expr);1093 render_node_grouped(ar, node->data.comptime_expr.expr);
1092 break;1094 break;
1093 }1095 }
1096 case NodeTypeNoAsync:
1097 {
1098 fprintf(ar->f, "noasync ");
1099 render_node_grouped(ar, node->data.noasync_expr.expr);
1100 break;
1101 }
1094 case NodeTypeForExpr:1102 case NodeTypeForExpr:
1095 {1103 {
1096 if (node->data.for_expr.name != nullptr) {1104 if (node->data.for_expr.name != nullptr) {
src/codegen.cpp+3-1
...@@ -687,6 +687,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {...@@ -687,6 +687,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
687 case ScopeIdLoop:687 case ScopeIdLoop:
688 case ScopeIdSuspend:688 case ScopeIdSuspend:
689 case ScopeIdCompTime:689 case ScopeIdCompTime:
690 case ScopeIdNoAsync:
690 case ScopeIdRuntime:691 case ScopeIdRuntime:
691 case ScopeIdTypeOf:692 case ScopeIdTypeOf:
692 case ScopeIdExpr:693 case ScopeIdExpr:
...@@ -968,7 +969,7 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {...@@ -968,7 +969,7 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
968 case PanicMsgIdResumedFnPendingAwait:969 case PanicMsgIdResumedFnPendingAwait:
969 return buf_create_from_str("resumed an async function which can only be awaited");970 return buf_create_from_str("resumed an async function which can only be awaited");
970 case PanicMsgIdBadNoAsyncCall:971 case PanicMsgIdBadNoAsyncCall:
971 return buf_create_from_str("async function called with noasync suspended");972 return buf_create_from_str("async function called in noasync scope suspended");
972 case PanicMsgIdResumeNotSuspendedFn:973 case PanicMsgIdResumeNotSuspendedFn:
973 return buf_create_from_str("resumed a non-suspended function");974 return buf_create_from_str("resumed a non-suspended function");
974 case PanicMsgIdBadSentinel:975 case PanicMsgIdBadSentinel:
...@@ -3934,6 +3935,7 @@ static void render_async_var_decls(CodeGen *g, Scope *scope) {...@@ -3934,6 +3935,7 @@ static void render_async_var_decls(CodeGen *g, Scope *scope) {
3934 case ScopeIdLoop:3935 case ScopeIdLoop:
3935 case ScopeIdSuspend:3936 case ScopeIdSuspend:
3936 case ScopeIdCompTime:3937 case ScopeIdCompTime:
3938 case ScopeIdNoAsync:
3937 case ScopeIdRuntime:3939 case ScopeIdRuntime:
3938 case ScopeIdTypeOf:3940 case ScopeIdTypeOf:
3939 case ScopeIdExpr:3941 case ScopeIdExpr:
src/ir.cpp+46-2
...@@ -4978,6 +4978,7 @@ static void ir_count_defers(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_...@@ -4978,6 +4978,7 @@ static void ir_count_defers(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_
4978 case ScopeIdLoop:4978 case ScopeIdLoop:
4979 case ScopeIdSuspend:4979 case ScopeIdSuspend:
4980 case ScopeIdCompTime:4980 case ScopeIdCompTime:
4981 case ScopeIdNoAsync:
4981 case ScopeIdRuntime:4982 case ScopeIdRuntime:
4982 case ScopeIdTypeOf:4983 case ScopeIdTypeOf:
4983 case ScopeIdExpr:4984 case ScopeIdExpr:
...@@ -5033,6 +5034,7 @@ static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope...@@ -5033,6 +5034,7 @@ static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope
5033 case ScopeIdLoop:5034 case ScopeIdLoop:
5034 case ScopeIdSuspend:5035 case ScopeIdSuspend:
5035 case ScopeIdCompTime:5036 case ScopeIdCompTime:
5037 case ScopeIdNoAsync:
5036 case ScopeIdRuntime:5038 case ScopeIdRuntime:
5037 case ScopeIdTypeOf:5039 case ScopeIdTypeOf:
5038 case ScopeIdExpr:5040 case ScopeIdExpr:
...@@ -7307,6 +7309,18 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod...@@ -7307,6 +7309,18 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod
7307 zig_unreachable();7309 zig_unreachable();
7308}7310}
73097311
7312static ScopeNoAsync *get_scope_noasync(Scope *scope) {
7313 while (scope) {
7314 if (scope->id == ScopeIdNoAsync)
7315 return (ScopeNoAsync *)scope;
7316 if (scope->id == ScopeIdFnDef)
7317 return nullptr;
7318
7319 scope = scope->parent;
7320 }
7321 return nullptr;
7322}
7323
7310static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval,7324static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval,
7311 ResultLoc *result_loc)7325 ResultLoc *result_loc)
7312{7326{
...@@ -7315,8 +7329,19 @@ static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node,...@@ -7315,8 +7329,19 @@ static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node,
7315 if (node->data.fn_call_expr.modifier == CallModifierBuiltin)7329 if (node->data.fn_call_expr.modifier == CallModifierBuiltin)
7316 return ir_gen_builtin_fn_call(irb, scope, node, lval, result_loc);7330 return ir_gen_builtin_fn_call(irb, scope, node, lval, result_loc);
73177331
7332 bool is_noasync = get_scope_noasync(scope) != nullptr;
7333 CallModifier modifier = node->data.fn_call_expr.modifier;
7334 if (is_noasync) {
7335 if (modifier == CallModifierAsync) {
7336 add_node_error(irb->codegen, node,
7337 buf_sprintf("async call in noasync scope"));
7338 return irb->codegen->invalid_inst_src;
7339 }
7340 modifier = CallModifierNoAsync;
7341 }
7342
7318 AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;7343 AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;
7319 return ir_gen_fn_call_with_args(irb, scope, node, fn_ref_node, node->data.fn_call_expr.modifier,7344 return ir_gen_fn_call_with_args(irb, scope, node, fn_ref_node, modifier,
7320 nullptr, node->data.fn_call_expr.params.items, node->data.fn_call_expr.params.length, lval, result_loc);7345 nullptr, node->data.fn_call_expr.params.items, node->data.fn_call_expr.params.length, lval, result_loc);
7321}7346}
73227347
...@@ -9170,6 +9195,14 @@ static IrInstSrc *ir_gen_comptime(IrBuilderSrc *irb, Scope *parent_scope, AstNod...@@ -9170,6 +9195,14 @@ static IrInstSrc *ir_gen_comptime(IrBuilderSrc *irb, Scope *parent_scope, AstNod
9170 return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr);9195 return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr);
9171}9196}
91729197
9198static IrInstSrc *ir_gen_noasync(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval) {
9199 assert(node->type == NodeTypeNoAsync);
9200
9201 Scope *child_scope = create_noasync_scope(irb->codegen, node, parent_scope);
9202 // purposefully pass null for result_loc and let EndExpr handle it
9203 return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr);
9204}
9205
9173static IrInstSrc *ir_gen_return_from_block(IrBuilderSrc *irb, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) {9206static IrInstSrc *ir_gen_return_from_block(IrBuilderSrc *irb, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) {
9174 IrInstSrc *is_comptime;9207 IrInstSrc *is_comptime;
9175 if (ir_should_inline(irb->exec, break_scope)) {9208 if (ir_should_inline(irb->exec, break_scope)) {
...@@ -9750,6 +9783,10 @@ static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNod...@@ -9750,6 +9783,10 @@ static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNod
97509783
9751static IrInstSrc *ir_gen_resume(IrBuilderSrc *irb, Scope *scope, AstNode *node) {9784static IrInstSrc *ir_gen_resume(IrBuilderSrc *irb, Scope *scope, AstNode *node) {
9752 assert(node->type == NodeTypeResume);9785 assert(node->type == NodeTypeResume);
9786 if (get_scope_noasync(scope) != nullptr) {
9787 add_node_error(irb->codegen, node, buf_sprintf("resume in noasync scope"));
9788 return irb->codegen->invalid_inst_src;
9789 }
97539790
9754 IrInstSrc *target_inst = ir_gen_node_extra(irb, node->data.resume_expr.expr, scope, LValPtr, nullptr);9791 IrInstSrc *target_inst = ir_gen_node_extra(irb, node->data.resume_expr.expr, scope, LValPtr, nullptr);
9755 if (target_inst == irb->codegen->invalid_inst_src)9792 if (target_inst == irb->codegen->invalid_inst_src)
...@@ -9763,7 +9800,7 @@ static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no...@@ -9763,7 +9800,7 @@ static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
9763{9800{
9764 assert(node->type == NodeTypeAwaitExpr);9801 assert(node->type == NodeTypeAwaitExpr);
97659802
9766 bool is_noasync = node->data.await_expr.noasync_token != nullptr;9803 bool is_noasync = get_scope_noasync(scope) != nullptr;
97679804
9768 AstNode *expr_node = node->data.await_expr.expr;9805 AstNode *expr_node = node->data.await_expr.expr;
9769 if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.modifier == CallModifierBuiltin) {9806 if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.modifier == CallModifierBuiltin) {
...@@ -9809,6 +9846,11 @@ static IrInstSrc *ir_gen_suspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode...@@ -9809,6 +9846,11 @@ static IrInstSrc *ir_gen_suspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode
9809 add_node_error(irb->codegen, node, buf_sprintf("suspend outside function definition"));9846 add_node_error(irb->codegen, node, buf_sprintf("suspend outside function definition"));
9810 return irb->codegen->invalid_inst_src;9847 return irb->codegen->invalid_inst_src;
9811 }9848 }
9849 if (get_scope_noasync(parent_scope) != nullptr) {
9850 add_node_error(irb->codegen, node, buf_sprintf("suspend in noasync scope"));
9851 return irb->codegen->invalid_inst_src;
9852 }
9853
9812 ScopeSuspend *existing_suspend_scope = get_scope_suspend(parent_scope);9854 ScopeSuspend *existing_suspend_scope = get_scope_suspend(parent_scope);
9813 if (existing_suspend_scope) {9855 if (existing_suspend_scope) {
9814 if (!existing_suspend_scope->reported_err) {9856 if (!existing_suspend_scope->reported_err) {
...@@ -9938,6 +9980,8 @@ static IrInstSrc *ir_gen_node_raw(IrBuilderSrc *irb, AstNode *node, Scope *scope...@@ -9938,6 +9980,8 @@ static IrInstSrc *ir_gen_node_raw(IrBuilderSrc *irb, AstNode *node, Scope *scope
9938 return ir_gen_switch_expr(irb, scope, node, lval, result_loc);9980 return ir_gen_switch_expr(irb, scope, node, lval, result_loc);
9939 case NodeTypeCompTime:9981 case NodeTypeCompTime:
9940 return ir_expr_wrap(irb, scope, ir_gen_comptime(irb, scope, node, lval), result_loc);9982 return ir_expr_wrap(irb, scope, ir_gen_comptime(irb, scope, node, lval), result_loc);
9983 case NodeTypeNoAsync:
9984 return ir_expr_wrap(irb, scope, ir_gen_noasync(irb, scope, node, lval), result_loc);
9941 case NodeTypeErrorType:9985 case NodeTypeErrorType:
9942 return ir_lval_wrap(irb, scope, ir_gen_error_type(irb, scope, node), lval, result_loc);9986 return ir_lval_wrap(irb, scope, ir_gen_error_type(irb, scope, node), lval, result_loc);
9943 case NodeTypeBreak:9987 case NodeTypeBreak:
src/parser.cpp+34-11
...@@ -876,6 +876,7 @@ static AstNode *ast_parse_container_field(ParseContext *pc) {...@@ -876,6 +876,7 @@ static AstNode *ast_parse_container_field(ParseContext *pc) {
876// Statement876// Statement
877// <- KEYWORD_comptime? VarDecl877// <- KEYWORD_comptime? VarDecl
878// / KEYWORD_comptime BlockExprStatement878// / KEYWORD_comptime BlockExprStatement
879// / KEYWORD_noasync BlockExprStatement
879// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)880// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)
880// / KEYWORD_defer BlockExprStatement881// / KEYWORD_defer BlockExprStatement
881// / KEYWORD_errdefer BlockExprStatement882// / KEYWORD_errdefer BlockExprStatement
...@@ -899,6 +900,14 @@ static AstNode *ast_parse_statement(ParseContext *pc) {...@@ -899,6 +900,14 @@ static AstNode *ast_parse_statement(ParseContext *pc) {
899 return res;900 return res;
900 }901 }
901902
903 Token *noasync = eat_token_if(pc, TokenIdKeywordNoAsync);
904 if (noasync != nullptr) {
905 AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement);
906 AstNode *res = ast_create_node(pc, NodeTypeNoAsync, noasync);
907 res->data.noasync_expr.expr = statement;
908 return res;
909 }
910
902 Token *suspend = eat_token_if(pc, TokenIdKeywordSuspend);911 Token *suspend = eat_token_if(pc, TokenIdKeywordSuspend);
903 if (suspend != nullptr) {912 if (suspend != nullptr) {
904 AstNode *statement = nullptr;913 AstNode *statement = nullptr;
...@@ -1237,6 +1246,7 @@ static AstNode *ast_parse_prefix_expr(ParseContext *pc) {...@@ -1237,6 +1246,7 @@ static AstNode *ast_parse_prefix_expr(ParseContext *pc) {
1237// / IfExpr1246// / IfExpr
1238// / KEYWORD_break BreakLabel? Expr?1247// / KEYWORD_break BreakLabel? Expr?
1239// / KEYWORD_comptime Expr1248// / KEYWORD_comptime Expr
1249// / KEYWORD_noasync Expr
1240// / KEYWORD_continue BreakLabel?1250// / KEYWORD_continue BreakLabel?
1241// / KEYWORD_resume Expr1251// / KEYWORD_resume Expr
1242// / KEYWORD_return Expr?1252// / KEYWORD_return Expr?
...@@ -1271,6 +1281,14 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc) {...@@ -1271,6 +1281,14 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc) {
1271 return res;1281 return res;
1272 }1282 }
12731283
1284 Token *noasync = eat_token_if(pc, TokenIdKeywordNoAsync);
1285 if (noasync != nullptr) {
1286 AstNode *expr = ast_expect(pc, ast_parse_expr);
1287 AstNode *res = ast_create_node(pc, NodeTypeNoAsync, noasync);
1288 res->data.noasync_expr.expr = expr;
1289 return res;
1290 }
1291
1274 Token *continue_token = eat_token_if(pc, TokenIdKeywordContinue);1292 Token *continue_token = eat_token_if(pc, TokenIdKeywordContinue);
1275 if (continue_token != nullptr) {1293 if (continue_token != nullptr) {
1276 Token *label = ast_parse_break_label(pc);1294 Token *label = ast_parse_break_label(pc);
...@@ -1459,13 +1477,11 @@ static AstNode *ast_parse_error_union_expr(ParseContext *pc) {...@@ -1459,13 +1477,11 @@ static AstNode *ast_parse_error_union_expr(ParseContext *pc) {
14591477
1460// SuffixExpr1478// SuffixExpr
1461// <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments1479// <- KEYWORD_async PrimaryTypeExpr SuffixOp* FnCallArguments
1462// / KEYWORD_noasync PrimaryTypeExpr SuffixOp* FnCallArguments
1463// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*1480// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
1464static AstNode *ast_parse_suffix_expr(ParseContext *pc) {1481static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
1465 Token *async_token = eat_token(pc);1482 Token *async_token = eat_token_if(pc, TokenIdKeywordAsync);
1466 bool is_async = async_token->id == TokenIdKeywordAsync;1483 if (async_token) {
1467 if (is_async || async_token->id == TokenIdKeywordNoAsync) {1484 if (eat_token_if(pc, TokenIdKeywordFn) != nullptr) {
1468 if (is_async && eat_token_if(pc, TokenIdKeywordFn) != nullptr) {
1469 // HACK: If we see the keyword `fn`, then we assume that1485 // HACK: If we see the keyword `fn`, then we assume that
1470 // we are parsing an async fn proto, and not a call.1486 // we are parsing an async fn proto, and not a call.
1471 // We therefore put back all tokens consumed by the async1487 // We therefore put back all tokens consumed by the async
...@@ -1515,13 +1531,12 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {...@@ -1515,13 +1531,12 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
1515 assert(args->type == NodeTypeFnCallExpr);1531 assert(args->type == NodeTypeFnCallExpr);
15161532
1517 AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, async_token);1533 AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, async_token);
1518 res->data.fn_call_expr.modifier = is_async ? CallModifierAsync : CallModifierNoAsync;1534 res->data.fn_call_expr.modifier = CallModifierAsync;
1519 res->data.fn_call_expr.seen = false;1535 res->data.fn_call_expr.seen = false;
1520 res->data.fn_call_expr.fn_ref_expr = child;1536 res->data.fn_call_expr.fn_ref_expr = child;
1521 res->data.fn_call_expr.params = args->data.fn_call_expr.params;1537 res->data.fn_call_expr.params = args->data.fn_call_expr.params;
1522 return res;1538 return res;
1523 }1539 }
1524 put_back_token(pc);
15251540
1526 AstNode *res = ast_parse_primary_type_expr(pc);1541 AstNode *res = ast_parse_primary_type_expr(pc);
1527 if (res == nullptr)1542 if (res == nullptr)
...@@ -1582,6 +1597,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {...@@ -1582,6 +1597,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
1582// / IfTypeExpr1597// / IfTypeExpr
1583// / INTEGER1598// / INTEGER
1584// / KEYWORD_comptime TypeExpr1599// / KEYWORD_comptime TypeExpr
1600// / KEYWORD_noasync TypeExpr
1585// / KEYWORD_error DOT IDENTIFIER1601// / KEYWORD_error DOT IDENTIFIER
1586// / KEYWORD_false1602// / KEYWORD_false
1587// / KEYWORD_null1603// / KEYWORD_null
...@@ -1683,6 +1699,14 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {...@@ -1683,6 +1699,14 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {
1683 return res;1699 return res;
1684 }1700 }
16851701
1702 Token *noasync = eat_token_if(pc, TokenIdKeywordNoAsync);
1703 if (noasync != nullptr) {
1704 AstNode *expr = ast_expect(pc, ast_parse_type_expr);
1705 AstNode *res = ast_create_node(pc, NodeTypeNoAsync, noasync);
1706 res->data.noasync_expr.expr = expr;
1707 return res;
1708 }
1709
1686 Token *error = eat_token_if(pc, TokenIdKeywordError);1710 Token *error = eat_token_if(pc, TokenIdKeywordError);
1687 if (error != nullptr) {1711 if (error != nullptr) {
1688 Token *dot = expect_token(pc, TokenIdDot);1712 Token *dot = expect_token(pc, TokenIdDot);
...@@ -2599,14 +2623,10 @@ static AstNode *ast_parse_prefix_op(ParseContext *pc) {...@@ -2599,14 +2623,10 @@ static AstNode *ast_parse_prefix_op(ParseContext *pc) {
2599 return res;2623 return res;
2600 }2624 }
26012625
2602 Token *noasync_token = eat_token_if(pc, TokenIdKeywordNoAsync);
2603 Token *await = eat_token_if(pc, TokenIdKeywordAwait);2626 Token *await = eat_token_if(pc, TokenIdKeywordAwait);
2604 if (await != nullptr) {2627 if (await != nullptr) {
2605 AstNode *res = ast_create_node(pc, NodeTypeAwaitExpr, await);2628 AstNode *res = ast_create_node(pc, NodeTypeAwaitExpr, await);
2606 res->data.await_expr.noasync_token = noasync_token;
2607 return res;2629 return res;
2608 } else if (noasync_token != nullptr) {
2609 put_back_token(pc);
2610 }2630 }
26112631
2612 return nullptr;2632 return nullptr;
...@@ -3125,6 +3145,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -3125,6 +3145,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
3125 case NodeTypeCompTime:3145 case NodeTypeCompTime:
3126 visit_field(&node->data.comptime_expr.expr, visit, context);3146 visit_field(&node->data.comptime_expr.expr, visit, context);
3127 break;3147 break;
3148 case NodeTypeNoAsync:
3149 visit_field(&node->data.comptime_expr.expr, visit, context);
3150 break;
3128 case NodeTypeBreak:3151 case NodeTypeBreak:
3129 // none3152 // none
3130 break;3153 break;
test/compile_errors.zig+15
...@@ -2,6 +2,21 @@ const tests = @import("tests.zig");...@@ -2,6 +2,21 @@ const tests = @import("tests.zig");
2const std = @import("std");2const std = @import("std");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.addTest("combination of noasync and async",
6 \\export fn entry() void {
7 \\ noasync {
8 \\ const bar = async foo();
9 \\ suspend;
10 \\ resume bar;
11 \\ }
12 \\}
13 \\fn foo() void {}
14 , &[_][]const u8{
15 "tmp.zig:3:21: error: async call in noasync scope",
16 "tmp.zig:4:9: error: suspend in noasync scope",
17 "tmp.zig:5:9: error: resume in noasync scope",
18 });
19
5 cases.addTest("@TypeOf with no arguments",20 cases.addTest("@TypeOf with no arguments",
6 \\export fn entry() void {21 \\export fn entry() void {
7 \\ _ = @TypeOf();22 \\ _ = @TypeOf();
test/stage1/behavior/async_fn.zig+16
...@@ -1531,3 +1531,19 @@ test "noasync await" {...@@ -1531,3 +1531,19 @@ test "noasync await" {
1531 S.doTheTest();1531 S.doTheTest();
1532 expect(S.finished);1532 expect(S.finished);
1533}1533}
1534
1535test "noasync on function calls" {
1536 const S0 = struct {
1537 b: i32 = 42,
1538 };
1539 const S1 = struct {
1540 fn c() S0 {
1541 return S0{};
1542 }
1543 fn d() !S0 {
1544 return S0{};
1545 }
1546 };
1547 expectEqual(@as(i32, 42), noasync S1.c().b);
1548 expectEqual(@as(i32, 42), (try noasync S1.d()).b);
1549}