authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-03-09 15:51:51+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-03-09 15:51:51+02:00
log03c1431f9c0b651f3f1853f11112edc07555883d
tree4d87acafcb8b97bf99292559894205bdced12dc1
parent3618256c97a9988f7d623eeabb667010ca30656f
signaturelock-open Commit is signed but in an unrecognized format.

disallow resume and suspend in noasync scopes


4 files changed, 43 insertions(+), 27 deletions(-)

lib/std/zig/ast.zig-1
...@@ -1081,7 +1081,6 @@ pub const Node = struct {...@@ -1081,7 +1081,6 @@ pub const Node = struct {
10811081
1082 pub const Noasync = struct {1082 pub const Noasync = struct {
1083 base: Node = Node{ .id = .Noasync },1083 base: Node = Node{ .id = .Noasync },
1084 doc_comments: ?*DocComment,
1085 noasync_token: TokenIndex,1084 noasync_token: TokenIndex,
1086 expr: *Node,1085 expr: *Node,
10871086
lib/std/zig/parse.zig+14-2
...@@ -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
...@@ -898,7 +912,6 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -898,7 +912,6 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
898 });912 });
899 const node = try arena.create(Node.Noasync);913 const node = try arena.create(Node.Noasync);
900 node.* = .{914 node.* = .{
901 .doc_comments = null,
902 .noasync_token = token,915 .noasync_token = token,
903 .expr = expr_node,916 .expr = expr_node,
904 };917 };
...@@ -1280,7 +1293,6 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N...@@ -1280,7 +1293,6 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N
1280 const expr = (try parseTypeExpr(arena, it, tree)) orelse return null;1293 const expr = (try parseTypeExpr(arena, it, tree)) orelse return null;
1281 const node = try arena.create(Node.Noasync);1294 const node = try arena.create(Node.Noasync);
1282 node.* = .{1295 node.* = .{
1283 .doc_comments = null,
1284 .noasync_token = token,1296 .noasync_token = token,
1285 .expr = expr,1297 .expr = expr,
1286 };1298 };
src/ir.cpp+20-24
...@@ -7309,29 +7309,16 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod...@@ -7309,29 +7309,16 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod
7309 zig_unreachable();7309 zig_unreachable();
7310}7310}
73117311
7312static bool is_noasync_scope(Scope *scope) {7312static ScopeNoAsync *get_scope_noasync(Scope *scope) {
7313 for (;;) {7313 while (scope) {
7314 switch (scope->id) {7314 if (scope->id == ScopeIdNoAsync)
7315 case ScopeIdNoAsync:7315 return (ScopeNoAsync *)scope;
7316 return true;7316 if (scope->id == ScopeIdFnDef)
7317 case ScopeIdDefer:7317 return nullptr;
7318 case ScopeIdDeferExpr:7318
7319 case ScopeIdDecls:7319 scope = scope->parent;
7320 case ScopeIdFnDef:
7321 case ScopeIdCompTime:
7322 case ScopeIdVarDecl:
7323 case ScopeIdCImport:
7324 case ScopeIdSuspend:
7325 return false;
7326 case ScopeIdExpr:
7327 case ScopeIdTypeOf:
7328 case ScopeIdBlock:
7329 case ScopeIdLoop:
7330 case ScopeIdRuntime:
7331 scope = scope->parent;
7332 continue;
7333 }
7334 }7320 }
7321 return nullptr;
7335}7322}
73367323
7337static 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,
...@@ -7342,7 +7329,7 @@ static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node,...@@ -7342,7 +7329,7 @@ static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node,
7342 if (node->data.fn_call_expr.modifier == CallModifierBuiltin)7329 if (node->data.fn_call_expr.modifier == CallModifierBuiltin)
7343 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);
73447331
7345 bool is_noasync = is_noasync_scope(scope);7332 bool is_noasync = get_scope_noasync(scope) != nullptr;
7346 CallModifier modifier = node->data.fn_call_expr.modifier;7333 CallModifier modifier = node->data.fn_call_expr.modifier;
7347 if (is_noasync) {7334 if (is_noasync) {
7348 if (modifier == CallModifierAsync) {7335 if (modifier == CallModifierAsync) {
...@@ -9796,6 +9783,10 @@ static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNod...@@ -9796,6 +9783,10 @@ static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNod
97969783
9797static IrInstSrc *ir_gen_resume(IrBuilderSrc *irb, Scope *scope, AstNode *node) {9784static IrInstSrc *ir_gen_resume(IrBuilderSrc *irb, Scope *scope, AstNode *node) {
9798 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 }
97999790
9800 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);
9801 if (target_inst == irb->codegen->invalid_inst_src)9792 if (target_inst == irb->codegen->invalid_inst_src)
...@@ -9809,7 +9800,7 @@ static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no...@@ -9809,7 +9800,7 @@ static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no
9809{9800{
9810 assert(node->type == NodeTypeAwaitExpr);9801 assert(node->type == NodeTypeAwaitExpr);
98119802
9812 bool is_noasync = is_noasync_scope(scope);9803 bool is_noasync = get_scope_noasync(scope) != nullptr;
98139804
9814 AstNode *expr_node = node->data.await_expr.expr;9805 AstNode *expr_node = node->data.await_expr.expr;
9815 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) {
...@@ -9855,6 +9846,11 @@ static IrInstSrc *ir_gen_suspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode...@@ -9855,6 +9846,11 @@ static IrInstSrc *ir_gen_suspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode
9855 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"));
9856 return irb->codegen->invalid_inst_src;9847 return irb->codegen->invalid_inst_src;
9857 }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
9858 ScopeSuspend *existing_suspend_scope = get_scope_suspend(parent_scope);9854 ScopeSuspend *existing_suspend_scope = get_scope_suspend(parent_scope);
9859 if (existing_suspend_scope) {9855 if (existing_suspend_scope) {
9860 if (!existing_suspend_scope->reported_err) {9856 if (!existing_suspend_scope->reported_err) {
src/parser.cpp+9
...@@ -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;