diff options
| author | Jimmi Holst Christensen <jhc@liab.dk> | 2018-04-10 11:25:58 +0200 |
|---|---|---|
| committer | Jimmi Holst Christensen <jhc@liab.dk> | 2018-04-10 11:25:58 +0200 |
| commit | f85b9f2bf3ac0c5af7804921d2003c2992558cb7 (patch) | |
| tree | f3cb7897b44e3634c90be907f14192f4d2d66d9f /std | |
| parent | 5cd69ee6a4b7d02dbc48d93e8f8f95bd608d9d7c (diff) | |
| download | zig-f85b9f2bf3ac0c5af7804921d2003c2992558cb7.tar.gz zig-f85b9f2bf3ac0c5af7804921d2003c2992558cb7.zip | |
std.zig.parser now parses coroutine code
Diffstat (limited to 'std')
| -rw-r--r-- | std/zig/ast.zig | 157 | ||||
| -rw-r--r-- | std/zig/parser.zig | 277 |
2 files changed, 345 insertions, 89 deletions
diff --git a/std/zig/ast.zig b/std/zig/ast.zig index 86a706f1c7..9043a66ac3 100644 --- a/std/zig/ast.zig +++ b/std/zig/ast.zig @@ -17,14 +17,15 @@ pub const Node = struct { UnionTag, EnumTag, Identifier, + AsyncAttribute, FnProto, ParamDecl, Block, Defer, Comptime, - ErrorPayload, - ValuePayload, - ValueIndexPayload, + Payload, + PointerPayload, + PointerIndexPayload, Else, Switch, SwitchCase, @@ -37,6 +38,7 @@ pub const Node = struct { SuffixOp, GroupedExpression, ControlFlowExpression, + Suspend, FieldInitializer, IntegerLiteral, FloatLiteral, @@ -67,14 +69,15 @@ pub const Node = struct { Id.UnionTag => @fieldParentPtr(NodeUnionTag, "base", base).iterate(index), Id.EnumTag => @fieldParentPtr(NodeEnumTag, "base", base).iterate(index), Id.Identifier => @fieldParentPtr(NodeIdentifier, "base", base).iterate(index), + Id.AsyncAttribute => @fieldParentPtr(NodeAsyncAttribute, "base", base).iterate(index), Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).iterate(index), Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).iterate(index), Id.Block => @fieldParentPtr(NodeBlock, "base", base).iterate(index), Id.Defer => @fieldParentPtr(NodeDefer, "base", base).iterate(index), Id.Comptime => @fieldParentPtr(NodeComptime, "base", base).iterate(index), - Id.ErrorPayload => @fieldParentPtr(NodeErrorPayload, "base", base).iterate(index), - Id.ValuePayload => @fieldParentPtr(NodeValuePayload, "base", base).iterate(index), - Id.ValueIndexPayload => @fieldParentPtr(NodeValueIndexPayload, "base", base).iterate(index), + Id.Payload => @fieldParentPtr(NodePayload, "base", base).iterate(index), + Id.PointerPayload => @fieldParentPtr(NodePointerPayload, "base", base).iterate(index), + Id.PointerIndexPayload => @fieldParentPtr(NodePointerIndexPayload, "base", base).iterate(index), Id.Else => @fieldParentPtr(NodeSwitch, "base", base).iterate(index), Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).iterate(index), Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).iterate(index), @@ -87,6 +90,7 @@ pub const Node = struct { Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).iterate(index), Id.GroupedExpression => @fieldParentPtr(NodeGroupedExpression, "base", base).iterate(index), Id.ControlFlowExpression => @fieldParentPtr(NodeControlFlowExpression, "base", base).iterate(index), + Id.Suspend => @fieldParentPtr(NodeSuspend, "base", base).iterate(index), Id.FieldInitializer => @fieldParentPtr(NodeFieldInitializer, "base", base).iterate(index), Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).iterate(index), Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).iterate(index), @@ -118,14 +122,15 @@ pub const Node = struct { Id.UnionTag => @fieldParentPtr(NodeUnionTag, "base", base).firstToken(), Id.EnumTag => @fieldParentPtr(NodeEnumTag, "base", base).firstToken(), Id.Identifier => @fieldParentPtr(NodeIdentifier, "base", base).firstToken(), + Id.AsyncAttribute => @fieldParentPtr(NodeAsyncAttribute, "base", base).firstToken(), Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).firstToken(), Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).firstToken(), Id.Block => @fieldParentPtr(NodeBlock, "base", base).firstToken(), Id.Defer => @fieldParentPtr(NodeDefer, "base", base).firstToken(), Id.Comptime => @fieldParentPtr(NodeComptime, "base", base).firstToken(), - Id.ErrorPayload => @fieldParentPtr(NodeErrorPayload, "base", base).firstToken(), - Id.ValuePayload => @fieldParentPtr(NodeValuePayload, "base", base).firstToken(), - Id.ValueIndexPayload => @fieldParentPtr(NodeValueIndexPayload, "base", base).firstToken(), + Id.Payload => @fieldParentPtr(NodePayload, "base", base).firstToken(), + Id.PointerPayload => @fieldParentPtr(NodePointerPayload, "base", base).firstToken(), + Id.PointerIndexPayload => @fieldParentPtr(NodePointerIndexPayload, "base", base).firstToken(), Id.Else => @fieldParentPtr(NodeSwitch, "base", base).firstToken(), Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).firstToken(), Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).firstToken(), @@ -138,6 +143,7 @@ pub const Node = struct { Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).firstToken(), Id.GroupedExpression => @fieldParentPtr(NodeGroupedExpression, "base", base).firstToken(), Id.ControlFlowExpression => @fieldParentPtr(NodeControlFlowExpression, "base", base).firstToken(), + Id.Suspend => @fieldParentPtr(NodeSuspend, "base", base).firstToken(), Id.FieldInitializer => @fieldParentPtr(NodeFieldInitializer, "base", base).firstToken(), Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).firstToken(), Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).firstToken(), @@ -169,14 +175,15 @@ pub const Node = struct { Id.UnionTag => @fieldParentPtr(NodeUnionTag, "base", base).lastToken(), Id.EnumTag => @fieldParentPtr(NodeEnumTag, "base", base).lastToken(), Id.Identifier => @fieldParentPtr(NodeIdentifier, "base", base).lastToken(), + Id.AsyncAttribute => @fieldParentPtr(NodeAsyncAttribute, "base", base).lastToken(), Id.FnProto => @fieldParentPtr(NodeFnProto, "base", base).lastToken(), Id.ParamDecl => @fieldParentPtr(NodeParamDecl, "base", base).lastToken(), Id.Block => @fieldParentPtr(NodeBlock, "base", base).lastToken(), Id.Defer => @fieldParentPtr(NodeDefer, "base", base).lastToken(), Id.Comptime => @fieldParentPtr(NodeComptime, "base", base).lastToken(), - Id.ErrorPayload => @fieldParentPtr(NodeErrorPayload, "base", base).lastToken(), - Id.ValuePayload => @fieldParentPtr(NodeValuePayload, "base", base).lastToken(), - Id.ValueIndexPayload => @fieldParentPtr(NodeValueIndexPayload, "base", base).lastToken(), + Id.Payload => @fieldParentPtr(NodePayload, "base", base).lastToken(), + Id.PointerPayload => @fieldParentPtr(NodePointerPayload, "base", base).lastToken(), + Id.PointerIndexPayload => @fieldParentPtr(NodePointerIndexPayload, "base", base).lastToken(), Id.Else => @fieldParentPtr(NodeElse, "base", base).lastToken(), Id.Switch => @fieldParentPtr(NodeSwitch, "base", base).lastToken(), Id.SwitchCase => @fieldParentPtr(NodeSwitchCase, "base", base).lastToken(), @@ -189,6 +196,7 @@ pub const Node = struct { Id.SuffixOp => @fieldParentPtr(NodeSuffixOp, "base", base).lastToken(), Id.GroupedExpression => @fieldParentPtr(NodeGroupedExpression, "base", base).lastToken(), Id.ControlFlowExpression => @fieldParentPtr(NodeControlFlowExpression, "base", base).lastToken(), + Id.Suspend => @fieldParentPtr(NodeSuspend, "base", base).lastToken(), Id.FieldInitializer => @fieldParentPtr(NodeFieldInitializer, "base", base).lastToken(), Id.IntegerLiteral => @fieldParentPtr(NodeIntegerLiteral, "base", base).lastToken(), Id.FloatLiteral => @fieldParentPtr(NodeFloatLiteral, "base", base).lastToken(), @@ -456,6 +464,36 @@ pub const NodeIdentifier = struct { } }; +pub const NodeAsyncAttribute = struct { + base: Node, + async_token: Token, + allocator_type: ?&Node, + rangle_bracket: ?Token, + + pub fn iterate(self: &NodeAsyncAttribute, index: usize) ?&Node { + var i = index; + + if (self.allocator_type) |allocator_type| { + if (i < 1) return allocator_type; + i -= 1; + } + + return null; + } + + pub fn firstToken(self: &NodeAsyncAttribute) Token { + return self.async_token; + } + + pub fn lastToken(self: &NodeAsyncAttribute) Token { + if (self.rangle_bracket) |rangle_bracket| { + return rangle_bracket; + } + + return self.async_token; + } +}; + pub const NodeFnProto = struct { base: Node, visib_token: ?Token, @@ -467,6 +505,7 @@ pub const NodeFnProto = struct { extern_token: ?Token, inline_token: ?Token, cc_token: ?Token, + async_attr: ?&NodeAsyncAttribute, body_node: ?&Node, lib_name: ?&Node, // populated if this is an extern declaration align_expr: ?&Node, // populated if align(A) is present @@ -511,6 +550,14 @@ pub const NodeFnProto = struct { i -= 1; } + switch (self.call_convetion) { + CallConvetion.Async => |attr| { + if (i < 1) return &attr.base; + i -= 1; + }, + else => {}, + } + return null; } @@ -645,13 +692,13 @@ pub const NodeComptime = struct { } }; -pub const NodeErrorPayload = struct { +pub const NodePayload = struct { base: Node, lpipe: Token, error_symbol: &NodeIdentifier, rpipe: Token, - pub fn iterate(self: &NodeErrorPayload, index: usize) ?&Node { + pub fn iterate(self: &NodePayload, index: usize) ?&Node { var i = index; if (i < 1) return &self.error_symbol.base; @@ -660,23 +707,23 @@ pub const NodeErrorPayload = struct { return null; } - pub fn firstToken(self: &NodeErrorPayload) Token { + pub fn firstToken(self: &NodePayload) Token { return self.lpipe; } - pub fn lastToken(self: &NodeErrorPayload) Token { + pub fn lastToken(self: &NodePayload) Token { return self.rpipe; } }; -pub const NodeValuePayload = struct { +pub const NodePointerPayload = struct { base: Node, lpipe: Token, is_ptr: bool, value_symbol: &NodeIdentifier, rpipe: Token, - pub fn iterate(self: &NodeValuePayload, index: usize) ?&Node { + pub fn iterate(self: &NodePointerPayload, index: usize) ?&Node { var i = index; if (i < 1) return &self.value_symbol.base; @@ -685,16 +732,16 @@ pub const NodeValuePayload = struct { return null; } - pub fn firstToken(self: &NodeValuePayload) Token { + pub fn firstToken(self: &NodePointerPayload) Token { return self.lpipe; } - pub fn lastToken(self: &NodeValuePayload) Token { + pub fn lastToken(self: &NodePointerPayload) Token { return self.rpipe; } }; -pub const NodeValueIndexPayload = struct { +pub const NodePointerIndexPayload = struct { base: Node, lpipe: Token, is_ptr: bool, @@ -702,7 +749,7 @@ pub const NodeValueIndexPayload = struct { index_symbol: ?&NodeIdentifier, rpipe: Token, - pub fn iterate(self: &NodeValueIndexPayload, index: usize) ?&Node { + pub fn iterate(self: &NodePointerIndexPayload, index: usize) ?&Node { var i = index; if (i < 1) return &self.value_symbol.base; @@ -716,11 +763,11 @@ pub const NodeValueIndexPayload = struct { return null; } - pub fn firstToken(self: &NodeValueIndexPayload) Token { + pub fn firstToken(self: &NodePointerIndexPayload) Token { return self.lpipe; } - pub fn lastToken(self: &NodeValueIndexPayload) Token { + pub fn lastToken(self: &NodePointerIndexPayload) Token { return self.rpipe; } }; @@ -728,7 +775,7 @@ pub const NodeValueIndexPayload = struct { pub const NodeElse = struct { base: Node, else_token: Token, - payload: ?&NodeErrorPayload, + payload: ?&NodePayload, body: &Node, pub fn iterate(self: &NodeElse, index: usize) ?&Node { @@ -785,7 +832,7 @@ pub const NodeSwitch = struct { pub const NodeSwitchCase = struct { base: Node, items: ArrayList(&Node), - payload: ?&NodeValuePayload, + payload: ?&NodePointerPayload, expr: &Node, pub fn iterate(self: &NodeSwitchCase, index: usize) ?&Node { @@ -837,7 +884,7 @@ pub const NodeWhile = struct { inline_token: ?Token, while_token: Token, condition: &Node, - payload: ?&NodeValuePayload, + payload: ?&NodePointerPayload, continue_expr: ?&Node, body: &Node, @"else": ?&NodeElse, @@ -896,7 +943,7 @@ pub const NodeFor = struct { inline_token: ?Token, for_token: Token, array_expr: &Node, - payload: ?&NodeValueIndexPayload, + payload: ?&NodePointerIndexPayload, body: &Node, @"else": ?&NodeElse, @@ -947,7 +994,7 @@ pub const NodeIf = struct { base: Node, if_token: Token, condition: &Node, - payload: ?&NodeValuePayload, + payload: ?&NodePointerPayload, body: &Node, @"else": ?&NodeElse, @@ -1020,7 +1067,7 @@ pub const NodeInfixOp = struct { BitXor, BoolAnd, BoolOr, - Catch: ?&NodeErrorPayload, + Catch: ?&NodePayload, Div, EqualEqual, ErrorUnion, @@ -1113,13 +1160,16 @@ pub const NodePrefixOp = struct { const PrefixOp = union(enum) { AddrOf: AddrOfInfo, + ArrayType: &Node, + Await, BitNot, BoolNot, + Cancel, Deref, MaybeType, Negation, NegationWrap, - ArrayType: &Node, + Resume, SliceType: AddrOfInfo, Try, UnwrapMaybe, @@ -1153,13 +1203,16 @@ pub const NodePrefixOp = struct { if (i < 1) return size_expr; i -= 1; }, + PrefixOp.Await, PrefixOp.BitNot, PrefixOp.BoolNot, + PrefixOp.Cancel, PrefixOp.Deref, PrefixOp.Negation, PrefixOp.NegationWrap, PrefixOp.Return, PrefixOp.Try, + PrefixOp.Resume, PrefixOp.UnwrapMaybe => {}, } @@ -1218,8 +1271,7 @@ pub const NodeSuffixOp = struct { const CallInfo = struct { params: ArrayList(&Node), - is_async: bool, - allocator: ?&Node, + async_attr: ?&NodeAsyncAttribute, }; const SliceRange = struct { @@ -1347,6 +1399,45 @@ pub const NodeControlFlowExpression = struct { } }; +pub const NodeSuspend = struct { + base: Node, + suspend_token: Token, + payload: ?&NodePayload, + body: ?&Node, + + pub fn iterate(self: &NodeSuspend, index: usize) ?&Node { + var i = index; + + if (self.payload) |payload| { + if (i < 1) return &payload.base; + i -= 1; + } + + if (self.body) |body| { + if (i < 1) return body; + i -= 1; + } + + return null; + } + + pub fn firstToken(self: &NodeSuspend) Token { + return self.suspend_token; + } + + pub fn lastToken(self: &NodeSuspend) Token { + if (self.body) |body| { + return body.lastToken(); + } + + if (self.payload) |payload| { + return payload.lastToken(); + } + + return self.suspend_token; + } +}; + pub const NodeIntegerLiteral = struct { base: Node, token: Token, diff --git a/std/zig/parser.zig b/std/zig/parser.zig index ff3b35c193..9d6d5de6d3 100644 --- a/std/zig/parser.zig +++ b/std/zig/parser.zig @@ -134,6 +134,11 @@ pub const Parser = struct { dest_ptr: DestPtr, }; + const AsyncEndCtx = struct { + dest_ptr: DestPtr, + attribute: &ast.NodeAsyncAttribute, + }; + const State = union(enum) { TopLevel, TopLevelExtern: TopLevelDeclCtx, @@ -173,9 +178,11 @@ pub const Parser = struct { FieldInitListCommaOrEnd: ListSave(&ast.NodeFieldInitializer), FieldListCommaOrEnd: &ast.NodeContainerDecl, SwitchCaseOrEnd: ListSave(&ast.NodeSwitchCase), - ErrorPayload: &?&ast.NodeErrorPayload, - ValuePayload: &?&ast.NodeValuePayload, - ValueIndexPayload: &?&ast.NodeValueIndexPayload, + SuspendBody: &ast.NodeSuspend, + AsyncEnd: AsyncEndCtx, + Payload: &?&ast.NodePayload, + PointerPayload: &?&ast.NodePointerPayload, + PointerIndexPayload: &?&ast.NodePointerIndexPayload, SwitchCaseCommaOrEnd: ListSave(&ast.NodeSwitchCase), SwitchCaseItem: &ArrayList(&ast.Node), SwitchCaseItemCommaOrEnd: &ArrayList(&ast.Node), @@ -399,6 +406,45 @@ pub const Parser = struct { }); continue; }, + Token.Id.Keyword_async => { + // TODO shouldn't need this cast + const fn_proto = try self.createAttachFnProto(arena, ctx.decls, undefined, + ctx.extern_token, ctx.lib_name, (?Token)(null), (?Token)(null), (?Token)(null)); + + const async_node = try arena.create(ast.NodeAsyncAttribute); + *async_node = ast.NodeAsyncAttribute { + .base = self.initNode(ast.Node.Id.AsyncAttribute), + .async_token = token, + .allocator_type = null, + .rangle_bracket = null, + }; + + fn_proto.async_attr = async_node; + stack.append(State { .FnDef = fn_proto }) catch unreachable; + try stack.append(State { .FnProto = fn_proto }); + try stack.append(State { + .ExpectTokenSave = ExpectTokenSave { + .id = Token.Id.Keyword_fn, + .ptr = &fn_proto.fn_token, + } + }); + + const langle_bracket = self.getNextToken(); + if (langle_bracket.id != Token.Id.AngleBracketLeft) { + self.putBackToken(langle_bracket); + continue; + } + + async_node.rangle_bracket = Token(undefined); + try stack.append(State { + .ExpectTokenSave = ExpectTokenSave { + .id = Token.Id.AngleBracketRight, + .ptr = &??async_node.rangle_bracket, + } + }); + try stack.append(State { .TypeExprBegin = DestPtr { .NullableField = &async_node.allocator_type } }); + continue; + }, else => { try self.parseError(&stack, token, "expected variable declaration or function, found {}", @tagName(token.id)); continue; @@ -711,13 +757,14 @@ pub const Parser = struct { continue; }, Token.Id.Keyword_cancel => { - @panic("TODO: cancel"); + const cancel_node = try self.createPrefixOp(arena, token, ast.NodePrefixOp.PrefixOp.Cancel); + dest_ptr.store(&cancel_node.base); + stack.append(State { .Expression = DestPtr { .Field = &cancel_node.rhs } }) catch unreachable; }, Token.Id.Keyword_resume => { - @panic("TODO: resume"); - }, - Token.Id.Keyword_await => { - @panic("TODO: await"); + const resume_node = try self.createPrefixOp(arena, token, ast.NodePrefixOp.PrefixOp.Resume); + dest_ptr.store(&resume_node.base); + stack.append(State { .Expression = DestPtr { .Field = &resume_node.rhs } }) catch unreachable; }, else => { self.putBackToken(token); @@ -786,7 +833,7 @@ pub const Parser = struct { stack.append(State { .UnwrapExpressionEnd = dest_ptr }) catch unreachable; try stack.append(State { .Expression = DestPtr { .Field = &node.rhs } }); - try stack.append(State { .ErrorPayload = &node.op.Catch }); + try stack.append(State { .Payload = &node.op.Catch }); continue; }, Token.Id.QuestionMarkQuestionMark => { @@ -1113,6 +1160,9 @@ pub const Parser = struct { try stack.append(State { .AddrOfModifiers = &node.op.AddrOf }); } continue; + //Token.Id.Keyword_await => { + // @panic("TODO: await"); + //}, } else { self.putBackToken(token); stack.append(State { .SuffixOpExpressionBegin = dest_ptr }) catch unreachable; @@ -1124,7 +1174,38 @@ pub const Parser = struct { const token = self.getNextToken(); switch (token.id) { Token.Id.Keyword_async => { - @panic("TODO: Parse async"); + const async_node = try arena.create(ast.NodeAsyncAttribute); + *async_node = ast.NodeAsyncAttribute { + .base = self.initNode(ast.Node.Id.AsyncAttribute), + .async_token = token, + .allocator_type = null, + .rangle_bracket = null, + }; + + stack.append(State { + .AsyncEnd = AsyncEndCtx { + .dest_ptr = dest_ptr, + .attribute = async_node, + } + }) catch unreachable; + try stack.append(State { .SuffixOpExpressionEnd = dest_ptr }); + try stack.append(State { .PrimaryExpression = dest_ptr }); + + const langle_bracket = self.getNextToken(); + if (langle_bracket.id != Token.Id.AngleBracketLeft) { + self.putBackToken(langle_bracket); + continue; + } + + async_node.rangle_bracket = Token(undefined); + try stack.append(State { + .ExpectTokenSave = ExpectTokenSave { + .id = Token.Id.AngleBracketRight, + .ptr = &??async_node.rangle_bracket, + } + }); + try stack.append(State { .TypeExprBegin = DestPtr { .NullableField = &async_node.allocator_type } }); + continue; }, else => { self.putBackToken(token); @@ -1142,8 +1223,7 @@ pub const Parser = struct { const node = try self.createSuffixOp(arena, ast.NodeSuffixOp.SuffixOp { .Call = ast.NodeSuffixOp.CallInfo { .params = ArrayList(&ast.Node).init(arena), - .is_async = false, // TODO: ASYNC - .allocator = null, + .async_attr = null, } }); node.lhs = dest_ptr.get(); @@ -1257,6 +1337,19 @@ pub const Parser = struct { dest_ptr.store(&node.base); continue; }, + Token.Id.Keyword_suspend => { + const node = try arena.create(ast.NodeSuspend); + *node = ast.NodeSuspend { + .base = self.initNode(ast.Node.Id.Suspend), + .suspend_token = token, + .payload = null, + .body = null, + }; + dest_ptr.store(&node.base); + stack.append(State { .SuspendBody = node }) catch unreachable; + try stack.append(State { .Payload = &node.payload }); + continue; + }, Token.Id.MultilineStringLiteralLine => { const node = try arena.create(ast.NodeMultilineStringLiteral); *node = ast.NodeMultilineStringLiteral { @@ -1477,17 +1570,12 @@ pub const Parser = struct { continue; }, Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => { + const fn_token = (try self.eatToken(&stack, Token.Id.Keyword_fn)) ?? continue; // TODO shouldn't need this cast - const fn_proto = try self.createFnProto(arena, undefined, + const fn_proto = try self.createFnProto(arena, fn_token, (?Token)(null), (?&ast.Node)(null), (?Token)(token), (?Token)(null), (?Token)(null)); dest_ptr.store(&fn_proto.base); stack.append(State { .FnProto = fn_proto }) catch unreachable; - try stack.append(State { - .ExpectTokenSave = ExpectTokenSave { - .id = Token.Id.Keyword_fn, - .ptr = &fn_proto.fn_token, - } - }); continue; }, Token.Id.Keyword_asm => { @@ -1544,7 +1632,7 @@ pub const Parser = struct { stack.append(State { .Else = &node.@"else" }) catch unreachable; try stack.append(State { .Expression = DestPtr { .Field = &node.body } }); - try stack.append(State { .ValuePayload = &node.payload }); + try stack.append(State { .PointerPayload = &node.payload }); try stack.append(State { .ExpectToken = Token.Id.RParen }); try stack.append(State { .Expression = DestPtr { .Field = &node.condition } }); try stack.append(State { .ExpectToken = Token.Id.LParen }); @@ -1816,7 +1904,7 @@ pub const Parser = struct { try list_state.list.append(node); stack.append(State { .SwitchCaseCommaOrEnd = list_state }) catch unreachable; try stack.append(State { .Expression = DestPtr{ .Field = &node.expr } }); - try stack.append(State { .ValuePayload = &node.payload }); + try stack.append(State { .PointerPayload = &node.payload }); const maybe_else = self.getNextToken(); if (maybe_else.id == Token.Id.Keyword_else) { @@ -1883,7 +1971,7 @@ pub const Parser = struct { *dest = node; stack.append(State { .Expression = DestPtr { .Field = &node.body } }) catch unreachable; - try stack.append(State { .ErrorPayload = &node.payload }); + try stack.append(State { .Payload = &node.payload }); }, State.WhileContinueExpr => |dest| { @@ -1898,7 +1986,41 @@ pub const Parser = struct { try stack.append(State { .AssignmentExpressionBegin = DestPtr { .NullableField = dest } }); }, - State.ErrorPayload => |dest| { + State.SuspendBody => |suspend_node| { + if (suspend_node.payload != null) { + try stack.append(State { .AssignmentExpressionBegin = DestPtr { .NullableField = &suspend_node.body } }); + } + continue; + }, + + State.AsyncEnd => |ctx| { + const node = ctx.dest_ptr.get(); + + switch (node.id) { + ast.Node.Id.FnProto => { + const fn_proto = @fieldParentPtr(ast.NodeFnProto, "base", node); + fn_proto.async_attr = ctx.attribute; + }, + ast.Node.Id.SuffixOp => { + const suffix_op = @fieldParentPtr(ast.NodeSuffixOp, "base", node); + if (suffix_op.op == ast.NodeSuffixOp.SuffixOp.Call) { + suffix_op.op.Call.async_attr = ctx.attribute; + continue; + } + + try self.parseError(&stack, node.firstToken(), "expected call or fn proto, found {}.", + @tagName(suffix_op.op)); + continue; + }, + else => { + try self.parseError(&stack, node.firstToken(), "expected call or fn proto, found {}.", + @tagName(node.id)); + continue; + } + } + }, + + State.Payload => |dest| { const lpipe = self.getNextToken(); if (lpipe.id != Token.Id.Pipe) { self.putBackToken(lpipe); @@ -1907,9 +2029,9 @@ pub const Parser = struct { const error_symbol = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue; const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue; - const node = try arena.create(ast.NodeErrorPayload); - *node = ast.NodeErrorPayload { - .base = self.initNode(ast.Node.Id.ErrorPayload), + const node = try arena.create(ast.NodePayload); + *node = ast.NodePayload { + .base = self.initNode(ast.Node.Id.Payload), .lpipe = lpipe, .error_symbol = try self.createIdentifier(arena, error_symbol), .rpipe = rpipe @@ -1917,7 +2039,7 @@ pub const Parser = struct { *dest = node; }, - State.ValuePayload => |dest| { + State.PointerPayload => |dest| { const lpipe = self.getNextToken(); if (lpipe.id != Token.Id.Pipe) { self.putBackToken(lpipe); @@ -1936,9 +2058,9 @@ pub const Parser = struct { const value_symbol = (try self.eatToken(&stack, Token.Id.Identifier)) ?? continue; const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue; - const node = try arena.create(ast.NodeValuePayload); - *node = ast.NodeValuePayload { - .base = self.initNode(ast.Node.Id.ValuePayload), + const node = try arena.create(ast.NodePointerPayload); + *node = ast.NodePointerPayload { + .base = self.initNode(ast.Node.Id.PointerPayload), .lpipe = lpipe, .is_ptr = is_ptr, .value_symbol = try self.createIdentifier(arena, value_symbol), @@ -1947,7 +2069,7 @@ pub const Parser = struct { *dest = node; }, - State.ValueIndexPayload => |dest| { + State.PointerIndexPayload => |dest| { const lpipe = self.getNextToken(); if (lpipe.id != Token.Id.Pipe) { self.putBackToken(lpipe); @@ -1977,9 +2099,9 @@ pub const Parser = struct { }; const rpipe = (try self.eatToken(&stack, Token.Id.Pipe)) ?? continue; - const node = try arena.create(ast.NodeValueIndexPayload); - *node = ast.NodeValueIndexPayload { - .base = self.initNode(ast.Node.Id.ValueIndexPayload), + const node = try arena.create(ast.NodePointerIndexPayload); + *node = ast.NodePointerIndexPayload { + .base = self.initNode(ast.Node.Id.PointerIndexPayload), .lpipe = lpipe, .is_ptr = is_ptr, .value_symbol = try self.createIdentifier(arena, value_symbol), @@ -2249,7 +2371,7 @@ pub const Parser = struct { stack.append(State { .Else = &node.@"else" }) catch unreachable; try stack.append(State { .Expression = DestPtr { .Field = &node.body } }); try stack.append(State { .WhileContinueExpr = &node.continue_expr }); - try stack.append(State { .ValuePayload = &node.payload }); + try stack.append(State { .PointerPayload = &node.payload }); try stack.append(State { .ExpectToken = Token.Id.RParen }); try stack.append(State { .Expression = DestPtr { .Field = &node.condition } }); try stack.append(State { .ExpectToken = Token.Id.LParen }); @@ -2271,7 +2393,7 @@ pub const Parser = struct { stack.append(State { .Else = &node.@"else" }) catch unreachable; try stack.append(State { .Expression = DestPtr { .Field = &node.body } }); - try stack.append(State { .ValueIndexPayload = &node.payload }); + try stack.append(State { .PointerIndexPayload = &node.payload }); try stack.append(State { .ExpectToken = Token.Id.RParen }); try stack.append(State { .Expression = DestPtr { .Field = &node.array_expr } }); try stack.append(State { .ExpectToken = Token.Id.LParen }); @@ -2374,9 +2496,9 @@ pub const Parser = struct { ast.Node.Id.EnumTag, ast.Node.Id.ParamDecl, ast.Node.Id.Block, - ast.Node.Id.ErrorPayload, - ast.Node.Id.ValuePayload, - ast.Node.Id.ValueIndexPayload, + ast.Node.Id.Payload, + ast.Node.Id.PointerPayload, + ast.Node.Id.PointerIndexPayload, ast.Node.Id.Switch, ast.Node.Id.SwitchCase, ast.Node.Id.SwitchElse, @@ -2422,6 +2544,15 @@ pub const Parser = struct { const comptime_node = @fieldParentPtr(ast.NodeComptime, "base", n); n = comptime_node.expr; }, + ast.Node.Id.Suspend => { + const suspend_node = @fieldParentPtr(ast.NodeSuspend, "base", n); + if (suspend_node.body) |body| { + n = body; + continue; + } + + return true; + }, else => return true, } } @@ -2540,6 +2671,7 @@ pub const Parser = struct { }, Token.Id.QuestionMark => (ast.NodePrefixOp.PrefixOp)(ast.NodePrefixOp.PrefixOp.MaybeType), Token.Id.QuestionMarkQuestionMark => (ast.NodePrefixOp.PrefixOp)(ast.NodePrefixOp.PrefixOp.UnwrapMaybe), + Token.Id.Keyword_await => (ast.NodePrefixOp.PrefixOp)(ast.NodePrefixOp.PrefixOp.Await), else => null, }; } @@ -2628,6 +2760,7 @@ pub const Parser = struct { .extern_token = *extern_token, .inline_token = *inline_token, .cc_token = *cc_token, + .async_attr = null, .body_node = null, .lib_name = lib_name, .align_expr = null, @@ -3105,6 +3238,30 @@ pub const Parser = struct { try stream.print("{} ", self.tokenizer.getTokenSlice(comptime_node.comptime_token)); try stack.append(RenderState { .Expression = comptime_node.expr }); }, + ast.Node.Id.AsyncAttribute => { + const async_attr = @fieldParentPtr(ast.NodeAsyncAttribute, "base", base); + try stream.print("{}", self.tokenizer.getTokenSlice(async_attr.async_token)); + + if (async_attr.allocator_type) |allocator_type| { + try stack.append(RenderState { .Text = ">" }); + try stack.append(RenderState { .Expression = allocator_type }); + try stack.append(RenderState { .Text = "<" }); + } + }, + ast.Node.Id.Suspend => { + const suspend_node = @fieldParentPtr(ast.NodeSuspend, "base", base); + try stream.print("{}", self.tokenizer.getTokenSlice(suspend_node.suspend_token)); + + if (suspend_node.body) |body| { + try stack.append(RenderState { .Expression = body }); + try stack.append(RenderState { .Text = " " }); + } + + if (suspend_node.payload) |payload| { + try stack.append(RenderState { .Expression = &payload.base }); + try stack.append(RenderState { .Text = " " }); + } + }, ast.Node.Id.InfixOp => { const prefix_op_node = @fieldParentPtr(ast.NodeInfixOp, "base", base); try stack.append(RenderState { .Expression = prefix_op_node.rhs }); @@ -3211,6 +3368,9 @@ pub const Parser = struct { ast.NodePrefixOp.PrefixOp.Try => try stream.write("try "), ast.NodePrefixOp.PrefixOp.UnwrapMaybe => try stream.write("??"), ast.NodePrefixOp.PrefixOp.MaybeType => try stream.write("?"), + ast.NodePrefixOp.PrefixOp.Await => try stream.write("await "), + ast.NodePrefixOp.PrefixOp.Cancel => try stream.write("cancel "), + ast.NodePrefixOp.PrefixOp.Resume => try stream.write("resume "), } }, ast.Node.Id.SuffixOp => { @@ -3229,11 +3389,18 @@ pub const Parser = struct { } } try stack.append(RenderState { .Text = "("}); + try stack.append(RenderState { .Expression = suffix_op.lhs }); + + if (call_info.async_attr) |async_attr| { + try stack.append(RenderState { .Text = " "}); + try stack.append(RenderState { .Expression = &async_attr.base }); + } }, ast.NodeSuffixOp.SuffixOp.ArrayAccess => |index_expr| { try stack.append(RenderState { .Text = "]"}); try stack.append(RenderState { .Expression = index_expr}); try stack.append(RenderState { .Text = "["}); + try stack.append(RenderState { .Expression = suffix_op.lhs }); }, ast.NodeSuffixOp.SuffixOp.Slice => |range| { try stack.append(RenderState { .Text = "]"}); @@ -3243,6 +3410,7 @@ pub const Parser = struct { try stack.append(RenderState { .Text = ".."}); try stack.append(RenderState { .Expression = range.start}); try stack.append(RenderState { .Text = "["}); + try stack.append(RenderState { .Expression = suffix_op.lhs }); }, ast.NodeSuffixOp.SuffixOp.StructInitializer => |field_inits| { try stack.append(RenderState { .Text = " }"}); @@ -3257,6 +3425,7 @@ pub const Parser = struct { } } try stack.append(RenderState { .Text = "{"}); + try stack.append(RenderState { .Expression = suffix_op.lhs }); }, ast.NodeSuffixOp.SuffixOp.ArrayInitializer => |exprs| { try stack.append(RenderState { .Text = " }"}); @@ -3271,10 +3440,9 @@ pub const Parser = struct { } } try stack.append(RenderState { .Text = "{"}); + try stack.append(RenderState { .Expression = suffix_op.lhs }); }, } - - try stack.append(RenderState { .Expression = suffix_op.lhs }); }, ast.Node.Id.ControlFlowExpression => { const flow_expr = @fieldParentPtr(ast.NodeControlFlowExpression, "base", base); @@ -3302,14 +3470,14 @@ pub const Parser = struct { try stack.append(RenderState { .Expression = rhs }); } }, - ast.Node.Id.ErrorPayload => { - const payload = @fieldParentPtr(ast.NodeErrorPayload, "base", base); + ast.Node.Id.Payload => { + const payload = @fieldParentPtr(ast.NodePayload, "base", base); try stack.append(RenderState { .Text = "|"}); try stack.append(RenderState { .Expression = &payload.error_symbol.base }); try stack.append(RenderState { .Text = "|"}); }, - ast.Node.Id.ValuePayload => { - const payload = @fieldParentPtr(ast.NodeValuePayload, "base", base); + ast.Node.Id.PointerPayload => { + const payload = @fieldParentPtr(ast.NodePointerPayload, "base", base); try stack.append(RenderState { .Text = "|"}); try stack.append(RenderState { .Expression = &payload.value_symbol.base }); @@ -3319,8 +3487,8 @@ pub const Parser = struct { try stack.append(RenderState { .Text = "|"}); }, - ast.Node.Id.ValueIndexPayload => { - const payload = @fieldParentPtr(ast.NodeValueIndexPayload, "base", base); + ast.Node.Id.PointerIndexPayload => { + const payload = @fieldParentPtr(ast.NodePointerIndexPayload, "base", base); try stack.append(RenderState { .Text = "|"}); if (payload.index_symbol) |index_symbol| { @@ -3553,6 +3721,11 @@ pub const Parser = struct { try stack.append(RenderState { .Text = "fn" }); + if (fn_proto.async_attr) |async_attr| { + try stack.append(RenderState { .Text = " " }); + try stack.append(RenderState { .Expression = &async_attr.base }); + } + if (fn_proto.cc_token) |cc_token| { try stack.append(RenderState { .Text = " " }); try stack.append(RenderState { .Text = self.tokenizer.getTokenSlice(cc_token) }); @@ -4789,8 +4962,7 @@ test "zig fmt: coroutines" { \\ x += 1; \\ suspend; \\ x += 1; - \\ suspend |p| { - \\ } + \\ suspend |p| {} \\ const p = async simpleAsyncFn() catch unreachable; \\ await p; \\} @@ -4803,10 +4975,3 @@ test "zig fmt: coroutines" { \\ ); } - -test "zig fmt: zig fmt" { - try testCanonical(@embedFile("ast.zig")); - try testCanonical(@embedFile("index.zig")); - try testCanonical(@embedFile("parser.zig")); - try testCanonical(@embedFile("tokenizer.zig")); -} |
