authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-03 17:02:12-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-02-03 17:02:12-07:00
logf5279cbada9199023049abe02dbf65a894ba317c
tree8b44865f69b2cda7522cc7b2eeb9ecde54cc777f
parent1a83b29bea486050544acc7935c0c438da2c2654

zig fmt: implement top-level fields


3 files changed, 340 insertions(+), 283 deletions(-)

lib/std/zig/ast.zig+157-86
......@@ -195,6 +195,7 @@ pub const Tree = struct {
195195 const tags = tree.nodes.items(.tag);
196196 const datas = tree.nodes.items(.data);
197197 const main_tokens = tree.nodes.items(.main_token);
198 const token_tags = tree.tokens.items(.tag);
198199 var n = node;
199200 while (true) switch (tags[n]) {
200201 .Root => return 0,
......@@ -304,39 +305,49 @@ pub const Tree = struct {
304305 .FnDecl,
305306 => n = datas[n].lhs,
306307
307 .GlobalVarDecl,
308 .LocalVarDecl,
309 .SimpleVarDecl,
310 .AlignedVarDecl,
311 .ArrayType,
312 .ArrayTypeSentinel,
313 .PtrTypeAligned,
314 .PtrTypeSentinel,
315 .PtrType,
316 .SliceType,
317 .StructInit,
318 .SwitchCaseMulti,
319 .WhileSimple,
320 .WhileCont,
321 .While,
322 .ForSimple,
323 .For,
324 .FnProtoSimple,
325 .FnProtoSimpleMulti,
326 .FnProtoOne,
327 .FnProto,
328 .ContainerDecl,
329 .ContainerDeclArg,
330 .TaggedUnion,
331 .TaggedUnionEnumTag,
332308 .ContainerFieldInit,
333309 .ContainerFieldAlign,
334310 .ContainerField,
335 .AsmOutput,
336 .AsmInput,
337 .ErrorValue,
338 .ErrorUnion,
339 => @panic("TODO finish implementing firstToken"),
311 => {
312 const name_token = main_tokens[n];
313 if (name_token > 0 and
314 token_tags[name_token - 1] == .Keyword_comptime)
315 {
316 return name_token - 1;
317 } else {
318 return name_token;
319 }
320 },
321
322 .GlobalVarDecl => unreachable,
323 .LocalVarDecl => unreachable,
324 .SimpleVarDecl => unreachable,
325 .AlignedVarDecl => unreachable,
326 .ArrayType => unreachable,
327 .ArrayTypeSentinel => unreachable,
328 .PtrTypeAligned => unreachable,
329 .PtrTypeSentinel => unreachable,
330 .PtrType => unreachable,
331 .SliceType => unreachable,
332 .StructInit => unreachable,
333 .SwitchCaseMulti => unreachable,
334 .WhileSimple => unreachable,
335 .WhileCont => unreachable,
336 .While => unreachable,
337 .ForSimple => unreachable,
338 .For => unreachable,
339 .FnProtoSimple => unreachable,
340 .FnProtoSimpleMulti => unreachable,
341 .FnProtoOne => unreachable,
342 .FnProto => unreachable,
343 .ContainerDecl => unreachable,
344 .ContainerDeclArg => unreachable,
345 .TaggedUnion => unreachable,
346 .TaggedUnionEnumTag => unreachable,
347 .AsmOutput => unreachable,
348 .AsmInput => unreachable,
349 .ErrorValue => unreachable,
350 .ErrorUnion => unreachable,
340351 };
341352 }
342353
......@@ -431,6 +442,7 @@ pub const Tree = struct {
431442 .NullLiteral,
432443 .UndefinedLiteral,
433444 .UnreachableLiteral,
445 .Identifier,
434446 => return main_tokens[n] + end_offset,
435447
436448 .Call => {
......@@ -449,62 +461,61 @@ pub const Tree = struct {
449461 n = datas[n].rhs;
450462 },
451463
452 .ArrayInitDotTwo,
453 .ArrayInitDot,
454 .StructInitDotTwo,
455 .StructInitDot,
456 .Switch,
457 .If,
458 .Continue,
459 .Identifier,
460 .EnumLiteral,
461 .BuiltinCallTwo,
462 .BuiltinCall,
463 .ErrorSetDecl,
464 .Block,
465 .AsmSimple,
466 .Asm,
467 .SliceOpen,
468 .Slice,
469 .Deref,
470 .ArrayAccess,
471 .ArrayInitOne,
472 .ArrayInit,
473 .StructInitOne,
474 .SwitchCaseOne,
475 .SwitchRange,
476 .FnDecl,
477 .GlobalVarDecl,
478 .LocalVarDecl,
479 .SimpleVarDecl,
480 .AlignedVarDecl,
481 .ArrayType,
482 .ArrayTypeSentinel,
483 .PtrTypeAligned,
484 .PtrTypeSentinel,
485 .PtrType,
486 .SliceType,
487 .StructInit,
488 .SwitchCaseMulti,
489 .WhileCont,
490 .While,
491 .ForSimple,
492 .For,
493 .FnProtoSimple,
494 .FnProtoSimpleMulti,
495 .FnProtoOne,
496 .FnProto,
497 .ContainerDecl,
498 .ContainerDeclArg,
499 .TaggedUnion,
500 .TaggedUnionEnumTag,
501 .ContainerFieldInit,
502 .ContainerFieldAlign,
503 .ContainerField,
504 .AsmOutput,
505 .AsmInput,
506 .ErrorValue,
507 => @panic("TODO finish implementing lastToken"),
464 .ContainerFieldInit => unreachable,
465 .ContainerFieldAlign => unreachable,
466 .ContainerField => unreachable,
467
468 .ArrayInitDotTwo => unreachable,
469 .ArrayInitDot => unreachable,
470 .StructInitDotTwo => unreachable,
471 .StructInitDot => unreachable,
472 .Switch => unreachable,
473 .If => unreachable,
474 .Continue => unreachable,
475 .EnumLiteral => unreachable,
476 .BuiltinCallTwo => unreachable,
477 .BuiltinCall => unreachable,
478 .ErrorSetDecl => unreachable,
479 .Block => unreachable,
480 .AsmSimple => unreachable,
481 .Asm => unreachable,
482 .SliceOpen => unreachable,
483 .Slice => unreachable,
484 .Deref => unreachable,
485 .ArrayAccess => unreachable,
486 .ArrayInitOne => unreachable,
487 .ArrayInit => unreachable,
488 .StructInitOne => unreachable,
489 .SwitchCaseOne => unreachable,
490 .SwitchRange => unreachable,
491 .FnDecl => unreachable,
492 .GlobalVarDecl => unreachable,
493 .LocalVarDecl => unreachable,
494 .SimpleVarDecl => unreachable,
495 .AlignedVarDecl => unreachable,
496 .ArrayType => unreachable,
497 .ArrayTypeSentinel => unreachable,
498 .PtrTypeAligned => unreachable,
499 .PtrTypeSentinel => unreachable,
500 .PtrType => unreachable,
501 .SliceType => unreachable,
502 .StructInit => unreachable,
503 .SwitchCaseMulti => unreachable,
504 .WhileCont => unreachable,
505 .While => unreachable,
506 .ForSimple => unreachable,
507 .For => unreachable,
508 .FnProtoSimple => unreachable,
509 .FnProtoSimpleMulti => unreachable,
510 .FnProtoOne => unreachable,
511 .FnProto => unreachable,
512 .ContainerDecl => unreachable,
513 .ContainerDeclArg => unreachable,
514 .TaggedUnion => unreachable,
515 .TaggedUnionEnumTag => unreachable,
516 .AsmOutput => unreachable,
517 .AsmInput => unreachable,
518 .ErrorValue => unreachable,
508519 };
509520 }
510521
......@@ -587,6 +598,40 @@ pub const Tree = struct {
587598 });
588599 }
589600
601 pub fn containerField(tree: Tree, node: Node.Index) Full.ContainerField {
602 assert(tree.nodes.items(.tag)[node] == .ContainerField);
603 const data = tree.nodes.items(.data)[node];
604 const extra = tree.extraData(data.rhs, Node.ContainerField);
605 return tree.fullContainerField(.{
606 .name_token = tree.nodes.items(.main_token)[node],
607 .type_expr = data.lhs,
608 .value_expr = extra.value_expr,
609 .align_expr = extra.align_expr,
610 });
611 }
612
613 pub fn containerFieldInit(tree: Tree, node: Node.Index) Full.ContainerField {
614 assert(tree.nodes.items(.tag)[node] == .ContainerFieldInit);
615 const data = tree.nodes.items(.data)[node];
616 return tree.fullContainerField(.{
617 .name_token = tree.nodes.items(.main_token)[node],
618 .type_expr = data.lhs,
619 .value_expr = data.rhs,
620 .align_expr = 0,
621 });
622 }
623
624 pub fn containerFieldAlign(tree: Tree, node: Node.Index) Full.ContainerField {
625 assert(tree.nodes.items(.tag)[node] == .ContainerFieldAlign);
626 const data = tree.nodes.items(.data)[node];
627 return tree.fullContainerField(.{
628 .name_token = tree.nodes.items(.main_token)[node],
629 .type_expr = data.lhs,
630 .value_expr = 0,
631 .align_expr = data.rhs,
632 });
633 }
634
590635 fn fullVarDecl(tree: Tree, info: Full.VarDecl.Ast) Full.VarDecl {
591636 const token_tags = tree.tokens.items(.tag);
592637 var result: Full.VarDecl = .{
......@@ -636,6 +681,20 @@ pub const Tree = struct {
636681 }
637682 return result;
638683 }
684
685 fn fullContainerField(tree: Tree, info: Full.ContainerField.Ast) Full.ContainerField {
686 const token_tags = tree.tokens.items(.tag);
687 var result: Full.ContainerField = .{
688 .ast = info,
689 .comptime_token = null,
690 };
691 // comptime name: type = init,
692 // ^
693 if (info.name_token > 0 and token_tags[info.name_token - 1] == .Keyword_comptime) {
694 result.comptime_token = info.name_token - 1;
695 }
696 return result;
697 }
639698};
640699
641700/// Fully assembled AST node information.
......@@ -674,6 +733,18 @@ pub const Full = struct {
674733 else_expr: Node.Index,
675734 };
676735 };
736
737 pub const ContainerField = struct {
738 comptime_token: ?TokenIndex,
739 ast: Ast,
740
741 pub const Ast = struct {
742 name_token: TokenIndex,
743 type_expr: Node.Index,
744 value_expr: Node.Index,
745 align_expr: Node.Index,
746 };
747 };
677748};
678749
679750pub const Error = union(enum) {
lib/std/zig/parser_test.zig+9-9
......@@ -91,15 +91,15 @@ test "zig fmt: if statment" {
9191 );
9292}
9393
94//test "zig fmt: top-level fields" {
95// try testCanonical(
96// \\a: did_you_know,
97// \\b: all_files_are,
98// \\structs: ?x,
99// \\
100// );
101//}
102//
94test "zig fmt: top-level fields" {
95 try testCanonical(
96 \\a: did_you_know,
97 \\b: all_files_are,
98 \\structs: ?x,
99 \\
100 );
101}
102
103103//test "zig fmt: decl between fields" {
104104// try testError(
105105// \\const S = struct {
lib/std/zig/render.zig+174-188
......@@ -28,7 +28,7 @@ const Ais = std.io.AutoIndentingStream(Writer);
2828pub fn render(gpa: *mem.Allocator, writer: Writer, tree: ast.Tree) Error!void {
2929 assert(tree.errors.len == 0); // cannot render an invalid tree
3030 var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, writer);
31 try renderRoot(&auto_indenting_stream, tree);
31 return renderRoot(&auto_indenting_stream, tree);
3232}
3333
3434/// Assumes there are no tokens in between start and end.
......@@ -66,10 +66,9 @@ fn renderRoot(ais: *Ais, tree: ast.Tree) Error!void {
6666 // Root is always index 0.
6767 const nodes_data = tree.nodes.items(.data);
6868 const root_decls = tree.extra_data[nodes_data[0].lhs..nodes_data[0].rhs];
69 if (root_decls.len == 0) return;
7069
7170 for (root_decls) |decl| {
72 return renderContainerDecl(ais, tree, decl, .Newline);
71 try renderContainerDecl(ais, tree, decl, .Newline);
7372 }
7473}
7574
......@@ -102,17 +101,11 @@ fn renderContainerDecl(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: S
102101 const datas = tree.nodes.items(.data);
103102 try renderDocComments(ais, tree, tree.firstToken(decl));
104103 switch (tree.nodes.items(.tag)[decl]) {
105 .UsingNamespace,
106 .FnProtoSimple,
107 .FnProtoSimpleMulti,
108 .FnProtoOne,
109 .FnProto,
110 .FnDecl,
111 .ContainerFieldInit,
112 .ContainerFieldAlign,
113 .ContainerField,
114 => @panic("TODO implement renderContainerDecl"),
115
104 .FnProtoSimple => unreachable, // TODO
105 .FnProtoSimpleMulti => unreachable, // TODO
106 .FnProtoOne => unreachable, // TODO
107 .FnDecl => unreachable, // TODO
108 .FnProto => unreachable, // TODO
116109 // .FnProto => {
117110 // const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
118111
......@@ -127,6 +120,7 @@ fn renderContainerDecl(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: S
127120 // }
128121 // },
129122
123 .UsingNamespace => unreachable, // TODO
130124 // .Use => {
131125 // const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl);
132126
......@@ -152,88 +146,10 @@ fn renderContainerDecl(ais: *Ais, tree: ast.Tree, decl: ast.Node.Index, space: S
152146 try renderExpression(ais, tree, datas[decl].rhs, space);
153147 },
154148
155 // .ContainerField => {
156 // const field = @fieldParentPtr(ast.Node.ContainerField, "base", decl);
157
158 // try renderDocComments(ais, tree, field, field.doc_comments);
159 // if (field.comptime_token) |t| {
160 // try renderToken(ais, tree, t, .Space); // comptime
161 // }
162
163 // const src_has_trailing_comma = blk: {
164 // const maybe_comma = tree.nextToken(field.lastToken());
165 // break :blk tree.token_tags[maybe_comma] == .Comma;
166 // };
167
168 // // The trailing comma is emitted at the end, but if it's not present
169 // // we still have to respect the specified `space` parameter
170 // const last_token_space: Space = if (src_has_trailing_comma) .None else space;
171
172 // if (field.type_expr == null and field.value_expr == null) {
173 // try renderToken(ais, tree, field.name_token, last_token_space); // name
174 // } else if (field.type_expr != null and field.value_expr == null) {
175 // try renderToken(ais, tree, field.name_token, .None); // name
176 // try renderToken(ais, tree, tree.nextToken(field.name_token), .Space); // :
177
178 // if (field.align_expr) |align_value_expr| {
179 // try renderExpression(ais, tree, field.type_expr.?, .Space); // type
180 // const lparen_token = tree.prevToken(align_value_expr.firstToken());
181 // const align_kw = tree.prevToken(lparen_token);
182 // const rparen_token = tree.nextToken(align_value_expr.lastToken());
183 // try renderToken(ais, tree, align_kw, .None); // align
184 // try renderToken(ais, tree, lparen_token, .None); // (
185 // try renderExpression(ais, tree, align_value_expr, .None); // alignment
186 // try renderToken(ais, tree, rparen_token, last_token_space); // )
187 // } else {
188 // try renderExpression(ais, tree, field.type_expr.?, last_token_space); // type
189 // }
190 // } else if (field.type_expr == null and field.value_expr != null) {
191 // try renderToken(ais, tree, field.name_token, .Space); // name
192 // try renderToken(ais, tree, tree.nextToken(field.name_token), .Space); // =
193 // try renderExpression(ais, tree, field.value_expr.?, last_token_space); // value
194 // } else {
195 // try renderToken(ais, tree, field.name_token, .None); // name
196 // try renderToken(ais, tree, tree.nextToken(field.name_token), .Space); // :
197
198 // if (field.align_expr) |align_value_expr| {
199 // try renderExpression(ais, tree, field.type_expr.?, .Space); // type
200 // const lparen_token = tree.prevToken(align_value_expr.firstToken());
201 // const align_kw = tree.prevToken(lparen_token);
202 // const rparen_token = tree.nextToken(align_value_expr.lastToken());
203 // try renderToken(ais, tree, align_kw, .None); // align
204 // try renderToken(ais, tree, lparen_token, .None); // (
205 // try renderExpression(ais, tree, align_value_expr, .None); // alignment
206 // try renderToken(ais, tree, rparen_token, .Space); // )
207 // } else {
208 // try renderExpression(ais, tree, field.type_expr.?, .Space); // type
209 // }
210 // try renderToken(ais, tree, tree.prevToken(field.value_expr.?.firstToken()), .Space); // =
211 // try renderExpression(ais, tree, field.value_expr.?, last_token_space); // value
212 // }
213
214 // if (src_has_trailing_comma) {
215 // const comma = tree.nextToken(field.lastToken());
216 // try renderToken(ais, tree, comma, space);
217 // }
218 // },
149 .ContainerFieldInit => return renderContainerField(ais, tree, tree.containerFieldInit(decl), space),
150 .ContainerFieldAlign => return renderContainerField(ais, tree, tree.containerFieldAlign(decl), space),
151 .ContainerField => return renderContainerField(ais, tree, tree.containerField(decl), space),
219152 .Comptime => return renderExpression(ais, tree, decl, space),
220
221 // .DocComment => {
222 // const comment = @fieldParentPtr(ast.Node.DocComment, "base", decl);
223 // const kind = tree.token_tags[comment.first_line];
224 // try renderToken(ais, tree, comment.first_line, .Newline);
225 // var tok_i = comment.first_line + 1;
226 // while (true) : (tok_i += 1) {
227 // const tok_id = tree.token_tags[tok_i];
228 // if (tok_id == kind) {
229 // try renderToken(ais, tree, tok_i, .Newline);
230 // } else if (tok_id == .LineComment) {
231 // continue;
232 // } else {
233 // break;
234 // }
235 // }
236 // },
237153 else => unreachable,
238154 }
239155}
......@@ -254,8 +170,12 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
254170 .NullLiteral,
255171 .UnreachableLiteral,
256172 .UndefinedLiteral,
173 .AnyFrameLiteral,
257174 => return renderToken(ais, tree, main_tokens[node], space),
258175
176 .ErrorValue => unreachable, // TODO
177
178 .AnyType => unreachable, // TODO
259179 //.AnyType => {
260180 // const any_type = base.castTag(.AnyType).?;
261181 // if (mem.eql(u8, tree.tokenSlice(any_type.token), "var")) {
......@@ -322,6 +242,8 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
322242 }
323243 },
324244
245 .Defer => unreachable, // TODO
246 .ErrDefer => unreachable, // TODO
325247 //.Defer => {
326248 // const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base);
327249
......@@ -337,6 +259,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
337259 try renderToken(ais, tree, comptime_token, .Space);
338260 return renderExpression(ais, tree, block, space);
339261 },
262 .Nosuspend => unreachable, // TODO
340263 //.Nosuspend => {
341264 // const nosuspend_node = @fieldParentPtr(ast.Node.Nosuspend, "base", base);
342265 // if (mem.eql(u8, tree.tokenSlice(nosuspend_node.nosuspend_token), "noasync")) {
......@@ -348,6 +271,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
348271 // return renderExpression(ais, tree, nosuspend_node.expr, space);
349272 //},
350273
274 .Suspend => unreachable, // TODO
351275 //.Suspend => {
352276 // const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base);
353277
......@@ -359,6 +283,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
359283 // }
360284 //},
361285
286 .Catch => unreachable, // TODO
362287 //.Catch => {
363288 // const infix_op_node = @fieldParentPtr(ast.Node.Catch, "base", base);
364289
......@@ -452,27 +377,26 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
452377 return renderExpression(ais, tree, infix.rhs, space);
453378 },
454379
455 //.BitNot,
456 //.BoolNot,
457 //.Negation,
458 //.NegationWrap,
459 //.OptionalType,
460 //.AddressOf,
461 //=> {
462 // const casted_node = @fieldParentPtr(ast.Node.SimplePrefixOp, "base", base);
463 // try renderToken(ais, tree, casted_node.op_token, Space.None);
464 // return renderExpression(ais, tree, casted_node.rhs, space);
465 //},
380 .BitNot,
381 .BoolNot,
382 .Negation,
383 .NegationWrap,
384 .OptionalType,
385 .AddressOf,
386 => {
387 try renderToken(ais, tree, main_tokens[node], .None);
388 return renderExpression(ais, tree, datas[node].lhs, space);
389 },
466390
467 //.Try,
468 //.Resume,
469 //.Await,
470 //=> {
471 // const casted_node = @fieldParentPtr(ast.Node.SimplePrefixOp, "base", base);
472 // try renderToken(ais, tree, casted_node.op_token, Space.Space);
473 // return renderExpression(ais, tree, casted_node.rhs, space);
474 //},
391 .Try,
392 .Resume,
393 .Await,
394 => {
395 try renderToken(ais, tree, main_tokens[node], .Space);
396 return renderExpression(ais, tree, datas[node].lhs, space);
397 },
475398
399 .ArrayType => unreachable, // TODO
476400 //.ArrayType => {
477401 // const array_type = @fieldParentPtr(ast.Node.ArrayType, "base", base);
478402 // return renderArrayType(
......@@ -486,6 +410,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
486410 // space,
487411 // );
488412 //},
413 .ArrayTypeSentinel => unreachable, // TODO
489414 //.ArrayTypeSentinel => {
490415 // const array_type = @fieldParentPtr(ast.Node.ArrayTypeSentinel, "base", base);
491416 // return renderArrayType(
......@@ -500,6 +425,9 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
500425 // );
501426 //},
502427
428 .PtrType => unreachable, // TODO
429 .PtrTypeAligned => unreachable, // TODO
430 .PtrTypeSentinel => unreachable, // TODO
503431 //.PtrType => {
504432 // const ptr_type = @fieldParentPtr(ast.Node.PtrType, "base", base);
505433 // const op_tok_id = tree.token_tags[ptr_type.op_token];
......@@ -562,6 +490,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
562490 // return renderExpression(ais, tree, ptr_type.rhs, space);
563491 //},
564492
493 .SliceType => unreachable, // TODO
565494 //.SliceType => {
566495 // const slice_type = @fieldParentPtr(ast.Node.SliceType, "base", base);
567496 // try renderToken(ais, tree, slice_type.op_token, Space.None); // [
......@@ -611,6 +540,10 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
611540 // return renderExpression(ais, tree, slice_type.rhs, space);
612541 //},
613542
543 .ArrayInitOne => unreachable, // TODO
544 .ArrayInitDotTwo => unreachable, // TODO
545 .ArrayInitDot => unreachable, // TODO
546 .ArrayInit => unreachable, // TODO
614547 //.ArrayInitializer, .ArrayInitializerDot => {
615548 // var rtoken: ast.TokenIndex = undefined;
616549 // var exprs: []ast.Node.Index = undefined;
......@@ -823,6 +756,10 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
823756 // return renderToken(ais, tree, rtoken, space);
824757 //},
825758
759 .StructInitOne => unreachable, // TODO
760 .StructInitDotTwo => unreachable, // TODO
761 .StructInitDot => unreachable, // TODO
762 .StructInit => unreachable, // TODO
826763 //.StructInitializer, .StructInitializerDot => {
827764 // var rtoken: ast.TokenIndex = undefined;
828765 // var field_inits: []ast.Node.Index = undefined;
......@@ -959,6 +896,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
959896 // return renderToken(ais, tree, rtoken, space);
960897 //},
961898
899 .CallOne => unreachable, // TODO
962900 .Call => {
963901 const call = datas[node];
964902 const params_range = tree.extraData(call.rhs, ast.Node.SubRange);
......@@ -1017,6 +955,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
1017955 return renderToken(ais, tree, after_last_param_tok, space); // )
1018956 },
1019957
958 .ArrayAccess => unreachable, // TODO
1020959 //.ArrayAccess => {
1021960 // const suffix_op = base.castTag(.ArrayAccess).?;
1022961
......@@ -1039,6 +978,8 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
1039978 // return renderToken(ais, tree, rbracket, space); // ]
1040979 //},
1041980
981 .Slice => unreachable, // TODO
982 .SliceOpen => unreachable, // TODO
1042983 //.Slice => {
1043984 // const suffix_op = base.castTag(.Slice).?;
1044985 // try renderExpression(ais, tree, suffix_op.lhs, Space.None);
......@@ -1066,12 +1007,14 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
10661007 // return renderToken(ais, tree, suffix_op.rtoken, space); // ]
10671008 //},
10681009
1010 .Deref => unreachable, // TODO
10691011 //.Deref => {
10701012 // const suffix_op = base.castTag(.Deref).?;
10711013
10721014 // try renderExpression(ais, tree, suffix_op.lhs, Space.None);
10731015 // return renderToken(ais, tree, suffix_op.rtoken, space); // .*
10741016 //},
1017 .UnwrapOptional => unreachable, // TODO
10751018 //.UnwrapOptional => {
10761019 // const suffix_op = base.castTag(.UnwrapOptional).?;
10771020
......@@ -1080,6 +1023,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
10801023 // return renderToken(ais, tree, suffix_op.rtoken, space); // ?
10811024 //},
10821025
1026 .Break => unreachable, // TODO
10831027 //.Break => {
10841028 // const flow_expr = base.castTag(.Break).?;
10851029 // const maybe_rhs = flow_expr.getRHS();
......@@ -1102,6 +1046,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
11021046 // return renderExpression(ais, tree, maybe_rhs.?, space);
11031047 //},
11041048
1049 .Continue => unreachable, // TODO
11051050 //.Continue => {
11061051 // const flow_expr = base.castTag(.Continue).?;
11071052 // if (flow_expr.getLabel()) |label| {
......@@ -1114,6 +1059,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
11141059 // }
11151060 //},
11161061
1062 .Return => unreachable, // TODO
11171063 //.Return => {
11181064 // const flow_expr = base.castTag(.Return).?;
11191065 // if (flow_expr.getRHS()) |rhs| {
......@@ -1124,36 +1070,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
11241070 // }
11251071 //},
11261072
1127 //.PointerPayload => {
1128 // const payload = @fieldParentPtr(ast.Node.PointerPayload, "base", base);
1129
1130 // try renderToken(ais, tree, payload.lpipe, Space.None);
1131 // if (payload.ptr_token) |ptr_token| {
1132 // try renderToken(ais, tree, ptr_token, Space.None);
1133 // }
1134 // try renderExpression(ais, tree, payload.value_symbol, Space.None);
1135 // return renderToken(ais, tree, payload.rpipe, space);
1136 //},
1137
1138 //.PointerIndexPayload => {
1139 // const payload = @fieldParentPtr(ast.Node.PointerIndexPayload, "base", base);
1140
1141 // try renderToken(ais, tree, payload.lpipe, Space.None);
1142 // if (payload.ptr_token) |ptr_token| {
1143 // try renderToken(ais, tree, ptr_token, Space.None);
1144 // }
1145 // try renderExpression(ais, tree, payload.value_symbol, Space.None);
1146
1147 // if (payload.index_symbol) |index_symbol| {
1148 // const comma = tree.nextToken(payload.value_symbol.lastToken());
1149
1150 // try renderToken(ais, tree, comma, Space.Space);
1151 // try renderExpression(ais, tree, index_symbol, Space.None);
1152 // }
1153
1154 // return renderToken(ais, tree, payload.rpipe, space);
1155 //},
1156
1073 .GroupedExpression => unreachable, // TODO
11571074 //.GroupedExpression => {
11581075 // const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base);
11591076
......@@ -1165,15 +1082,10 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
11651082 // return renderToken(ais, tree, grouped_expr.rparen, space);
11661083 //},
11671084
1168 //.FieldInitializer => {
1169 // const field_init = @fieldParentPtr(ast.Node.FieldInitializer, "base", base);
1170
1171 // try renderToken(ais, tree, field_init.period_token, Space.None); // .
1172 // try renderToken(ais, tree, field_init.name_token, Space.Space); // name
1173 // try renderToken(ais, tree, tree.nextToken(field_init.name_token), Space.Space); // =
1174 // return renderExpression(ais, tree, field_init.expr, space);
1175 //},
1176
1085 .ContainerDecl => unreachable, // TODO
1086 .ContainerDeclArg => unreachable, // TODO
1087 .TaggedUnion => unreachable, // TODO
1088 .TaggedUnionEnumTag => unreachable, // TODO
11771089 //.ContainerDecl => {
11781090 // const container_decl = @fieldParentPtr(ast.Node.ContainerDecl, "base", base);
11791091
......@@ -1289,6 +1201,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
12891201 // return renderToken(ais, tree, container_decl.rbrace_token, space); // }
12901202 //},
12911203
1204 .ErrorSetDecl => unreachable, // TODO
12921205 //.ErrorSetDecl => {
12931206 // const err_set_decl = @fieldParentPtr(ast.Node.ErrorSetDecl, "base", base);
12941207
......@@ -1365,28 +1278,8 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
13651278 // }
13661279 //},
13671280
1368 //.ErrorTag => {
1369 // const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", base);
1370
1371 // try renderDocComments(ais, tree, tag, tag.doc_comments);
1372 // return renderToken(ais, tree, tag.name_token, space); // name
1373 //},
1374
1375 //.MultilineStringLiteral => {
1376 // const multiline_str_literal = @fieldParentPtr(ast.Node.MultilineStringLiteral, "base", base);
1377
1378 // {
1379 // const locked_indents = ais.lockOneShotIndent();
1380 // defer {
1381 // var i: u8 = 0;
1382 // while (i < locked_indents) : (i += 1) ais.popIndent();
1383 // }
1384 // try ais.maybeInsertNewline();
1385
1386 // for (multiline_str_literal.lines()) |t| try renderToken(ais, tree, t, Space.None);
1387 // }
1388 //},
1389
1281 .BuiltinCall => unreachable, // TODO
1282 .BuiltinCallTwo => unreachable, // TODO
13901283 //.BuiltinCall => {
13911284 // const builtin_call = @fieldParentPtr(ast.Node.BuiltinCall, "base", base);
13921285
......@@ -1448,6 +1341,10 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
14481341 // return renderToken(ais, tree, builtin_call.rparen_token, space); // )
14491342 //},
14501343
1344 .FnProtoSimple => unreachable, // TODO
1345 .FnProtoSimpleMulti => unreachable, // TODO
1346 .FnProtoOne => unreachable, // TODO
1347 .FnProto => unreachable, // TODO
14511348 //.FnProto => {
14521349 // const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", base);
14531350
......@@ -1579,6 +1476,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
15791476 // }
15801477 //},
15811478
1479 .AnyFrameType => unreachable, // TODO
15821480 //.AnyFrameType => {
15831481 // const anyframe_type = @fieldParentPtr(ast.Node.AnyFrameType, "base", base);
15841482
......@@ -1591,8 +1489,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
15911489 // }
15921490 //},
15931491
1594 //.DocComment => unreachable, // doc comments are attached to nodes
1595
1492 .Switch => unreachable, // TODO
15961493 //.Switch => {
15971494 // const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base);
15981495
......@@ -1630,6 +1527,8 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
16301527 // return renderToken(ais, tree, switch_node.rbrace, space); // }
16311528 //},
16321529
1530 .SwitchCaseOne => unreachable, // TODO
1531 .SwitchCaseMulti => unreachable, // TODO
16331532 //.SwitchCase => {
16341533 // const switch_case = @fieldParentPtr(ast.Node.SwitchCase, "base", base);
16351534
......@@ -1676,11 +1575,10 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
16761575
16771576 // return renderExpression(ais, tree, switch_case.expr, space);
16781577 //},
1679 //.SwitchElse => {
1680 // const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base);
1681 // return renderToken(ais, tree, switch_else.token, space);
1682 //},
16831578
1579 .WhileSimple => unreachable, // TODO
1580 .WhileCont => unreachable, // TODO
1581 .While => unreachable, // TODO
16841582 //.While => {
16851583 // const while_node = @fieldParentPtr(ast.Node.While, "base", base);
16861584
......@@ -1749,6 +1647,8 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
17491647 // }
17501648 //},
17511649
1650 .ForSimple => unreachable, // TODO
1651 .For => unreachable, // TODO
17521652 //.For => {
17531653 // const for_node = @fieldParentPtr(ast.Node.For, "base", base);
17541654
......@@ -1802,6 +1702,11 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
18021702
18031703 .IfSimple => return renderIf(ais, tree, tree.ifSimple(node), space),
18041704 .If => return renderIf(ais, tree, tree.ifFull(node), space),
1705
1706 .Asm => unreachable, // TODO
1707 .AsmSimple => unreachable, // TODO
1708 .AsmOutput => unreachable, // TODO
1709 .AsmInput => unreachable, // TODO
18051710 //.Asm => {
18061711 // const asm_node = @fieldParentPtr(ast.Node.Asm, "base", base);
18071712
......@@ -1911,6 +1816,7 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
19111816 // return renderToken(ais, tree, asm_node.rparen, space);
19121817 //},
19131818
1819 .EnumLiteral => unreachable, // TODO
19141820 //.EnumLiteral => {
19151821 // const enum_literal = @fieldParentPtr(ast.Node.EnumLiteral, "base", base);
19161822
......@@ -1918,13 +1824,17 @@ fn renderExpression(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Spac
19181824 // return renderToken(ais, tree, enum_literal.name, space); // name
19191825 //},
19201826
1921 //.ContainerField,
1922 //.Root,
1923 //.VarDecl,
1924 //.Use,
1925 //.TestDecl,
1926 //=> unreachable,
1927 else => @panic("TODO implement more renderExpression"),
1827 .FnDecl => unreachable,
1828 .ContainerField => unreachable,
1829 .ContainerFieldInit => unreachable,
1830 .ContainerFieldAlign => unreachable,
1831 .Root => unreachable,
1832 .GlobalVarDecl => unreachable,
1833 .LocalVarDecl => unreachable,
1834 .SimpleVarDecl => unreachable,
1835 .AlignedVarDecl => unreachable,
1836 .UsingNamespace => unreachable,
1837 .TestDecl => unreachable,
19281838 }
19291839}
19301840
......@@ -2234,6 +2144,59 @@ fn renderIf(ais: *Ais, tree: ast.Tree, if_node: ast.Full.If, space: Space) Error
22342144 }
22352145}
22362146
2147fn renderContainerField(
2148 ais: *Ais,
2149 tree: ast.Tree,
2150 field: ast.Full.ContainerField,
2151 space: Space,
2152) Error!void {
2153 const main_tokens = tree.nodes.items(.main_token);
2154 if (field.comptime_token) |t| {
2155 try renderToken(ais, tree, t, .Space); // comptime
2156 }
2157 if (field.ast.type_expr == 0 and field.ast.value_expr == 0) {
2158 return renderTokenComma(ais, tree, field.ast.name_token, space); // name
2159 }
2160 if (field.ast.type_expr != 0 and field.ast.value_expr == 0) {
2161 try renderToken(ais, tree, field.ast.name_token, .None); // name
2162 try renderToken(ais, tree, field.ast.name_token + 1, .Space); // :
2163
2164 if (field.ast.align_expr != 0) {
2165 try renderExpression(ais, tree, field.ast.type_expr, .Space); // type
2166 const align_token = tree.firstToken(field.ast.align_expr) - 2;
2167 try renderToken(ais, tree, align_token, .None); // align
2168 try renderToken(ais, tree, align_token + 1, .None); // (
2169 try renderExpression(ais, tree, field.ast.align_expr, .None); // alignment
2170 const rparen = tree.lastToken(field.ast.align_expr) + 1;
2171 return renderTokenComma(ais, tree, rparen, space); // )
2172 } else {
2173 return renderExpressionComma(ais, tree, field.ast.type_expr, space); // type
2174 }
2175 }
2176 if (field.ast.type_expr == 0 and field.ast.value_expr != 0) {
2177 try renderToken(ais, tree, field.ast.name_token, .Space); // name
2178 try renderToken(ais, tree, field.ast.name_token + 1, .Space); // =
2179 return renderExpressionComma(ais, tree, field.ast.value_expr, space); // value
2180 }
2181
2182 try renderToken(ais, tree, field.ast.name_token, .None); // name
2183 try renderToken(ais, tree, field.ast.name_token + 1, .Space); // :
2184 try renderExpression(ais, tree, field.ast.type_expr, .Space); // type
2185
2186 if (field.ast.align_expr != 0) {
2187 const lparen_token = tree.firstToken(field.ast.align_expr) - 1;
2188 const align_kw = lparen_token - 1;
2189 const rparen_token = tree.lastToken(field.ast.align_expr) + 1;
2190 try renderToken(ais, tree, align_kw, .None); // align
2191 try renderToken(ais, tree, lparen_token, .None); // (
2192 try renderExpression(ais, tree, field.ast.align_expr, .None); // alignment
2193 try renderToken(ais, tree, rparen_token, .Space); // )
2194 }
2195 const eq_token = tree.firstToken(field.ast.value_expr) - 1;
2196 try renderToken(ais, tree, eq_token, .Space); // =
2197 return renderExpressionComma(ais, tree, field.ast.value_expr, space); // value
2198}
2199
22372200fn renderParamDecl(
22382201 allocator: *mem.Allocator,
22392202 ais: *Ais,
......@@ -2258,6 +2221,29 @@ fn renderParamDecl(
22582221 }
22592222}
22602223
2224/// Render an expression, and the comma that follows it, if it is present in the source.
2225fn renderExpressionComma(ais: *Ais, tree: ast.Tree, node: ast.Node.Index, space: Space) Error!void {
2226 const token_tags = tree.tokens.items(.tag);
2227 const maybe_comma = tree.lastToken(node) + 1;
2228 if (token_tags[maybe_comma] == .Comma) {
2229 try renderExpression(ais, tree, node, .None);
2230 return renderToken(ais, tree, maybe_comma, space);
2231 } else {
2232 return renderExpression(ais, tree, node, space);
2233 }
2234}
2235
2236fn renderTokenComma(ais: *Ais, tree: ast.Tree, token: ast.TokenIndex, space: Space) Error!void {
2237 const token_tags = tree.tokens.items(.tag);
2238 const maybe_comma = token + 1;
2239 if (token_tags[maybe_comma] == .Comma) {
2240 try renderToken(ais, tree, token, .None);
2241 return renderToken(ais, tree, maybe_comma, space);
2242 } else {
2243 return renderToken(ais, tree, token, space);
2244 }
2245}
2246
22612247const Space = enum {
22622248 None,
22632249 Newline,