@@ -14,8 +14,13 @@ const RenderState = union(enum) {
14
14
Statement : & ast.Node ,
15
15
PrintIndent ,
16
16
Indent : usize ,
17
+ MaybeSemiColon : & ast.Node ,
18
+ Token : ast.TokenIndex ,
19
+ NonBreakToken : ast.TokenIndex ,
17
20
};
18
21
22
+ const indent_delta = 4 ;
23
+
19
24
pub fn render (allocator : & mem.Allocator , stream : var , tree : & ast.Tree ) ! void {
20
25
var stack = SegmentedList (RenderState , 32 ).init (allocator );
21
26
defer stack .deinit ();
@@ -44,7 +49,6 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void {
44
49
}
45
50
}
46
51
47
- const indent_delta = 4 ;
48
52
var indent : usize = 0 ;
49
53
while (stack .pop ()) | state | {
50
54
switch (state ) {
@@ -92,7 +96,7 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void {
92
96
try stream .print ("{} " , tree .tokenSlice (visib_token ));
93
97
}
94
98
try stream .print ("{}: " , tree .tokenSlice (field .name_token ));
95
- try stack .push (RenderState { .Text = "," });
99
+ try stack .push (RenderState { .Token = field . lastToken () + 1 });
96
100
try stack .push (RenderState { .Expression = field .type_expr });
97
101
},
98
102
ast .Node .Id .UnionTag = > {
@@ -129,9 +133,7 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void {
129
133
try stream .print ("{}" , tree .tokenSlice (tag .name_token ));
130
134
},
131
135
ast .Node .Id .Comptime = > {
132
- if (decl .requireSemiColon ()) {
133
- try stack .push (RenderState { .Text = ";" });
134
- }
136
+ try stack .push (RenderState { .MaybeSemiColon = decl });
135
137
try stack .push (RenderState { .Expression = decl });
136
138
},
137
139
ast .Node .Id .LineComment = > {
@@ -143,7 +145,7 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void {
143
145
},
144
146
145
147
RenderState .VarDecl = > | var_decl | {
146
- try stack .push (RenderState { .Text = ";" });
148
+ try stack .push (RenderState { .Token = var_decl . semicolon_token });
147
149
if (var_decl .init_node ) | init_node | {
148
150
try stack .push (RenderState { .Expression = init_node });
149
151
const text = if (init_node .id == ast .Node .Id .MultilineStringLiteral ) " =" else " = " ;
@@ -895,7 +897,7 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void {
895
897
ast .Node .Id .SwitchCase = > {
896
898
const switch_case = @fieldParentPtr (ast .Node .SwitchCase , "base" , base );
897
899
898
- try stack .push (RenderState { .Text = "," });
900
+ try stack .push (RenderState { .Token = switch_case . lastToken () + 1 });
899
901
try stack .push (RenderState { .Expression = switch_case .expr });
900
902
if (switch_case .payload ) | payload | {
901
903
try stack .push (RenderState { .Text = " " });
@@ -1072,14 +1074,13 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void {
1072
1074
}
1073
1075
1074
1076
try stack .push (RenderState { .Expression = if_node .body });
1075
- try stack .push (RenderState { .Text = " " });
1076
1077
1077
1078
if (if_node .payload ) | payload | {
1078
- try stack .push (RenderState { .Expression = payload });
1079
1079
try stack .push (RenderState { .Text = " " });
1080
+ try stack .push (RenderState { .Expression = payload });
1080
1081
}
1081
1082
1082
- try stack .push (RenderState { .Text = ")" });
1083
+ try stack .push (RenderState { .NonBreakToken = if_node . condition . lastToken () + 1 });
1083
1084
try stack .push (RenderState { .Expression = if_node .condition });
1084
1085
try stack .push (RenderState { .Text = "(" });
1085
1086
},
@@ -1217,17 +1218,46 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void {
1217
1218
try stack .push (RenderState { .VarDecl = var_decl });
1218
1219
},
1219
1220
else = > {
1220
- if (base .requireSemiColon ()) {
1221
- try stack .push (RenderState { .Text = ";" });
1222
- }
1221
+ try stack .push (RenderState { .MaybeSemiColon = base });
1223
1222
try stack .push (RenderState { .Expression = base });
1224
1223
},
1225
1224
}
1226
1225
},
1227
1226
RenderState .Indent = > | new_indent | indent = new_indent ,
1228
1227
RenderState .PrintIndent = > try stream .writeByteNTimes (' ' , indent ),
1228
+ RenderState .Token = > | token_index | try renderToken (tree , stream , token_index , indent , true ),
1229
+ RenderState .NonBreakToken = > | token_index | try renderToken (tree , stream , token_index , indent , false ),
1230
+ RenderState .MaybeSemiColon = > | base | {
1231
+ if (base .requireSemiColon ()) {
1232
+ const semicolon_index = base .lastToken () + 1 ;
1233
+ assert (tree .tokens .at (semicolon_index ).id == Token .Id .Semicolon );
1234
+ try renderToken (tree , stream , semicolon_index , indent , true );
1235
+ }
1236
+ },
1237
+ }
1238
+ }
1239
+ }
1240
+
1241
+ fn renderToken (tree : & ast.Tree , stream : var , token_index : ast.TokenIndex , indent : usize , line_break : bool ) ! void {
1242
+ const token = tree .tokens .at (token_index );
1243
+ try stream .write (tree .tokenSlicePtr (token ));
1244
+
1245
+ const next_token = tree .tokens .at (token_index + 1 );
1246
+ if (next_token .id == Token .Id .LineComment ) {
1247
+ const loc = tree .tokenLocationPtr (token .end , next_token );
1248
+ if (loc .line == 0 ) {
1249
+ try stream .print (" {}" , tree .tokenSlicePtr (next_token ));
1250
+ if (! line_break ) {
1251
+ try stream .write ("\n " );
1252
+ try stream .writeByteNTimes (' ' , indent + indent_delta );
1253
+ return ;
1254
+ }
1229
1255
}
1230
1256
}
1257
+
1258
+ if (! line_break ) {
1259
+ try stream .writeByte (' ' );
1260
+ }
1231
1261
}
1232
1262
1233
1263
fn renderComments (tree : & ast.Tree , stream : var , node : var , indent : usize ) ! void {
0 commit comments