From 15603f403c9ca91f7530798a5a7751cace284a28 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 21 Feb 2021 16:01:22 -0700 Subject: [PATCH] AST: use fn_proto not fn_decl for extern decls saves a few bytes per extern function declaration --- lib/std/zig/ast.zig | 13 +++++++++++-- lib/std/zig/parse.zig | 11 ++--------- lib/std/zig/render.zig | 34 +++++++++++++++++++++++++++------- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index 785c58b067..72c2f82d09 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -2642,20 +2642,29 @@ pub const Node = struct { @"return", /// `fn(a: lhs) rhs`. lhs can be omitted. /// anytype and ... parameters are omitted from the AST tree. + /// main_token is the `fn` keyword. + /// extern function declarations use this tag. fn_proto_simple, /// `fn(a: b, c: d) rhs`. `sub_range_list[lhs]`. /// anytype and ... parameters are omitted from the AST tree. + /// main_token is the `fn` keyword. + /// extern function declarations use this tag. fn_proto_multi, /// `fn(a: b) rhs linksection(e) callconv(f)`. `FnProtoOne[lhs]`. /// zero or one parameters. /// anytype and ... parameters are omitted from the AST tree. + /// main_token is the `fn` keyword. + /// extern function declarations use this tag. fn_proto_one, /// `fn(a: b, c: d) rhs linksection(e) callconv(f)`. `FnProto[lhs]`. /// anytype and ... parameters are omitted from the AST tree. + /// main_token is the `fn` keyword. + /// extern function declarations use this tag. fn_proto, /// lhs is the fn_proto. - /// rhs is the function body block if non-zero. - /// if rhs is zero, the function decl has no body (e.g. an extern function) + /// rhs is the function body block. + /// Note that extern function declarations use the fn_proto tags rather + /// than this one. fn_decl, /// `anyframe->rhs`. main_token is `anyframe`. `lhs` is arrow token index. anyframe_type, diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index c980602b7c..fc57084ad8 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -542,15 +542,8 @@ const Parser = struct { if (fn_proto != 0) { switch (p.token_tags[p.tok_i]) { .semicolon => { - const semicolon_token = p.nextToken(); - return p.addNode(.{ - .tag = .fn_decl, - .main_token = p.nodes.items(.main_token)[fn_proto], - .data = .{ - .lhs = fn_proto, - .rhs = 0, - }, - }); + p.tok_i += 1; + return fn_proto; }, .l_brace => { const body_block = try p.parseBlock(); diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 96721f27c0..48746ec391 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -81,19 +81,39 @@ fn renderMember(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: Space) E while (i < fn_token) : (i += 1) { try renderToken(ais, tree, i, .space); } - if (datas[decl].rhs != 0) { - try renderExpression(ais, tree, fn_proto, .space); - return renderExpression(ais, tree, datas[decl].rhs, space); - } else { - try renderExpression(ais, tree, fn_proto, .none); - return renderToken(ais, tree, tree.lastToken(fn_proto) + 1, space); // semicolon - } + assert(datas[decl].rhs != 0); + try renderExpression(ais, tree, fn_proto, .space); + return renderExpression(ais, tree, datas[decl].rhs, space); }, .fn_proto_simple, .fn_proto_multi, .fn_proto_one, .fn_proto, => { + // Extern function prototypes are parsed as these tags. + // Go back to the first token we should render here. + const fn_token = main_tokens[decl]; + var i = fn_token; + while (i > 0) { + i -= 1; + switch (token_tags[i]) { + .keyword_extern, + .keyword_export, + .keyword_pub, + .string_literal, + .keyword_inline, + .keyword_noinline, + => continue, + + else => { + i += 1; + break; + }, + } + } + while (i < fn_token) : (i += 1) { + try renderToken(ais, tree, i, .space); + } try renderExpression(ais, tree, decl, .none); return renderToken(ais, tree, tree.lastToken(decl) + 1, space); // semicolon },