authorgravatar for lachlan@lakebythewoods.xyzLachlan Easton <lachlan@lakebythewoods.xyz> 2020-08-30 10:32:21+10:00
committergravatar for lachlan@lakebythewoods.xyzLachlan Easton <lachlan@lakebythewoods.xyz> 2020-08-30 10:32:21+10:00
log50c8a53188bdd20321990b7a4999f534b9e613dd
treeedc5d0a481dc18a160848956451d483e36fc83ff
parent7d950210a64f51cba6c4edaacbd9c67f12e72604

Use ArrayList instead of fixed array for auto_indenting_stream


3 files changed, 82 insertions(+), 69 deletions(-)

lib/std/io/auto_indenting_stream.zig+43-33
......@@ -1,26 +1,36 @@
11const std = @import("../std.zig");
22const io = std.io;
33const mem = std.mem;
4const Allocator = mem.Allocator;
5const ArrayList = std.ArrayList;
46const assert = std.debug.assert;
57
68/// Automatically inserts indentation of written data by keeping
79/// track of the current indentation level
8pub fn AutoIndentingStream(comptime indent_delta: u8, comptime WriterType: type) type {
10pub fn AutoIndentingStream(comptime indent_delta: usize, comptime WriterType: type) type {
911 return struct {
1012 const Self = @This();
1113 pub const Error = WriterType.Error;
14 pub const PushError = Allocator.Error;
1215 pub const Writer = io.Writer(*Self, Error, write);
16 const Stack = ArrayList(usize);
1317
1418 writer_pointer: *WriterType,
19 indent_stack: Stack,
20
1521 current_line_empty: bool = true,
16 indent_stack: [255]u8 = undefined,
17 indent_stack_top: u8 = 0,
18 indent_one_shot_count: u8 = 0, // automatically popped when applied
19 applied_indent: u8 = 0, // the most recently applied indent
20 indent_next_line: u8 = 0, // not used until the next line
22 indent_one_shot_count: usize = 0, // automatically popped when applied
23 applied_indent: usize = 0, // the most recently applied indent
24 indent_next_line: usize = 0, // not used until the next line
25
26 pub fn init(writer_pointer: *WriterType, allocator: *Allocator) Self {
27 var indent_stack = Stack.init(allocator);
28 return Self{ .writer_pointer = writer_pointer, .indent_stack = indent_stack };
29 }
2130
22 pub fn init(writer_pointer: *WriterType) Self {
23 return Self{ .writer_pointer = writer_pointer };
31 /// Release all allocated memory.
32 pub fn deinit(self: Self) void {
33 self.indent_stack.deinit();
2434 }
2535
2636 pub fn writer(self: *Self) Writer {
......@@ -39,7 +49,7 @@ pub fn AutoIndentingStream(comptime indent_delta: u8, comptime WriterType: type)
3949 if (bytes.len == 0)
4050 return @as(usize, 0);
4151
42 try self.writer_pointer.outStream().writeAll(bytes);
52 try self.writer_pointer.writer().writeAll(bytes);
4353 if (bytes[bytes.len - 1] == '\n')
4454 self.resetLine();
4555 return bytes.len;
......@@ -61,53 +71,52 @@ pub fn AutoIndentingStream(comptime indent_delta: u8, comptime WriterType: type)
6171 }
6272
6373 /// Push default indentation
64 pub fn pushIndent(self: *Self) void {
65 // Doesn't actually write any indentation. Just primes the stream to be able to write the correct indentation if it needs to.
66 self.pushIndentN(indent_delta);
74 pub fn pushIndent(self: *Self) PushError!void {
75 // Doesn't actually write any indentation.
76 // Just primes the stream to be able to write the correct indentation if it needs to.
77 try self.pushIndentN(indent_delta);
6778 }
6879
6980 /// Push an indent of arbitrary width
70 pub fn pushIndentN(self: *Self, n: u8) void {
71 assert(self.indent_stack_top < std.math.maxInt(u8));
72 self.indent_stack[self.indent_stack_top] = n;
73 self.indent_stack_top += 1;
81 pub fn pushIndentN(self: *Self, n: usize) PushError!void {
82 try self.indent_stack.append(n);
7483 }
7584
7685 /// Push an indent that is automatically popped after being applied
77 pub fn pushIndentOneShot(self: *Self) void {
86 pub fn pushIndentOneShot(self: *Self) PushError!void {
7887 self.indent_one_shot_count += 1;
79 self.pushIndent();
88 try self.pushIndent();
8089 }
8190
8291 /// Turns all one-shot indents into regular indents
8392 /// Returns number of indents that must now be manually popped
84 pub fn lockOneShotIndent(self: *Self) u8 {
93 pub fn lockOneShotIndent(self: *Self) usize {
8594 var locked_count = self.indent_one_shot_count;
8695 self.indent_one_shot_count = 0;
8796 return locked_count;
8897 }
8998
9099 /// Push an indent that should not take effect until the next line
91 pub fn pushIndentNextLine(self: *Self) void {
100 pub fn pushIndentNextLine(self: *Self) PushError!void {
92101 self.indent_next_line += 1;
93 self.pushIndent();
102 try self.pushIndent();
94103 }
95104
96105 pub fn popIndent(self: *Self) void {
97 assert(self.indent_stack_top != 0);
98 self.indent_stack_top -= 1;
99 self.indent_next_line = std.math.min(self.indent_stack_top, self.indent_next_line); // Tentative indent may have been popped before there was a newline
106 assert(self.indent_stack.items.len != 0);
107 self.indent_stack.items.len -= 1;
108 self.indent_next_line = std.math.min(self.indent_stack.items.len, self.indent_next_line); // Tentative indent may have been popped before there was a newline
100109 }
101110
102111 /// Writes ' ' bytes if the current line is empty
103112 fn applyIndent(self: *Self) Error!void {
104113 const current_indent = self.currentIndent();
105114 if (self.current_line_empty and current_indent > 0) {
106 try self.writer_pointer.outStream().writeByteNTimes(' ', current_indent);
115 try self.writer_pointer.writer().writeByteNTimes(' ', current_indent);
107116 self.applied_indent = current_indent;
108117 }
109118
110 self.indent_stack_top -= self.indent_one_shot_count;
119 self.indent_stack.items.len -= self.indent_one_shot_count;
111120 self.indent_one_shot_count = 0;
112121 self.current_line_empty = false;
113122 }
......@@ -118,11 +127,11 @@ pub fn AutoIndentingStream(comptime indent_delta: u8, comptime WriterType: type)
118127 return self.applied_indent > self.currentIndent();
119128 }
120129
121 fn currentIndent(self: *Self) u8 {
122 var indent_current: u8 = 0;
123 if (self.indent_stack_top > 0) {
124 const stack_top = self.indent_stack_top - self.indent_next_line;
125 for (self.indent_stack[0..stack_top]) |indent| {
130 fn currentIndent(self: *Self) usize {
131 var indent_current: usize = 0;
132 if (self.indent_stack.items.len > 0) {
133 const stack_top = self.indent_stack.items.len - self.indent_next_line;
134 for (self.indent_stack.items[0..stack_top]) |indent| {
126135 indent_current += indent;
127136 }
128137 }
......@@ -132,9 +141,10 @@ pub fn AutoIndentingStream(comptime indent_delta: u8, comptime WriterType: type)
132141}
133142
134143pub fn autoIndentingStream(
135 comptime indent_delta: u8,
144 comptime indent_delta: usize,
136145 underlying_stream: anytype,
146 allocator: *Allocator,
137147) AutoIndentingStream(indent_delta, @TypeOf(underlying_stream).Child) {
138148 comptime assert(@typeInfo(@TypeOf(underlying_stream)) == .Pointer);
139 return AutoIndentingStream(indent_delta, @TypeOf(underlying_stream).Child).init(underlying_stream);
149 return AutoIndentingStream(indent_delta, @TypeOf(underlying_stream).Child).init(underlying_stream, allocator);
140150}
lib/std/io/find_byte_out_stream.zig+2-2
......@@ -8,7 +8,7 @@ pub fn FindByteOutStream(comptime WriterType: type) type {
88 return struct {
99 const Self = @This();
1010 pub const Error = WriterType.Error;
11 pub const OutStream = io.OutStream(*Self, Error, write);
11 pub const Writer = io.Writer(*Self, Error, write);
1212
1313 writer_pointer: *WriterType,
1414 byte_found: bool,
......@@ -22,7 +22,7 @@ pub fn FindByteOutStream(comptime WriterType: type) type {
2222 };
2323 }
2424
25 pub fn outStream(self: *Self) OutStream {
25 pub fn writer(self: *Self) Writer {
2626 return .{ .context = self };
2727 }
2828
lib/std/zig/render.zig+37-34
......@@ -24,7 +24,8 @@ pub fn render(allocator: *mem.Allocator, stream: anytype, tree: *ast.Tree) (meta
2424
2525 var s = stream.*;
2626 var change_detection_stream = std.io.changeDetectionStream(tree.source, &s);
27 var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, &change_detection_stream);
27 var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, &change_detection_stream, allocator);
28 defer auto_indenting_stream.deinit();
2829
2930 try renderRoot(allocator, &auto_indenting_stream, tree);
3031
......@@ -388,11 +389,11 @@ fn renderExpression(
388389 }
389390
390391 if (block.statements.len == 0) {
391 stream.pushIndentNextLine();
392 try stream.pushIndentNextLine();
392393 defer stream.popIndent();
393394 try renderToken(tree, stream, block.lbrace, Space.None);
394395 } else {
395 stream.pushIndentNextLine();
396 try stream.pushIndentNextLine();
396397 defer stream.popIndent();
397398
398399 try renderToken(tree, stream, block.lbrace, Space.Newline);
......@@ -462,7 +463,7 @@ fn renderExpression(
462463 try renderExpression(allocator, stream, tree, payload, Space.Space);
463464 }
464465
465 stream.pushIndentOneShot();
466 try stream.pushIndentOneShot();
466467 return renderExpression(allocator, stream, tree, infix_op_node.rhs, space);
467468 },
468469
......@@ -523,7 +524,7 @@ fn renderExpression(
523524 };
524525
525526 try renderToken(tree, stream, infix_op_node.op_token, after_op_space);
526 stream.pushIndentOneShot();
527 try stream.pushIndentOneShot();
527528 return renderExpression(allocator, stream, tree, infix_op_node.rhs, space);
528529 },
529530
......@@ -717,7 +718,7 @@ fn renderExpression(
717718 }
718719
719720 {
720 stream.pushIndent();
721 try stream.pushIndent();
721722 defer stream.popIndent();
722723 try renderToken(tree, stream, lbrace, Space.None);
723724 }
......@@ -782,7 +783,8 @@ fn renderExpression(
782783
783784 // Null stream for counting the printed length of each expression
784785 var counting_stream = std.io.countingOutStream(std.io.null_out_stream);
785 var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, &counting_stream);
786 var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, &counting_stream, allocator);
787 defer auto_indenting_stream.deinit();
786788
787789 for (exprs) |expr, i| {
788790 counting_stream.bytes_written = 0;
......@@ -794,7 +796,7 @@ fn renderExpression(
794796 }
795797
796798 {
797 stream.pushIndentNextLine();
799 try stream.pushIndentNextLine();
798800 defer stream.popIndent();
799801 try renderToken(tree, stream, lbrace, Space.Newline);
800802
......@@ -878,7 +880,7 @@ fn renderExpression(
878880 }
879881
880882 {
881 stream.pushIndentNextLine();
883 try stream.pushIndentNextLine();
882884 defer stream.popIndent();
883885 try renderToken(tree, stream, lbrace, Space.None);
884886 }
......@@ -900,7 +902,8 @@ fn renderExpression(
900902 // render field expressions until a LF is found
901903 for (field_inits) |field_init| {
902904 var find_stream = std.io.findByteOutStream('\n', &std.io.null_out_stream);
903 var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, &find_stream);
905 var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, &find_stream, allocator);
906 defer auto_indenting_stream.deinit();
904907
905908 try renderExpression(allocator, &auto_indenting_stream, tree, field_init, Space.None);
906909 if (find_stream.byte_found) break :blk false;
......@@ -960,7 +963,7 @@ fn renderExpression(
960963 .node => |node| try renderExpression(allocator, stream, tree, node, Space.None),
961964 }
962965
963 stream.pushIndentNextLine();
966 try stream.pushIndentNextLine();
964967 defer stream.popIndent();
965968
966969 try renderToken(tree, stream, lbrace, Space.Newline);
......@@ -1008,7 +1011,7 @@ fn renderExpression(
10081011
10091012 const params = call.params();
10101013 for (params) |param_node, i| {
1011 stream.pushIndent();
1014 try stream.pushIndent();
10121015 defer stream.popIndent();
10131016
10141017 if (i + 1 < params.len) {
......@@ -1028,7 +1031,7 @@ fn renderExpression(
10281031
10291032 const params = call.params();
10301033 for (params) |param_node, i| {
1031 if (param_node.*.tag == .MultilineStringLiteral) stream.pushIndentOneShot();
1034 if (param_node.*.tag == .MultilineStringLiteral) try stream.pushIndentOneShot();
10321035
10331036 try renderExpression(allocator, stream, tree, param_node, Space.None);
10341037
......@@ -1055,7 +1058,7 @@ fn renderExpression(
10551058 {
10561059 const new_space = if (ends_with_comment) Space.Newline else Space.None;
10571060
1058 stream.pushIndent();
1061 try stream.pushIndent();
10591062 defer stream.popIndent();
10601063 try renderExpression(allocator, stream, tree, suffix_op.index_expr, new_space);
10611064 }
......@@ -1191,7 +1194,7 @@ fn renderExpression(
11911194
11921195 try renderToken(tree, stream, grouped_expr.lparen, Space.None);
11931196 {
1194 stream.pushIndentOneShot();
1197 try stream.pushIndentOneShot();
11951198 try renderExpression(allocator, stream, tree, grouped_expr.expr, Space.None);
11961199 }
11971200 return renderToken(tree, stream, grouped_expr.rparen, space);
......@@ -1251,7 +1254,7 @@ fn renderExpression(
12511254
12521255 if (container_decl.fields_and_decls_len == 0) {
12531256 {
1254 stream.pushIndentNextLine();
1257 try stream.pushIndentNextLine();
12551258 defer stream.popIndent();
12561259 try renderToken(tree, stream, container_decl.lbrace_token, Space.None); // {
12571260 }
......@@ -1286,7 +1289,7 @@ fn renderExpression(
12861289
12871290 if (src_has_trailing_comma or !src_has_only_fields) {
12881291 // One declaration per line
1289 stream.pushIndentNextLine();
1292 try stream.pushIndentNextLine();
12901293 defer stream.popIndent();
12911294 try renderToken(tree, stream, container_decl.lbrace_token, .Newline); // {
12921295
......@@ -1302,7 +1305,7 @@ fn renderExpression(
13021305 // their own line
13031306 try renderToken(tree, stream, container_decl.lbrace_token, .Newline); // {
13041307
1305 stream.pushIndent();
1308 try stream.pushIndent();
13061309 defer stream.popIndent();
13071310
13081311 for (fields_and_decls) |decl, i| {
......@@ -1358,7 +1361,7 @@ fn renderExpression(
13581361
13591362 if (src_has_trailing_comma) {
13601363 {
1361 stream.pushIndent();
1364 try stream.pushIndent();
13621365 defer stream.popIndent();
13631366
13641367 try renderToken(tree, stream, lbrace, Space.Newline); // {
......@@ -1448,7 +1451,7 @@ fn renderExpression(
14481451 }
14491452 } else {
14501453 // one param per line
1451 stream.pushIndent();
1454 try stream.pushIndent();
14521455 defer stream.popIndent();
14531456 try renderToken(tree, stream, lparen, Space.Newline); // (
14541457
......@@ -1527,7 +1530,7 @@ fn renderExpression(
15271530 }
15281531 } else {
15291532 // one param per line
1530 stream.pushIndent();
1533 try stream.pushIndent();
15311534 defer stream.popIndent();
15321535 try renderToken(tree, stream, lparen, Space.Newline); // (
15331536
......@@ -1624,7 +1627,7 @@ fn renderExpression(
16241627 try renderToken(tree, stream, rparen, Space.Space); // )
16251628
16261629 {
1627 stream.pushIndentNextLine();
1630 try stream.pushIndentNextLine();
16281631 defer stream.popIndent();
16291632 try renderToken(tree, stream, lbrace, Space.Newline); // {
16301633
......@@ -1708,7 +1711,7 @@ fn renderExpression(
17081711 if (same_line) {
17091712 return renderExpression(allocator, stream, tree, else_node.body, space);
17101713 } else {
1711 stream.pushIndent();
1714 try stream.pushIndent();
17121715 defer stream.popIndent();
17131716 return renderExpression(allocator, stream, tree, else_node.body, space);
17141717 }
......@@ -1772,7 +1775,7 @@ fn renderExpression(
17721775 }
17731776
17741777 {
1775 if (!body_is_block) stream.pushIndent();
1778 if (!body_is_block) try stream.pushIndent();
17761779 defer if (!body_is_block) stream.popIndent();
17771780 try renderExpression(allocator, stream, tree, while_node.body, after_body_space);
17781781 }
......@@ -1823,7 +1826,7 @@ fn renderExpression(
18231826 };
18241827
18251828 {
1826 if (!body_on_same_line) stream.pushIndent();
1829 if (!body_on_same_line) try stream.pushIndent();
18271830 defer if (!body_on_same_line) stream.popIndent();
18281831 try renderExpression(allocator, stream, tree, for_node.body, space_after_body); // { body }
18291832 }
......@@ -1879,7 +1882,7 @@ fn renderExpression(
18791882 const else_is_block = nodeIsBlock(@"else".body);
18801883
18811884 {
1882 stream.pushIndent();
1885 try stream.pushIndent();
18831886 defer stream.popIndent();
18841887 try renderExpression(allocator, stream, tree, if_node.body, Space.Newline);
18851888 }
......@@ -1900,12 +1903,12 @@ fn renderExpression(
19001903 try renderExpression(allocator, stream, tree, payload, Space.Newline);
19011904 }
19021905
1903 stream.pushIndent();
1906 try stream.pushIndent();
19041907 defer stream.popIndent();
19051908 return renderExpression(allocator, stream, tree, @"else".body, space);
19061909 }
19071910 } else {
1908 stream.pushIndent();
1911 try stream.pushIndent();
19091912 defer stream.popIndent();
19101913 return renderExpression(allocator, stream, tree, if_node.body, space);
19111914 }
......@@ -1946,7 +1949,7 @@ fn renderExpression(
19461949 }
19471950
19481951 asmblk: {
1949 stream.pushIndent();
1952 try stream.pushIndent();
19501953 defer stream.popIndent();
19511954
19521955 if (asm_node.outputs.len == 0 and asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) {
......@@ -1965,7 +1968,7 @@ fn renderExpression(
19651968 } else blk: {
19661969 try renderToken(tree, stream, colon1, Space.Space); // :
19671970
1968 stream.pushIndentN(2);
1971 try stream.pushIndentN(2);
19691972 defer stream.popIndent();
19701973
19711974 for (asm_node.outputs) |*asm_output, i| {
......@@ -1996,7 +1999,7 @@ fn renderExpression(
19961999 break :blk tree.nextToken(colon2);
19972000 } else blk: {
19982001 try renderToken(tree, stream, colon2, Space.Space); // :
1999 stream.pushIndentN(2);
2002 try stream.pushIndentN(2);
20002003 defer stream.popIndent();
20012004 for (asm_node.inputs) |*asm_input, i| {
20022005 if (i + 1 < asm_node.inputs.len) {
......@@ -2022,7 +2025,7 @@ fn renderExpression(
20222025 };
20232026
20242027 try renderToken(tree, stream, colon3, Space.Space); // :
2025 stream.pushIndentN(2);
2028 try stream.pushIndentN(2);
20262029 defer stream.popIndent();
20272030 for (asm_node.clobbers) |clobber_node, i| {
20282031 if (i + 1 >= asm_node.clobbers.len) {
......@@ -2075,7 +2078,7 @@ fn renderArrayType(
20752078 const new_space = if (ends_with_comment) Space.Newline else Space.None;
20762079 {
20772080 const do_indent = (starts_with_comment or ends_with_comment);
2078 if (do_indent) stream.pushIndent();
2081 if (do_indent) try stream.pushIndent();
20792082 defer if (do_indent) stream.popIndent();
20802083
20812084 try renderToken(tree, stream, lbracket, Space.None); // [
......@@ -2209,7 +2212,7 @@ fn renderVarDecl(
22092212 if (var_decl.getTrailer("init_node")) |init_node| {
22102213 const s = if (init_node.tag == .MultilineStringLiteral) Space.None else Space.Space;
22112214 try renderToken(tree, stream, var_decl.getTrailer("eq_token").?, s); // =
2212 stream.pushIndentOneShot();
2215 try stream.pushIndentOneShot();
22132216 try renderExpression(allocator, stream, tree, init_node, Space.None);
22142217 }
22152218