| author | |
| committer | |
| log | 7c2c0e36f8378d8efaf64d859bdffb91007db82a |
| tree | a8335099205f30d5bf9b4478ee9d73824b2f0abf |
| parent | 5db9f306ba88087d269dc5fe5672a5af5ab55333 |
Instead of being its own node, it's a struct inside FnProto.
Instead of FnProto having a SinglyLinkedList of ParamDecl nodes,
ParamDecls are appended directly in memory after the FnProto.
throughput: 72.2 MiB/s => 72.9 MiB/s
maxrss: 70 KB => 68 KB
Importantly, the API is improved as well since the data is arranged
linearly in memory.3 files changed, 123 insertions(+), 105 deletions(-)
lib/std/zig/ast.zig+89-62| ... | ... | @@ -477,7 +477,6 @@ pub const Node = struct { |
| 477 | 477 | ErrorTag, |
| 478 | 478 | AsmInput, |
| 479 | 479 | AsmOutput, |
| 480 | ParamDecl, | |
| 481 | 480 | FieldInitializer, |
| 482 | 481 | }; |
| 483 | 482 | |
| ... | ... | @@ -533,7 +532,6 @@ pub const Node = struct { |
| 533 | 532 | switch (n.id) { |
| 534 | 533 | .Root, |
| 535 | 534 | .ContainerField, |
| 536 | .ParamDecl, | |
| 537 | 535 | .Block, |
| 538 | 536 | .Payload, |
| 539 | 537 | .PointerPayload, |
| ... | ... | @@ -819,7 +817,7 @@ pub const Node = struct { |
| 819 | 817 | return @ptrCast(*ContainerDecl, bytes.ptr); |
| 820 | 818 | } |
| 821 | 819 | |
| 822 | pub fn free(self: *Decl, allocator: *mem.Allocator) void { | |
| 820 | pub fn free(self: *ContainerDecl, allocator: *mem.Allocator) void { | |
| 823 | 821 | const bytes = @ptrCast([*]u8, self)[0..sizeInBytes(self.fields_and_decls_len)]; |
| 824 | 822 | allocator.free(bytes); |
| 825 | 823 | } |
| ... | ... | @@ -979,13 +977,14 @@ pub const Node = struct { |
| 979 | 977 | } |
| 980 | 978 | }; |
| 981 | 979 | |
| 980 | /// The params are directly after the FnProto in memory. | |
| 982 | 981 | pub const FnProto = struct { |
| 983 | 982 | base: Node = Node{ .id = .FnProto }, |
| 984 | 983 | doc_comments: ?*DocComment, |
| 985 | 984 | visib_token: ?TokenIndex, |
| 986 | 985 | fn_token: TokenIndex, |
| 987 | 986 | name_token: ?TokenIndex, |
| 988 | params: ParamList, | |
| 987 | params_len: NodeIndex, | |
| 989 | 988 | return_type: ReturnType, |
| 990 | 989 | var_args_token: ?TokenIndex, |
| 991 | 990 | extern_export_inline_token: ?TokenIndex, |
| ... | ... | @@ -997,16 +996,75 @@ pub const Node = struct { |
| 997 | 996 | is_extern_prototype: bool = false, // TODO: Remove once extern fn rewriting is |
| 998 | 997 | is_async: bool = false, // TODO: remove once async fn rewriting is |
| 999 | 998 | |
| 1000 | pub const ParamList = LinkedList(*Node); | |
| 1001 | ||
| 1002 | 999 | pub const ReturnType = union(enum) { |
| 1003 | 1000 | Explicit: *Node, |
| 1004 | 1001 | InferErrorSet: *Node, |
| 1005 | 1002 | Invalid: TokenIndex, |
| 1006 | 1003 | }; |
| 1007 | 1004 | |
| 1005 | pub const ParamDecl = struct { | |
| 1006 | doc_comments: ?*DocComment, | |
| 1007 | comptime_token: ?TokenIndex, | |
| 1008 | noalias_token: ?TokenIndex, | |
| 1009 | name_token: ?TokenIndex, | |
| 1010 | param_type: ParamType, | |
| 1011 | ||
| 1012 | pub const ParamType = union(enum) { | |
| 1013 | var_type: *Node, | |
| 1014 | var_args: TokenIndex, | |
| 1015 | type_expr: *Node, | |
| 1016 | }; | |
| 1017 | ||
| 1018 | pub fn iterate(self: *const ParamDecl) Node.Iterator { | |
| 1019 | return .{ .parent_node = &self.base, .index = 0, .node = null }; | |
| 1020 | } | |
| 1021 | ||
| 1022 | pub fn iterateNext(self: *const ParamDecl, it: *Node.Iterator) ?*Node { | |
| 1023 | var i = it.index; | |
| 1024 | it.index += 1; | |
| 1025 | ||
| 1026 | if (i < 1) { | |
| 1027 | switch (self.param_type) { | |
| 1028 | .var_args => return null, | |
| 1029 | .var_type, .type_expr => |node| return node, | |
| 1030 | } | |
| 1031 | } | |
| 1032 | i -= 1; | |
| 1033 | ||
| 1034 | return null; | |
| 1035 | } | |
| 1036 | ||
| 1037 | pub fn firstToken(self: *const ParamDecl) TokenIndex { | |
| 1038 | if (self.comptime_token) |comptime_token| return comptime_token; | |
| 1039 | if (self.noalias_token) |noalias_token| return noalias_token; | |
| 1040 | if (self.name_token) |name_token| return name_token; | |
| 1041 | switch (self.param_type) { | |
| 1042 | .var_args => |tok| return tok, | |
| 1043 | .var_type, .type_expr => |node| return node.firstToken(), | |
| 1044 | } | |
| 1045 | } | |
| 1046 | ||
| 1047 | pub fn lastToken(self: *const ParamDecl) TokenIndex { | |
| 1048 | switch (self.param_type) { | |
| 1049 | .var_args => |tok| return tok, | |
| 1050 | .var_type, .type_expr => |node| return node.lastToken(), | |
| 1051 | } | |
| 1052 | } | |
| 1053 | }; | |
| 1054 | ||
| 1055 | /// After this the caller must initialize the params list. | |
| 1056 | pub fn alloc(allocator: *mem.Allocator, params_len: NodeIndex) !*FnProto { | |
| 1057 | const bytes = try allocator.alignedAlloc(u8, @alignOf(FnProto), sizeInBytes(params_len)); | |
| 1058 | return @ptrCast(*FnProto, bytes.ptr); | |
| 1059 | } | |
| 1060 | ||
| 1061 | pub fn free(self: *FnProto, allocator: *mem.Allocator) void { | |
| 1062 | const bytes = @ptrCast([*]u8, self)[0..sizeInBytes(self.params_len)]; | |
| 1063 | allocator.free(bytes); | |
| 1064 | } | |
| 1065 | ||
| 1008 | 1066 | pub fn iterate(self: *const FnProto) Node.Iterator { |
| 1009 | return .{ .parent_node = &self.base, .index = 0, .node = self.params.first }; | |
| 1067 | return .{ .parent_node = &self.base, .index = 0, .node = null }; | |
| 1010 | 1068 | } |
| 1011 | 1069 | |
| 1012 | 1070 | pub fn iterateNext(self: *const FnProto, it: *Node.Iterator) ?*Node { |
| ... | ... | @@ -1018,11 +1076,17 @@ pub const Node = struct { |
| 1018 | 1076 | i -= 1; |
| 1019 | 1077 | } |
| 1020 | 1078 | |
| 1021 | if (it.node) |param| { | |
| 1022 | it.index -= 1; | |
| 1023 | it.node = param.next; | |
| 1024 | return param.data; | |
| 1079 | if (i < self.params_len) { | |
| 1080 | switch (self.paramsConst()[i].param_type) { | |
| 1081 | .var_type => |n| return n, | |
| 1082 | .var_args => { | |
| 1083 | i += 1; | |
| 1084 | it.index += 1; | |
| 1085 | }, | |
| 1086 | .type_expr => |n| return n, | |
| 1087 | } | |
| 1025 | 1088 | } |
| 1089 | i -= self.params_len; | |
| 1026 | 1090 | |
| 1027 | 1091 | if (self.align_expr) |align_expr| { |
| 1028 | 1092 | if (i < 1) return align_expr; |
| ... | ... | @@ -1064,6 +1128,20 @@ pub const Node = struct { |
| 1064 | 1128 | .Invalid => |tok| return tok, |
| 1065 | 1129 | } |
| 1066 | 1130 | } |
| 1131 | ||
| 1132 | pub fn params(self: *FnProto) []ParamDecl { | |
| 1133 | const decls_start = @ptrCast([*]u8, self) + @sizeOf(FnProto); | |
| 1134 | return @ptrCast([*]ParamDecl, decls_start)[0..self.params_len]; | |
| 1135 | } | |
| 1136 | ||
| 1137 | pub fn paramsConst(self: *const FnProto) []const ParamDecl { | |
| 1138 | const decls_start = @ptrCast([*]const u8, self) + @sizeOf(FnProto); | |
| 1139 | return @ptrCast([*]const ParamDecl, decls_start)[0..self.params_len]; | |
| 1140 | } | |
| 1141 | ||
| 1142 | fn sizeInBytes(params_len: NodeIndex) usize { | |
| 1143 | return @sizeOf(FnProto) + @sizeOf(ParamDecl) * @as(usize, params_len); | |
| 1144 | } | |
| 1067 | 1145 | }; |
| 1068 | 1146 | |
| 1069 | 1147 | pub const AnyFrameType = struct { |
| ... | ... | @@ -1102,57 +1180,6 @@ pub const Node = struct { |
| 1102 | 1180 | } |
| 1103 | 1181 | }; |
| 1104 | 1182 | |
| 1105 | pub const ParamDecl = struct { | |
| 1106 | base: Node = Node{ .id = .ParamDecl }, | |
| 1107 | doc_comments: ?*DocComment, | |
| 1108 | comptime_token: ?TokenIndex, | |
| 1109 | noalias_token: ?TokenIndex, | |
| 1110 | name_token: ?TokenIndex, | |
| 1111 | param_type: ParamType, | |
| 1112 | ||
| 1113 | pub const ParamType = union(enum) { | |
| 1114 | var_type: *Node, | |
| 1115 | var_args: TokenIndex, | |
| 1116 | type_expr: *Node, | |
| 1117 | }; | |
| 1118 | ||
| 1119 | pub fn iterate(self: *const ParamDecl) Node.Iterator { | |
| 1120 | return .{ .parent_node = &self.base, .index = 0, .node = null }; | |
| 1121 | } | |
| 1122 | ||
| 1123 | pub fn iterateNext(self: *const ParamDecl, it: *Node.Iterator) ?*Node { | |
| 1124 | var i = it.index; | |
| 1125 | it.index += 1; | |
| 1126 | ||
| 1127 | if (i < 1) { | |
| 1128 | switch (self.param_type) { | |
| 1129 | .var_args => return null, | |
| 1130 | .var_type, .type_expr => |node| return node, | |
| 1131 | } | |
| 1132 | } | |
| 1133 | i -= 1; | |
| 1134 | ||
| 1135 | return null; | |
| 1136 | } | |
| 1137 | ||
| 1138 | pub fn firstToken(self: *const ParamDecl) TokenIndex { | |
| 1139 | if (self.comptime_token) |comptime_token| return comptime_token; | |
| 1140 | if (self.noalias_token) |noalias_token| return noalias_token; | |
| 1141 | if (self.name_token) |name_token| return name_token; | |
| 1142 | switch (self.param_type) { | |
| 1143 | .var_args => |tok| return tok, | |
| 1144 | .var_type, .type_expr => |node| return node.firstToken(), | |
| 1145 | } | |
| 1146 | } | |
| 1147 | ||
| 1148 | pub fn lastToken(self: *const ParamDecl) TokenIndex { | |
| 1149 | switch (self.param_type) { | |
| 1150 | .var_args => |tok| return tok, | |
| 1151 | .var_type, .type_expr => |node| return node.lastToken(), | |
| 1152 | } | |
| 1153 | } | |
| 1154 | }; | |
| 1155 | ||
| 1156 | 1183 | pub const Block = struct { |
| 1157 | 1184 | base: Node = Node{ .id = .Block }, |
| 1158 | 1185 | label: ?TokenIndex, |
lib/std/zig/parse.zig+27-29| ... | ... | @@ -71,7 +71,7 @@ const Parser = struct { |
| 71 | 71 | const eof_token = p.eatToken(.Eof).?; |
| 72 | 72 | |
| 73 | 73 | const node = try Node.Root.create(&p.arena.allocator, decls.len, eof_token); |
| 74 | std.mem.copy(*ast.Node, node.decls(), decls); | |
| 74 | std.mem.copy(*Node, node.decls(), decls); | |
| 75 | 75 | |
| 76 | 76 | return node; |
| 77 | 77 | } |
| ... | ... | @@ -96,8 +96,8 @@ const Parser = struct { |
| 96 | 96 | /// / ContainerField COMMA ContainerMembers |
| 97 | 97 | /// / ContainerField |
| 98 | 98 | /// / |
| 99 | fn parseContainerMembers(p: *Parser, top_level: bool) ![]*ast.Node { | |
| 100 | var list = std.ArrayList(*ast.Node).init(p.gpa); | |
| 99 | fn parseContainerMembers(p: *Parser, top_level: bool) ![]*Node { | |
| 100 | var list = std.ArrayList(*Node).init(p.gpa); | |
| 101 | 101 | defer list.deinit(); |
| 102 | 102 | |
| 103 | 103 | var field_state: union(enum) { |
| ... | ... | @@ -522,6 +522,7 @@ const Parser = struct { |
| 522 | 522 | const name_token = p.eatToken(.Identifier); |
| 523 | 523 | const lparen = try p.expectToken(.LParen); |
| 524 | 524 | const params = try p.parseParamDeclList(&var_args_token); |
| 525 | defer p.gpa.free(params); | |
| 525 | 526 | const rparen = try p.expectToken(.RParen); |
| 526 | 527 | const align_expr = try p.parseByteAlign(); |
| 527 | 528 | const section_expr = try p.parseLinkSection(); |
| ... | ... | @@ -544,13 +545,13 @@ const Parser = struct { |
| 544 | 545 | else |
| 545 | 546 | R{ .Explicit = return_type_expr.? }; |
| 546 | 547 | |
| 547 | const fn_proto_node = try p.arena.allocator.create(Node.FnProto); | |
| 548 | const fn_proto_node = try Node.FnProto.alloc(&p.arena.allocator, params.len); | |
| 548 | 549 | fn_proto_node.* = .{ |
| 549 | 550 | .doc_comments = null, |
| 550 | 551 | .visib_token = null, |
| 551 | 552 | .fn_token = fn_token, |
| 552 | 553 | .name_token = name_token, |
| 553 | .params = params, | |
| 554 | .params_len = params.len, | |
| 554 | 555 | .return_type = return_type, |
| 555 | 556 | .var_args_token = var_args_token, |
| 556 | 557 | .extern_export_inline_token = null, |
| ... | ... | @@ -562,6 +563,7 @@ const Parser = struct { |
| 562 | 563 | .is_extern_prototype = is_extern, |
| 563 | 564 | .is_async = is_async, |
| 564 | 565 | }; |
| 566 | std.mem.copy(Node.FnProto.ParamDecl, fn_proto_node.params(), params); | |
| 565 | 567 | |
| 566 | 568 | return &fn_proto_node.base; |
| 567 | 569 | } |
| ... | ... | @@ -621,7 +623,7 @@ const Parser = struct { |
| 621 | 623 | var type_expr: ?*Node = null; |
| 622 | 624 | if (p.eatToken(.Colon)) |_| { |
| 623 | 625 | if (p.eatToken(.Keyword_var)) |var_tok| { |
| 624 | const node = try p.arena.allocator.create(ast.Node.VarType); | |
| 626 | const node = try p.arena.allocator.create(Node.VarType); | |
| 625 | 627 | node.* = .{ .token = var_tok }; |
| 626 | 628 | type_expr = &node.base; |
| 627 | 629 | } else { |
| ... | ... | @@ -1936,7 +1938,7 @@ const Parser = struct { |
| 1936 | 1938 | } |
| 1937 | 1939 | |
| 1938 | 1940 | /// ParamDecl <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType |
| 1939 | fn parseParamDecl(p: *Parser) !?*Node { | |
| 1941 | fn parseParamDecl(p: *Parser, list: *std.ArrayList(Node.FnProto.ParamDecl)) !bool { | |
| 1940 | 1942 | const doc_comments = try p.parseDocComment(); |
| 1941 | 1943 | const noalias_token = p.eatToken(.Keyword_noalias); |
| 1942 | 1944 | const comptime_token = if (noalias_token == null) p.eatToken(.Keyword_comptime) else null; |
| ... | ... | @@ -1951,31 +1953,30 @@ const Parser = struct { |
| 1951 | 1953 | if (noalias_token == null and |
| 1952 | 1954 | comptime_token == null and |
| 1953 | 1955 | name_token == null and |
| 1954 | doc_comments == null) return null; | |
| 1956 | doc_comments == null) return false; | |
| 1955 | 1957 | try p.errors.append(p.gpa, .{ |
| 1956 | 1958 | .ExpectedParamType = .{ .token = p.tok_i }, |
| 1957 | 1959 | }); |
| 1958 | 1960 | return error.ParseError; |
| 1959 | 1961 | }; |
| 1960 | 1962 | |
| 1961 | const param_decl = try p.arena.allocator.create(Node.ParamDecl); | |
| 1962 | param_decl.* = .{ | |
| 1963 | (try list.addOne()).* = .{ | |
| 1963 | 1964 | .doc_comments = doc_comments, |
| 1964 | 1965 | .comptime_token = comptime_token, |
| 1965 | 1966 | .noalias_token = noalias_token, |
| 1966 | 1967 | .name_token = name_token, |
| 1967 | 1968 | .param_type = param_type, |
| 1968 | 1969 | }; |
| 1969 | return &param_decl.base; | |
| 1970 | return true; | |
| 1970 | 1971 | } |
| 1971 | 1972 | |
| 1972 | 1973 | /// ParamType |
| 1973 | 1974 | /// <- KEYWORD_var |
| 1974 | 1975 | /// / DOT3 |
| 1975 | 1976 | /// / TypeExpr |
| 1976 | fn parseParamType(p: *Parser) !?Node.ParamDecl.ParamType { | |
| 1977 | fn parseParamType(p: *Parser) !?Node.FnProto.ParamDecl.ParamType { | |
| 1977 | 1978 | // TODO cast from tuple to error union is broken |
| 1978 | const P = Node.ParamDecl.ParamType; | |
| 1979 | const P = Node.FnProto.ParamDecl.ParamType; | |
| 1979 | 1980 | if (try p.parseVarType()) |node| return P{ .var_type = node }; |
| 1980 | 1981 | if (p.eatToken(.Ellipsis3)) |token| return P{ .var_args = token }; |
| 1981 | 1982 | if (try p.parseTypeExpr()) |node| return P{ .type_expr = node }; |
| ... | ... | @@ -2587,7 +2588,7 @@ const Parser = struct { |
| 2587 | 2588 | |
| 2588 | 2589 | if (p.eatToken(.Ellipsis2) != null) { |
| 2589 | 2590 | const end_expr = try p.parseExpr(); |
| 2590 | const sentinel: ?*ast.Node = if (p.eatToken(.Colon) != null) | |
| 2591 | const sentinel: ?*Node = if (p.eatToken(.Colon) != null) | |
| 2591 | 2592 | try p.parseExpr() |
| 2592 | 2593 | else |
| 2593 | 2594 | null; |
| ... | ... | @@ -2616,7 +2617,7 @@ const Parser = struct { |
| 2616 | 2617 | if (p.eatToken(.Period)) |period| { |
| 2617 | 2618 | if (try p.parseIdentifier()) |identifier| { |
| 2618 | 2619 | // TODO: It's a bit weird to return an InfixOp from the SuffixOp parser. |
| 2619 | // Should there be an ast.Node.SuffixOp.FieldAccess variant? Or should | |
| 2620 | // Should there be an Node.SuffixOp.FieldAccess variant? Or should | |
| 2620 | 2621 | // this grammar rule be altered? |
| 2621 | 2622 | const node = try p.arena.allocator.create(Node.InfixOp); |
| 2622 | 2623 | node.* = .{ |
| ... | ... | @@ -2652,13 +2653,13 @@ const Parser = struct { |
| 2652 | 2653 | /// ExprList <- (Expr COMMA)* Expr? |
| 2653 | 2654 | fn parseFnCallArguments(p: *Parser) !?AnnotatedParamList { |
| 2654 | 2655 | if (p.eatToken(.LParen) == null) return null; |
| 2655 | const list = try ListParseFn(Node.FnProto.ParamList, parseExpr)(p); | |
| 2656 | const list = try ListParseFn(std.SinglyLinkedList(*Node), parseExpr)(p); | |
| 2656 | 2657 | const rparen = try p.expectToken(.RParen); |
| 2657 | 2658 | return AnnotatedParamList{ .list = list, .rparen = rparen }; |
| 2658 | 2659 | } |
| 2659 | 2660 | |
| 2660 | 2661 | const AnnotatedParamList = struct { |
| 2661 | list: Node.FnProto.ParamList, // NOTE: may also be any other type SegmentedList(*Node, 2) | |
| 2662 | list: std.SinglyLinkedList(*Node), | |
| 2662 | 2663 | rparen: TokenIndex, |
| 2663 | 2664 | }; |
| 2664 | 2665 | |
| ... | ... | @@ -2797,14 +2798,14 @@ const Parser = struct { |
| 2797 | 2798 | .lbrace_token = lbrace, |
| 2798 | 2799 | .rbrace_token = rbrace, |
| 2799 | 2800 | }; |
| 2800 | std.mem.copy(*ast.Node, node.fieldsAndDecls(), members); | |
| 2801 | std.mem.copy(*Node, node.fieldsAndDecls(), members); | |
| 2801 | 2802 | return &node.base; |
| 2802 | 2803 | } |
| 2803 | 2804 | |
| 2804 | 2805 | /// Holds temporary data until we are ready to construct the full ContainerDecl AST node. |
| 2805 | 2806 | const ContainerDeclType = struct { |
| 2806 | 2807 | kind_token: TokenIndex, |
| 2807 | init_arg_expr: ast.Node.ContainerDecl.InitArg, | |
| 2808 | init_arg_expr: Node.ContainerDecl.InitArg, | |
| 2808 | 2809 | }; |
| 2809 | 2810 | |
| 2810 | 2811 | /// ContainerDeclType |
| ... | ... | @@ -2893,14 +2894,11 @@ const Parser = struct { |
| 2893 | 2894 | } |
| 2894 | 2895 | |
| 2895 | 2896 | /// ParamDeclList <- (ParamDecl COMMA)* ParamDecl? |
| 2896 | fn parseParamDeclList(p: *Parser, var_args_token: *?TokenIndex) !Node.FnProto.ParamList { | |
| 2897 | var list = Node.FnProto.ParamList{}; | |
| 2898 | var list_it = &list.first; | |
| 2899 | var last: ?*Node = null; | |
| 2900 | while (try p.parseParamDecl()) |node| { | |
| 2901 | last = node; | |
| 2902 | list_it = try p.llpush(*Node, list_it, node); | |
| 2897 | fn parseParamDeclList(p: *Parser, var_args_token: *?TokenIndex) ![]Node.FnProto.ParamDecl { | |
| 2898 | var list = std.ArrayList(Node.FnProto.ParamDecl).init(p.gpa); | |
| 2899 | defer list.deinit(); | |
| 2903 | 2900 | |
| 2901 | while (try p.parseParamDecl(&list)) { | |
| 2904 | 2902 | switch (p.tokens[p.tok_i].id) { |
| 2905 | 2903 | .Comma => _ = p.nextToken(), |
| 2906 | 2904 | // all possible delimiters |
| ... | ... | @@ -2914,13 +2912,13 @@ const Parser = struct { |
| 2914 | 2912 | }, |
| 2915 | 2913 | } |
| 2916 | 2914 | } |
| 2917 | if (last) |node| { | |
| 2918 | const param_type = node.cast(Node.ParamDecl).?.param_type; | |
| 2915 | if (list.items.len != 0) { | |
| 2916 | const param_type = list.items[list.items.len - 1].param_type; | |
| 2919 | 2917 | if (param_type == .var_args) { |
| 2920 | 2918 | var_args_token.* = param_type.var_args; |
| 2921 | 2919 | } |
| 2922 | 2920 | } |
| 2923 | return list; | |
| 2921 | return list.toOwnedSlice(); | |
| 2924 | 2922 | } |
| 2925 | 2923 | |
| 2926 | 2924 | const NodeParseFn = fn (p: *Parser) Error!?*Node; |
lib/std/zig/render.zig+7-14| ... | ... | @@ -1479,13 +1479,11 @@ fn renderExpression( |
| 1479 | 1479 | try renderToken(tree, stream, lparen, indent, start_col, Space.None); // ( |
| 1480 | 1480 | |
| 1481 | 1481 | // render all on one line, no trailing comma |
| 1482 | var it = fn_proto.params.first; | |
| 1483 | while (it) |param_decl_node_node| : (it = param_decl_node_node.next) { | |
| 1484 | const param_decl_node = param_decl_node_node.data; | |
| 1485 | try renderParamDecl(allocator, stream, tree, indent, start_col, param_decl_node, Space.None); | |
| 1482 | for (fn_proto.params()) |param_decl, i| { | |
| 1483 | try renderParamDecl(allocator, stream, tree, indent, start_col, param_decl, Space.None); | |
| 1486 | 1484 | |
| 1487 | if (param_decl_node_node.next != null) { | |
| 1488 | const comma = tree.nextToken(param_decl_node.lastToken()); | |
| 1485 | if (i + 1 < fn_proto.params_len) { | |
| 1486 | const comma = tree.nextToken(param_decl.lastToken()); | |
| 1489 | 1487 | try renderToken(tree, stream, comma, indent, start_col, Space.Space); // , |
| 1490 | 1488 | } |
| 1491 | 1489 | } |
| ... | ... | @@ -1494,11 +1492,9 @@ fn renderExpression( |
| 1494 | 1492 | const new_indent = indent + indent_delta; |
| 1495 | 1493 | try renderToken(tree, stream, lparen, new_indent, start_col, Space.Newline); // ( |
| 1496 | 1494 | |
| 1497 | var it = fn_proto.params.first; | |
| 1498 | while (it) |param_decl_node_node| : (it = param_decl_node_node.next) { | |
| 1499 | const param_decl_node = param_decl_node_node.data; | |
| 1495 | for (fn_proto.params()) |param_decl| { | |
| 1500 | 1496 | try stream.writeByteNTimes(' ', new_indent); |
| 1501 | try renderParamDecl(allocator, stream, tree, new_indent, start_col, param_decl_node, Space.Comma); | |
| 1497 | try renderParamDecl(allocator, stream, tree, new_indent, start_col, param_decl, Space.Comma); | |
| 1502 | 1498 | } |
| 1503 | 1499 | try stream.writeByteNTimes(' ', indent); |
| 1504 | 1500 | } |
| ... | ... | @@ -2079,7 +2075,6 @@ fn renderExpression( |
| 2079 | 2075 | .VarDecl, |
| 2080 | 2076 | .Use, |
| 2081 | 2077 | .TestDecl, |
| 2082 | .ParamDecl, | |
| 2083 | 2078 | => unreachable, |
| 2084 | 2079 | } |
| 2085 | 2080 | } |
| ... | ... | @@ -2162,11 +2157,9 @@ fn renderParamDecl( |
| 2162 | 2157 | tree: *ast.Tree, |
| 2163 | 2158 | indent: usize, |
| 2164 | 2159 | start_col: *usize, |
| 2165 | base: *ast.Node, | |
| 2160 | param_decl: ast.Node.FnProto.ParamDecl, | |
| 2166 | 2161 | space: Space, |
| 2167 | 2162 | ) (@TypeOf(stream).Error || Error)!void { |
| 2168 | const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", base); | |
| 2169 | ||
| 2170 | 2163 | try renderDocComments(tree, stream, param_decl, indent, start_col); |
| 2171 | 2164 | |
| 2172 | 2165 | if (param_decl.comptime_token) |comptime_token| { |