diff options
| author | Lachlan Easton <lachlan@lakebythewoods.xyz> | 2020-08-30 10:32:21 +1000 |
|---|---|---|
| committer | Lachlan Easton <lachlan@lakebythewoods.xyz> | 2020-08-30 10:32:21 +1000 |
| commit | 50c8a53188bdd20321990b7a4999f534b9e613dd (patch) | |
| tree | edc5d0a481dc18a160848956451d483e36fc83ff | |
| parent | 7d950210a64f51cba6c4edaacbd9c67f12e72604 (diff) | |
| download | zig-50c8a53188bdd20321990b7a4999f534b9e613dd.tar.gz zig-50c8a53188bdd20321990b7a4999f534b9e613dd.zip | |
Use ArrayList instead of fixed array for auto_indenting_stream
| -rw-r--r-- | lib/std/io/auto_indenting_stream.zig | 76 | ||||
| -rw-r--r-- | lib/std/io/find_byte_out_stream.zig | 4 | ||||
| -rw-r--r-- | lib/std/zig/render.zig | 71 |
3 files changed, 82 insertions, 69 deletions
diff --git a/lib/std/io/auto_indenting_stream.zig b/lib/std/io/auto_indenting_stream.zig index 227dd616a1..71547026a4 100644 --- a/lib/std/io/auto_indenting_stream.zig +++ b/lib/std/io/auto_indenting_stream.zig @@ -1,26 +1,36 @@ const std = @import("../std.zig"); const io = std.io; const mem = std.mem; +const Allocator = mem.Allocator; +const ArrayList = std.ArrayList; const assert = std.debug.assert; /// Automatically inserts indentation of written data by keeping /// track of the current indentation level -pub fn AutoIndentingStream(comptime indent_delta: u8, comptime WriterType: type) type { +pub fn AutoIndentingStream(comptime indent_delta: usize, comptime WriterType: type) type { return struct { const Self = @This(); pub const Error = WriterType.Error; + pub const PushError = Allocator.Error; pub const Writer = io.Writer(*Self, Error, write); + const Stack = ArrayList(usize); writer_pointer: *WriterType, + indent_stack: Stack, + current_line_empty: bool = true, - indent_stack: [255]u8 = undefined, - indent_stack_top: u8 = 0, - indent_one_shot_count: u8 = 0, // automatically popped when applied - applied_indent: u8 = 0, // the most recently applied indent - indent_next_line: u8 = 0, // not used until the next line + indent_one_shot_count: usize = 0, // automatically popped when applied + applied_indent: usize = 0, // the most recently applied indent + indent_next_line: usize = 0, // not used until the next line + + pub fn init(writer_pointer: *WriterType, allocator: *Allocator) Self { + var indent_stack = Stack.init(allocator); + return Self{ .writer_pointer = writer_pointer, .indent_stack = indent_stack }; + } - pub fn init(writer_pointer: *WriterType) Self { - return Self{ .writer_pointer = writer_pointer }; + /// Release all allocated memory. + pub fn deinit(self: Self) void { + self.indent_stack.deinit(); } pub fn writer(self: *Self) Writer { @@ -39,7 +49,7 @@ pub fn AutoIndentingStream(comptime indent_delta: u8, comptime WriterType: type) if (bytes.len == 0) return @as(usize, 0); - try self.writer_pointer.outStream().writeAll(bytes); + try self.writer_pointer.writer().writeAll(bytes); if (bytes[bytes.len - 1] == '\n') self.resetLine(); return bytes.len; @@ -61,53 +71,52 @@ pub fn AutoIndentingStream(comptime indent_delta: u8, comptime WriterType: type) } /// Push default indentation - pub fn pushIndent(self: *Self) void { - // Doesn't actually write any indentation. Just primes the stream to be able to write the correct indentation if it needs to. - self.pushIndentN(indent_delta); + pub fn pushIndent(self: *Self) PushError!void { + // Doesn't actually write any indentation. + // Just primes the stream to be able to write the correct indentation if it needs to. + try self.pushIndentN(indent_delta); } /// Push an indent of arbitrary width - pub fn pushIndentN(self: *Self, n: u8) void { - assert(self.indent_stack_top < std.math.maxInt(u8)); - self.indent_stack[self.indent_stack_top] = n; - self.indent_stack_top += 1; + pub fn pushIndentN(self: *Self, n: usize) PushError!void { + try self.indent_stack.append(n); } /// Push an indent that is automatically popped after being applied - pub fn pushIndentOneShot(self: *Self) void { + pub fn pushIndentOneShot(self: *Self) PushError!void { self.indent_one_shot_count += 1; - self.pushIndent(); + try self.pushIndent(); } /// Turns all one-shot indents into regular indents /// Returns number of indents that must now be manually popped - pub fn lockOneShotIndent(self: *Self) u8 { + pub fn lockOneShotIndent(self: *Self) usize { var locked_count = self.indent_one_shot_count; self.indent_one_shot_count = 0; return locked_count; } /// Push an indent that should not take effect until the next line - pub fn pushIndentNextLine(self: *Self) void { + pub fn pushIndentNextLine(self: *Self) PushError!void { self.indent_next_line += 1; - self.pushIndent(); + try self.pushIndent(); } pub fn popIndent(self: *Self) void { - assert(self.indent_stack_top != 0); - self.indent_stack_top -= 1; - 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 + assert(self.indent_stack.items.len != 0); + self.indent_stack.items.len -= 1; + 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 } /// Writes ' ' bytes if the current line is empty fn applyIndent(self: *Self) Error!void { const current_indent = self.currentIndent(); if (self.current_line_empty and current_indent > 0) { - try self.writer_pointer.outStream().writeByteNTimes(' ', current_indent); + try self.writer_pointer.writer().writeByteNTimes(' ', current_indent); self.applied_indent = current_indent; } - self.indent_stack_top -= self.indent_one_shot_count; + self.indent_stack.items.len -= self.indent_one_shot_count; self.indent_one_shot_count = 0; self.current_line_empty = false; } @@ -118,11 +127,11 @@ pub fn AutoIndentingStream(comptime indent_delta: u8, comptime WriterType: type) return self.applied_indent > self.currentIndent(); } - fn currentIndent(self: *Self) u8 { - var indent_current: u8 = 0; - if (self.indent_stack_top > 0) { - const stack_top = self.indent_stack_top - self.indent_next_line; - for (self.indent_stack[0..stack_top]) |indent| { + fn currentIndent(self: *Self) usize { + var indent_current: usize = 0; + if (self.indent_stack.items.len > 0) { + const stack_top = self.indent_stack.items.len - self.indent_next_line; + for (self.indent_stack.items[0..stack_top]) |indent| { indent_current += indent; } } @@ -132,9 +141,10 @@ pub fn AutoIndentingStream(comptime indent_delta: u8, comptime WriterType: type) } pub fn autoIndentingStream( - comptime indent_delta: u8, + comptime indent_delta: usize, underlying_stream: anytype, + allocator: *Allocator, ) AutoIndentingStream(indent_delta, @TypeOf(underlying_stream).Child) { comptime assert(@typeInfo(@TypeOf(underlying_stream)) == .Pointer); - return AutoIndentingStream(indent_delta, @TypeOf(underlying_stream).Child).init(underlying_stream); + return AutoIndentingStream(indent_delta, @TypeOf(underlying_stream).Child).init(underlying_stream, allocator); } diff --git a/lib/std/io/find_byte_out_stream.zig b/lib/std/io/find_byte_out_stream.zig index b316a98549..0bf3a15545 100644 --- a/lib/std/io/find_byte_out_stream.zig +++ b/lib/std/io/find_byte_out_stream.zig @@ -8,7 +8,7 @@ pub fn FindByteOutStream(comptime WriterType: type) type { return struct { const Self = @This(); pub const Error = WriterType.Error; - pub const OutStream = io.OutStream(*Self, Error, write); + pub const Writer = io.Writer(*Self, Error, write); writer_pointer: *WriterType, byte_found: bool, @@ -22,7 +22,7 @@ pub fn FindByteOutStream(comptime WriterType: type) type { }; } - pub fn outStream(self: *Self) OutStream { + pub fn writer(self: *Self) Writer { return .{ .context = self }; } diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index d7bba2f6bf..e3133a5501 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -24,7 +24,8 @@ pub fn render(allocator: *mem.Allocator, stream: anytype, tree: *ast.Tree) (meta var s = stream.*; var change_detection_stream = std.io.changeDetectionStream(tree.source, &s); - var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, &change_detection_stream); + var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, &change_detection_stream, allocator); + defer auto_indenting_stream.deinit(); try renderRoot(allocator, &auto_indenting_stream, tree); @@ -388,11 +389,11 @@ fn renderExpression( } if (block.statements.len == 0) { - stream.pushIndentNextLine(); + try stream.pushIndentNextLine(); defer stream.popIndent(); try renderToken(tree, stream, block.lbrace, Space.None); } else { - stream.pushIndentNextLine(); + try stream.pushIndentNextLine(); defer stream.popIndent(); try renderToken(tree, stream, block.lbrace, Space.Newline); @@ -462,7 +463,7 @@ fn renderExpression( try renderExpression(allocator, stream, tree, payload, Space.Space); } - stream.pushIndentOneShot(); + try stream.pushIndentOneShot(); return renderExpression(allocator, stream, tree, infix_op_node.rhs, space); }, @@ -523,7 +524,7 @@ fn renderExpression( }; try renderToken(tree, stream, infix_op_node.op_token, after_op_space); - stream.pushIndentOneShot(); + try stream.pushIndentOneShot(); return renderExpression(allocator, stream, tree, infix_op_node.rhs, space); }, @@ -717,7 +718,7 @@ fn renderExpression( } { - stream.pushIndent(); + try stream.pushIndent(); defer stream.popIndent(); try renderToken(tree, stream, lbrace, Space.None); } @@ -782,7 +783,8 @@ fn renderExpression( // Null stream for counting the printed length of each expression var counting_stream = std.io.countingOutStream(std.io.null_out_stream); - var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, &counting_stream); + var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, &counting_stream, allocator); + defer auto_indenting_stream.deinit(); for (exprs) |expr, i| { counting_stream.bytes_written = 0; @@ -794,7 +796,7 @@ fn renderExpression( } { - stream.pushIndentNextLine(); + try stream.pushIndentNextLine(); defer stream.popIndent(); try renderToken(tree, stream, lbrace, Space.Newline); @@ -878,7 +880,7 @@ fn renderExpression( } { - stream.pushIndentNextLine(); + try stream.pushIndentNextLine(); defer stream.popIndent(); try renderToken(tree, stream, lbrace, Space.None); } @@ -900,7 +902,8 @@ fn renderExpression( // render field expressions until a LF is found for (field_inits) |field_init| { var find_stream = std.io.findByteOutStream('\n', &std.io.null_out_stream); - var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, &find_stream); + var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, &find_stream, allocator); + defer auto_indenting_stream.deinit(); try renderExpression(allocator, &auto_indenting_stream, tree, field_init, Space.None); if (find_stream.byte_found) break :blk false; @@ -960,7 +963,7 @@ fn renderExpression( .node => |node| try renderExpression(allocator, stream, tree, node, Space.None), } - stream.pushIndentNextLine(); + try stream.pushIndentNextLine(); defer stream.popIndent(); try renderToken(tree, stream, lbrace, Space.Newline); @@ -1008,7 +1011,7 @@ fn renderExpression( const params = call.params(); for (params) |param_node, i| { - stream.pushIndent(); + try stream.pushIndent(); defer stream.popIndent(); if (i + 1 < params.len) { @@ -1028,7 +1031,7 @@ fn renderExpression( const params = call.params(); for (params) |param_node, i| { - if (param_node.*.tag == .MultilineStringLiteral) stream.pushIndentOneShot(); + if (param_node.*.tag == .MultilineStringLiteral) try stream.pushIndentOneShot(); try renderExpression(allocator, stream, tree, param_node, Space.None); @@ -1055,7 +1058,7 @@ fn renderExpression( { const new_space = if (ends_with_comment) Space.Newline else Space.None; - stream.pushIndent(); + try stream.pushIndent(); defer stream.popIndent(); try renderExpression(allocator, stream, tree, suffix_op.index_expr, new_space); } @@ -1191,7 +1194,7 @@ fn renderExpression( try renderToken(tree, stream, grouped_expr.lparen, Space.None); { - stream.pushIndentOneShot(); + try stream.pushIndentOneShot(); try renderExpression(allocator, stream, tree, grouped_expr.expr, Space.None); } return renderToken(tree, stream, grouped_expr.rparen, space); @@ -1251,7 +1254,7 @@ fn renderExpression( if (container_decl.fields_and_decls_len == 0) { { - stream.pushIndentNextLine(); + try stream.pushIndentNextLine(); defer stream.popIndent(); try renderToken(tree, stream, container_decl.lbrace_token, Space.None); // { } @@ -1286,7 +1289,7 @@ fn renderExpression( if (src_has_trailing_comma or !src_has_only_fields) { // One declaration per line - stream.pushIndentNextLine(); + try stream.pushIndentNextLine(); defer stream.popIndent(); try renderToken(tree, stream, container_decl.lbrace_token, .Newline); // { @@ -1302,7 +1305,7 @@ fn renderExpression( // their own line try renderToken(tree, stream, container_decl.lbrace_token, .Newline); // { - stream.pushIndent(); + try stream.pushIndent(); defer stream.popIndent(); for (fields_and_decls) |decl, i| { @@ -1358,7 +1361,7 @@ fn renderExpression( if (src_has_trailing_comma) { { - stream.pushIndent(); + try stream.pushIndent(); defer stream.popIndent(); try renderToken(tree, stream, lbrace, Space.Newline); // { @@ -1448,7 +1451,7 @@ fn renderExpression( } } else { // one param per line - stream.pushIndent(); + try stream.pushIndent(); defer stream.popIndent(); try renderToken(tree, stream, lparen, Space.Newline); // ( @@ -1527,7 +1530,7 @@ fn renderExpression( } } else { // one param per line - stream.pushIndent(); + try stream.pushIndent(); defer stream.popIndent(); try renderToken(tree, stream, lparen, Space.Newline); // ( @@ -1624,7 +1627,7 @@ fn renderExpression( try renderToken(tree, stream, rparen, Space.Space); // ) { - stream.pushIndentNextLine(); + try stream.pushIndentNextLine(); defer stream.popIndent(); try renderToken(tree, stream, lbrace, Space.Newline); // { @@ -1708,7 +1711,7 @@ fn renderExpression( if (same_line) { return renderExpression(allocator, stream, tree, else_node.body, space); } else { - stream.pushIndent(); + try stream.pushIndent(); defer stream.popIndent(); return renderExpression(allocator, stream, tree, else_node.body, space); } @@ -1772,7 +1775,7 @@ fn renderExpression( } { - if (!body_is_block) stream.pushIndent(); + if (!body_is_block) try stream.pushIndent(); defer if (!body_is_block) stream.popIndent(); try renderExpression(allocator, stream, tree, while_node.body, after_body_space); } @@ -1823,7 +1826,7 @@ fn renderExpression( }; { - if (!body_on_same_line) stream.pushIndent(); + if (!body_on_same_line) try stream.pushIndent(); defer if (!body_on_same_line) stream.popIndent(); try renderExpression(allocator, stream, tree, for_node.body, space_after_body); // { body } } @@ -1879,7 +1882,7 @@ fn renderExpression( const else_is_block = nodeIsBlock(@"else".body); { - stream.pushIndent(); + try stream.pushIndent(); defer stream.popIndent(); try renderExpression(allocator, stream, tree, if_node.body, Space.Newline); } @@ -1900,12 +1903,12 @@ fn renderExpression( try renderExpression(allocator, stream, tree, payload, Space.Newline); } - stream.pushIndent(); + try stream.pushIndent(); defer stream.popIndent(); return renderExpression(allocator, stream, tree, @"else".body, space); } } else { - stream.pushIndent(); + try stream.pushIndent(); defer stream.popIndent(); return renderExpression(allocator, stream, tree, if_node.body, space); } @@ -1946,7 +1949,7 @@ fn renderExpression( } asmblk: { - stream.pushIndent(); + try stream.pushIndent(); defer stream.popIndent(); if (asm_node.outputs.len == 0 and asm_node.inputs.len == 0 and asm_node.clobbers.len == 0) { @@ -1965,7 +1968,7 @@ fn renderExpression( } else blk: { try renderToken(tree, stream, colon1, Space.Space); // : - stream.pushIndentN(2); + try stream.pushIndentN(2); defer stream.popIndent(); for (asm_node.outputs) |*asm_output, i| { @@ -1996,7 +1999,7 @@ fn renderExpression( break :blk tree.nextToken(colon2); } else blk: { try renderToken(tree, stream, colon2, Space.Space); // : - stream.pushIndentN(2); + try stream.pushIndentN(2); defer stream.popIndent(); for (asm_node.inputs) |*asm_input, i| { if (i + 1 < asm_node.inputs.len) { @@ -2022,7 +2025,7 @@ fn renderExpression( }; try renderToken(tree, stream, colon3, Space.Space); // : - stream.pushIndentN(2); + try stream.pushIndentN(2); defer stream.popIndent(); for (asm_node.clobbers) |clobber_node, i| { if (i + 1 >= asm_node.clobbers.len) { @@ -2075,7 +2078,7 @@ fn renderArrayType( const new_space = if (ends_with_comment) Space.Newline else Space.None; { const do_indent = (starts_with_comment or ends_with_comment); - if (do_indent) stream.pushIndent(); + if (do_indent) try stream.pushIndent(); defer if (do_indent) stream.popIndent(); try renderToken(tree, stream, lbracket, Space.None); // [ @@ -2209,7 +2212,7 @@ fn renderVarDecl( if (var_decl.getTrailer("init_node")) |init_node| { const s = if (init_node.tag == .MultilineStringLiteral) Space.None else Space.Space; try renderToken(tree, stream, var_decl.getTrailer("eq_token").?, s); // = - stream.pushIndentOneShot(); + try stream.pushIndentOneShot(); try renderExpression(allocator, stream, tree, init_node, Space.None); } |
