| ... | @@ -14,8 +14,13 @@ const RenderState = union(enum) { | ... | @@ -14,8 +14,13 @@ const RenderState = union(enum) { |
| 14 | Statement: &ast.Node, | 14 | Statement: &ast.Node, |
| 15 | PrintIndent, | 15 | PrintIndent, |
| 16 | Indent: usize, | 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 | pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void { | 24 | pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void { |
| 20 | var stack = SegmentedList(RenderState, 32).init(allocator); | 25 | var stack = SegmentedList(RenderState, 32).init(allocator); |
| 21 | defer stack.deinit(); | 26 | defer stack.deinit(); |
| ... | @@ -44,7 +49,6 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void { | ... | @@ -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 | var indent: usize = 0; | 52 | var indent: usize = 0; |
| 49 | while (stack.pop()) |state| { | 53 | while (stack.pop()) |state| { |
| 50 | switch (state) { | 54 | switch (state) { |
| ... | @@ -92,7 +96,7 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void { | ... | @@ -92,7 +96,7 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void { |
| 92 | try stream.print("{} ", tree.tokenSlice(visib_token)); | 96 | try stream.print("{} ", tree.tokenSlice(visib_token)); |
| 93 | } | 97 | } |
| 94 | try stream.print("{}: ", tree.tokenSlice(field.name_token)); | 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 | try stack.push(RenderState { .Expression = field.type_expr}); | 100 | try stack.push(RenderState { .Expression = field.type_expr}); |
| 97 | }, | 101 | }, |
| 98 | ast.Node.Id.UnionTag => { | 102 | ast.Node.Id.UnionTag => { |
| ... | @@ -129,9 +133,7 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void { | ... | @@ -129,9 +133,7 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void { |
| 129 | try stream.print("{}", tree.tokenSlice(tag.name_token)); | 133 | try stream.print("{}", tree.tokenSlice(tag.name_token)); |
| 130 | }, | 134 | }, |
| 131 | ast.Node.Id.Comptime => { | 135 | ast.Node.Id.Comptime => { |
| 132 | if (decl.requireSemiColon()) { | 136 | try stack.push(RenderState { .MaybeSemiColon = decl }); |
| 133 | try stack.push(RenderState { .Text = ";" }); | | |
| 134 | } | | |
| 135 | try stack.push(RenderState { .Expression = decl }); | 137 | try stack.push(RenderState { .Expression = decl }); |
| 136 | }, | 138 | }, |
| 137 | ast.Node.Id.LineComment => { | 139 | ast.Node.Id.LineComment => { |
| ... | @@ -143,7 +145,7 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void { | ... | @@ -143,7 +145,7 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void { |
| 143 | }, | 145 | }, |
| 144 | | 146 | |
| 145 | RenderState.VarDecl => |var_decl| { | 147 | RenderState.VarDecl => |var_decl| { |
| 146 | try stack.push(RenderState { .Text = ";" }); | 148 | try stack.push(RenderState { .Token = var_decl.semicolon_token }); |
| 147 | if (var_decl.init_node) |init_node| { | 149 | if (var_decl.init_node) |init_node| { |
| 148 | try stack.push(RenderState { .Expression = init_node }); | 150 | try stack.push(RenderState { .Expression = init_node }); |
| 149 | const text = if (init_node.id == ast.Node.Id.MultilineStringLiteral) " =" else " = "; | 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,7 +897,7 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void { |
| 895 | ast.Node.Id.SwitchCase => { | 897 | ast.Node.Id.SwitchCase => { |
| 896 | const switch_case = @fieldParentPtr(ast.Node.SwitchCase, "base", base); | 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 | try stack.push(RenderState { .Expression = switch_case.expr }); | 901 | try stack.push(RenderState { .Expression = switch_case.expr }); |
| 900 | if (switch_case.payload) |payload| { | 902 | if (switch_case.payload) |payload| { |
| 901 | try stack.push(RenderState { .Text = " " }); | 903 | try stack.push(RenderState { .Text = " " }); |
| ... | @@ -1072,14 +1074,13 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void { | ... | @@ -1072,14 +1074,13 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void { |
| 1072 | } | 1074 | } |
| 1073 | | 1075 | |
| 1074 | try stack.push(RenderState { .Expression = if_node.body }); | 1076 | try stack.push(RenderState { .Expression = if_node.body }); |
| 1075 | try stack.push(RenderState { .Text = " " }); | | |
| 1076 | | 1077 | |
| 1077 | if (if_node.payload) |payload| { | 1078 | if (if_node.payload) |payload| { |
| 1078 | try stack.push(RenderState { .Expression = payload }); | | |
| 1079 | try stack.push(RenderState { .Text = " " }); | 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 | try stack.push(RenderState { .Expression = if_node.condition }); | 1084 | try stack.push(RenderState { .Expression = if_node.condition }); |
| 1084 | try stack.push(RenderState { .Text = "(" }); | 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,17 +1218,46 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) !void { |
| 1217 | try stack.push(RenderState { .VarDecl = var_decl}); | 1218 | try stack.push(RenderState { .VarDecl = var_decl}); |
| 1218 | }, | 1219 | }, |
| 1219 | else => { | 1220 | else => { |
| 1220 | if (base.requireSemiColon()) { | 1221 | try stack.push(RenderState { .MaybeSemiColon = base }); |
| 1221 | try stack.push(RenderState { .Text = ";" }); | | |
| 1222 | } | | |
| 1223 | try stack.push(RenderState { .Expression = base }); | 1222 | try stack.push(RenderState { .Expression = base }); |
| 1224 | }, | 1223 | }, |
| 1225 | } | 1224 | } |
| 1226 | }, | 1225 | }, |
| 1227 | RenderState.Indent => |new_indent| indent = new_indent, | 1226 | RenderState.Indent => |new_indent| indent = new_indent, |
| 1228 | RenderState.PrintIndent => try stream.writeByteNTimes(' ', indent), | 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 | fn renderComments(tree: &ast.Tree, stream: var, node: var, indent: usize) !void { | 1263 | fn renderComments(tree: &ast.Tree, stream: var, node: var, indent: usize) !void { |