Commit f85b9f2bf3
Changed files (2)
std
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,
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"));
-}