Commit 070e548acf
Changed files (6)
lib/std/io/auto_indenting_stream.zig
@@ -1,154 +0,0 @@
-// SPDX-License-Identifier: MIT
-// Copyright (c) 2015-2021 Zig Contributors
-// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
-// The MIT license requires this copyright notice to be included in all copies
-// and substantial portions of the software.
-
-const std = @import("../std.zig");
-const io = std.io;
-const mem = std.mem;
-const assert = std.debug.assert;
-
-/// Automatically inserts indentation of written data by keeping
-/// track of the current indentation level
-pub fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
- return struct {
- const Self = @This();
- pub const Error = UnderlyingWriter.Error;
- pub const Writer = io.Writer(*Self, Error, write);
-
- underlying_writer: UnderlyingWriter,
-
- indent_count: usize = 0,
- indent_delta: usize,
- current_line_empty: bool = true,
- 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 writer(self: *Self) Writer {
- return .{ .context = self };
- }
-
- pub fn write(self: *Self, bytes: []const u8) Error!usize {
- if (bytes.len == 0)
- return @as(usize, 0);
-
- try self.applyIndent();
- return self.writeNoIndent(bytes);
- }
-
- // Change the indent delta without changing the final indentation level
- pub fn setIndentDelta(self: *Self, indent_delta: usize) void {
- if (self.indent_delta == indent_delta) {
- return;
- } else if (self.indent_delta > indent_delta) {
- assert(self.indent_delta % indent_delta == 0);
- self.indent_count = self.indent_count * (self.indent_delta / indent_delta);
- } else {
- // assert that the current indentation (in spaces) in a multiple of the new delta
- assert((self.indent_count * self.indent_delta) % indent_delta == 0);
- self.indent_count = self.indent_count / (indent_delta / self.indent_delta);
- }
- self.indent_delta = indent_delta;
- }
-
- fn writeNoIndent(self: *Self, bytes: []const u8) Error!usize {
- if (bytes.len == 0)
- return @as(usize, 0);
-
- try self.underlying_writer.writeAll(bytes);
- if (bytes[bytes.len - 1] == '\n')
- self.resetLine();
- return bytes.len;
- }
-
- pub fn insertNewline(self: *Self) Error!void {
- _ = try self.writeNoIndent("\n");
- }
-
- fn resetLine(self: *Self) void {
- self.current_line_empty = true;
- self.indent_next_line = 0;
- }
-
- /// Insert a newline unless the current line is blank
- pub fn maybeInsertNewline(self: *Self) Error!void {
- if (!self.current_line_empty)
- try self.insertNewline();
- }
-
- /// 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.indent_count += 1;
- }
-
- /// Push an indent that is automatically popped after being applied
- pub fn pushIndentOneShot(self: *Self) void {
- self.indent_one_shot_count += 1;
- 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) 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 {
- self.indent_next_line += 1;
- self.pushIndent();
- }
-
- pub fn popIndent(self: *Self) void {
- assert(self.indent_count != 0);
- self.indent_count -= 1;
-
- if (self.indent_next_line > 0)
- self.indent_next_line -= 1;
- }
-
- /// 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.underlying_writer.writeByteNTimes(' ', current_indent);
- self.applied_indent = current_indent;
- }
-
- self.indent_count -= self.indent_one_shot_count;
- self.indent_one_shot_count = 0;
- self.current_line_empty = false;
- }
-
- /// Checks to see if the most recent indentation exceeds the currently pushed indents
- pub fn isLineOverIndented(self: *Self) bool {
- if (self.current_line_empty) return false;
- return self.applied_indent > self.currentIndent();
- }
-
- fn currentIndent(self: *Self) usize {
- var indent_current: usize = 0;
- if (self.indent_count > 0) {
- const indent_count = self.indent_count - self.indent_next_line;
- indent_current = indent_count * self.indent_delta;
- }
- return indent_current;
- }
- };
-}
-
-pub fn autoIndentingStream(
- indent_delta: usize,
- underlying_writer: anytype,
-) AutoIndentingStream(@TypeOf(underlying_writer)) {
- return AutoIndentingStream(@TypeOf(underlying_writer)){
- .underlying_writer = underlying_writer,
- .indent_delta = indent_delta,
- };
-}
lib/std/zig/render.zig
@@ -15,12 +15,14 @@ const asm_indent_delta = 2;
pub const Error = ast.Tree.RenderError;
-const Writer = std.ArrayList(u8).Writer;
-const Ais = std.io.AutoIndentingStream(Writer);
+const Ais = AutoIndentingStream(std.ArrayList(u8).Writer);
pub fn renderTree(buffer: *std.ArrayList(u8), tree: ast.Tree) Error!void {
assert(tree.errors.len == 0); // Cannot render an invalid tree.
- var auto_indenting_stream = std.io.autoIndentingStream(indent_delta, buffer.writer());
+ var auto_indenting_stream = Ais{
+ .indent_delta = indent_delta,
+ .underlying_writer = buffer.writer(),
+ };
const ais = &auto_indenting_stream;
// Render all the line comments at the beginning of the file.
@@ -2132,3 +2134,137 @@ fn nodeCausesSliceOpSpace(tag: ast.Node.Tag) bool {
else => false,
};
}
+
+/// Automatically inserts indentation of written data by keeping
+/// track of the current indentation level
+fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
+ return struct {
+ const Self = @This();
+ pub const Error = UnderlyingWriter.Error;
+ pub const Writer = std.io.Writer(*Self, Error, write);
+
+ underlying_writer: UnderlyingWriter,
+
+ indent_count: usize = 0,
+ indent_delta: usize,
+ current_line_empty: bool = true,
+ 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 writer(self: *Self) Writer {
+ return .{ .context = self };
+ }
+
+ pub fn write(self: *Self, bytes: []const u8) Error!usize {
+ if (bytes.len == 0)
+ return @as(usize, 0);
+
+ try self.applyIndent();
+ return self.writeNoIndent(bytes);
+ }
+
+ // Change the indent delta without changing the final indentation level
+ pub fn setIndentDelta(self: *Self, new_indent_delta: usize) void {
+ if (self.indent_delta == new_indent_delta) {
+ return;
+ } else if (self.indent_delta > new_indent_delta) {
+ assert(self.indent_delta % new_indent_delta == 0);
+ self.indent_count = self.indent_count * (self.indent_delta / new_indent_delta);
+ } else {
+ // assert that the current indentation (in spaces) in a multiple of the new delta
+ assert((self.indent_count * self.indent_delta) % new_indent_delta == 0);
+ self.indent_count = self.indent_count / (new_indent_delta / self.indent_delta);
+ }
+ self.indent_delta = new_indent_delta;
+ }
+
+ fn writeNoIndent(self: *Self, bytes: []const u8) Error!usize {
+ if (bytes.len == 0)
+ return @as(usize, 0);
+
+ try self.underlying_writer.writeAll(bytes);
+ if (bytes[bytes.len - 1] == '\n')
+ self.resetLine();
+ return bytes.len;
+ }
+
+ pub fn insertNewline(self: *Self) Error!void {
+ _ = try self.writeNoIndent("\n");
+ }
+
+ fn resetLine(self: *Self) void {
+ self.current_line_empty = true;
+ self.indent_next_line = 0;
+ }
+
+ /// Insert a newline unless the current line is blank
+ pub fn maybeInsertNewline(self: *Self) Error!void {
+ if (!self.current_line_empty)
+ try self.insertNewline();
+ }
+
+ /// 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.indent_count += 1;
+ }
+
+ /// Push an indent that is automatically popped after being applied
+ pub fn pushIndentOneShot(self: *Self) void {
+ self.indent_one_shot_count += 1;
+ 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) 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 {
+ self.indent_next_line += 1;
+ self.pushIndent();
+ }
+
+ pub fn popIndent(self: *Self) void {
+ assert(self.indent_count != 0);
+ self.indent_count -= 1;
+
+ if (self.indent_next_line > 0)
+ self.indent_next_line -= 1;
+ }
+
+ /// 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.underlying_writer.writeByteNTimes(' ', current_indent);
+ self.applied_indent = current_indent;
+ }
+
+ self.indent_count -= self.indent_one_shot_count;
+ self.indent_one_shot_count = 0;
+ self.current_line_empty = false;
+ }
+
+ /// Checks to see if the most recent indentation exceeds the currently pushed indents
+ pub fn isLineOverIndented(self: *Self) bool {
+ if (self.current_line_empty) return false;
+ return self.applied_indent > self.currentIndent();
+ }
+
+ fn currentIndent(self: *Self) usize {
+ var indent_current: usize = 0;
+ if (self.indent_count > 0) {
+ const indent_count = self.indent_count - self.indent_next_line;
+ indent_current = indent_count * self.indent_delta;
+ }
+ return indent_current;
+ }
+ };
+}
lib/std/io.zig
@@ -142,9 +142,6 @@ pub const bitReader = @import("io/bit_reader.zig").bitReader;
pub const BitWriter = @import("io/bit_writer.zig").BitWriter;
pub const bitWriter = @import("io/bit_writer.zig").bitWriter;
-pub const AutoIndentingStream = @import("io/auto_indenting_stream.zig").AutoIndentingStream;
-pub const autoIndentingStream = @import("io/auto_indenting_stream.zig").autoIndentingStream;
-
pub const ChangeDetectionStream = @import("io/change_detection_stream.zig").ChangeDetectionStream;
pub const changeDetectionStream = @import("io/change_detection_stream.zig").changeDetectionStream;
src/codegen/c.zig
@@ -1,4 +1,5 @@
const std = @import("std");
+const assert = std.debug.assert;
const mem = std.mem;
const log = std.log.scoped(.c);
@@ -42,7 +43,7 @@ pub const Object = struct {
next_arg_index: usize = 0,
next_local_index: usize = 0,
next_block_index: usize = 0,
- indent_writer: std.io.AutoIndentingStream(std.ArrayList(u8).Writer),
+ indent_writer: IndentWriter(std.ArrayList(u8).Writer),
fn resolveInst(o: *Object, inst: *Inst) !CValue {
if (inst.value()) |_| {
@@ -63,7 +64,7 @@ pub const Object = struct {
return local_value;
}
- fn writer(o: *Object) std.io.AutoIndentingStream(std.ArrayList(u8).Writer).Writer {
+ fn writer(o: *Object) IndentWriter(std.ArrayList(u8).Writer).Writer {
return o.indent_writer.writer();
}
@@ -796,3 +797,56 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {
return o.dg.fail(o.dg.decl.src(), "TODO: C backend: inline asm expression result used", .{});
}
+
+fn IndentWriter(comptime UnderlyingWriter: type) type {
+ return struct {
+ const Self = @This();
+ pub const Error = UnderlyingWriter.Error;
+ pub const Writer = std.io.Writer(*Self, Error, write);
+
+ pub const indent_delta = 4;
+
+ underlying_writer: UnderlyingWriter,
+ indent_count: usize = 0,
+ current_line_empty: bool = true,
+
+ pub fn writer(self: *Self) Writer {
+ return .{ .context = self };
+ }
+
+ pub fn write(self: *Self, bytes: []const u8) Error!usize {
+ if (bytes.len == 0) return @as(usize, 0);
+
+ const current_indent = self.indent_count * Self.indent_delta;
+ if (self.current_line_empty and current_indent > 0) {
+ try self.underlying_writer.writeByteNTimes(' ', current_indent);
+ }
+ self.current_line_empty = false;
+
+ return self.writeNoIndent(bytes);
+ }
+
+ pub fn insertNewline(self: *Self) Error!void {
+ _ = try self.writeNoIndent("\n");
+ }
+
+ pub fn pushIndent(self: *Self) void {
+ self.indent_count += 1;
+ }
+
+ pub fn popIndent(self: *Self) void {
+ assert(self.indent_count != 0);
+ self.indent_count -= 1;
+ }
+
+ fn writeNoIndent(self: *Self, bytes: []const u8) Error!usize {
+ if (bytes.len == 0) return @as(usize, 0);
+
+ try self.underlying_writer.writeAll(bytes);
+ if (bytes[bytes.len - 1] == '\n') {
+ self.current_line_empty = true;
+ }
+ return bytes.len;
+ }
+ };
+}
src/link/C.zig
@@ -97,7 +97,7 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {
.value_map = codegen.CValueMap.init(module.gpa),
.indent_writer = undefined, // set later so we can get a pointer to object.code
};
- object.indent_writer = std.io.autoIndentingStream(4, object.code.writer());
+ object.indent_writer = .{ .underlying_writer = object.code.writer() };
defer object.value_map.deinit();
defer object.code.deinit();
defer object.dg.fwd_decl.deinit();
CMakeLists.txt
@@ -370,7 +370,6 @@ set(ZIG_STAGE2_SOURCES
"${CMAKE_SOURCE_DIR}/lib/std/heap.zig"
"${CMAKE_SOURCE_DIR}/lib/std/heap/arena_allocator.zig"
"${CMAKE_SOURCE_DIR}/lib/std/io.zig"
- "${CMAKE_SOURCE_DIR}/lib/std/io/auto_indenting_stream.zig"
"${CMAKE_SOURCE_DIR}/lib/std/io/buffered_atomic_file.zig"
"${CMAKE_SOURCE_DIR}/lib/std/io/buffered_writer.zig"
"${CMAKE_SOURCE_DIR}/lib/std/io/change_detection_stream.zig"