authorgravatar for me@tadeo.caTadeo Kondrak <me@tadeo.ca> 2020-05-04 09:24:46-06:00
committergravatar for me@tadeo.caTadeo Kondrak <me@tadeo.ca> 2020-05-05 09:37:59-06:00
logd0e996405bff4352c78c570b4944b369d642d058
treed2b43b7fe6889a77a1c15e2e43bf4be1f8dc0e53
parent7ada59f873738931b4d162372dff0a33442112b6
signature Commit is signed but in an unrecognized format.

add zig fmt fix for async/extern fn


4 files changed, 63 insertions(+), 20 deletions(-)

lib/std/zig/ast.zig+2
......@@ -880,6 +880,8 @@ pub const Node = struct {
880880 align_expr: ?*Node, // populated if align(A) is present
881881 section_expr: ?*Node, // populated if linksection(A) is present
882882 callconv_expr: ?*Node, // populated if callconv(A) is present
883 is_extern_prototype: bool = false, // TODO: Remove once extern fn rewriting is
884 is_async: bool = false, // TODO: remove once async fn rewriting is
883885
884886 pub const ParamList = SegmentedList(*Node, 2);
885887
lib/std/zig/parse.zig+31-1
......@@ -337,7 +337,25 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
337337
338338/// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)
339339fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
340 const fn_token = eatToken(it, .Keyword_fn) orelse return null;
340 // TODO: Remove once extern/async fn rewriting is
341 var is_async = false;
342 var is_extern = false;
343 const cc_token: ?usize = blk: {
344 if (eatToken(it, .Keyword_extern)) |token| {
345 is_extern = true;
346 break :blk token;
347 }
348 if (eatToken(it, .Keyword_async)) |token| {
349 is_async = true;
350 break :blk token;
351 }
352 break :blk null;
353 };
354 const fn_token = eatToken(it, .Keyword_fn) orelse {
355 if (cc_token) |token|
356 putBackToken(it, token);
357 return null;
358 };
341359 const name_token = eatToken(it, .Identifier);
342360 const lparen = try expectToken(it, tree, .LParen);
343361 const params = try parseParamDeclList(arena, it, tree);
......@@ -381,6 +399,8 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
381399 .align_expr = align_expr,
382400 .section_expr = section_expr,
383401 .callconv_expr = callconv_expr,
402 .is_extern_prototype = is_extern,
403 .is_async = is_async,
384404 };
385405
386406 return &fn_proto_node.base;
......@@ -1175,6 +1195,16 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
11751195 const maybe_async = eatToken(it, .Keyword_async);
11761196 if (maybe_async) |async_token| {
11771197 const token_fn = eatToken(it, .Keyword_fn);
1198 if (token_fn != null) {
1199 // TODO: remove this hack when async fn rewriting is
1200 // HACK: If we see the keyword `fn`, then we assume that
1201 // we are parsing an async fn proto, and not a call.
1202 // We therefore put back all tokens consumed by the async
1203 // prefix...
1204 putBackToken(it, token_fn.?);
1205 putBackToken(it, async_token);
1206 return parsePrimaryTypeExpr(arena, it, tree);
1207 }
11781208 var res = try expectNode(arena, it, tree, parsePrimaryTypeExpr, .{
11791209 .ExpectedPrimaryTypeExpr = .{ .token = it.index },
11801210 });
lib/std/zig/parser_test.zig+24-18
......@@ -236,10 +236,10 @@ test "zig fmt: anon list literal syntax" {
236236test "zig fmt: async function" {
237237 try testCanonical(
238238 \\pub const Server = struct {
239 \\ handleRequestFn: async fn (*Server, *const std.net.Address, File) void,
239 \\ handleRequestFn: fn (*Server, *const std.net.Address, File) callconv(.Async) void,
240240 \\};
241241 \\test "hi" {
242 \\ var ptr = @ptrCast(async fn (i32) void, other);
242 \\ var ptr = @ptrCast(fn (i32) callconv(.Async) void, other);
243243 \\}
244244 \\
245245 );
......@@ -435,15 +435,6 @@ test "zig fmt: aligned struct field" {
435435 );
436436}
437437
438test "zig fmt: preserve space between async fn definitions" {
439 try testCanonical(
440 \\async fn a() void {}
441 \\
442 \\async fn b() void {}
443 \\
444 );
445}
446
447438test "zig fmt: comment to disable/enable zig fmt first" {
448439 try testCanonical(
449440 \\// Test trailing comma syntax
......@@ -1499,7 +1490,7 @@ test "zig fmt: line comments in struct initializer" {
14991490
15001491test "zig fmt: first line comment in struct initializer" {
15011492 try testCanonical(
1502 \\pub async fn acquire(self: *Self) HeldLock {
1493 \\pub fn acquire(self: *Self) HeldLock {
15031494 \\ return HeldLock{
15041495 \\ // guaranteed allocation elision
15051496 \\ .held = self.lock.acquire(),
......@@ -2461,8 +2452,7 @@ test "zig fmt: fn type" {
24612452 \\}
24622453 \\
24632454 \\const a: fn (u8) u8 = undefined;
2464 \\const b: extern fn (u8) u8 = undefined;
2465 \\const c: fn (u8) callconv(.Naked) u8 = undefined;
2455 \\const b: fn (u8) callconv(.Naked) u8 = undefined;
24662456 \\const ap: fn (u8) u8 = a;
24672457 \\
24682458 );
......@@ -2484,7 +2474,7 @@ test "zig fmt: inline asm" {
24842474
24852475test "zig fmt: async functions" {
24862476 try testCanonical(
2487 \\async fn simpleAsyncFn() void {
2477 \\fn simpleAsyncFn() void {
24882478 \\ const a = async a.b();
24892479 \\ x += 1;
24902480 \\ suspend;
......@@ -2920,6 +2910,25 @@ test "zig fmt: noasync to nosuspend" {
29202910 \\pub fn main() void {
29212911 \\ nosuspend call();
29222912 \\}
2913 );
2914}
2915
2916test "zig fmt: convert async fn into callconv(.Async)" {
2917 try testTransform(
2918 \\async fn foo() void {}
2919 ,
2920 \\fn foo() callconv(.Async) void {}
2921 \\
2922 );
2923}
2924
2925test "zig fmt: convert extern fn proto into callconv(.C)" {
2926 try testTransform(
2927 \\extern fn foo0() void {}
2928 \\const foo1 = extern fn () void;
2929 ,
2930 \\extern fn foo0() void {}
2931 \\const foo1 = fn () callconv(.C) void;
29232932 \\
29242933 );
29252934}
......@@ -2970,7 +2979,6 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b
29702979 anything_changed.* = try std.zig.render(allocator, buffer.outStream(), tree);
29712980 return buffer.toOwnedSlice();
29722981}
2973
29742982fn testTransform(source: []const u8, expected_source: []const u8) !void {
29752983 const needed_alloc_count = x: {
29762984 // Try it once with unlimited memory, make sure it works
......@@ -3018,11 +3026,9 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void {
30183026 }
30193027 }
30203028}
3021
30223029fn testCanonical(source: []const u8) !void {
30233030 return testTransform(source, source);
30243031}
3025
30263032fn testError(source: []const u8) !void {
30273033 const tree = try std.zig.parse(std.testing.allocator, source);
30283034 defer tree.deinit();
lib/std/zig/render.zig+6-1
......@@ -1414,7 +1414,8 @@ fn renderExpression(
14141414 }
14151415
14161416 if (fn_proto.extern_export_inline_token) |extern_export_inline_token| {
1417 try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export
1417 if (!fn_proto.is_extern_prototype)
1418 try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export/inline
14181419 }
14191420
14201421 if (fn_proto.lib_name) |lib_name| {
......@@ -1510,6 +1511,10 @@ fn renderExpression(
15101511 try renderToken(tree, stream, callconv_lparen, indent, start_col, Space.None); // (
15111512 try renderExpression(allocator, stream, tree, indent, start_col, callconv_expr, Space.None);
15121513 try renderToken(tree, stream, callconv_rparen, indent, start_col, Space.Space); // )
1514 } else if (fn_proto.is_extern_prototype) {
1515 try stream.writeAll("callconv(.C) ");
1516 } else if (fn_proto.is_async) {
1517 try stream.writeAll("callconv(.Async) ");
15131518 }
15141519
15151520 switch (fn_proto.return_type) {