mirror of
https://github.com/ziglang/zig.git
synced 2025-12-16 19:23:08 +00:00
much of the compiler upgraded to new API
This commit is contained in:
parent
f3be721785
commit
bb1dffcf32
@ -125,9 +125,9 @@ pub const Options = struct {
|
|||||||
/// Verify that the server certificate is authorized by a given ca bundle.
|
/// Verify that the server certificate is authorized by a given ca bundle.
|
||||||
bundle: Certificate.Bundle,
|
bundle: Certificate.Bundle,
|
||||||
},
|
},
|
||||||
/// If non-null, ssl secrets are logged to this file. Creating such a log file allows
|
/// If non-null, ssl secrets are logged to this stream. Creating such a log file allows
|
||||||
/// other programs with access to that file to decrypt all traffic over this connection.
|
/// other programs with access to that file to decrypt all traffic over this connection.
|
||||||
ssl_key_log_file: ?std.fs.File = null,
|
ssl_key_log_file: ?*std.io.BufferedWriter = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn InitError(comptime Stream: type) type {
|
pub fn InitError(comptime Stream: type) type {
|
||||||
|
|||||||
@ -282,8 +282,6 @@ pub const Reader = GenericReader;
|
|||||||
pub const Writer = @import("io/Writer.zig");
|
pub const Writer = @import("io/Writer.zig");
|
||||||
|
|
||||||
pub const AnyReader = @import("io/Reader.zig");
|
pub const AnyReader = @import("io/Reader.zig");
|
||||||
/// Deprecated; to be removed after 0.14.0 is tagged.
|
|
||||||
pub const AnyWriter = Writer;
|
|
||||||
|
|
||||||
pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;
|
pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;
|
||||||
|
|
||||||
|
|||||||
@ -663,9 +663,14 @@ pub fn printValue(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
.error_set => {
|
.error_set => {
|
||||||
if (actual_fmt.len != 0) invalidFmtError(fmt, value);
|
if (actual_fmt.len > 0 and actual_fmt.len[0] == 's') {
|
||||||
|
return bw.writeAll(@errorName(value));
|
||||||
|
} else if (actual_fmt.len != 0) {
|
||||||
|
invalidFmtError(fmt, value);
|
||||||
|
} else {
|
||||||
try bw.writeAll("error.");
|
try bw.writeAll("error.");
|
||||||
return bw.writeAll(@errorName(value));
|
return bw.writeAll(@errorName(value));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
.@"enum" => |enumInfo| {
|
.@"enum" => |enumInfo| {
|
||||||
try bw.writeAll(@typeName(T));
|
try bw.writeAll(@typeName(T));
|
||||||
|
|||||||
@ -603,9 +603,10 @@ fn PaxIterator(comptime ReaderType: type) type {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readUntil(self: *Self, delimiter: u8) ![]const u8 {
|
fn readUntil(self: *Self, delimiter: u8) anyerror![]const u8 {
|
||||||
var fbs: std.io.FixedBufferStream = .{ .buffer = &self.scratch };
|
var fbs: std.io.BufferedWriter = undefined;
|
||||||
try self.reader.streamUntilDelimiter(fbs.writer(), delimiter, null);
|
fbs.initFixed(&self.scratch);
|
||||||
|
try self.reader.streamUntilDelimiter(&fbs, delimiter, null);
|
||||||
return fbs.getWritten();
|
return fbs.getWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -199,27 +199,24 @@ pub fn parse(gpa: Allocator, source: [:0]const u8, mode: Mode) Allocator.Error!A
|
|||||||
|
|
||||||
/// `gpa` is used for allocating the resulting formatted source code.
|
/// `gpa` is used for allocating the resulting formatted source code.
|
||||||
/// Caller owns the returned slice of bytes, allocated with `gpa`.
|
/// Caller owns the returned slice of bytes, allocated with `gpa`.
|
||||||
pub fn render(tree: Ast, gpa: Allocator) RenderError![]u8 {
|
pub fn renderAlloc(tree: Ast, gpa: Allocator) RenderError![]u8 {
|
||||||
var buffer = std.ArrayList(u8).init(gpa);
|
var aw: std.io.AllocatingWriter = undefined;
|
||||||
defer buffer.deinit();
|
const bw = aw.init(gpa);
|
||||||
|
errdefer aw.deinit();
|
||||||
|
render(tree, gpa, bw, .{}) catch |err| return @errorCast(err); // TODO try @errorCast(...)
|
||||||
|
return aw.toOwnedSlice();
|
||||||
|
}
|
||||||
|
|
||||||
try tree.renderToArrayList(&buffer, .{});
|
pub fn render(tree: Ast, gpa: Allocator, bw: *std.io.BufferedWriter, fixups: Fixups) anyerror!void {
|
||||||
return buffer.toOwnedSlice();
|
return @import("./render.zig").renderTree(gpa, bw, tree, fixups);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const Fixups = private_render.Fixups;
|
pub const Fixups = private_render.Fixups;
|
||||||
|
|
||||||
pub fn renderToArrayList(tree: Ast, buffer: *std.ArrayList(u8), fixups: Fixups) RenderError!void {
|
|
||||||
return @import("./render.zig").renderTree(buffer, tree, fixups);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an extra offset for column and byte offset of errors that
|
/// Returns an extra offset for column and byte offset of errors that
|
||||||
/// should point after the token in the error message.
|
/// should point after the token in the error message.
|
||||||
pub fn errorOffset(tree: Ast, parse_error: Error) u32 {
|
pub fn errorOffset(tree: Ast, parse_error: Error) u32 {
|
||||||
return if (parse_error.token_is_prev)
|
return if (parse_error.token_is_prev) @intCast(tree.tokenSlice(parse_error.token).len) else 0;
|
||||||
@as(u32, @intCast(tree.tokenSlice(parse_error.token).len))
|
|
||||||
else
|
|
||||||
0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tokenLocation(self: Ast, start_offset: ByteOffset, token_index: TokenIndex) Location {
|
pub fn tokenLocation(self: Ast, start_offset: ByteOffset, token_index: TokenIndex) Location {
|
||||||
@ -318,254 +315,254 @@ pub fn rootDecls(tree: Ast) []const Node.Index {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
|
pub fn renderError(tree: Ast, parse_error: Error, bw: *std.io.BufferedWriter) anyerror!void {
|
||||||
switch (parse_error.tag) {
|
switch (parse_error.tag) {
|
||||||
.asterisk_after_ptr_deref => {
|
.asterisk_after_ptr_deref => {
|
||||||
// Note that the token will point at the `.*` but ideally the source
|
// Note that the token will point at the `.*` but ideally the source
|
||||||
// location would point to the `*` after the `.*`.
|
// location would point to the `*` after the `.*`.
|
||||||
return stream.writeAll("'.*' cannot be followed by '*'; are you missing a space?");
|
return bw.writeAll("'.*' cannot be followed by '*'; are you missing a space?");
|
||||||
},
|
},
|
||||||
.chained_comparison_operators => {
|
.chained_comparison_operators => {
|
||||||
return stream.writeAll("comparison operators cannot be chained");
|
return bw.writeAll("comparison operators cannot be chained");
|
||||||
},
|
},
|
||||||
.decl_between_fields => {
|
.decl_between_fields => {
|
||||||
return stream.writeAll("declarations are not allowed between container fields");
|
return bw.writeAll("declarations are not allowed between container fields");
|
||||||
},
|
},
|
||||||
.expected_block => {
|
.expected_block => {
|
||||||
return stream.print("expected block, found '{s}'", .{
|
return bw.print("expected block, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_block_or_assignment => {
|
.expected_block_or_assignment => {
|
||||||
return stream.print("expected block or assignment, found '{s}'", .{
|
return bw.print("expected block or assignment, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_block_or_expr => {
|
.expected_block_or_expr => {
|
||||||
return stream.print("expected block or expression, found '{s}'", .{
|
return bw.print("expected block or expression, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_block_or_field => {
|
.expected_block_or_field => {
|
||||||
return stream.print("expected block or field, found '{s}'", .{
|
return bw.print("expected block or field, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_container_members => {
|
.expected_container_members => {
|
||||||
return stream.print("expected test, comptime, var decl, or container field, found '{s}'", .{
|
return bw.print("expected test, comptime, var decl, or container field, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token).symbol(),
|
tree.tokenTag(parse_error.token).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_expr => {
|
.expected_expr => {
|
||||||
return stream.print("expected expression, found '{s}'", .{
|
return bw.print("expected expression, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_expr_or_assignment => {
|
.expected_expr_or_assignment => {
|
||||||
return stream.print("expected expression or assignment, found '{s}'", .{
|
return bw.print("expected expression or assignment, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_expr_or_var_decl => {
|
.expected_expr_or_var_decl => {
|
||||||
return stream.print("expected expression or var decl, found '{s}'", .{
|
return bw.print("expected expression or var decl, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_fn => {
|
.expected_fn => {
|
||||||
return stream.print("expected function, found '{s}'", .{
|
return bw.print("expected function, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_inlinable => {
|
.expected_inlinable => {
|
||||||
return stream.print("expected 'while' or 'for', found '{s}'", .{
|
return bw.print("expected 'while' or 'for', found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_labelable => {
|
.expected_labelable => {
|
||||||
return stream.print("expected 'while', 'for', 'inline', or '{{', found '{s}'", .{
|
return bw.print("expected 'while', 'for', 'inline', or '{{', found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_param_list => {
|
.expected_param_list => {
|
||||||
return stream.print("expected parameter list, found '{s}'", .{
|
return bw.print("expected parameter list, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_prefix_expr => {
|
.expected_prefix_expr => {
|
||||||
return stream.print("expected prefix expression, found '{s}'", .{
|
return bw.print("expected prefix expression, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_primary_type_expr => {
|
.expected_primary_type_expr => {
|
||||||
return stream.print("expected primary type expression, found '{s}'", .{
|
return bw.print("expected primary type expression, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_pub_item => {
|
.expected_pub_item => {
|
||||||
return stream.writeAll("expected function or variable declaration after pub");
|
return bw.writeAll("expected function or variable declaration after pub");
|
||||||
},
|
},
|
||||||
.expected_return_type => {
|
.expected_return_type => {
|
||||||
return stream.print("expected return type expression, found '{s}'", .{
|
return bw.print("expected return type expression, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_semi_or_else => {
|
.expected_semi_or_else => {
|
||||||
return stream.writeAll("expected ';' or 'else' after statement");
|
return bw.writeAll("expected ';' or 'else' after statement");
|
||||||
},
|
},
|
||||||
.expected_semi_or_lbrace => {
|
.expected_semi_or_lbrace => {
|
||||||
return stream.writeAll("expected ';' or block after function prototype");
|
return bw.writeAll("expected ';' or block after function prototype");
|
||||||
},
|
},
|
||||||
.expected_statement => {
|
.expected_statement => {
|
||||||
return stream.print("expected statement, found '{s}'", .{
|
return bw.print("expected statement, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token).symbol(),
|
tree.tokenTag(parse_error.token).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_suffix_op => {
|
.expected_suffix_op => {
|
||||||
return stream.print("expected pointer dereference, optional unwrap, or field access, found '{s}'", .{
|
return bw.print("expected pointer dereference, optional unwrap, or field access, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_type_expr => {
|
.expected_type_expr => {
|
||||||
return stream.print("expected type expression, found '{s}'", .{
|
return bw.print("expected type expression, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_var_decl => {
|
.expected_var_decl => {
|
||||||
return stream.print("expected variable declaration, found '{s}'", .{
|
return bw.print("expected variable declaration, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_var_decl_or_fn => {
|
.expected_var_decl_or_fn => {
|
||||||
return stream.print("expected variable declaration or function, found '{s}'", .{
|
return bw.print("expected variable declaration or function, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_loop_payload => {
|
.expected_loop_payload => {
|
||||||
return stream.print("expected loop payload, found '{s}'", .{
|
return bw.print("expected loop payload, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.expected_container => {
|
.expected_container => {
|
||||||
return stream.print("expected a struct, enum or union, found '{s}'", .{
|
return bw.print("expected a struct, enum or union, found '{s}'", .{
|
||||||
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev)).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.extern_fn_body => {
|
.extern_fn_body => {
|
||||||
return stream.writeAll("extern functions have no body");
|
return bw.writeAll("extern functions have no body");
|
||||||
},
|
},
|
||||||
.extra_addrspace_qualifier => {
|
.extra_addrspace_qualifier => {
|
||||||
return stream.writeAll("extra addrspace qualifier");
|
return bw.writeAll("extra addrspace qualifier");
|
||||||
},
|
},
|
||||||
.extra_align_qualifier => {
|
.extra_align_qualifier => {
|
||||||
return stream.writeAll("extra align qualifier");
|
return bw.writeAll("extra align qualifier");
|
||||||
},
|
},
|
||||||
.extra_allowzero_qualifier => {
|
.extra_allowzero_qualifier => {
|
||||||
return stream.writeAll("extra allowzero qualifier");
|
return bw.writeAll("extra allowzero qualifier");
|
||||||
},
|
},
|
||||||
.extra_const_qualifier => {
|
.extra_const_qualifier => {
|
||||||
return stream.writeAll("extra const qualifier");
|
return bw.writeAll("extra const qualifier");
|
||||||
},
|
},
|
||||||
.extra_volatile_qualifier => {
|
.extra_volatile_qualifier => {
|
||||||
return stream.writeAll("extra volatile qualifier");
|
return bw.writeAll("extra volatile qualifier");
|
||||||
},
|
},
|
||||||
.ptr_mod_on_array_child_type => {
|
.ptr_mod_on_array_child_type => {
|
||||||
return stream.print("pointer modifier '{s}' not allowed on array child type", .{
|
return bw.print("pointer modifier '{s}' not allowed on array child type", .{
|
||||||
tree.tokenTag(parse_error.token).symbol(),
|
tree.tokenTag(parse_error.token).symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.invalid_bit_range => {
|
.invalid_bit_range => {
|
||||||
return stream.writeAll("bit range not allowed on slices and arrays");
|
return bw.writeAll("bit range not allowed on slices and arrays");
|
||||||
},
|
},
|
||||||
.same_line_doc_comment => {
|
.same_line_doc_comment => {
|
||||||
return stream.writeAll("same line documentation comment");
|
return bw.writeAll("same line documentation comment");
|
||||||
},
|
},
|
||||||
.unattached_doc_comment => {
|
.unattached_doc_comment => {
|
||||||
return stream.writeAll("unattached documentation comment");
|
return bw.writeAll("unattached documentation comment");
|
||||||
},
|
},
|
||||||
.test_doc_comment => {
|
.test_doc_comment => {
|
||||||
return stream.writeAll("documentation comments cannot be attached to tests");
|
return bw.writeAll("documentation comments cannot be attached to tests");
|
||||||
},
|
},
|
||||||
.comptime_doc_comment => {
|
.comptime_doc_comment => {
|
||||||
return stream.writeAll("documentation comments cannot be attached to comptime blocks");
|
return bw.writeAll("documentation comments cannot be attached to comptime blocks");
|
||||||
},
|
},
|
||||||
.varargs_nonfinal => {
|
.varargs_nonfinal => {
|
||||||
return stream.writeAll("function prototype has parameter after varargs");
|
return bw.writeAll("function prototype has parameter after varargs");
|
||||||
},
|
},
|
||||||
.expected_continue_expr => {
|
.expected_continue_expr => {
|
||||||
return stream.writeAll("expected ':' before while continue expression");
|
return bw.writeAll("expected ':' before while continue expression");
|
||||||
},
|
},
|
||||||
|
|
||||||
.expected_semi_after_decl => {
|
.expected_semi_after_decl => {
|
||||||
return stream.writeAll("expected ';' after declaration");
|
return bw.writeAll("expected ';' after declaration");
|
||||||
},
|
},
|
||||||
.expected_semi_after_stmt => {
|
.expected_semi_after_stmt => {
|
||||||
return stream.writeAll("expected ';' after statement");
|
return bw.writeAll("expected ';' after statement");
|
||||||
},
|
},
|
||||||
.expected_comma_after_field => {
|
.expected_comma_after_field => {
|
||||||
return stream.writeAll("expected ',' after field");
|
return bw.writeAll("expected ',' after field");
|
||||||
},
|
},
|
||||||
.expected_comma_after_arg => {
|
.expected_comma_after_arg => {
|
||||||
return stream.writeAll("expected ',' after argument");
|
return bw.writeAll("expected ',' after argument");
|
||||||
},
|
},
|
||||||
.expected_comma_after_param => {
|
.expected_comma_after_param => {
|
||||||
return stream.writeAll("expected ',' after parameter");
|
return bw.writeAll("expected ',' after parameter");
|
||||||
},
|
},
|
||||||
.expected_comma_after_initializer => {
|
.expected_comma_after_initializer => {
|
||||||
return stream.writeAll("expected ',' after initializer");
|
return bw.writeAll("expected ',' after initializer");
|
||||||
},
|
},
|
||||||
.expected_comma_after_switch_prong => {
|
.expected_comma_after_switch_prong => {
|
||||||
return stream.writeAll("expected ',' after switch prong");
|
return bw.writeAll("expected ',' after switch prong");
|
||||||
},
|
},
|
||||||
.expected_comma_after_for_operand => {
|
.expected_comma_after_for_operand => {
|
||||||
return stream.writeAll("expected ',' after for operand");
|
return bw.writeAll("expected ',' after for operand");
|
||||||
},
|
},
|
||||||
.expected_comma_after_capture => {
|
.expected_comma_after_capture => {
|
||||||
return stream.writeAll("expected ',' after for capture");
|
return bw.writeAll("expected ',' after for capture");
|
||||||
},
|
},
|
||||||
.expected_initializer => {
|
.expected_initializer => {
|
||||||
return stream.writeAll("expected field initializer");
|
return bw.writeAll("expected field initializer");
|
||||||
},
|
},
|
||||||
.mismatched_binary_op_whitespace => {
|
.mismatched_binary_op_whitespace => {
|
||||||
return stream.print("binary operator '{s}' has whitespace on one side, but not the other", .{tree.tokenTag(parse_error.token).lexeme().?});
|
return bw.print("binary operator '{s}' has whitespace on one side, but not the other", .{tree.tokenTag(parse_error.token).lexeme().?});
|
||||||
},
|
},
|
||||||
.invalid_ampersand_ampersand => {
|
.invalid_ampersand_ampersand => {
|
||||||
return stream.writeAll("ambiguous use of '&&'; use 'and' for logical AND, or change whitespace to ' & &' for bitwise AND");
|
return bw.writeAll("ambiguous use of '&&'; use 'and' for logical AND, or change whitespace to ' & &' for bitwise AND");
|
||||||
},
|
},
|
||||||
.c_style_container => {
|
.c_style_container => {
|
||||||
return stream.print("'{s} {s}' is invalid", .{
|
return bw.print("'{s} {s}' is invalid", .{
|
||||||
parse_error.extra.expected_tag.symbol(), tree.tokenSlice(parse_error.token),
|
parse_error.extra.expected_tag.symbol(), tree.tokenSlice(parse_error.token),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.zig_style_container => {
|
.zig_style_container => {
|
||||||
return stream.print("to declare a container do 'const {s} = {s}'", .{
|
return bw.print("to declare a container do 'const {s} = {s}'", .{
|
||||||
tree.tokenSlice(parse_error.token), parse_error.extra.expected_tag.symbol(),
|
tree.tokenSlice(parse_error.token), parse_error.extra.expected_tag.symbol(),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.previous_field => {
|
.previous_field => {
|
||||||
return stream.writeAll("field before declarations here");
|
return bw.writeAll("field before declarations here");
|
||||||
},
|
},
|
||||||
.next_field => {
|
.next_field => {
|
||||||
return stream.writeAll("field after declarations here");
|
return bw.writeAll("field after declarations here");
|
||||||
},
|
},
|
||||||
.expected_var_const => {
|
.expected_var_const => {
|
||||||
return stream.writeAll("expected 'var' or 'const' before variable declaration");
|
return bw.writeAll("expected 'var' or 'const' before variable declaration");
|
||||||
},
|
},
|
||||||
.wrong_equal_var_decl => {
|
.wrong_equal_var_decl => {
|
||||||
return stream.writeAll("variable initialized with '==' instead of '='");
|
return bw.writeAll("variable initialized with '==' instead of '='");
|
||||||
},
|
},
|
||||||
.var_const_decl => {
|
.var_const_decl => {
|
||||||
return stream.writeAll("use 'var' or 'const' to declare variable");
|
return bw.writeAll("use 'var' or 'const' to declare variable");
|
||||||
},
|
},
|
||||||
.extra_for_capture => {
|
.extra_for_capture => {
|
||||||
return stream.writeAll("extra capture in for loop");
|
return bw.writeAll("extra capture in for loop");
|
||||||
},
|
},
|
||||||
.for_input_not_captured => {
|
.for_input_not_captured => {
|
||||||
return stream.writeAll("for input is not captured");
|
return bw.writeAll("for input is not captured");
|
||||||
},
|
},
|
||||||
|
|
||||||
.invalid_byte => {
|
.invalid_byte => {
|
||||||
const tok_slice = tree.source[tree.tokens.items(.start)[parse_error.token]..];
|
const tok_slice = tree.source[tree.tokens.items(.start)[parse_error.token]..];
|
||||||
return stream.print("{s} contains invalid byte: '{'}'", .{
|
return bw.print("{s} contains invalid byte: '{'}'", .{
|
||||||
switch (tok_slice[0]) {
|
switch (tok_slice[0]) {
|
||||||
'\'' => "character literal",
|
'\'' => "character literal",
|
||||||
'"', '\\' => "string literal",
|
'"', '\\' => "string literal",
|
||||||
@ -580,10 +577,10 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
|
|||||||
const found_tag = tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev));
|
const found_tag = tree.tokenTag(parse_error.token + @intFromBool(parse_error.token_is_prev));
|
||||||
const expected_symbol = parse_error.extra.expected_tag.symbol();
|
const expected_symbol = parse_error.extra.expected_tag.symbol();
|
||||||
switch (found_tag) {
|
switch (found_tag) {
|
||||||
.invalid => return stream.print("expected '{s}', found invalid bytes", .{
|
.invalid => return bw.print("expected '{s}', found invalid bytes", .{
|
||||||
expected_symbol,
|
expected_symbol,
|
||||||
}),
|
}),
|
||||||
else => return stream.print("expected '{s}', found '{s}'", .{
|
else => return bw.print("expected '{s}', found '{s}'", .{
|
||||||
expected_symbol, found_tag.symbol(),
|
expected_symbol, found_tag.symbol(),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11441,10 +11441,13 @@ fn parseStrLit(
|
|||||||
offset: u32,
|
offset: u32,
|
||||||
) InnerError!void {
|
) InnerError!void {
|
||||||
const raw_string = bytes[offset..];
|
const raw_string = bytes[offset..];
|
||||||
var buf_managed = buf.toManaged(astgen.gpa);
|
const result = r: {
|
||||||
const result = std.zig.string_literal.parseWrite(buf_managed.writer(), raw_string);
|
var aw: std.io.AllocatingWriter = undefined;
|
||||||
buf.* = buf_managed.moveToUnmanaged();
|
const bw = aw.fromArrayList(astgen.gpa, buf);
|
||||||
switch (try result) {
|
defer buf.* = aw.toArrayList();
|
||||||
|
break :r std.zig.string_literal.parseWrite(bw, raw_string) catch |err| return @errorCast(err);
|
||||||
|
};
|
||||||
|
switch (result) {
|
||||||
.success => return,
|
.success => return,
|
||||||
.failure => |err| return astgen.failWithStrLitError(err, token, bytes, offset),
|
.failure => |err| return astgen.failWithStrLitError(err, token, bytes, offset),
|
||||||
}
|
}
|
||||||
@ -11493,17 +11496,18 @@ fn appendErrorNodeNotes(
|
|||||||
notes: []const u32,
|
notes: []const u32,
|
||||||
) Allocator.Error!void {
|
) Allocator.Error!void {
|
||||||
@branchHint(.cold);
|
@branchHint(.cold);
|
||||||
|
const gpa = astgen.gpa;
|
||||||
const string_bytes = &astgen.string_bytes;
|
const string_bytes = &astgen.string_bytes;
|
||||||
const msg: Zir.NullTerminatedString = @enumFromInt(string_bytes.items.len);
|
const msg: Zir.NullTerminatedString = @enumFromInt(string_bytes.items.len);
|
||||||
try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args);
|
try string_bytes.print(gpa, format ++ "\x00", args);
|
||||||
const notes_index: u32 = if (notes.len != 0) blk: {
|
const notes_index: u32 = if (notes.len != 0) blk: {
|
||||||
const notes_start = astgen.extra.items.len;
|
const notes_start = astgen.extra.items.len;
|
||||||
try astgen.extra.ensureTotalCapacity(astgen.gpa, notes_start + 1 + notes.len);
|
try astgen.extra.ensureTotalCapacity(gpa, notes_start + 1 + notes.len);
|
||||||
astgen.extra.appendAssumeCapacity(@intCast(notes.len));
|
astgen.extra.appendAssumeCapacity(@intCast(notes.len));
|
||||||
astgen.extra.appendSliceAssumeCapacity(notes);
|
astgen.extra.appendSliceAssumeCapacity(notes);
|
||||||
break :blk @intCast(notes_start);
|
break :blk @intCast(notes_start);
|
||||||
} else 0;
|
} else 0;
|
||||||
try astgen.compile_errors.append(astgen.gpa, .{
|
try astgen.compile_errors.append(gpa, .{
|
||||||
.msg = msg,
|
.msg = msg,
|
||||||
.node = node.toOptional(),
|
.node = node.toOptional(),
|
||||||
.token = .none,
|
.token = .none,
|
||||||
@ -11587,7 +11591,7 @@ fn appendErrorTokNotesOff(
|
|||||||
const gpa = astgen.gpa;
|
const gpa = astgen.gpa;
|
||||||
const string_bytes = &astgen.string_bytes;
|
const string_bytes = &astgen.string_bytes;
|
||||||
const msg: Zir.NullTerminatedString = @enumFromInt(string_bytes.items.len);
|
const msg: Zir.NullTerminatedString = @enumFromInt(string_bytes.items.len);
|
||||||
try string_bytes.writer(gpa).print(format ++ "\x00", args);
|
try string_bytes.print(gpa, format ++ "\x00", args);
|
||||||
const notes_index: u32 = if (notes.len != 0) blk: {
|
const notes_index: u32 = if (notes.len != 0) blk: {
|
||||||
const notes_start = astgen.extra.items.len;
|
const notes_start = astgen.extra.items.len;
|
||||||
try astgen.extra.ensureTotalCapacity(gpa, notes_start + 1 + notes.len);
|
try astgen.extra.ensureTotalCapacity(gpa, notes_start + 1 + notes.len);
|
||||||
@ -11623,7 +11627,7 @@ fn errNoteTokOff(
|
|||||||
@branchHint(.cold);
|
@branchHint(.cold);
|
||||||
const string_bytes = &astgen.string_bytes;
|
const string_bytes = &astgen.string_bytes;
|
||||||
const msg: Zir.NullTerminatedString = @enumFromInt(string_bytes.items.len);
|
const msg: Zir.NullTerminatedString = @enumFromInt(string_bytes.items.len);
|
||||||
try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args);
|
try string_bytes.print(astgen.gpa, format ++ "\x00", args);
|
||||||
return astgen.addExtra(Zir.Inst.CompileErrors.Item{
|
return astgen.addExtra(Zir.Inst.CompileErrors.Item{
|
||||||
.msg = msg,
|
.msg = msg,
|
||||||
.node = .none,
|
.node = .none,
|
||||||
@ -11642,7 +11646,7 @@ fn errNoteNode(
|
|||||||
@branchHint(.cold);
|
@branchHint(.cold);
|
||||||
const string_bytes = &astgen.string_bytes;
|
const string_bytes = &astgen.string_bytes;
|
||||||
const msg: Zir.NullTerminatedString = @enumFromInt(string_bytes.items.len);
|
const msg: Zir.NullTerminatedString = @enumFromInt(string_bytes.items.len);
|
||||||
try string_bytes.writer(astgen.gpa).print(format ++ "\x00", args);
|
try string_bytes.print(astgen.gpa, format ++ "\x00", args);
|
||||||
return astgen.addExtra(Zir.Inst.CompileErrors.Item{
|
return astgen.addExtra(Zir.Inst.CompileErrors.Item{
|
||||||
.msg = msg,
|
.msg = msg,
|
||||||
.node = node.toOptional(),
|
.node = node.toOptional(),
|
||||||
@ -13888,13 +13892,14 @@ fn emitDbgStmtForceCurrentIndex(gz: *GenZir, lc: LineColumn) !void {
|
|||||||
} });
|
} });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lowerAstErrors(astgen: *AstGen) !void {
|
fn lowerAstErrors(astgen: *AstGen) error{OutOfMemory}!void {
|
||||||
const gpa = astgen.gpa;
|
const gpa = astgen.gpa;
|
||||||
const tree = astgen.tree;
|
const tree = astgen.tree;
|
||||||
assert(tree.errors.len > 0);
|
assert(tree.errors.len > 0);
|
||||||
|
|
||||||
var msg: std.ArrayListUnmanaged(u8) = .empty;
|
var msg: std.io.AllocatingWriter = undefined;
|
||||||
defer msg.deinit(gpa);
|
const msg_writer = msg.init(gpa);
|
||||||
|
defer msg.deinit();
|
||||||
|
|
||||||
var notes: std.ArrayListUnmanaged(u32) = .empty;
|
var notes: std.ArrayListUnmanaged(u32) = .empty;
|
||||||
defer notes.deinit(gpa);
|
defer notes.deinit(gpa);
|
||||||
@ -13928,20 +13933,20 @@ fn lowerAstErrors(astgen: *AstGen) !void {
|
|||||||
.extra = .{ .offset = bad_off },
|
.extra = .{ .offset = bad_off },
|
||||||
};
|
};
|
||||||
msg.clearRetainingCapacity();
|
msg.clearRetainingCapacity();
|
||||||
try tree.renderError(err, msg.writer(gpa));
|
tree.renderError(err, msg_writer) catch |e| return @errorCast(e); // TODO try @errorCast(...)
|
||||||
return try astgen.appendErrorTokNotesOff(tok, bad_off, "{s}", .{msg.items}, notes.items);
|
return try astgen.appendErrorTokNotesOff(tok, bad_off, "{s}", .{msg.getWritten()}, notes.items);
|
||||||
}
|
}
|
||||||
|
|
||||||
var cur_err = tree.errors[0];
|
var cur_err = tree.errors[0];
|
||||||
for (tree.errors[1..]) |err| {
|
for (tree.errors[1..]) |err| {
|
||||||
if (err.is_note) {
|
if (err.is_note) {
|
||||||
try tree.renderError(err, msg.writer(gpa));
|
tree.renderError(err, msg_writer) catch |e| return @errorCast(e); // TODO try @errorCast(...)
|
||||||
try notes.append(gpa, try astgen.errNoteTok(err.token, "{s}", .{msg.items}));
|
try notes.append(gpa, try astgen.errNoteTok(err.token, "{s}", .{msg.getWritten()}));
|
||||||
} else {
|
} else {
|
||||||
// Flush error
|
// Flush error
|
||||||
const extra_offset = tree.errorOffset(cur_err);
|
const extra_offset = tree.errorOffset(cur_err);
|
||||||
try tree.renderError(cur_err, msg.writer(gpa));
|
tree.renderError(cur_err, msg_writer) catch |e| return @errorCast(e); // TODO try @errorCast(...)
|
||||||
try astgen.appendErrorTokNotesOff(cur_err.token, extra_offset, "{s}", .{msg.items}, notes.items);
|
try astgen.appendErrorTokNotesOff(cur_err.token, extra_offset, "{s}", .{msg.getWritten()}, notes.items);
|
||||||
notes.clearRetainingCapacity();
|
notes.clearRetainingCapacity();
|
||||||
cur_err = err;
|
cur_err = err;
|
||||||
|
|
||||||
@ -13954,8 +13959,8 @@ fn lowerAstErrors(astgen: *AstGen) !void {
|
|||||||
|
|
||||||
// Flush error
|
// Flush error
|
||||||
const extra_offset = tree.errorOffset(cur_err);
|
const extra_offset = tree.errorOffset(cur_err);
|
||||||
try tree.renderError(cur_err, msg.writer(gpa));
|
tree.renderError(cur_err, msg_writer) catch |e| return @errorCast(e); // TODO try @errorCast(...)
|
||||||
try astgen.appendErrorTokNotesOff(cur_err.token, extra_offset, "{s}", .{msg.items}, notes.items);
|
try astgen.appendErrorTokNotesOff(cur_err.token, extra_offset, "{s}", .{msg.getWritten()}, notes.items);
|
||||||
}
|
}
|
||||||
|
|
||||||
const DeclarationName = union(enum) {
|
const DeclarationName = union(enum) {
|
||||||
|
|||||||
@ -452,20 +452,27 @@ fn expr(zg: *ZonGen, node: Ast.Node.Index, dest_node: Zoir.Node.Index) Allocator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn appendIdentStr(zg: *ZonGen, ident_token: Ast.TokenIndex) !u32 {
|
fn appendIdentStr(zg: *ZonGen, ident_token: Ast.TokenIndex) error{ OutOfMemory, BadString }!u32 {
|
||||||
|
const gpa = zg.gpa;
|
||||||
const tree = zg.tree;
|
const tree = zg.tree;
|
||||||
assert(tree.tokenTag(ident_token) == .identifier);
|
assert(tree.tokenTag(ident_token) == .identifier);
|
||||||
const ident_name = tree.tokenSlice(ident_token);
|
const ident_name = tree.tokenSlice(ident_token);
|
||||||
if (!mem.startsWith(u8, ident_name, "@")) {
|
if (!mem.startsWith(u8, ident_name, "@")) {
|
||||||
const start = zg.string_bytes.items.len;
|
const start = zg.string_bytes.items.len;
|
||||||
try zg.string_bytes.appendSlice(zg.gpa, ident_name);
|
try zg.string_bytes.appendSlice(gpa, ident_name);
|
||||||
return @intCast(start);
|
return @intCast(start);
|
||||||
} else {
|
}
|
||||||
const offset = 1;
|
const offset = 1;
|
||||||
const start: u32 = @intCast(zg.string_bytes.items.len);
|
const start: u32 = @intCast(zg.string_bytes.items.len);
|
||||||
const raw_string = zg.tree.tokenSlice(ident_token)[offset..];
|
const raw_string = zg.tree.tokenSlice(ident_token)[offset..];
|
||||||
try zg.string_bytes.ensureUnusedCapacity(zg.gpa, raw_string.len);
|
try zg.string_bytes.ensureUnusedCapacity(gpa, raw_string.len);
|
||||||
switch (try std.zig.string_literal.parseWrite(zg.string_bytes.writer(zg.gpa), raw_string)) {
|
const result = r: {
|
||||||
|
var aw: std.io.AllocatingWriter = undefined;
|
||||||
|
const bw = aw.fromArrayList(gpa, &zg.string_bytes);
|
||||||
|
defer zg.string_bytes = aw.toArrayList();
|
||||||
|
break :r std.zig.string_literal.parseWrite(bw, raw_string) catch |err| return @errorCast(err);
|
||||||
|
};
|
||||||
|
switch (result) {
|
||||||
.success => {},
|
.success => {},
|
||||||
.failure => |err| {
|
.failure => |err| {
|
||||||
try zg.lowerStrLitError(err, ident_token, raw_string, offset);
|
try zg.lowerStrLitError(err, ident_token, raw_string, offset);
|
||||||
@ -482,7 +489,6 @@ fn appendIdentStr(zg: *ZonGen, ident_token: Ast.TokenIndex) !u32 {
|
|||||||
return error.BadString;
|
return error.BadString;
|
||||||
}
|
}
|
||||||
return start;
|
return start;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Estimates the size of a string node without parsing it.
|
/// Estimates the size of a string node without parsing it.
|
||||||
@ -513,8 +519,8 @@ pub fn strLitSizeHint(tree: Ast, node: Ast.Node.Index) usize {
|
|||||||
pub fn parseStrLit(
|
pub fn parseStrLit(
|
||||||
tree: Ast,
|
tree: Ast,
|
||||||
node: Ast.Node.Index,
|
node: Ast.Node.Index,
|
||||||
writer: anytype,
|
writer: *std.io.BufferedWriter,
|
||||||
) error{OutOfMemory}!std.zig.string_literal.Result {
|
) anyerror!std.zig.string_literal.Result {
|
||||||
switch (tree.nodeTag(node)) {
|
switch (tree.nodeTag(node)) {
|
||||||
.string_literal => {
|
.string_literal => {
|
||||||
const token = tree.nodeMainToken(node);
|
const token = tree.nodeMainToken(node);
|
||||||
@ -549,15 +555,21 @@ const StringLiteralResult = union(enum) {
|
|||||||
slice: struct { start: u32, len: u32 },
|
slice: struct { start: u32, len: u32 },
|
||||||
};
|
};
|
||||||
|
|
||||||
fn strLitAsString(zg: *ZonGen, str_node: Ast.Node.Index) !StringLiteralResult {
|
fn strLitAsString(zg: *ZonGen, str_node: Ast.Node.Index) error{ OutOfMemory, BadString }!StringLiteralResult {
|
||||||
if (!zg.options.parse_str_lits) return .{ .slice = .{ .start = 0, .len = 0 } };
|
if (!zg.options.parse_str_lits) return .{ .slice = .{ .start = 0, .len = 0 } };
|
||||||
|
|
||||||
const gpa = zg.gpa;
|
const gpa = zg.gpa;
|
||||||
const string_bytes = &zg.string_bytes;
|
const string_bytes = &zg.string_bytes;
|
||||||
const str_index: u32 = @intCast(zg.string_bytes.items.len);
|
const str_index: u32 = @intCast(zg.string_bytes.items.len);
|
||||||
const size_hint = strLitSizeHint(zg.tree, str_node);
|
const size_hint = strLitSizeHint(zg.tree, str_node);
|
||||||
try string_bytes.ensureUnusedCapacity(zg.gpa, size_hint);
|
try string_bytes.ensureUnusedCapacity(gpa, size_hint);
|
||||||
switch (try parseStrLit(zg.tree, str_node, zg.string_bytes.writer(zg.gpa))) {
|
const result = r: {
|
||||||
|
var aw: std.io.AllocatingWriter = undefined;
|
||||||
|
const bw = aw.fromArrayList(gpa, &zg.string_bytes);
|
||||||
|
defer zg.string_bytes = aw.toArrayList();
|
||||||
|
break :r parseStrLit(zg.tree, str_node, bw) catch |err| return @errorCast(err);
|
||||||
|
};
|
||||||
|
switch (result) {
|
||||||
.success => {},
|
.success => {},
|
||||||
.failure => |err| {
|
.failure => |err| {
|
||||||
const token = zg.tree.nodeMainToken(str_node);
|
const token = zg.tree.nodeMainToken(str_node);
|
||||||
@ -805,10 +817,7 @@ fn lowerNumberError(zg: *ZonGen, err: std.zig.number_literal.Error, token: Ast.T
|
|||||||
|
|
||||||
fn errNoteNode(zg: *ZonGen, node: Ast.Node.Index, comptime format: []const u8, args: anytype) Allocator.Error!Zoir.CompileError.Note {
|
fn errNoteNode(zg: *ZonGen, node: Ast.Node.Index, comptime format: []const u8, args: anytype) Allocator.Error!Zoir.CompileError.Note {
|
||||||
const message_idx: u32 = @intCast(zg.string_bytes.items.len);
|
const message_idx: u32 = @intCast(zg.string_bytes.items.len);
|
||||||
const writer = zg.string_bytes.writer(zg.gpa);
|
try zg.string_bytes.print(zg.gpa, format ++ "\x00", args);
|
||||||
try writer.print(format, args);
|
|
||||||
try writer.writeByte(0);
|
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.msg = @enumFromInt(message_idx),
|
.msg = @enumFromInt(message_idx),
|
||||||
.token = .none,
|
.token = .none,
|
||||||
@ -818,10 +827,7 @@ fn errNoteNode(zg: *ZonGen, node: Ast.Node.Index, comptime format: []const u8, a
|
|||||||
|
|
||||||
fn errNoteTok(zg: *ZonGen, tok: Ast.TokenIndex, comptime format: []const u8, args: anytype) Allocator.Error!Zoir.CompileError.Note {
|
fn errNoteTok(zg: *ZonGen, tok: Ast.TokenIndex, comptime format: []const u8, args: anytype) Allocator.Error!Zoir.CompileError.Note {
|
||||||
const message_idx: u32 = @intCast(zg.string_bytes.items.len);
|
const message_idx: u32 = @intCast(zg.string_bytes.items.len);
|
||||||
const writer = zg.string_bytes.writer(zg.gpa);
|
try zg.string_bytes.print(zg.gpa, format ++ "\x00", args);
|
||||||
try writer.print(format, args);
|
|
||||||
try writer.writeByte(0);
|
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.msg = @enumFromInt(message_idx),
|
.msg = @enumFromInt(message_idx),
|
||||||
.token = .fromToken(tok),
|
.token = .fromToken(tok),
|
||||||
@ -862,9 +868,7 @@ fn addErrorInner(
|
|||||||
try zg.error_notes.appendSlice(gpa, notes);
|
try zg.error_notes.appendSlice(gpa, notes);
|
||||||
|
|
||||||
const message_idx: u32 = @intCast(zg.string_bytes.items.len);
|
const message_idx: u32 = @intCast(zg.string_bytes.items.len);
|
||||||
const writer = zg.string_bytes.writer(zg.gpa);
|
try zg.string_bytes.print(gpa, format ++ "\x00", args);
|
||||||
try writer.print(format, args);
|
|
||||||
try writer.writeByte(0);
|
|
||||||
|
|
||||||
try zg.compile_errors.append(gpa, .{
|
try zg.compile_errors.append(gpa, .{
|
||||||
.msg = @enumFromInt(message_idx),
|
.msg = @enumFromInt(message_idx),
|
||||||
@ -880,8 +884,9 @@ fn lowerAstErrors(zg: *ZonGen) Allocator.Error!void {
|
|||||||
const tree = zg.tree;
|
const tree = zg.tree;
|
||||||
assert(tree.errors.len > 0);
|
assert(tree.errors.len > 0);
|
||||||
|
|
||||||
var msg: std.ArrayListUnmanaged(u8) = .empty;
|
var msg: std.io.AllocatingWriter = undefined;
|
||||||
defer msg.deinit(gpa);
|
const msg_bw = msg.init(gpa);
|
||||||
|
defer msg.deinit();
|
||||||
|
|
||||||
var notes: std.ArrayListUnmanaged(Zoir.CompileError.Note) = .empty;
|
var notes: std.ArrayListUnmanaged(Zoir.CompileError.Note) = .empty;
|
||||||
defer notes.deinit(gpa);
|
defer notes.deinit(gpa);
|
||||||
@ -889,18 +894,20 @@ fn lowerAstErrors(zg: *ZonGen) Allocator.Error!void {
|
|||||||
var cur_err = tree.errors[0];
|
var cur_err = tree.errors[0];
|
||||||
for (tree.errors[1..]) |err| {
|
for (tree.errors[1..]) |err| {
|
||||||
if (err.is_note) {
|
if (err.is_note) {
|
||||||
try tree.renderError(err, msg.writer(gpa));
|
tree.renderError(err, msg_bw) catch |e| return @errorCast(e); // TODO: try @errorCast(...)
|
||||||
try notes.append(gpa, try zg.errNoteTok(err.token, "{s}", .{msg.items}));
|
try notes.append(gpa, try zg.errNoteTok(err.token, "{s}", .{msg.getWritten()}));
|
||||||
} else {
|
} else {
|
||||||
// Flush error
|
// Flush error
|
||||||
try tree.renderError(cur_err, msg.writer(gpa));
|
tree.renderError(cur_err, msg_bw) catch |e| return @errorCast(e); // TODO try @errorCast(...)
|
||||||
const extra_offset = tree.errorOffset(cur_err);
|
const extra_offset = tree.errorOffset(cur_err);
|
||||||
try zg.addErrorTokNotesOff(cur_err.token, extra_offset, "{s}", .{msg.items}, notes.items);
|
try zg.addErrorTokNotesOff(cur_err.token, extra_offset, "{s}", .{msg.getWritten()}, notes.items);
|
||||||
notes.clearRetainingCapacity();
|
notes.clearRetainingCapacity();
|
||||||
cur_err = err;
|
cur_err = err;
|
||||||
|
|
||||||
// TODO: `Parse` currently does not have good error recovery mechanisms, so the remaining errors could be bogus.
|
// TODO: `Parse` currently does not have good error recovery
|
||||||
// As such, we'll ignore all remaining errors for now. We should improve `Parse` so that we can report all the errors.
|
// mechanisms, so the remaining errors could be bogus. As such,
|
||||||
|
// we'll ignore all remaining errors for now. We should improve
|
||||||
|
// `Parse` so that we can report all the errors.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
msg.clearRetainingCapacity();
|
msg.clearRetainingCapacity();
|
||||||
@ -908,8 +915,8 @@ fn lowerAstErrors(zg: *ZonGen) Allocator.Error!void {
|
|||||||
|
|
||||||
// Flush error
|
// Flush error
|
||||||
const extra_offset = tree.errorOffset(cur_err);
|
const extra_offset = tree.errorOffset(cur_err);
|
||||||
try tree.renderError(cur_err, msg.writer(gpa));
|
tree.renderError(cur_err, msg_bw) catch |e| return @errorCast(e); // TODO try @errorCast(...)
|
||||||
try zg.addErrorTokNotesOff(cur_err.token, extra_offset, "{s}", .{msg.items}, notes.items);
|
try zg.addErrorTokNotesOff(cur_err.token, extra_offset, "{s}", .{msg.getWritten()}, notes.items);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|||||||
@ -10,10 +10,6 @@ const primitives = std.zig.primitives;
|
|||||||
const indent_delta = 4;
|
const indent_delta = 4;
|
||||||
const asm_indent_delta = 2;
|
const asm_indent_delta = 2;
|
||||||
|
|
||||||
pub const Error = Ast.RenderError;
|
|
||||||
|
|
||||||
const Ais = AutoIndentingStream(std.ArrayList(u8).Writer);
|
|
||||||
|
|
||||||
pub const Fixups = struct {
|
pub const Fixups = struct {
|
||||||
/// The key is the mut token (`var`/`const`) of the variable declaration
|
/// The key is the mut token (`var`/`const`) of the variable declaration
|
||||||
/// that should have a `_ = foo;` inserted afterwards.
|
/// that should have a `_ = foo;` inserted afterwards.
|
||||||
@ -74,17 +70,17 @@ pub const Fixups = struct {
|
|||||||
|
|
||||||
const Render = struct {
|
const Render = struct {
|
||||||
gpa: Allocator,
|
gpa: Allocator,
|
||||||
ais: *Ais,
|
ais: *AutoIndentingStream,
|
||||||
tree: Ast,
|
tree: Ast,
|
||||||
fixups: Fixups,
|
fixups: Fixups,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn renderTree(buffer: *std.ArrayList(u8), tree: Ast, fixups: Fixups) Error!void {
|
pub fn renderTree(gpa: Allocator, bw: *std.io.BufferedWriter, tree: Ast, fixups: Fixups) anyerror!void {
|
||||||
assert(tree.errors.len == 0); // Cannot render an invalid tree.
|
assert(tree.errors.len == 0); // Cannot render an invalid tree.
|
||||||
var auto_indenting_stream = Ais.init(buffer, indent_delta);
|
var auto_indenting_stream: AutoIndentingStream = .init(bw, indent_delta);
|
||||||
defer auto_indenting_stream.deinit();
|
defer auto_indenting_stream.deinit();
|
||||||
var r: Render = .{
|
var r: Render = .{
|
||||||
.gpa = buffer.allocator,
|
.gpa = gpa,
|
||||||
.ais = &auto_indenting_stream,
|
.ais = &auto_indenting_stream,
|
||||||
.tree = tree,
|
.tree = tree,
|
||||||
.fixups = fixups,
|
.fixups = fixups,
|
||||||
@ -115,7 +111,7 @@ pub fn renderTree(buffer: *std.ArrayList(u8), tree: Ast, fixups: Fixups) Error!v
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Render all members in the given slice, keeping empty lines where appropriate
|
/// Render all members in the given slice, keeping empty lines where appropriate
|
||||||
fn renderMembers(r: *Render, members: []const Ast.Node.Index) Error!void {
|
fn renderMembers(r: *Render, members: []const Ast.Node.Index) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
if (members.len == 0) return;
|
if (members.len == 0) return;
|
||||||
const container: Container = for (members) |member| {
|
const container: Container = for (members) |member| {
|
||||||
@ -139,7 +135,7 @@ fn renderMember(
|
|||||||
container: Container,
|
container: Container,
|
||||||
decl: Ast.Node.Index,
|
decl: Ast.Node.Index,
|
||||||
space: Space,
|
space: Space,
|
||||||
) Error!void {
|
) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
if (r.fixups.omit_nodes.contains(decl)) return;
|
if (r.fixups.omit_nodes.contains(decl)) return;
|
||||||
@ -186,7 +182,7 @@ fn renderMember(
|
|||||||
if (opt_callconv_expr.unwrap()) |callconv_expr| {
|
if (opt_callconv_expr.unwrap()) |callconv_expr| {
|
||||||
if (tree.nodeTag(callconv_expr) == .enum_literal) {
|
if (tree.nodeTag(callconv_expr) == .enum_literal) {
|
||||||
if (mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodeMainToken(callconv_expr)))) {
|
if (mem.eql(u8, "@\"inline\"", tree.tokenSlice(tree.nodeMainToken(callconv_expr)))) {
|
||||||
try ais.writer().writeAll("inline ");
|
try ais.underlying_writer.writeAll("inline ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -200,7 +196,7 @@ fn renderMember(
|
|||||||
const lbrace = tree.nodeMainToken(body_node);
|
const lbrace = tree.nodeMainToken(body_node);
|
||||||
try renderToken(r, lbrace, .newline);
|
try renderToken(r, lbrace, .newline);
|
||||||
try discardAllParams(r, fn_proto);
|
try discardAllParams(r, fn_proto);
|
||||||
try ais.writer().writeAll("@trap();");
|
try ais.writeAll("@trap();");
|
||||||
ais.popIndent();
|
ais.popIndent();
|
||||||
try ais.insertNewline();
|
try ais.insertNewline();
|
||||||
try renderToken(r, tree.lastToken(body_node), space); // rbrace
|
try renderToken(r, tree.lastToken(body_node), space); // rbrace
|
||||||
@ -216,10 +212,9 @@ fn renderMember(
|
|||||||
const name_ident = param.name_token.?;
|
const name_ident = param.name_token.?;
|
||||||
assert(tree.tokenTag(name_ident) == .identifier);
|
assert(tree.tokenTag(name_ident) == .identifier);
|
||||||
if (r.fixups.unused_var_decls.contains(name_ident)) {
|
if (r.fixups.unused_var_decls.contains(name_ident)) {
|
||||||
const w = ais.writer();
|
try ais.writeAll("_ = ");
|
||||||
try w.writeAll("_ = ");
|
try ais.writeAll(tokenSliceForRender(r.tree, name_ident));
|
||||||
try w.writeAll(tokenSliceForRender(r.tree, name_ident));
|
try ais.writeAll(";\n");
|
||||||
try w.writeAll(";\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var statements_buf: [2]Ast.Node.Index = undefined;
|
var statements_buf: [2]Ast.Node.Index = undefined;
|
||||||
@ -310,7 +305,7 @@ fn renderMember(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Render all expressions in the slice, keeping empty lines where appropriate
|
/// Render all expressions in the slice, keeping empty lines where appropriate
|
||||||
fn renderExpressions(r: *Render, expressions: []const Ast.Node.Index, space: Space) Error!void {
|
fn renderExpressions(r: *Render, expressions: []const Ast.Node.Index, space: Space) anyerror!void {
|
||||||
if (expressions.len == 0) return;
|
if (expressions.len == 0) return;
|
||||||
try renderExpression(r, expressions[0], space);
|
try renderExpression(r, expressions[0], space);
|
||||||
for (expressions[1..]) |expression| {
|
for (expressions[1..]) |expression| {
|
||||||
@ -319,11 +314,11 @@ fn renderExpressions(r: *Render, expressions: []const Ast.Node.Index, space: Spa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
|
fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
if (r.fixups.replace_nodes_with_string.get(node)) |replacement| {
|
if (r.fixups.replace_nodes_with_string.get(node)) |replacement| {
|
||||||
try ais.writer().writeAll(replacement);
|
try ais.writeAll(replacement);
|
||||||
try renderOnlySpace(r, space);
|
try renderOnlySpace(r, space);
|
||||||
return;
|
return;
|
||||||
} else if (r.fixups.replace_nodes_with_node.get(node)) |replacement| {
|
} else if (r.fixups.replace_nodes_with_node.get(node)) |replacement| {
|
||||||
@ -891,11 +886,11 @@ fn renderExpression(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
|
|||||||
|
|
||||||
/// Same as `renderExpression`, but afterwards looks for any
|
/// Same as `renderExpression`, but afterwards looks for any
|
||||||
/// append_string_after_node fixups to apply
|
/// append_string_after_node fixups to apply
|
||||||
fn renderExpressionFixup(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
|
fn renderExpressionFixup(r: *Render, node: Ast.Node.Index, space: Space) anyerror!void {
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
try renderExpression(r, node, space);
|
try renderExpression(r, node, space);
|
||||||
if (r.fixups.append_string_after_node.get(node)) |bytes| {
|
if (r.fixups.append_string_after_node.get(node)) |bytes| {
|
||||||
try ais.writer().writeAll(bytes);
|
try ais.writeAll(bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -903,7 +898,7 @@ fn renderArrayType(
|
|||||||
r: *Render,
|
r: *Render,
|
||||||
array_type: Ast.full.ArrayType,
|
array_type: Ast.full.ArrayType,
|
||||||
space: Space,
|
space: Space,
|
||||||
) Error!void {
|
) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
const rbracket = tree.firstToken(array_type.ast.elem_type) - 1;
|
const rbracket = tree.firstToken(array_type.ast.elem_type) - 1;
|
||||||
@ -921,7 +916,7 @@ fn renderArrayType(
|
|||||||
return renderExpression(r, array_type.ast.elem_type, space);
|
return renderExpression(r, array_type.ast.elem_type, space);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) Error!void {
|
fn renderPtrType(r: *Render, ptr_type: Ast.full.PtrType, space: Space) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const main_token = ptr_type.ast.main_token;
|
const main_token = ptr_type.ast.main_token;
|
||||||
switch (ptr_type.size) {
|
switch (ptr_type.size) {
|
||||||
@ -1015,7 +1010,7 @@ fn renderSlice(
|
|||||||
slice_node: Ast.Node.Index,
|
slice_node: Ast.Node.Index,
|
||||||
slice: Ast.full.Slice,
|
slice: Ast.full.Slice,
|
||||||
space: Space,
|
space: Space,
|
||||||
) Error!void {
|
) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const after_start_space_bool = nodeCausesSliceOpSpace(tree.nodeTag(slice.ast.start)) or
|
const after_start_space_bool = nodeCausesSliceOpSpace(tree.nodeTag(slice.ast.start)) or
|
||||||
if (slice.ast.end.unwrap()) |end| nodeCausesSliceOpSpace(tree.nodeTag(end)) else false;
|
if (slice.ast.end.unwrap()) |end| nodeCausesSliceOpSpace(tree.nodeTag(end)) else false;
|
||||||
@ -1048,7 +1043,7 @@ fn renderAsmOutput(
|
|||||||
r: *Render,
|
r: *Render,
|
||||||
asm_output: Ast.Node.Index,
|
asm_output: Ast.Node.Index,
|
||||||
space: Space,
|
space: Space,
|
||||||
) Error!void {
|
) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
assert(tree.nodeTag(asm_output) == .asm_output);
|
assert(tree.nodeTag(asm_output) == .asm_output);
|
||||||
const symbolic_name = tree.nodeMainToken(asm_output);
|
const symbolic_name = tree.nodeMainToken(asm_output);
|
||||||
@ -1074,7 +1069,7 @@ fn renderAsmInput(
|
|||||||
r: *Render,
|
r: *Render,
|
||||||
asm_input: Ast.Node.Index,
|
asm_input: Ast.Node.Index,
|
||||||
space: Space,
|
space: Space,
|
||||||
) Error!void {
|
) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
assert(tree.nodeTag(asm_input) == .asm_input);
|
assert(tree.nodeTag(asm_input) == .asm_input);
|
||||||
const symbolic_name = tree.nodeMainToken(asm_input);
|
const symbolic_name = tree.nodeMainToken(asm_input);
|
||||||
@ -1096,14 +1091,14 @@ fn renderVarDecl(
|
|||||||
ignore_comptime_token: bool,
|
ignore_comptime_token: bool,
|
||||||
/// `comma_space` and `space` are used for destructure LHS decls.
|
/// `comma_space` and `space` are used for destructure LHS decls.
|
||||||
space: Space,
|
space: Space,
|
||||||
) Error!void {
|
) anyerror!void {
|
||||||
try renderVarDeclWithoutFixups(r, var_decl, ignore_comptime_token, space);
|
try renderVarDeclWithoutFixups(r, var_decl, ignore_comptime_token, space);
|
||||||
if (r.fixups.unused_var_decls.contains(var_decl.ast.mut_token + 1)) {
|
if (r.fixups.unused_var_decls.contains(var_decl.ast.mut_token + 1)) {
|
||||||
// Discard the variable like this: `_ = foo;`
|
// Discard the variable like this: `_ = foo;`
|
||||||
const w = r.ais.writer();
|
const ais = r.ais;
|
||||||
try w.writeAll("_ = ");
|
try ais.writeAll("_ = ");
|
||||||
try w.writeAll(tokenSliceForRender(r.tree, var_decl.ast.mut_token + 1));
|
try ais.writeAll(tokenSliceForRender(r.tree, var_decl.ast.mut_token + 1));
|
||||||
try w.writeAll(";\n");
|
try ais.writeAll(";\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1114,7 +1109,7 @@ fn renderVarDeclWithoutFixups(
|
|||||||
ignore_comptime_token: bool,
|
ignore_comptime_token: bool,
|
||||||
/// `comma_space` and `space` are used for destructure LHS decls.
|
/// `comma_space` and `space` are used for destructure LHS decls.
|
||||||
space: Space,
|
space: Space,
|
||||||
) Error!void {
|
) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
|
|
||||||
@ -1226,7 +1221,7 @@ fn renderVarDeclWithoutFixups(
|
|||||||
ais.popIndent();
|
ais.popIndent();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) Error!void {
|
fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) anyerror!void {
|
||||||
return renderWhile(r, .{
|
return renderWhile(r, .{
|
||||||
.ast = .{
|
.ast = .{
|
||||||
.while_token = if_node.ast.if_token,
|
.while_token = if_node.ast.if_token,
|
||||||
@ -1245,7 +1240,7 @@ fn renderIf(r: *Render, if_node: Ast.full.If, space: Space) Error!void {
|
|||||||
|
|
||||||
/// Note that this function is additionally used to render if expressions, with
|
/// Note that this function is additionally used to render if expressions, with
|
||||||
/// respective values set to null.
|
/// respective values set to null.
|
||||||
fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) Error!void {
|
fn renderWhile(r: *Render, while_node: Ast.full.While, space: Space) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
|
|
||||||
if (while_node.label_token) |label| {
|
if (while_node.label_token) |label| {
|
||||||
@ -1315,7 +1310,7 @@ fn renderThenElse(
|
|||||||
maybe_error_token: ?Ast.TokenIndex,
|
maybe_error_token: ?Ast.TokenIndex,
|
||||||
opt_else_expr: Ast.Node.OptionalIndex,
|
opt_else_expr: Ast.Node.OptionalIndex,
|
||||||
space: Space,
|
space: Space,
|
||||||
) Error!void {
|
) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
const then_expr_is_block = nodeIsBlock(tree.nodeTag(then_expr));
|
const then_expr_is_block = nodeIsBlock(tree.nodeTag(then_expr));
|
||||||
@ -1370,7 +1365,7 @@ fn renderThenElse(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) Error!void {
|
fn renderFor(r: *Render, for_node: Ast.full.For, space: Space) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
const token_tags = tree.tokens.items(.tag);
|
const token_tags = tree.tokens.items(.tag);
|
||||||
@ -1445,7 +1440,7 @@ fn renderContainerField(
|
|||||||
container: Container,
|
container: Container,
|
||||||
field_param: Ast.full.ContainerField,
|
field_param: Ast.full.ContainerField,
|
||||||
space: Space,
|
space: Space,
|
||||||
) Error!void {
|
) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
var field = field_param;
|
var field = field_param;
|
||||||
@ -1554,7 +1549,7 @@ fn renderBuiltinCall(
|
|||||||
builtin_token: Ast.TokenIndex,
|
builtin_token: Ast.TokenIndex,
|
||||||
params: []const Ast.Node.Index,
|
params: []const Ast.Node.Index,
|
||||||
space: Space,
|
space: Space,
|
||||||
) Error!void {
|
) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
|
|
||||||
@ -1581,7 +1576,7 @@ fn renderBuiltinCall(
|
|||||||
defer r.gpa.free(new_string);
|
defer r.gpa.free(new_string);
|
||||||
|
|
||||||
try renderToken(r, builtin_token + 1, .none); // (
|
try renderToken(r, builtin_token + 1, .none); // (
|
||||||
try ais.writer().print("\"{}\"", .{std.zig.fmtEscapes(new_string)});
|
try ais.print("\"{}\"", .{std.zig.fmtEscapes(new_string)});
|
||||||
return renderToken(r, str_lit_token + 1, space); // )
|
return renderToken(r, str_lit_token + 1, space); // )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1627,7 +1622,7 @@ fn renderBuiltinCall(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) Error!void {
|
fn renderFnProto(r: *Render, fn_proto: Ast.full.FnProto, space: Space) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
|
|
||||||
@ -1852,7 +1847,7 @@ fn renderSwitchCase(
|
|||||||
r: *Render,
|
r: *Render,
|
||||||
switch_case: Ast.full.SwitchCase,
|
switch_case: Ast.full.SwitchCase,
|
||||||
space: Space,
|
space: Space,
|
||||||
) Error!void {
|
) anyerror!void {
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const trailing_comma = tree.tokenTag(switch_case.ast.arrow_token - 1) == .comma;
|
const trailing_comma = tree.tokenTag(switch_case.ast.arrow_token - 1) == .comma;
|
||||||
@ -1914,7 +1909,7 @@ fn renderBlock(
|
|||||||
block_node: Ast.Node.Index,
|
block_node: Ast.Node.Index,
|
||||||
statements: []const Ast.Node.Index,
|
statements: []const Ast.Node.Index,
|
||||||
space: Space,
|
space: Space,
|
||||||
) Error!void {
|
) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
const lbrace = tree.nodeMainToken(block_node);
|
const lbrace = tree.nodeMainToken(block_node);
|
||||||
@ -1939,7 +1934,7 @@ fn finishRenderBlock(
|
|||||||
block_node: Ast.Node.Index,
|
block_node: Ast.Node.Index,
|
||||||
statements: []const Ast.Node.Index,
|
statements: []const Ast.Node.Index,
|
||||||
space: Space,
|
space: Space,
|
||||||
) Error!void {
|
) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
for (statements, 0..) |stmt, i| {
|
for (statements, 0..) |stmt, i| {
|
||||||
@ -1967,7 +1962,7 @@ fn renderStructInit(
|
|||||||
struct_node: Ast.Node.Index,
|
struct_node: Ast.Node.Index,
|
||||||
struct_init: Ast.full.StructInit,
|
struct_init: Ast.full.StructInit,
|
||||||
space: Space,
|
space: Space,
|
||||||
) Error!void {
|
) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
|
|
||||||
@ -2038,7 +2033,7 @@ fn renderArrayInit(
|
|||||||
r: *Render,
|
r: *Render,
|
||||||
array_init: Ast.full.ArrayInit,
|
array_init: Ast.full.ArrayInit,
|
||||||
space: Space,
|
space: Space,
|
||||||
) Error!void {
|
) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
const gpa = r.gpa;
|
const gpa = r.gpa;
|
||||||
@ -2139,13 +2134,14 @@ fn renderArrayInit(
|
|||||||
|
|
||||||
const section_exprs = row_exprs[0..section_end];
|
const section_exprs = row_exprs[0..section_end];
|
||||||
|
|
||||||
var sub_expr_buffer = std.ArrayList(u8).init(gpa);
|
var sub_expr_buffer: std.io.AllocatingWriter = undefined;
|
||||||
|
const sub_expr_buffer_writer = sub_expr_buffer.init(gpa);
|
||||||
defer sub_expr_buffer.deinit();
|
defer sub_expr_buffer.deinit();
|
||||||
|
|
||||||
const sub_expr_buffer_starts = try gpa.alloc(usize, section_exprs.len + 1);
|
const sub_expr_buffer_starts = try gpa.alloc(usize, section_exprs.len + 1);
|
||||||
defer gpa.free(sub_expr_buffer_starts);
|
defer gpa.free(sub_expr_buffer_starts);
|
||||||
|
|
||||||
var auto_indenting_stream = Ais.init(&sub_expr_buffer, indent_delta);
|
var auto_indenting_stream: AutoIndentingStream = .init(sub_expr_buffer_writer, indent_delta);
|
||||||
defer auto_indenting_stream.deinit();
|
defer auto_indenting_stream.deinit();
|
||||||
var sub_render: Render = .{
|
var sub_render: Render = .{
|
||||||
.gpa = r.gpa,
|
.gpa = r.gpa,
|
||||||
@ -2159,13 +2155,13 @@ fn renderArrayInit(
|
|||||||
var single_line = true;
|
var single_line = true;
|
||||||
var contains_newline = false;
|
var contains_newline = false;
|
||||||
for (section_exprs, 0..) |expr, i| {
|
for (section_exprs, 0..) |expr, i| {
|
||||||
const start = sub_expr_buffer.items.len;
|
const start = sub_expr_buffer.getWritten().len;
|
||||||
sub_expr_buffer_starts[i] = start;
|
sub_expr_buffer_starts[i] = start;
|
||||||
|
|
||||||
if (i + 1 < section_exprs.len) {
|
if (i + 1 < section_exprs.len) {
|
||||||
try renderExpression(&sub_render, expr, .none);
|
try renderExpression(&sub_render, expr, .none);
|
||||||
const width = sub_expr_buffer.items.len - start;
|
const width = sub_expr_buffer.getWritten().len - start;
|
||||||
const this_contains_newline = mem.indexOfScalar(u8, sub_expr_buffer.items[start..], '\n') != null;
|
const this_contains_newline = mem.indexOfScalar(u8, sub_expr_buffer.getWritten()[start..], '\n') != null;
|
||||||
contains_newline = contains_newline or this_contains_newline;
|
contains_newline = contains_newline or this_contains_newline;
|
||||||
expr_widths[i] = width;
|
expr_widths[i] = width;
|
||||||
expr_newlines[i] = this_contains_newline;
|
expr_newlines[i] = this_contains_newline;
|
||||||
@ -2188,7 +2184,7 @@ fn renderArrayInit(
|
|||||||
ais.popSpace();
|
ais.popSpace();
|
||||||
|
|
||||||
const width = sub_expr_buffer.items.len - start - 2;
|
const width = sub_expr_buffer.items.len - start - 2;
|
||||||
const this_contains_newline = mem.indexOfScalar(u8, sub_expr_buffer.items[start .. sub_expr_buffer.items.len - 1], '\n') != null;
|
const this_contains_newline = mem.indexOfScalar(u8, sub_expr_buffer.getWritten()[start .. sub_expr_buffer.items.len - 1], '\n') != null;
|
||||||
contains_newline = contains_newline or this_contains_newline;
|
contains_newline = contains_newline or this_contains_newline;
|
||||||
expr_widths[i] = width;
|
expr_widths[i] = width;
|
||||||
expr_newlines[i] = contains_newline;
|
expr_newlines[i] = contains_newline;
|
||||||
@ -2199,20 +2195,20 @@ fn renderArrayInit(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sub_expr_buffer_starts[section_exprs.len] = sub_expr_buffer.items.len;
|
sub_expr_buffer_starts[section_exprs.len] = sub_expr_buffer.getWritten().len;
|
||||||
|
|
||||||
// Render exprs in current section.
|
// Render exprs in current section.
|
||||||
column_counter = 0;
|
column_counter = 0;
|
||||||
for (section_exprs, 0..) |expr, i| {
|
for (section_exprs, 0..) |expr, i| {
|
||||||
const start = sub_expr_buffer_starts[i];
|
const start = sub_expr_buffer_starts[i];
|
||||||
const end = sub_expr_buffer_starts[i + 1];
|
const end = sub_expr_buffer_starts[i + 1];
|
||||||
const expr_text = sub_expr_buffer.items[start..end];
|
const expr_text = sub_expr_buffer.getWritten()[start..end];
|
||||||
if (!expr_newlines[i]) {
|
if (!expr_newlines[i]) {
|
||||||
try ais.writer().writeAll(expr_text);
|
try ais.writeAll(expr_text);
|
||||||
} else {
|
} else {
|
||||||
var by_line = std.mem.splitScalar(u8, expr_text, '\n');
|
var by_line = std.mem.splitScalar(u8, expr_text, '\n');
|
||||||
var last_line_was_empty = false;
|
var last_line_was_empty = false;
|
||||||
try ais.writer().writeAll(by_line.first());
|
try ais.writeAll(by_line.first());
|
||||||
while (by_line.next()) |line| {
|
while (by_line.next()) |line| {
|
||||||
if (std.mem.startsWith(u8, line, "//") and last_line_was_empty) {
|
if (std.mem.startsWith(u8, line, "//") and last_line_was_empty) {
|
||||||
try ais.insertNewline();
|
try ais.insertNewline();
|
||||||
@ -2220,7 +2216,7 @@ fn renderArrayInit(
|
|||||||
try ais.maybeInsertNewline();
|
try ais.maybeInsertNewline();
|
||||||
}
|
}
|
||||||
last_line_was_empty = (line.len == 0);
|
last_line_was_empty = (line.len == 0);
|
||||||
try ais.writer().writeAll(line);
|
try ais.writeAll(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2234,7 +2230,7 @@ fn renderArrayInit(
|
|||||||
try renderToken(r, comma, .space); // ,
|
try renderToken(r, comma, .space); // ,
|
||||||
assert(column_widths[column_counter % row_size] >= expr_widths[i]);
|
assert(column_widths[column_counter % row_size] >= expr_widths[i]);
|
||||||
const padding = column_widths[column_counter % row_size] - expr_widths[i];
|
const padding = column_widths[column_counter % row_size] - expr_widths[i];
|
||||||
try ais.writer().writeByteNTimes(' ', padding);
|
try ais.splatByteAll(' ', padding);
|
||||||
|
|
||||||
column_counter += 1;
|
column_counter += 1;
|
||||||
continue;
|
continue;
|
||||||
@ -2265,7 +2261,7 @@ fn renderContainerDecl(
|
|||||||
container_decl_node: Ast.Node.Index,
|
container_decl_node: Ast.Node.Index,
|
||||||
container_decl: Ast.full.ContainerDecl,
|
container_decl: Ast.full.ContainerDecl,
|
||||||
space: Space,
|
space: Space,
|
||||||
) Error!void {
|
) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
|
|
||||||
@ -2384,7 +2380,7 @@ fn renderAsm(
|
|||||||
r: *Render,
|
r: *Render,
|
||||||
asm_node: Ast.full.Asm,
|
asm_node: Ast.full.Asm,
|
||||||
space: Space,
|
space: Space,
|
||||||
) Error!void {
|
) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
|
|
||||||
@ -2550,7 +2546,7 @@ fn renderCall(
|
|||||||
r: *Render,
|
r: *Render,
|
||||||
call: Ast.full.Call,
|
call: Ast.full.Call,
|
||||||
space: Space,
|
space: Space,
|
||||||
) Error!void {
|
) anyerror!void {
|
||||||
if (call.async_token) |async_token| {
|
if (call.async_token) |async_token| {
|
||||||
try renderToken(r, async_token, .space);
|
try renderToken(r, async_token, .space);
|
||||||
}
|
}
|
||||||
@ -2563,7 +2559,7 @@ fn renderParamList(
|
|||||||
lparen: Ast.TokenIndex,
|
lparen: Ast.TokenIndex,
|
||||||
params: []const Ast.Node.Index,
|
params: []const Ast.Node.Index,
|
||||||
space: Space,
|
space: Space,
|
||||||
) Error!void {
|
) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
|
|
||||||
@ -2616,7 +2612,7 @@ fn renderParamList(
|
|||||||
|
|
||||||
/// Render an expression, and the comma that follows it, if it is present in the source.
|
/// Render an expression, and the comma that follows it, if it is present in the source.
|
||||||
/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
|
/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
|
||||||
fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) Error!void {
|
fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const maybe_comma = tree.lastToken(node) + 1;
|
const maybe_comma = tree.lastToken(node) + 1;
|
||||||
if (tree.tokenTag(maybe_comma) == .comma and space != .comma) {
|
if (tree.tokenTag(maybe_comma) == .comma and space != .comma) {
|
||||||
@ -2629,7 +2625,7 @@ fn renderExpressionComma(r: *Render, node: Ast.Node.Index, space: Space) Error!v
|
|||||||
|
|
||||||
/// Render a token, and the comma that follows it, if it is present in the source.
|
/// Render a token, and the comma that follows it, if it is present in the source.
|
||||||
/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
|
/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
|
||||||
fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) Error!void {
|
fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const maybe_comma = token + 1;
|
const maybe_comma = token + 1;
|
||||||
if (tree.tokenTag(maybe_comma) == .comma and space != .comma) {
|
if (tree.tokenTag(maybe_comma) == .comma and space != .comma) {
|
||||||
@ -2642,7 +2638,7 @@ fn renderTokenComma(r: *Render, token: Ast.TokenIndex, space: Space) Error!void
|
|||||||
|
|
||||||
/// Render an identifier, and the comma that follows it, if it is present in the source.
|
/// Render an identifier, and the comma that follows it, if it is present in the source.
|
||||||
/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
|
/// If a comma is present, and `space` is `Space.comma`, render only a single comma.
|
||||||
fn renderIdentifierComma(r: *Render, token: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {
|
fn renderIdentifierComma(r: *Render, token: Ast.TokenIndex, space: Space, quote: QuoteBehavior) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const maybe_comma = token + 1;
|
const maybe_comma = token + 1;
|
||||||
if (tree.tokenTag(maybe_comma) == .comma and space != .comma) {
|
if (tree.tokenTag(maybe_comma) == .comma and space != .comma) {
|
||||||
@ -2674,15 +2670,15 @@ const Space = enum {
|
|||||||
skip,
|
skip,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn renderToken(r: *Render, token_index: Ast.TokenIndex, space: Space) Error!void {
|
fn renderToken(r: *Render, token_index: Ast.TokenIndex, space: Space) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
const lexeme = tokenSliceForRender(tree, token_index);
|
const lexeme = tokenSliceForRender(tree, token_index);
|
||||||
try ais.writer().writeAll(lexeme);
|
try ais.writeAll(lexeme);
|
||||||
try renderSpace(r, token_index, lexeme.len, space);
|
try renderSpace(r, token_index, lexeme.len, space);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderTokenOverrideSpaceMode(r: *Render, token_index: Ast.TokenIndex, space: Space, override_space: Space) Error!void {
|
fn renderTokenOverrideSpaceMode(r: *Render, token_index: Ast.TokenIndex, space: Space, override_space: Space) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
const lexeme = tokenSliceForRender(tree, token_index);
|
const lexeme = tokenSliceForRender(tree, token_index);
|
||||||
@ -2692,7 +2688,7 @@ fn renderTokenOverrideSpaceMode(r: *Render, token_index: Ast.TokenIndex, space:
|
|||||||
try renderSpace(r, token_index, lexeme.len, space);
|
try renderSpace(r, token_index, lexeme.len, space);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space: Space) Error!void {
|
fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space: Space) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
|
|
||||||
@ -2701,7 +2697,7 @@ fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space
|
|||||||
if (space == .skip) return;
|
if (space == .skip) return;
|
||||||
|
|
||||||
if (space == .comma and next_token_tag != .comma) {
|
if (space == .comma and next_token_tag != .comma) {
|
||||||
try ais.writer().writeByte(',');
|
try ais.underlying_writer.writeByte(',');
|
||||||
}
|
}
|
||||||
if (space == .semicolon or space == .comma) ais.enableSpaceMode(space);
|
if (space == .semicolon or space == .comma) ais.enableSpaceMode(space);
|
||||||
defer ais.disableSpaceMode();
|
defer ais.disableSpaceMode();
|
||||||
@ -2712,7 +2708,7 @@ fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space
|
|||||||
);
|
);
|
||||||
switch (space) {
|
switch (space) {
|
||||||
.none => {},
|
.none => {},
|
||||||
.space => if (!comment) try ais.writer().writeByte(' '),
|
.space => if (!comment) try ais.writeByte(' '),
|
||||||
.newline => if (!comment) try ais.insertNewline(),
|
.newline => if (!comment) try ais.insertNewline(),
|
||||||
|
|
||||||
.comma => if (next_token_tag == .comma) {
|
.comma => if (next_token_tag == .comma) {
|
||||||
@ -2724,7 +2720,7 @@ fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space
|
|||||||
.comma_space => if (next_token_tag == .comma) {
|
.comma_space => if (next_token_tag == .comma) {
|
||||||
try renderToken(r, token_index + 1, .space);
|
try renderToken(r, token_index + 1, .space);
|
||||||
} else if (!comment) {
|
} else if (!comment) {
|
||||||
try ais.writer().writeByte(' ');
|
try ais.writeByte(' ');
|
||||||
},
|
},
|
||||||
|
|
||||||
.semicolon => if (next_token_tag == .semicolon) {
|
.semicolon => if (next_token_tag == .semicolon) {
|
||||||
@ -2737,15 +2733,15 @@ fn renderSpace(r: *Render, token_index: Ast.TokenIndex, lexeme_len: usize, space
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderOnlySpace(r: *Render, space: Space) Error!void {
|
fn renderOnlySpace(r: *Render, space: Space) anyerror!void {
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
switch (space) {
|
switch (space) {
|
||||||
.none => {},
|
.none => {},
|
||||||
.space => try ais.writer().writeByte(' '),
|
.space => try ais.writeByte(' '),
|
||||||
.newline => try ais.insertNewline(),
|
.newline => try ais.insertNewline(),
|
||||||
.comma => try ais.writer().writeAll(",\n"),
|
.comma => try ais.writeAll(",\n"),
|
||||||
.comma_space => try ais.writer().writeAll(", "),
|
.comma_space => try ais.writeAll(", "),
|
||||||
.semicolon => try ais.writer().writeAll(";\n"),
|
.semicolon => try ais.writeAll(";\n"),
|
||||||
.skip => unreachable,
|
.skip => unreachable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2756,13 +2752,13 @@ const QuoteBehavior = enum {
|
|||||||
eagerly_unquote_except_underscore,
|
eagerly_unquote_except_underscore,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote: QuoteBehavior) Error!void {
|
fn renderIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space, quote: QuoteBehavior) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
assert(tree.tokenTag(token_index) == .identifier);
|
assert(tree.tokenTag(token_index) == .identifier);
|
||||||
const lexeme = tokenSliceForRender(tree, token_index);
|
const lexeme = tokenSliceForRender(tree, token_index);
|
||||||
|
|
||||||
if (r.fixups.rename_identifiers.get(lexeme)) |mangled| {
|
if (r.fixups.rename_identifiers.get(lexeme)) |mangled| {
|
||||||
try r.ais.writer().writeAll(mangled);
|
try r.ais.writeAll(mangled);
|
||||||
try renderSpace(r, token_index, lexeme.len, space);
|
try renderSpace(r, token_index, lexeme.len, space);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2871,15 +2867,15 @@ fn renderQuotedIdentifier(r: *Render, token_index: Ast.TokenIndex, space: Space,
|
|||||||
const lexeme = tokenSliceForRender(tree, token_index);
|
const lexeme = tokenSliceForRender(tree, token_index);
|
||||||
assert(lexeme.len >= 3 and lexeme[0] == '@');
|
assert(lexeme.len >= 3 and lexeme[0] == '@');
|
||||||
|
|
||||||
if (!unquote) try ais.writer().writeAll("@\"");
|
if (!unquote) try ais.writeAll("@\"");
|
||||||
const contents = lexeme[2 .. lexeme.len - 1];
|
const contents = lexeme[2 .. lexeme.len - 1];
|
||||||
try renderIdentifierContents(ais.writer(), contents);
|
try renderIdentifierContents(ais, contents);
|
||||||
if (!unquote) try ais.writer().writeByte('\"');
|
if (!unquote) try ais.writeByte('\"');
|
||||||
|
|
||||||
try renderSpace(r, token_index, lexeme.len, space);
|
try renderSpace(r, token_index, lexeme.len, space);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void {
|
fn renderIdentifierContents(ais: *AutoIndentingStream, bytes: []const u8) !void {
|
||||||
var pos: usize = 0;
|
var pos: usize = 0;
|
||||||
while (pos < bytes.len) {
|
while (pos < bytes.len) {
|
||||||
const byte = bytes[pos];
|
const byte = bytes[pos];
|
||||||
@ -2892,23 +2888,23 @@ fn renderIdentifierContents(writer: anytype, bytes: []const u8) !void {
|
|||||||
.success => |codepoint| {
|
.success => |codepoint| {
|
||||||
if (codepoint <= 0x7f) {
|
if (codepoint <= 0x7f) {
|
||||||
const buf = [1]u8{@as(u8, @intCast(codepoint))};
|
const buf = [1]u8{@as(u8, @intCast(codepoint))};
|
||||||
try std.fmt.format(writer, "{}", .{std.zig.fmtEscapes(&buf)});
|
try ais.print("{}", .{std.zig.fmtEscapes(&buf)});
|
||||||
} else {
|
} else {
|
||||||
try writer.writeAll(escape_sequence);
|
try ais.writeAll(escape_sequence);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.failure => {
|
.failure => {
|
||||||
try writer.writeAll(escape_sequence);
|
try ais.writeAll(escape_sequence);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
0x00...('\\' - 1), ('\\' + 1)...0x7f => {
|
0x00...('\\' - 1), ('\\' + 1)...0x7f => {
|
||||||
const buf = [1]u8{byte};
|
const buf = [1]u8{byte};
|
||||||
try std.fmt.format(writer, "{}", .{std.zig.fmtEscapes(&buf)});
|
try ais.print("{}", .{std.zig.fmtEscapes(&buf)});
|
||||||
pos += 1;
|
pos += 1;
|
||||||
},
|
},
|
||||||
0x80...0xff => {
|
0x80...0xff => {
|
||||||
try writer.writeByte(byte);
|
try ais.writeByte(byte);
|
||||||
pos += 1;
|
pos += 1;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -2942,7 +2938,7 @@ fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.Tok
|
|||||||
|
|
||||||
/// Assumes that start is the first byte past the previous token and
|
/// Assumes that start is the first byte past the previous token and
|
||||||
/// that end is the last byte before the next token.
|
/// that end is the last byte before the next token.
|
||||||
fn renderComments(r: *Render, start: usize, end: usize) Error!bool {
|
fn renderComments(r: *Render, start: usize, end: usize) anyerror!bool {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
|
|
||||||
@ -2970,7 +2966,7 @@ fn renderComments(r: *Render, start: usize, end: usize) Error!bool {
|
|||||||
} else if (index == start) {
|
} else if (index == start) {
|
||||||
// Otherwise if the first comment is on the same line as
|
// Otherwise if the first comment is on the same line as
|
||||||
// the token before it, prefix it with a single space.
|
// the token before it, prefix it with a single space.
|
||||||
try ais.writer().writeByte(' ');
|
try ais.writeByte(' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2987,11 +2983,11 @@ fn renderComments(r: *Render, start: usize, end: usize) Error!bool {
|
|||||||
ais.disabled_offset = null;
|
ais.disabled_offset = null;
|
||||||
} else if (ais.disabled_offset == null and mem.eql(u8, comment_content, "zig fmt: off")) {
|
} else if (ais.disabled_offset == null and mem.eql(u8, comment_content, "zig fmt: off")) {
|
||||||
// Write with the canonical single space.
|
// Write with the canonical single space.
|
||||||
try ais.writer().writeAll("// zig fmt: off\n");
|
try ais.writeAll("// zig fmt: off\n");
|
||||||
ais.disabled_offset = index;
|
ais.disabled_offset = index;
|
||||||
} else {
|
} else {
|
||||||
// Write the comment minus trailing whitespace.
|
// Write the comment minus trailing whitespace.
|
||||||
try ais.writer().print("{s}\n", .{trimmed_comment});
|
try ais.print("{s}\n", .{trimmed_comment});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3005,12 +3001,12 @@ fn renderComments(r: *Render, start: usize, end: usize) Error!bool {
|
|||||||
return index != start;
|
return index != start;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderExtraNewline(r: *Render, node: Ast.Node.Index) Error!void {
|
fn renderExtraNewline(r: *Render, node: Ast.Node.Index) anyerror!void {
|
||||||
return renderExtraNewlineToken(r, r.tree.firstToken(node));
|
return renderExtraNewlineToken(r, r.tree.firstToken(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if there is an empty line immediately before the given token. If so, render it.
|
/// Check if there is an empty line immediately before the given token. If so, render it.
|
||||||
fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void {
|
fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
const token_start = tree.tokenStart(token_index);
|
const token_start = tree.tokenStart(token_index);
|
||||||
@ -3038,7 +3034,7 @@ fn renderExtraNewlineToken(r: *Render, token_index: Ast.TokenIndex) Error!void {
|
|||||||
|
|
||||||
/// end_token is the token one past the last doc comment token. This function
|
/// end_token is the token one past the last doc comment token. This function
|
||||||
/// searches backwards from there.
|
/// searches backwards from there.
|
||||||
fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {
|
fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
// Search backwards for the first doc comment.
|
// Search backwards for the first doc comment.
|
||||||
if (end_token == 0) return;
|
if (end_token == 0) return;
|
||||||
@ -3069,7 +3065,7 @@ fn renderDocComments(r: *Render, end_token: Ast.TokenIndex) Error!void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// start_token is first container doc comment token.
|
/// start_token is first container doc comment token.
|
||||||
fn renderContainerDocComments(r: *Render, start_token: Ast.TokenIndex) Error!void {
|
fn renderContainerDocComments(r: *Render, start_token: Ast.TokenIndex) anyerror!void {
|
||||||
const tree = r.tree;
|
const tree = r.tree;
|
||||||
var tok = start_token;
|
var tok = start_token;
|
||||||
while (tree.tokenTag(tok) == .container_doc_comment) : (tok += 1) {
|
while (tree.tokenTag(tok) == .container_doc_comment) : (tok += 1) {
|
||||||
@ -3083,7 +3079,7 @@ fn renderContainerDocComments(r: *Render, start_token: Ast.TokenIndex) Error!voi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) Error!void {
|
fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) anyerror!void {
|
||||||
const tree = &r.tree;
|
const tree = &r.tree;
|
||||||
const ais = r.ais;
|
const ais = r.ais;
|
||||||
var buf: [1]Ast.Node.Index = undefined;
|
var buf: [1]Ast.Node.Index = undefined;
|
||||||
@ -3092,10 +3088,9 @@ fn discardAllParams(r: *Render, fn_proto_node: Ast.Node.Index) Error!void {
|
|||||||
while (it.next()) |param| {
|
while (it.next()) |param| {
|
||||||
const name_ident = param.name_token.?;
|
const name_ident = param.name_token.?;
|
||||||
assert(tree.tokenTag(name_ident) == .identifier);
|
assert(tree.tokenTag(name_ident) == .identifier);
|
||||||
const w = ais.writer();
|
try ais.writeAll("_ = ");
|
||||||
try w.writeAll("_ = ");
|
try ais.writeAll(tokenSliceForRender(r.tree, name_ident));
|
||||||
try w.writeAll(tokenSliceForRender(r.tree, name_ident));
|
try ais.writeAll(";\n");
|
||||||
try w.writeAll(";\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3132,11 +3127,11 @@ fn anythingBetween(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenI
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeFixingWhitespace(writer: std.ArrayList(u8).Writer, slice: []const u8) Error!void {
|
fn writeFixingWhitespace(bw: *std.io.BufferedWriter, slice: []const u8) anyerror!void {
|
||||||
for (slice) |byte| switch (byte) {
|
for (slice) |byte| switch (byte) {
|
||||||
'\t' => try writer.writeAll(" " ** indent_delta),
|
'\t' => try bw.splatByteAll(' ', indent_delta),
|
||||||
'\r' => {},
|
'\r' => {},
|
||||||
else => try writer.writeByte(byte),
|
else => try bw.writeByte(byte),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3261,11 +3256,18 @@ fn rowSize(tree: Ast, exprs: []const Ast.Node.Index, rtoken: Ast.TokenIndex) usi
|
|||||||
/// of the appropriate indentation level for them with pushSpace/popSpace.
|
/// of the appropriate indentation level for them with pushSpace/popSpace.
|
||||||
/// This should be done whenever a scope that ends in a .semicolon or a
|
/// This should be done whenever a scope that ends in a .semicolon or a
|
||||||
/// .comma is introduced.
|
/// .comma is introduced.
|
||||||
fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
|
const AutoIndentingStream = struct {
|
||||||
return struct {
|
underlying_writer: *std.io.BufferedWriter,
|
||||||
const Self = @This();
|
|
||||||
pub const WriteError = UnderlyingWriter.Error;
|
indent_count: usize = 0,
|
||||||
pub const Writer = std.io.Writer(*Self, WriteError, write);
|
indent_delta: usize,
|
||||||
|
indent_stack: std.ArrayList(StackElem),
|
||||||
|
space_stack: std.ArrayList(SpaceElem),
|
||||||
|
space_mode: ?usize = null,
|
||||||
|
disable_indent_committing: usize = 0,
|
||||||
|
current_line_empty: bool = true,
|
||||||
|
/// the most recently applied indent
|
||||||
|
applied_indent: usize = 0,
|
||||||
|
|
||||||
pub const IndentType = enum {
|
pub const IndentType = enum {
|
||||||
normal,
|
normal,
|
||||||
@ -3282,27 +3284,7 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
|
|||||||
indent_count: usize,
|
indent_count: usize,
|
||||||
};
|
};
|
||||||
|
|
||||||
underlying_writer: UnderlyingWriter,
|
pub fn init(buffer: *std.ArrayList(u8), indent_delta_: usize) AutoIndentingStream {
|
||||||
|
|
||||||
/// Offset into the source at which formatting has been disabled with
|
|
||||||
/// a `zig fmt: off` comment.
|
|
||||||
///
|
|
||||||
/// If non-null, the AutoIndentingStream will not write any bytes
|
|
||||||
/// to the underlying writer. It will however continue to track the
|
|
||||||
/// indentation level.
|
|
||||||
disabled_offset: ?usize = null,
|
|
||||||
|
|
||||||
indent_count: usize = 0,
|
|
||||||
indent_delta: usize,
|
|
||||||
indent_stack: std.ArrayList(StackElem),
|
|
||||||
space_stack: std.ArrayList(SpaceElem),
|
|
||||||
space_mode: ?usize = null,
|
|
||||||
disable_indent_committing: usize = 0,
|
|
||||||
current_line_empty: bool = true,
|
|
||||||
/// the most recently applied indent
|
|
||||||
applied_indent: usize = 0,
|
|
||||||
|
|
||||||
pub fn init(buffer: *std.ArrayList(u8), indent_delta_: usize) Self {
|
|
||||||
return .{
|
return .{
|
||||||
.underlying_writer = buffer.writer(),
|
.underlying_writer = buffer.writer(),
|
||||||
.indent_delta = indent_delta_,
|
.indent_delta = indent_delta_,
|
||||||
@ -3311,65 +3293,102 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Self) void {
|
pub fn deinit(self: *AutoIndentingStream) void {
|
||||||
self.indent_stack.deinit();
|
self.indent_stack.deinit();
|
||||||
self.space_stack.deinit();
|
self.space_stack.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn writer(self: *Self) Writer {
|
pub fn writeAll(ais: *AutoIndentingStream, bytes: []const u8) anyerror!void {
|
||||||
return .{ .context = self };
|
if (bytes.len == 0) return;
|
||||||
|
try ais.applyIndent();
|
||||||
|
if (ais.disabled_offset == null) try ais.underlying_writer.writeAll(bytes);
|
||||||
|
if (bytes[bytes.len - 1] == '\n') ais.resetLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(self: *Self, bytes: []const u8) WriteError!usize {
|
pub fn print(ais: *AutoIndentingStream, comptime format: []const u8, args: anytype) anyerror!void {
|
||||||
if (bytes.len == 0)
|
comptime assert(format[format.len - 1] != '}');
|
||||||
return @as(usize, 0);
|
try ais.applyIndent();
|
||||||
|
if (ais.disabled_offset == null) try ais.underlying_writer.print(format, args);
|
||||||
|
if (format[format.len - 1] == '\n') ais.resetLine();
|
||||||
|
}
|
||||||
|
|
||||||
try self.applyIndent();
|
pub fn writeByte(ais: *AutoIndentingStream, byte: u8) anyerror!void {
|
||||||
return self.writeNoIndent(bytes);
|
try ais.applyIndent();
|
||||||
|
if (ais.disabled_offset == null) try ais.underlying_writer.writeByte(byte);
|
||||||
|
assert(byte != '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn splatByteAll(ais: *AutoIndentingStream, byte: u8, n: usize) anyerror!void {
|
||||||
|
assert(byte != '\n');
|
||||||
|
try ais.applyIndent();
|
||||||
|
if (ais.disabled_offset == null) try ais.underlying_writer.splatByteAll(byte, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change the indent delta without changing the final indentation level
|
// Change the indent delta without changing the final indentation level
|
||||||
pub fn setIndentDelta(self: *Self, new_indent_delta: usize) void {
|
pub fn setIndentDelta(ais: *AutoIndentingStream, new_indent_delta: usize) void {
|
||||||
if (self.indent_delta == new_indent_delta) {
|
if (ais.indent_delta == new_indent_delta) {
|
||||||
return;
|
return;
|
||||||
} else if (self.indent_delta > new_indent_delta) {
|
} else if (ais.indent_delta > new_indent_delta) {
|
||||||
assert(self.indent_delta % new_indent_delta == 0);
|
assert(ais.indent_delta % new_indent_delta == 0);
|
||||||
self.indent_count = self.indent_count * (self.indent_delta / new_indent_delta);
|
ais.indent_count = ais.indent_count * (ais.indent_delta / new_indent_delta);
|
||||||
} else {
|
} else {
|
||||||
// assert that the current indentation (in spaces) in a multiple of the new delta
|
// 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);
|
assert((ais.indent_count * ais.indent_delta) % new_indent_delta == 0);
|
||||||
self.indent_count = self.indent_count / (new_indent_delta / self.indent_delta);
|
ais.indent_count = ais.indent_count / (new_indent_delta / ais.indent_delta);
|
||||||
}
|
}
|
||||||
self.indent_delta = new_indent_delta;
|
ais.indent_delta = new_indent_delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeNoIndent(self: *Self, bytes: []const u8) WriteError!usize {
|
pub fn insertNewline(ais: *AutoIndentingStream) anyerror!void {
|
||||||
if (bytes.len == 0)
|
if (ais.disabled_offset == null) try ais.underlying_writer.writeByte('\n');
|
||||||
return @as(usize, 0);
|
ais.resetLine();
|
||||||
|
|
||||||
if (self.disabled_offset == null) try self.underlying_writer.writeAll(bytes);
|
|
||||||
if (bytes[bytes.len - 1] == '\n')
|
|
||||||
self.resetLine();
|
|
||||||
return bytes.len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insertNewline(self: *Self) WriteError!void {
|
/// Insert a newline unless the current line is blank
|
||||||
_ = try self.writeNoIndent("\n");
|
pub fn maybeInsertNewline(ais: *AutoIndentingStream) anyerror!void {
|
||||||
|
if (!ais.current_line_empty)
|
||||||
|
try ais.insertNewline();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resetLine(self: *Self) void {
|
/// Push an indent that is automatically popped after being applied
|
||||||
self.current_line_empty = true;
|
pub fn pushIndentOneShot(ais: *AutoIndentingStream) void {
|
||||||
|
ais.indent_one_shot_count += 1;
|
||||||
|
ais.pushIndent();
|
||||||
|
}
|
||||||
|
|
||||||
if (self.disable_indent_committing > 0) return;
|
/// Turns all one-shot indents into regular indents
|
||||||
|
/// Returns number of indents that must now be manually popped
|
||||||
|
pub fn lockOneShotIndent(ais: *AutoIndentingStream) usize {
|
||||||
|
const locked_count = ais.indent_one_shot_count;
|
||||||
|
ais.indent_one_shot_count = 0;
|
||||||
|
return locked_count;
|
||||||
|
}
|
||||||
|
|
||||||
if (self.indent_stack.items.len > 0) {
|
/// Push an indent that should not take effect until the next line
|
||||||
|
pub fn pushIndentNextLine(ais: *AutoIndentingStream) void {
|
||||||
|
ais.indent_next_line += 1;
|
||||||
|
ais.pushIndent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks to see if the most recent indentation exceeds the currently pushed indents
|
||||||
|
pub fn isLineOverIndented(ais: *AutoIndentingStream) bool {
|
||||||
|
if (ais.current_line_empty) return false;
|
||||||
|
return ais.applied_indent > ais.currentIndent();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resetLine(ais: *AutoIndentingStream) void {
|
||||||
|
ais.current_line_empty = true;
|
||||||
|
|
||||||
|
if (ais.disable_indent_committing > 0) return;
|
||||||
|
|
||||||
|
if (ais.indent_stack.items.len > 0) {
|
||||||
// By default, we realize the most recent indentation scope.
|
// By default, we realize the most recent indentation scope.
|
||||||
var to_realize = self.indent_stack.items.len - 1;
|
var to_realize = ais.indent_stack.items.len - 1;
|
||||||
|
|
||||||
if (self.indent_stack.items.len >= 2 and
|
if (ais.indent_stack.items.len >= 2 and
|
||||||
self.indent_stack.items[to_realize - 1].indent_type == .after_equals and
|
ais.indent_stack.items[to_realize - 1].indent_type == .after_equals and
|
||||||
self.indent_stack.items[to_realize - 1].realized and
|
ais.indent_stack.items[to_realize - 1].realized and
|
||||||
self.indent_stack.items[to_realize].indent_type == .binop)
|
ais.indent_stack.items[to_realize].indent_type == .binop)
|
||||||
{
|
{
|
||||||
// If we are in a .binop scope and our direct parent is .after_equals, don't indent.
|
// If we are in a .binop scope and our direct parent is .after_equals, don't indent.
|
||||||
// This ensures correct indentation in the below example:
|
// This ensures correct indentation in the below example:
|
||||||
@ -3381,104 +3400,91 @@ fn AutoIndentingStream(comptime UnderlyingWriter: type) type {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.indent_stack.items[to_realize].indent_type == .field_access) {
|
if (ais.indent_stack.items[to_realize].indent_type == .field_access) {
|
||||||
// Only realize the top-most field_access in a chain.
|
// Only realize the top-most field_access in a chain.
|
||||||
while (to_realize > 0 and self.indent_stack.items[to_realize - 1].indent_type == .field_access)
|
while (to_realize > 0 and ais.indent_stack.items[to_realize - 1].indent_type == .field_access)
|
||||||
to_realize -= 1;
|
to_realize -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.indent_stack.items[to_realize].realized) return;
|
if (ais.indent_stack.items[to_realize].realized) return;
|
||||||
self.indent_stack.items[to_realize].realized = true;
|
ais.indent_stack.items[to_realize].realized = true;
|
||||||
self.indent_count += 1;
|
ais.indent_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disables indentation level changes during the next newlines until re-enabled.
|
/// Disables indentation level changes during the next newlines until re-enabled.
|
||||||
pub fn disableIndentCommitting(self: *Self) void {
|
pub fn disableIndentCommitting(ais: *AutoIndentingStream) void {
|
||||||
self.disable_indent_committing += 1;
|
ais.disable_indent_committing += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enableIndentCommitting(self: *Self) void {
|
pub fn enableIndentCommitting(ais: *AutoIndentingStream) void {
|
||||||
assert(self.disable_indent_committing > 0);
|
assert(ais.disable_indent_committing > 0);
|
||||||
self.disable_indent_committing -= 1;
|
ais.disable_indent_committing -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pushSpace(self: *Self, space: Space) !void {
|
pub fn pushSpace(ais: *AutoIndentingStream, space: Space) !void {
|
||||||
try self.space_stack.append(.{ .space = space, .indent_count = self.indent_count });
|
try ais.space_stack.append(.{ .space = space, .indent_count = ais.indent_count });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn popSpace(self: *Self) void {
|
pub fn popSpace(ais: *AutoIndentingStream) void {
|
||||||
_ = self.space_stack.pop();
|
_ = ais.space_stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets current indentation level to be the same as that of the last pushSpace.
|
/// Sets current indentation level to be the same as that of the last pushSpace.
|
||||||
pub fn enableSpaceMode(self: *Self, space: Space) void {
|
pub fn enableSpaceMode(ais: *AutoIndentingStream, space: Space) void {
|
||||||
if (self.space_stack.items.len == 0) return;
|
if (ais.space_stack.items.len == 0) return;
|
||||||
const curr = self.space_stack.getLast();
|
const curr = ais.space_stack.getLast();
|
||||||
if (curr.space != space) return;
|
if (curr.space != space) return;
|
||||||
self.space_mode = curr.indent_count;
|
ais.space_mode = curr.indent_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disableSpaceMode(self: *Self) void {
|
pub fn disableSpaceMode(ais: *AutoIndentingStream) void {
|
||||||
self.space_mode = null;
|
ais.space_mode = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lastSpaceModeIndent(self: *Self) usize {
|
pub fn lastSpaceModeIndent(ais: *AutoIndentingStream) usize {
|
||||||
if (self.space_stack.items.len == 0) return 0;
|
if (ais.space_stack.items.len == 0) return 0;
|
||||||
return self.space_stack.getLast().indent_count * self.indent_delta;
|
return ais.space_stack.getLast().indent_count * ais.indent_delta;
|
||||||
}
|
|
||||||
|
|
||||||
/// Insert a newline unless the current line is blank
|
|
||||||
pub fn maybeInsertNewline(self: *Self) WriteError!void {
|
|
||||||
if (!self.current_line_empty)
|
|
||||||
try self.insertNewline();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Push default indentation
|
/// Push default indentation
|
||||||
/// Doesn't actually write any indentation.
|
/// Doesn't actually write any indentation.
|
||||||
/// Just primes the stream to be able to write the correct indentation if it needs to.
|
/// Just primes the stream to be able to write the correct indentation if it needs to.
|
||||||
pub fn pushIndent(self: *Self, indent_type: IndentType) !void {
|
pub fn pushIndent(ais: *AutoIndentingStream, indent_type: IndentType) !void {
|
||||||
try self.indent_stack.append(.{ .indent_type = indent_type, .realized = false });
|
try ais.indent_stack.append(.{ .indent_type = indent_type, .realized = false });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Forces an indentation level to be realized.
|
/// Forces an indentation level to be realized.
|
||||||
pub fn forcePushIndent(self: *Self, indent_type: IndentType) !void {
|
pub fn forcePushIndent(ais: *AutoIndentingStream, indent_type: IndentType) !void {
|
||||||
try self.indent_stack.append(.{ .indent_type = indent_type, .realized = true });
|
try ais.indent_stack.append(.{ .indent_type = indent_type, .realized = true });
|
||||||
self.indent_count += 1;
|
ais.indent_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn popIndent(self: *Self) void {
|
pub fn popIndent(ais: *AutoIndentingStream) void {
|
||||||
if (self.indent_stack.pop().?.realized) {
|
if (ais.indent_stack.pop().?.realized) {
|
||||||
assert(self.indent_count > 0);
|
assert(ais.indent_count > 0);
|
||||||
self.indent_count -= 1;
|
ais.indent_count -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn indentStackEmpty(self: *Self) bool {
|
pub fn indentStackEmpty(ais: *AutoIndentingStream) bool {
|
||||||
return self.indent_stack.items.len == 0;
|
return ais.indent_stack.items.len == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes ' ' bytes if the current line is empty
|
/// Writes ' ' bytes if the current line is empty
|
||||||
fn applyIndent(self: *Self) WriteError!void {
|
fn applyIndent(ais: *AutoIndentingStream) anyerror!void {
|
||||||
const current_indent = self.currentIndent();
|
const current_indent = ais.currentIndent();
|
||||||
if (self.current_line_empty and current_indent > 0) {
|
if (ais.current_line_empty and current_indent > 0) {
|
||||||
if (self.disabled_offset == null) {
|
if (ais.disabled_offset == null) {
|
||||||
try self.underlying_writer.writeByteNTimes(' ', current_indent);
|
try ais.underlying_writer.writeByteNTimes(' ', current_indent);
|
||||||
}
|
}
|
||||||
self.applied_indent = current_indent;
|
ais.applied_indent = current_indent;
|
||||||
}
|
}
|
||||||
self.current_line_empty = false;
|
ais.current_line_empty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks to see if the most recent indentation exceeds the currently pushed indents
|
fn currentIndent(ais: *AutoIndentingStream) usize {
|
||||||
pub fn isLineOverIndented(self: *Self) bool {
|
const indent_count = ais.space_mode orelse ais.indent_count;
|
||||||
if (self.current_line_empty) return false;
|
return indent_count * ais.indent_delta;
|
||||||
return self.applied_indent > self.currentIndent();
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
fn currentIndent(self: *Self) usize {
|
|
||||||
const indent_count = self.space_mode orelse self.indent_count;
|
|
||||||
return indent_count * self.indent_delta;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|||||||
@ -322,9 +322,9 @@ test parseCharLiteral {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses `bytes` as a Zig string literal and writes the result to the std.io.Writer type.
|
/// Parses `bytes` as a Zig string literal and writes the result to the `std.io.Writer` type.
|
||||||
/// Asserts `bytes` has '"' at beginning and end.
|
/// Asserts `bytes` has '"' at beginning and end.
|
||||||
pub fn parseWrite(writer: anytype, bytes: []const u8) error{OutOfMemory}!Result {
|
pub fn parseWrite(writer: *std.io.BufferedWriter, bytes: []const u8) anyerror!Result {
|
||||||
assert(bytes.len >= 2 and bytes[0] == '"' and bytes[bytes.len - 1] == '"');
|
assert(bytes.len >= 2 and bytes[0] == '"' and bytes[bytes.len - 1] == '"');
|
||||||
|
|
||||||
var index: usize = 1;
|
var index: usize = 1;
|
||||||
@ -340,18 +340,18 @@ pub fn parseWrite(writer: anytype, bytes: []const u8) error{OutOfMemory}!Result
|
|||||||
if (bytes[escape_char_index] == 'u') {
|
if (bytes[escape_char_index] == 'u') {
|
||||||
var buf: [4]u8 = undefined;
|
var buf: [4]u8 = undefined;
|
||||||
const len = utf8Encode(codepoint, &buf) catch {
|
const len = utf8Encode(codepoint, &buf) catch {
|
||||||
return Result{ .failure = .{ .invalid_unicode_codepoint = escape_char_index + 1 } };
|
return .{ .failure = .{ .invalid_unicode_codepoint = escape_char_index + 1 } };
|
||||||
};
|
};
|
||||||
try writer.writeAll(buf[0..len]);
|
try writer.writeAll(buf[0..len]);
|
||||||
} else {
|
} else {
|
||||||
try writer.writeByte(@as(u8, @intCast(codepoint)));
|
try writer.writeByte(@as(u8, @intCast(codepoint)));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.failure => |err| return Result{ .failure = err },
|
.failure => |err| return .{ .failure = err },
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'\n' => return Result{ .failure = .{ .invalid_character = index } },
|
'\n' => return .{ .failure = .{ .invalid_character = index } },
|
||||||
'"' => return Result.success,
|
'"' => return .success,
|
||||||
else => {
|
else => {
|
||||||
try writer.writeByte(b);
|
try writer.writeByte(b);
|
||||||
index += 1;
|
index += 1;
|
||||||
@ -363,10 +363,12 @@ pub fn parseWrite(writer: anytype, bytes: []const u8) error{OutOfMemory}!Result
|
|||||||
/// Higher level API. Does not return extra info about parse errors.
|
/// Higher level API. Does not return extra info about parse errors.
|
||||||
/// Caller owns returned memory.
|
/// Caller owns returned memory.
|
||||||
pub fn parseAlloc(allocator: std.mem.Allocator, bytes: []const u8) ParseError![]u8 {
|
pub fn parseAlloc(allocator: std.mem.Allocator, bytes: []const u8) ParseError![]u8 {
|
||||||
var buf = std.ArrayList(u8).init(allocator);
|
var buf: std.io.AllocatingWriter = undefined;
|
||||||
|
const bw = buf.init(allocator);
|
||||||
defer buf.deinit();
|
defer buf.deinit();
|
||||||
|
// TODO try @errorCast(...)
|
||||||
switch (try parseWrite(buf.writer(), bytes)) {
|
const result = parseWrite(bw, bytes) catch |err| return @errorCast(err);
|
||||||
|
switch (result) {
|
||||||
.success => return buf.toOwnedSlice(),
|
.success => return buf.toOwnedSlice(),
|
||||||
.failure => return error.InvalidLiteral,
|
.failure => return error.InvalidLiteral,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
|
|
||||||
|
|
||||||
const build_options = @import("build_options");
|
const build_options = @import("build_options");
|
||||||
const Zcu = @import("../Zcu.zig");
|
const Zcu = @import("../Zcu.zig");
|
||||||
@ -25,20 +24,20 @@ pub fn write(air: Air, stream: anytype, pt: Zcu.PerThread, liveness: ?Air.Livene
|
|||||||
|
|
||||||
// zig fmt: off
|
// zig fmt: off
|
||||||
stream.print(
|
stream.print(
|
||||||
\\# Total AIR+Liveness bytes: {}
|
\\# Total AIR+Liveness bytes: {Bi}
|
||||||
\\# AIR Instructions: {d} ({})
|
\\# AIR Instructions: {d} ({Bi})
|
||||||
\\# AIR Extra Data: {d} ({})
|
\\# AIR Extra Data: {d} ({Bi})
|
||||||
\\# Liveness tomb_bits: {}
|
\\# Liveness tomb_bits: {Bi}
|
||||||
\\# Liveness Extra Data: {d} ({})
|
\\# Liveness Extra Data: {d} ({Bi})
|
||||||
\\# Liveness special table: {d} ({})
|
\\# Liveness special table: {d} ({Bi})
|
||||||
\\
|
\\
|
||||||
, .{
|
, .{
|
||||||
fmtIntSizeBin(total_bytes),
|
total_bytes,
|
||||||
air.instructions.len, fmtIntSizeBin(instruction_bytes),
|
air.instructions.len, instruction_bytes,
|
||||||
air.extra.items.len, fmtIntSizeBin(extra_bytes),
|
air.extra.items.len, extra_bytes,
|
||||||
fmtIntSizeBin(tomb_bytes),
|
tomb_bytes,
|
||||||
if (liveness) |l| l.extra.len else 0, fmtIntSizeBin(liveness_extra_bytes),
|
if (liveness) |l| l.extra.len else 0, liveness_extra_bytes,
|
||||||
if (liveness) |l| l.special.count() else 0, fmtIntSizeBin(liveness_special_bytes),
|
if (liveness) |l| l.special.count() else 0, liveness_special_bytes,
|
||||||
}) catch return;
|
}) catch return;
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
|
|
||||||
|
|||||||
@ -51,7 +51,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
|
|||||||
const zig_backend = opts.zig_backend;
|
const zig_backend = opts.zig_backend;
|
||||||
|
|
||||||
@setEvalBranchQuota(4000);
|
@setEvalBranchQuota(4000);
|
||||||
try buffer.writer().print(
|
try buffer.print(
|
||||||
\\const std = @import("std");
|
\\const std = @import("std");
|
||||||
\\/// Zig version. When writing code that supports multiple versions of Zig, prefer
|
\\/// Zig version. When writing code that supports multiple versions of Zig, prefer
|
||||||
\\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks.
|
\\/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks.
|
||||||
@ -89,10 +89,10 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
|
|||||||
const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize));
|
const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize));
|
||||||
const is_enabled = target.cpu.features.isEnabled(index);
|
const is_enabled = target.cpu.features.isEnabled(index);
|
||||||
if (is_enabled) {
|
if (is_enabled) {
|
||||||
try buffer.writer().print(" .{p_},\n", .{std.zig.fmtId(feature.name)});
|
try buffer.print(" .{p_},\n", .{std.zig.fmtId(feature.name)});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try buffer.writer().print(
|
try buffer.print(
|
||||||
\\ }}),
|
\\ }}),
|
||||||
\\}};
|
\\}};
|
||||||
\\pub const os: std.Target.Os = .{{
|
\\pub const os: std.Target.Os = .{{
|
||||||
@ -104,7 +104,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
|
|||||||
|
|
||||||
switch (target.os.versionRange()) {
|
switch (target.os.versionRange()) {
|
||||||
.none => try buffer.appendSlice(" .none = {} },\n"),
|
.none => try buffer.appendSlice(" .none = {} },\n"),
|
||||||
.semver => |semver| try buffer.writer().print(
|
.semver => |semver| try buffer.print(
|
||||||
\\ .semver = .{{
|
\\ .semver = .{{
|
||||||
\\ .min = .{{
|
\\ .min = .{{
|
||||||
\\ .major = {},
|
\\ .major = {},
|
||||||
@ -127,7 +127,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
|
|||||||
semver.max.minor,
|
semver.max.minor,
|
||||||
semver.max.patch,
|
semver.max.patch,
|
||||||
}),
|
}),
|
||||||
.linux => |linux| try buffer.writer().print(
|
.linux => |linux| try buffer.print(
|
||||||
\\ .linux = .{{
|
\\ .linux = .{{
|
||||||
\\ .range = .{{
|
\\ .range = .{{
|
||||||
\\ .min = .{{
|
\\ .min = .{{
|
||||||
@ -164,7 +164,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
|
|||||||
|
|
||||||
linux.android,
|
linux.android,
|
||||||
}),
|
}),
|
||||||
.hurd => |hurd| try buffer.writer().print(
|
.hurd => |hurd| try buffer.print(
|
||||||
\\ .hurd = .{{
|
\\ .hurd = .{{
|
||||||
\\ .range = .{{
|
\\ .range = .{{
|
||||||
\\ .min = .{{
|
\\ .min = .{{
|
||||||
@ -198,7 +198,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
|
|||||||
hurd.glibc.minor,
|
hurd.glibc.minor,
|
||||||
hurd.glibc.patch,
|
hurd.glibc.patch,
|
||||||
}),
|
}),
|
||||||
.windows => |windows| try buffer.writer().print(
|
.windows => |windows| try buffer.print(
|
||||||
\\ .windows = .{{
|
\\ .windows = .{{
|
||||||
\\ .min = {c},
|
\\ .min = {c},
|
||||||
\\ .max = {c},
|
\\ .max = {c},
|
||||||
@ -217,7 +217,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (target.dynamic_linker.get()) |dl| {
|
if (target.dynamic_linker.get()) |dl| {
|
||||||
try buffer.writer().print(
|
try buffer.print(
|
||||||
\\ .dynamic_linker = .init("{s}"),
|
\\ .dynamic_linker = .init("{s}"),
|
||||||
\\}};
|
\\}};
|
||||||
\\
|
\\
|
||||||
@ -237,7 +237,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
|
|||||||
// knows libc will provide it, and likewise c.zig will not export memcpy.
|
// knows libc will provide it, and likewise c.zig will not export memcpy.
|
||||||
const link_libc = opts.link_libc;
|
const link_libc = opts.link_libc;
|
||||||
|
|
||||||
try buffer.writer().print(
|
try buffer.print(
|
||||||
\\pub const object_format: std.Target.ObjectFormat = .{p_};
|
\\pub const object_format: std.Target.ObjectFormat = .{p_};
|
||||||
\\pub const mode: std.builtin.OptimizeMode = .{p_};
|
\\pub const mode: std.builtin.OptimizeMode = .{p_};
|
||||||
\\pub const link_libc = {};
|
\\pub const link_libc = {};
|
||||||
@ -269,7 +269,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (target.os.tag == .wasi) {
|
if (target.os.tag == .wasi) {
|
||||||
try buffer.writer().print(
|
try buffer.print(
|
||||||
\\pub const wasi_exec_model: std.builtin.WasiExecModel = .{p_};
|
\\pub const wasi_exec_model: std.builtin.WasiExecModel = .{p_};
|
||||||
\\
|
\\
|
||||||
, .{std.zig.fmtId(@tagName(opts.wasi_exec_model))});
|
, .{std.zig.fmtId(@tagName(opts.wasi_exec_model))});
|
||||||
|
|||||||
@ -1643,10 +1643,8 @@ fn dumpHashInfo(all_files: []const *const HashedFile) !void {
|
|||||||
const w = bw.writer();
|
const w = bw.writer();
|
||||||
|
|
||||||
for (all_files) |hashed_file| {
|
for (all_files) |hashed_file| {
|
||||||
try w.print("{s}: {s}: {s}\n", .{
|
try w.print("{s}: {x}: {s}\n", .{
|
||||||
@tagName(hashed_file.kind),
|
@tagName(hashed_file.kind), &hashed_file.hash, hashed_file.normalized_path,
|
||||||
std.fmt.fmtSliceHexLower(&hashed_file.hash),
|
|
||||||
hashed_file.normalized_path,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -127,7 +127,7 @@ pub const Oid = union(Format) {
|
|||||||
) @TypeOf(writer).Error!void {
|
) @TypeOf(writer).Error!void {
|
||||||
_ = fmt;
|
_ = fmt;
|
||||||
_ = options;
|
_ = options;
|
||||||
try writer.print("{}", .{std.fmt.fmtSliceHexLower(oid.slice())});
|
try writer.print("{x}", .{oid.slice()});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn slice(oid: *const Oid) []const u8 {
|
pub fn slice(oid: *const Oid) []const u8 {
|
||||||
|
|||||||
@ -477,11 +477,8 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
|
|||||||
if (std.zig.srcHashEql(old_hash, new_hash)) {
|
if (std.zig.srcHashEql(old_hash, new_hash)) {
|
||||||
break :hash_changed;
|
break :hash_changed;
|
||||||
}
|
}
|
||||||
log.debug("hash for (%{d} -> %{d}) changed: {} -> {}", .{
|
log.debug("hash for (%{d} -> %{d}) changed: {x} -> {x}", .{
|
||||||
old_inst,
|
old_inst, new_inst, &old_hash, &new_hash,
|
||||||
new_inst,
|
|
||||||
std.fmt.fmtSliceHexLower(&old_hash),
|
|
||||||
std.fmt.fmtSliceHexLower(&new_hash),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// The source hash associated with this instruction changed - invalidate relevant dependencies.
|
// The source hash associated with this instruction changed - invalidate relevant dependencies.
|
||||||
|
|||||||
@ -1205,9 +1205,9 @@ pub const Vex = struct {
|
|||||||
fn expectEqualHexStrings(expected: []const u8, given: []const u8, assembly: []const u8) !void {
|
fn expectEqualHexStrings(expected: []const u8, given: []const u8, assembly: []const u8) !void {
|
||||||
assert(expected.len > 0);
|
assert(expected.len > 0);
|
||||||
if (std.mem.eql(u8, expected, given)) return;
|
if (std.mem.eql(u8, expected, given)) return;
|
||||||
const expected_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{std.fmt.fmtSliceHexLower(expected)});
|
const expected_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{expected});
|
||||||
defer testing.allocator.free(expected_fmt);
|
defer testing.allocator.free(expected_fmt);
|
||||||
const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{std.fmt.fmtSliceHexLower(given)});
|
const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{given});
|
||||||
defer testing.allocator.free(given_fmt);
|
defer testing.allocator.free(given_fmt);
|
||||||
const idx = std.mem.indexOfDiff(u8, expected_fmt, given_fmt).?;
|
const idx = std.mem.indexOfDiff(u8, expected_fmt, given_fmt).?;
|
||||||
const padding = try testing.allocator.alloc(u8, idx + 5);
|
const padding = try testing.allocator.alloc(u8, idx + 5);
|
||||||
|
|||||||
40
src/fmt.zig
40
src/fmt.zig
@ -190,41 +190,7 @@ pub fn run(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const FmtError = error{
|
fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) anyerror!void {
|
||||||
SystemResources,
|
|
||||||
OperationAborted,
|
|
||||||
IoPending,
|
|
||||||
BrokenPipe,
|
|
||||||
Unexpected,
|
|
||||||
WouldBlock,
|
|
||||||
Canceled,
|
|
||||||
FileClosed,
|
|
||||||
DestinationAddressRequired,
|
|
||||||
DiskQuota,
|
|
||||||
FileTooBig,
|
|
||||||
MessageTooBig,
|
|
||||||
InputOutput,
|
|
||||||
NoSpaceLeft,
|
|
||||||
AccessDenied,
|
|
||||||
OutOfMemory,
|
|
||||||
RenameAcrossMountPoints,
|
|
||||||
ReadOnlyFileSystem,
|
|
||||||
LinkQuotaExceeded,
|
|
||||||
FileBusy,
|
|
||||||
EndOfStream,
|
|
||||||
Unseekable,
|
|
||||||
NotOpenForWriting,
|
|
||||||
UnsupportedEncoding,
|
|
||||||
InvalidEncoding,
|
|
||||||
ConnectionResetByPeer,
|
|
||||||
SocketNotConnected,
|
|
||||||
LockViolation,
|
|
||||||
NetNameDeleted,
|
|
||||||
InvalidArgument,
|
|
||||||
ProcessNotFound,
|
|
||||||
} || fs.File.OpenError;
|
|
||||||
|
|
||||||
fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) FmtError!void {
|
|
||||||
fmtPathFile(fmt, file_path, check_mode, dir, sub_path) catch |err| switch (err) {
|
fmtPathFile(fmt, file_path, check_mode, dir, sub_path) catch |err| switch (err) {
|
||||||
error.IsDir, error.AccessDenied => return fmtPathDir(fmt, file_path, check_mode, dir, sub_path),
|
error.IsDir, error.AccessDenied => return fmtPathDir(fmt, file_path, check_mode, dir, sub_path),
|
||||||
else => {
|
else => {
|
||||||
@ -241,7 +207,7 @@ fn fmtPathDir(
|
|||||||
check_mode: bool,
|
check_mode: bool,
|
||||||
parent_dir: fs.Dir,
|
parent_dir: fs.Dir,
|
||||||
parent_sub_path: []const u8,
|
parent_sub_path: []const u8,
|
||||||
) FmtError!void {
|
) anyerror!void {
|
||||||
var dir = try parent_dir.openDir(parent_sub_path, .{ .iterate = true });
|
var dir = try parent_dir.openDir(parent_sub_path, .{ .iterate = true });
|
||||||
defer dir.close();
|
defer dir.close();
|
||||||
|
|
||||||
@ -277,7 +243,7 @@ fn fmtPathFile(
|
|||||||
check_mode: bool,
|
check_mode: bool,
|
||||||
dir: fs.Dir,
|
dir: fs.Dir,
|
||||||
sub_path: []const u8,
|
sub_path: []const u8,
|
||||||
) FmtError!void {
|
) anyerror!void {
|
||||||
const source_file = try dir.openFile(sub_path, .{});
|
const source_file = try dir.openFile(sub_path, .{});
|
||||||
var file_closed = false;
|
var file_closed = false;
|
||||||
errdefer if (!file_closed) source_file.close();
|
errdefer if (!file_closed) source_file.close();
|
||||||
|
|||||||
@ -388,7 +388,7 @@ pub fn libExists(
|
|||||||
/// This function body is verbose but all it does is test 3 different paths and
|
/// This function body is verbose but all it does is test 3 different paths and
|
||||||
/// see if a .def file exists.
|
/// see if a .def file exists.
|
||||||
fn findDef(
|
fn findDef(
|
||||||
allocator: Allocator,
|
gpa: Allocator,
|
||||||
target: *const std.Target,
|
target: *const std.Target,
|
||||||
zig_lib_directory: Cache.Directory,
|
zig_lib_directory: Cache.Directory,
|
||||||
lib_name: []const u8,
|
lib_name: []const u8,
|
||||||
@ -401,7 +401,8 @@ fn findDef(
|
|||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
|
|
||||||
var override_path = std.ArrayList(u8).init(allocator);
|
var override_path: std.io.AllocatingWriter = undefined;
|
||||||
|
const override_path_writer = override_path.init(gpa);
|
||||||
defer override_path.deinit();
|
defer override_path.deinit();
|
||||||
|
|
||||||
const s = path.sep_str;
|
const s = path.sep_str;
|
||||||
@ -410,11 +411,11 @@ fn findDef(
|
|||||||
// Try the archtecture-specific path first.
|
// Try the archtecture-specific path first.
|
||||||
const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "{s}" ++ s ++ "{s}.def";
|
const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "{s}" ++ s ++ "{s}.def";
|
||||||
if (zig_lib_directory.path) |p| {
|
if (zig_lib_directory.path) |p| {
|
||||||
try override_path.writer().print("{s}" ++ s ++ fmt_path, .{ p, lib_path, lib_name });
|
try override_path_writer.print("{s}" ++ s ++ fmt_path, .{ p, lib_path, lib_name });
|
||||||
} else {
|
} else {
|
||||||
try override_path.writer().print(fmt_path, .{ lib_path, lib_name });
|
try override_path_writer.print(fmt_path, .{ lib_path, lib_name });
|
||||||
}
|
}
|
||||||
if (std.fs.cwd().access(override_path.items, .{})) |_| {
|
if (std.fs.cwd().access(override_path.getWritten(), .{})) |_| {
|
||||||
return override_path.toOwnedSlice();
|
return override_path.toOwnedSlice();
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
error.FileNotFound => {},
|
error.FileNotFound => {},
|
||||||
@ -424,14 +425,14 @@ fn findDef(
|
|||||||
|
|
||||||
{
|
{
|
||||||
// Try the generic version.
|
// Try the generic version.
|
||||||
override_path.shrinkRetainingCapacity(0);
|
override_path.clearRetainingCapacity();
|
||||||
const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def";
|
const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def";
|
||||||
if (zig_lib_directory.path) |p| {
|
if (zig_lib_directory.path) |p| {
|
||||||
try override_path.writer().print("{s}" ++ s ++ fmt_path, .{ p, lib_name });
|
try override_path_writer.print("{s}" ++ s ++ fmt_path, .{ p, lib_name });
|
||||||
} else {
|
} else {
|
||||||
try override_path.writer().print(fmt_path, .{lib_name});
|
try override_path_writer.print(fmt_path, .{lib_name});
|
||||||
}
|
}
|
||||||
if (std.fs.cwd().access(override_path.items, .{})) |_| {
|
if (std.fs.cwd().access(override_path.getWritten(), .{})) |_| {
|
||||||
return override_path.toOwnedSlice();
|
return override_path.toOwnedSlice();
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
error.FileNotFound => {},
|
error.FileNotFound => {},
|
||||||
@ -441,14 +442,14 @@ fn findDef(
|
|||||||
|
|
||||||
{
|
{
|
||||||
// Try the generic version and preprocess it.
|
// Try the generic version and preprocess it.
|
||||||
override_path.shrinkRetainingCapacity(0);
|
override_path.clearRetainingCapacity();
|
||||||
const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def.in";
|
const fmt_path = "libc" ++ s ++ "mingw" ++ s ++ "lib-common" ++ s ++ "{s}.def.in";
|
||||||
if (zig_lib_directory.path) |p| {
|
if (zig_lib_directory.path) |p| {
|
||||||
try override_path.writer().print("{s}" ++ s ++ fmt_path, .{ p, lib_name });
|
try override_path_writer.print("{s}" ++ s ++ fmt_path, .{ p, lib_name });
|
||||||
} else {
|
} else {
|
||||||
try override_path.writer().print(fmt_path, .{lib_name});
|
try override_path_writer.print(fmt_path, .{lib_name});
|
||||||
}
|
}
|
||||||
if (std.fs.cwd().access(override_path.items, .{})) |_| {
|
if (std.fs.cwd().access(override_path.getWritten(), .{})) |_| {
|
||||||
return override_path.toOwnedSlice();
|
return override_path.toOwnedSlice();
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
error.FileNotFound => {},
|
error.FileNotFound => {},
|
||||||
|
|||||||
@ -830,8 +830,8 @@ fn debugMem(allocator: Allocator, handle: std.process.Child.Id, pvaddr: std.os.w
|
|||||||
const buffer = try allocator.alloc(u8, code.len);
|
const buffer = try allocator.alloc(u8, code.len);
|
||||||
defer allocator.free(buffer);
|
defer allocator.free(buffer);
|
||||||
const memread = try std.os.windows.ReadProcessMemory(handle, pvaddr, buffer);
|
const memread = try std.os.windows.ReadProcessMemory(handle, pvaddr, buffer);
|
||||||
log.debug("to write: {x}", .{std.fmt.fmtSliceHexLower(code)});
|
log.debug("to write: {x}", .{code});
|
||||||
log.debug("in memory: {x}", .{std.fmt.fmtSliceHexLower(memread)});
|
log.debug("in memory: {x}", .{memread});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeMemProtected(handle: std.process.Child.Id, pvaddr: std.os.windows.LPVOID, code: []const u8) !void {
|
fn writeMemProtected(handle: std.process.Child.Id, pvaddr: std.os.windows.LPVOID, code: []const u8) !void {
|
||||||
|
|||||||
@ -336,9 +336,9 @@ const Edge = struct {
|
|||||||
fn expectEqualHexStrings(expected: []const u8, given: []const u8) !void {
|
fn expectEqualHexStrings(expected: []const u8, given: []const u8) !void {
|
||||||
assert(expected.len > 0);
|
assert(expected.len > 0);
|
||||||
if (mem.eql(u8, expected, given)) return;
|
if (mem.eql(u8, expected, given)) return;
|
||||||
const expected_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{std.fmt.fmtSliceHexLower(expected)});
|
const expected_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{expected});
|
||||||
defer testing.allocator.free(expected_fmt);
|
defer testing.allocator.free(expected_fmt);
|
||||||
const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{std.fmt.fmtSliceHexLower(given)});
|
const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{given});
|
||||||
defer testing.allocator.free(given_fmt);
|
defer testing.allocator.free(given_fmt);
|
||||||
const idx = mem.indexOfDiff(u8, expected_fmt, given_fmt).?;
|
const idx = mem.indexOfDiff(u8, expected_fmt, given_fmt).?;
|
||||||
const padding = try testing.allocator.alloc(u8, idx + 5);
|
const padding = try testing.allocator.alloc(u8, idx + 5);
|
||||||
|
|||||||
@ -1035,20 +1035,14 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void {
|
|||||||
var id: [16]u8 = undefined;
|
var id: [16]u8 = undefined;
|
||||||
std.crypto.hash.sha3.TurboShake128(null).hash(binary_bytes.items, &id, .{});
|
std.crypto.hash.sha3.TurboShake128(null).hash(binary_bytes.items, &id, .{});
|
||||||
var uuid: [36]u8 = undefined;
|
var uuid: [36]u8 = undefined;
|
||||||
_ = try std.fmt.bufPrint(&uuid, "{s}-{s}-{s}-{s}-{s}", .{
|
_ = try std.fmt.bufPrint(&uuid, "{x}-{x}-{x}-{x}-{x}", .{
|
||||||
std.fmt.fmtSliceHexLower(id[0..4]),
|
id[0..4], id[4..6], id[6..8], id[8..10], id[10..],
|
||||||
std.fmt.fmtSliceHexLower(id[4..6]),
|
|
||||||
std.fmt.fmtSliceHexLower(id[6..8]),
|
|
||||||
std.fmt.fmtSliceHexLower(id[8..10]),
|
|
||||||
std.fmt.fmtSliceHexLower(id[10..]),
|
|
||||||
});
|
});
|
||||||
try emitBuildIdSection(gpa, binary_bytes, &uuid);
|
try emitBuildIdSection(gpa, binary_bytes, &uuid);
|
||||||
},
|
},
|
||||||
.hexstring => |hs| {
|
.hexstring => |hs| {
|
||||||
var buffer: [32 * 2]u8 = undefined;
|
var buffer: [32 * 2]u8 = undefined;
|
||||||
const str = std.fmt.bufPrint(&buffer, "{s}", .{
|
const str = std.fmt.bufPrint(&buffer, "{x}", .{hs.toSlice()}) catch unreachable;
|
||||||
std.fmt.fmtSliceHexLower(hs.toSlice()),
|
|
||||||
}) catch unreachable;
|
|
||||||
try emitBuildIdSection(gpa, binary_bytes, str);
|
try emitBuildIdSection(gpa, binary_bytes, str);
|
||||||
},
|
},
|
||||||
else => |mode| {
|
else => |mode| {
|
||||||
|
|||||||
131
src/main.zig
131
src/main.zig
@ -65,6 +65,9 @@ pub fn wasi_cwd() std.os.wasi.fd_t {
|
|||||||
|
|
||||||
const fatal = std.process.fatal;
|
const fatal = std.process.fatal;
|
||||||
|
|
||||||
|
/// This can be global since stdout is a singleton.
|
||||||
|
var stdout_buffer: [4096]u8 = undefined;
|
||||||
|
|
||||||
/// Shaming all the locations that inappropriately use an O(N) search algorithm.
|
/// Shaming all the locations that inappropriately use an O(N) search algorithm.
|
||||||
/// Please delete this and fix the compilation errors!
|
/// Please delete this and fix the compilation errors!
|
||||||
pub const @"bad O(N)" = void;
|
pub const @"bad O(N)" = void;
|
||||||
@ -338,9 +341,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
|
|||||||
return cmdInit(gpa, arena, cmd_args);
|
return cmdInit(gpa, arena, cmd_args);
|
||||||
} else if (mem.eql(u8, cmd, "targets")) {
|
} else if (mem.eql(u8, cmd, "targets")) {
|
||||||
dev.check(.targets_command);
|
dev.check(.targets_command);
|
||||||
const host = std.zig.resolveTargetQueryOrFatal(.{});
|
return @import("print_targets.zig").cmdTargets(arena, cmd_args);
|
||||||
const stdout = io.getStdOut().writer();
|
|
||||||
return @import("print_targets.zig").cmdTargets(arena, cmd_args, stdout, &host);
|
|
||||||
} else if (mem.eql(u8, cmd, "version")) {
|
} else if (mem.eql(u8, cmd, "version")) {
|
||||||
dev.check(.version_command);
|
dev.check(.version_command);
|
||||||
try std.io.getStdOut().writeAll(build_options.version ++ "\n");
|
try std.io.getStdOut().writeAll(build_options.version ++ "\n");
|
||||||
@ -351,7 +352,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
|
|||||||
} else if (mem.eql(u8, cmd, "env")) {
|
} else if (mem.eql(u8, cmd, "env")) {
|
||||||
dev.check(.env_command);
|
dev.check(.env_command);
|
||||||
verifyLibcxxCorrectlyLinked();
|
verifyLibcxxCorrectlyLinked();
|
||||||
return @import("print_env.zig").cmdEnv(arena, cmd_args, io.getStdOut().writer());
|
return @import("print_env.zig").cmdEnv(arena, cmd_args);
|
||||||
} else if (mem.eql(u8, cmd, "reduce")) {
|
} else if (mem.eql(u8, cmd, "reduce")) {
|
||||||
return jitCmd(gpa, arena, cmd_args, .{
|
return jitCmd(gpa, arena, cmd_args, .{
|
||||||
.cmd_name = "reduce",
|
.cmd_name = "reduce",
|
||||||
@ -3334,9 +3335,8 @@ fn buildOutputType(
|
|||||||
var bin_digest: Cache.BinDigest = undefined;
|
var bin_digest: Cache.BinDigest = undefined;
|
||||||
hasher.final(&bin_digest);
|
hasher.final(&bin_digest);
|
||||||
|
|
||||||
const sub_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{s}-stdin{s}", .{
|
const sub_path = try std.fmt.allocPrint(arena, "tmp" ++ sep ++ "{x}-stdin{s}", .{
|
||||||
std.fmt.fmtSliceHexLower(&bin_digest),
|
&bin_digest, ext.canonicalName(target),
|
||||||
ext.canonicalName(target),
|
|
||||||
});
|
});
|
||||||
try dirs.local_cache.handle.rename(dump_path, sub_path);
|
try dirs.local_cache.handle.rename(dump_path, sub_path);
|
||||||
|
|
||||||
@ -6061,6 +6061,11 @@ fn cmdAstCheck(
|
|||||||
|
|
||||||
const tree = try Ast.parse(arena, source, mode);
|
const tree = try Ast.parse(arena, source, mode);
|
||||||
|
|
||||||
|
var bw: std.io.BufferedWriter = .{
|
||||||
|
.unbuffered_writer = io.getStdOut().writer(),
|
||||||
|
.buffer = &stdout_buffer,
|
||||||
|
};
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
.zig => {
|
.zig => {
|
||||||
const zir = try AstGen.generate(arena, tree);
|
const zir = try AstGen.generate(arena, tree);
|
||||||
@ -6103,31 +6108,30 @@ fn cmdAstCheck(
|
|||||||
const extra_bytes = zir.extra.len * @sizeOf(u32);
|
const extra_bytes = zir.extra.len * @sizeOf(u32);
|
||||||
const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes +
|
const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes +
|
||||||
zir.string_bytes.len * @sizeOf(u8);
|
zir.string_bytes.len * @sizeOf(u8);
|
||||||
const stdout = io.getStdOut();
|
|
||||||
const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
|
|
||||||
// zig fmt: off
|
// zig fmt: off
|
||||||
try stdout.writer().print(
|
try bw.print(
|
||||||
\\# Source bytes: {}
|
\\# Source bytes: {Bi}
|
||||||
\\# Tokens: {} ({})
|
\\# Tokens: {} ({Bi})
|
||||||
\\# AST Nodes: {} ({})
|
\\# AST Nodes: {} ({Bi})
|
||||||
\\# Total ZIR bytes: {}
|
\\# Total ZIR bytes: {Bi}
|
||||||
\\# Instructions: {d} ({})
|
\\# Instructions: {d} ({Bi})
|
||||||
\\# String Table Bytes: {}
|
\\# String Table Bytes: {}
|
||||||
\\# Extra Data Items: {d} ({})
|
\\# Extra Data Items: {d} ({Bi})
|
||||||
\\
|
\\
|
||||||
, .{
|
, .{
|
||||||
fmtIntSizeBin(source.len),
|
source.len,
|
||||||
tree.tokens.len, fmtIntSizeBin(token_bytes),
|
tree.tokens.len, token_bytes,
|
||||||
tree.nodes.len, fmtIntSizeBin(tree_bytes),
|
tree.nodes.len, tree_bytes,
|
||||||
fmtIntSizeBin(total_bytes),
|
total_bytes,
|
||||||
zir.instructions.len, fmtIntSizeBin(instruction_bytes),
|
zir.instructions.len, instruction_bytes,
|
||||||
fmtIntSizeBin(zir.string_bytes.len),
|
zir.string_bytes.len,
|
||||||
zir.extra.len, fmtIntSizeBin(extra_bytes),
|
zir.extra.len, extra_bytes,
|
||||||
});
|
});
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
}
|
}
|
||||||
|
|
||||||
try @import("print_zir.zig").renderAsTextToFile(arena, tree, zir, io.getStdOut());
|
try @import("print_zir.zig").renderAsText(arena, tree, zir, &bw);
|
||||||
|
try bw.flush();
|
||||||
|
|
||||||
if (zir.hasCompileErrors()) {
|
if (zir.hasCompileErrors()) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
@ -6154,7 +6158,8 @@ fn cmdAstCheck(
|
|||||||
fatal("-t option only available in builds of zig with debug extensions", .{});
|
fatal("-t option only available in builds of zig with debug extensions", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
try @import("print_zoir.zig").renderToFile(zoir, arena, io.getStdOut());
|
try @import("print_zoir.zig").renderToWriter(zoir, arena, &bw);
|
||||||
|
try bw.flush();
|
||||||
return cleanExit();
|
return cleanExit();
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -6275,11 +6280,13 @@ fn detectNativeCpuWithLLVM(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn printCpu(cpu: std.Target.Cpu) !void {
|
fn printCpu(cpu: std.Target.Cpu) !void {
|
||||||
var bw = io.bufferedWriter(io.getStdOut().writer());
|
var bw: std.io.BufferedWriter = .{
|
||||||
const stdout = bw.writer();
|
.unbuffered_writer = io.getStdOut().writer(),
|
||||||
|
.buffer = &stdout_buffer,
|
||||||
|
};
|
||||||
|
|
||||||
if (cpu.model.llvm_name) |llvm_name| {
|
if (cpu.model.llvm_name) |llvm_name| {
|
||||||
try stdout.print("{s}\n", .{llvm_name});
|
try bw.print("{s}\n", .{llvm_name});
|
||||||
}
|
}
|
||||||
|
|
||||||
const all_features = cpu.arch.allFeaturesList();
|
const all_features = cpu.arch.allFeaturesList();
|
||||||
@ -6288,7 +6295,7 @@ fn printCpu(cpu: std.Target.Cpu) !void {
|
|||||||
const index: std.Target.Cpu.Feature.Set.Index = @intCast(index_usize);
|
const index: std.Target.Cpu.Feature.Set.Index = @intCast(index_usize);
|
||||||
const is_enabled = cpu.features.isEnabled(index);
|
const is_enabled = cpu.features.isEnabled(index);
|
||||||
const plus_or_minus = "-+"[@intFromBool(is_enabled)];
|
const plus_or_minus = "-+"[@intFromBool(is_enabled)];
|
||||||
try stdout.print("{c}{s}\n", .{ plus_or_minus, llvm_name });
|
try bw.print("{c}{s}\n", .{ plus_or_minus, llvm_name });
|
||||||
}
|
}
|
||||||
|
|
||||||
try bw.flush();
|
try bw.flush();
|
||||||
@ -6356,6 +6363,11 @@ fn cmdDumpZir(
|
|||||||
|
|
||||||
const zir = try Zcu.loadZirCache(arena, f);
|
const zir = try Zcu.loadZirCache(arena, f);
|
||||||
|
|
||||||
|
var bw: std.io.BufferedWriter = .{
|
||||||
|
.unbuffered_writer = io.getStdOut().writer(),
|
||||||
|
.buffer = &stdout_buffer,
|
||||||
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
const instruction_bytes = zir.instructions.len *
|
const instruction_bytes = zir.instructions.len *
|
||||||
// Here we don't use @sizeOf(Zir.Inst.Data) because it would include
|
// Here we don't use @sizeOf(Zir.Inst.Data) because it would include
|
||||||
@ -6364,25 +6376,24 @@ fn cmdDumpZir(
|
|||||||
const extra_bytes = zir.extra.len * @sizeOf(u32);
|
const extra_bytes = zir.extra.len * @sizeOf(u32);
|
||||||
const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes +
|
const total_bytes = @sizeOf(Zir) + instruction_bytes + extra_bytes +
|
||||||
zir.string_bytes.len * @sizeOf(u8);
|
zir.string_bytes.len * @sizeOf(u8);
|
||||||
const stdout = io.getStdOut();
|
|
||||||
const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
|
|
||||||
// zig fmt: off
|
// zig fmt: off
|
||||||
try stdout.writer().print(
|
try bw.print(
|
||||||
\\# Total ZIR bytes: {}
|
\\# Total ZIR bytes: {Bi}
|
||||||
\\# Instructions: {d} ({})
|
\\# Instructions: {d} ({Bi})
|
||||||
\\# String Table Bytes: {}
|
\\# String Table Bytes: {Bi}
|
||||||
\\# Extra Data Items: {d} ({})
|
\\# Extra Data Items: {d} ({Bi})
|
||||||
\\
|
\\
|
||||||
, .{
|
, .{
|
||||||
fmtIntSizeBin(total_bytes),
|
total_bytes,
|
||||||
zir.instructions.len, fmtIntSizeBin(instruction_bytes),
|
zir.instructions.len, instruction_bytes,
|
||||||
fmtIntSizeBin(zir.string_bytes.len),
|
zir.string_bytes.len,
|
||||||
zir.extra.len, fmtIntSizeBin(extra_bytes),
|
zir.extra.len, extra_bytes,
|
||||||
});
|
});
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
}
|
}
|
||||||
|
|
||||||
return @import("print_zir.zig").renderAsTextToFile(arena, null, zir, io.getStdOut());
|
try @import("print_zir.zig").renderAsText(arena, null, zir, &bw);
|
||||||
|
try bw.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is only enabled for debug builds.
|
/// This is only enabled for debug builds.
|
||||||
@ -6440,13 +6451,15 @@ fn cmdChangelist(
|
|||||||
var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty;
|
var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .empty;
|
||||||
try Zcu.mapOldZirToNew(arena, old_zir, new_zir, &inst_map);
|
try Zcu.mapOldZirToNew(arena, old_zir, new_zir, &inst_map);
|
||||||
|
|
||||||
var bw = io.bufferedWriter(io.getStdOut().writer());
|
var bw: std.io.BufferedWriter = .{
|
||||||
const stdout = bw.writer();
|
.unbuffered_writer = io.getStdOut().writer(),
|
||||||
|
.buffer = &stdout_buffer,
|
||||||
|
};
|
||||||
{
|
{
|
||||||
try stdout.print("Instruction mappings:\n", .{});
|
try bw.print("Instruction mappings:\n", .{});
|
||||||
var it = inst_map.iterator();
|
var it = inst_map.iterator();
|
||||||
while (it.next()) |entry| {
|
while (it.next()) |entry| {
|
||||||
try stdout.print(" %{d} => %{d}\n", .{
|
try bw.print(" %{d} => %{d}\n", .{
|
||||||
@intFromEnum(entry.key_ptr.*),
|
@intFromEnum(entry.key_ptr.*),
|
||||||
@intFromEnum(entry.value_ptr.*),
|
@intFromEnum(entry.value_ptr.*),
|
||||||
});
|
});
|
||||||
@ -6714,13 +6727,10 @@ fn accessFrameworkPath(
|
|||||||
|
|
||||||
for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
|
for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
|
||||||
test_path.clearRetainingCapacity();
|
test_path.clearRetainingCapacity();
|
||||||
try test_path.writer().print("{s}" ++ sep ++ "{s}.framework" ++ sep ++ "{s}{s}", .{
|
try test_path.print("{s}" ++ sep ++ "{s}.framework" ++ sep ++ "{s}{s}", .{
|
||||||
framework_dir_path,
|
framework_dir_path, framework_name, framework_name, ext,
|
||||||
framework_name,
|
|
||||||
framework_name,
|
|
||||||
ext,
|
|
||||||
});
|
});
|
||||||
try checked_paths.writer().print("\n {s}", .{test_path.items});
|
try checked_paths.print("\n {s}", .{test_path.items});
|
||||||
fs.cwd().access(test_path.items, .{}) catch |err| switch (err) {
|
fs.cwd().access(test_path.items, .{}) catch |err| switch (err) {
|
||||||
error.FileNotFound => continue,
|
error.FileNotFound => continue,
|
||||||
else => |e| fatal("unable to search for {s} framework '{s}': {s}", .{
|
else => |e| fatal("unable to search for {s} framework '{s}': {s}", .{
|
||||||
@ -7033,14 +7043,19 @@ fn cmdFetch(
|
|||||||
try fixups.append_string_after_node.put(gpa, manifest.version_node, dependencies_text);
|
try fixups.append_string_after_node.put(gpa, manifest.version_node, dependencies_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
var rendered = std.ArrayList(u8).init(gpa);
|
var file = build_root.directory.handle.createFile(Package.Manifest.basename, .{}) catch |err| {
|
||||||
defer rendered.deinit();
|
fatal("unable to create {s} file: {s}", .{ Package.Manifest.basename, err });
|
||||||
try ast.renderToArrayList(&rendered, fixups);
|
|
||||||
|
|
||||||
build_root.directory.handle.writeFile(.{ .sub_path = Package.Manifest.basename, .data = rendered.items }) catch |err| {
|
|
||||||
fatal("unable to write {s} file: {s}", .{ Package.Manifest.basename, @errorName(err) });
|
|
||||||
};
|
};
|
||||||
|
defer file.close();
|
||||||
|
var buffer: [4096]u8 = undefined;
|
||||||
|
var bw: std.io.BufferedWriter = .{
|
||||||
|
.unbuffered_writer = file.writer(),
|
||||||
|
.buffer = &buffer,
|
||||||
|
};
|
||||||
|
ast.render(gpa, &bw, fixups) catch |err| fatal("failed to render AST to {s}: {s}", .{
|
||||||
|
Package.Manifest.basename, err,
|
||||||
|
});
|
||||||
|
bw.flush() catch |err| fatal("failed to flush {s}: {s}", .{ Package.Manifest.basename, err });
|
||||||
return cleanExit();
|
return cleanExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ const introspect = @import("introspect.zig");
|
|||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const fatal = std.process.fatal;
|
const fatal = std.process.fatal;
|
||||||
|
|
||||||
pub fn cmdEnv(arena: Allocator, args: []const []const u8, stdout: std.fs.File.Writer) !void {
|
pub fn cmdEnv(arena: Allocator, args: []const []const u8) !void {
|
||||||
_ = args;
|
_ = args;
|
||||||
const cwd_path = try introspect.getResolvedCwd(arena);
|
const cwd_path = try introspect.getResolvedCwd(arena);
|
||||||
const self_exe_path = try std.fs.selfExePathAlloc(arena);
|
const self_exe_path = try std.fs.selfExePathAlloc(arena);
|
||||||
@ -21,10 +21,12 @@ pub fn cmdEnv(arena: Allocator, args: []const []const u8, stdout: std.fs.File.Wr
|
|||||||
const host = try std.zig.system.resolveTargetQuery(.{});
|
const host = try std.zig.system.resolveTargetQuery(.{});
|
||||||
const triple = try host.zigTriple(arena);
|
const triple = try host.zigTriple(arena);
|
||||||
|
|
||||||
var bw = std.io.bufferedWriter(stdout);
|
var buffer: [1024]u8 = undefined;
|
||||||
const w = bw.writer();
|
var bw: std.io.BufferedWriter = .{
|
||||||
|
.buffer = &buffer,
|
||||||
var jws = std.json.writeStream(w, .{ .whitespace = .indent_1 });
|
.unbuffered_writer = std.io.getStdOut().writer(),
|
||||||
|
};
|
||||||
|
var jws = std.json.writeStream(bw, .{ .whitespace = .indent_1 });
|
||||||
|
|
||||||
try jws.beginObject();
|
try jws.beginObject();
|
||||||
|
|
||||||
@ -55,7 +57,7 @@ pub fn cmdEnv(arena: Allocator, args: []const []const u8, stdout: std.fs.File.Wr
|
|||||||
try jws.endObject();
|
try jws.endObject();
|
||||||
|
|
||||||
try jws.endObject();
|
try jws.endObject();
|
||||||
try w.writeByte('\n');
|
try bw.writeByte('\n');
|
||||||
|
|
||||||
try bw.flush();
|
try bw.flush();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,36 +11,36 @@ const assert = std.debug.assert;
|
|||||||
const glibc = @import("libs/glibc.zig");
|
const glibc = @import("libs/glibc.zig");
|
||||||
const introspect = @import("introspect.zig");
|
const introspect = @import("introspect.zig");
|
||||||
|
|
||||||
pub fn cmdTargets(
|
pub fn cmdTargets(arena: Allocator, args: []const []const u8) anyerror!void {
|
||||||
allocator: Allocator,
|
|
||||||
args: []const []const u8,
|
|
||||||
/// Output stream
|
|
||||||
stdout: anytype,
|
|
||||||
native_target: *const Target,
|
|
||||||
) !void {
|
|
||||||
_ = args;
|
_ = args;
|
||||||
var zig_lib_directory = introspect.findZigLibDir(allocator) catch |err| {
|
const host = std.zig.resolveTargetQueryOrFatal(.{});
|
||||||
|
var buffer: [1024]u8 = undefined;
|
||||||
|
var bw: std.io.BufferedWriter = .{
|
||||||
|
.unbuffered_writer = io.getStdOut().writer(),
|
||||||
|
.buffer = &buffer,
|
||||||
|
};
|
||||||
|
try print(arena, &bw, host);
|
||||||
|
try bw.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print(arena: Allocator, output: *std.io.BufferedWriter, host: *const Target) anyerror!void {
|
||||||
|
var zig_lib_directory = introspect.findZigLibDir(arena) catch |err| {
|
||||||
fatal("unable to find zig installation directory: {s}\n", .{@errorName(err)});
|
fatal("unable to find zig installation directory: {s}\n", .{@errorName(err)});
|
||||||
};
|
};
|
||||||
defer zig_lib_directory.handle.close();
|
defer zig_lib_directory.handle.close();
|
||||||
defer allocator.free(zig_lib_directory.path.?);
|
|
||||||
|
|
||||||
const abilists_contents = zig_lib_directory.handle.readFileAlloc(
|
const abilists_contents = zig_lib_directory.handle.readFileAlloc(
|
||||||
allocator,
|
arena,
|
||||||
glibc.abilists_path,
|
glibc.abilists_path,
|
||||||
glibc.abilists_max_size,
|
glibc.abilists_max_size,
|
||||||
) catch |err| switch (err) {
|
) catch |err| switch (err) {
|
||||||
error.OutOfMemory => return error.OutOfMemory,
|
error.OutOfMemory => return error.OutOfMemory,
|
||||||
else => fatal("unable to read " ++ glibc.abilists_path ++ ": {s}", .{@errorName(err)}),
|
else => fatal("unable to read " ++ glibc.abilists_path ++ ": {s}", .{@errorName(err)}),
|
||||||
};
|
};
|
||||||
defer allocator.free(abilists_contents);
|
|
||||||
|
|
||||||
const glibc_abi = try glibc.loadMetaData(allocator, abilists_contents);
|
const glibc_abi = try glibc.loadMetaData(arena, abilists_contents);
|
||||||
defer glibc_abi.destroy(allocator);
|
|
||||||
|
|
||||||
var bw = io.bufferedWriter(stdout);
|
var sz = std.zon.stringify.serializer(output, .{});
|
||||||
const w = bw.writer();
|
|
||||||
var sz = std.zon.stringify.serializer(w, .{});
|
|
||||||
|
|
||||||
{
|
{
|
||||||
var root_obj = try sz.beginStruct(.{});
|
var root_obj = try sz.beginStruct(.{});
|
||||||
@ -52,10 +52,9 @@ pub fn cmdTargets(
|
|||||||
{
|
{
|
||||||
var libc_obj = try root_obj.beginTupleField("libc", .{});
|
var libc_obj = try root_obj.beginTupleField("libc", .{});
|
||||||
for (std.zig.target.available_libcs) |libc| {
|
for (std.zig.target.available_libcs) |libc| {
|
||||||
const tmp = try std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{
|
const tmp = try std.fmt.allocPrint(arena, "{s}-{s}-{s}", .{
|
||||||
@tagName(libc.arch), @tagName(libc.os), @tagName(libc.abi),
|
@tagName(libc.arch), @tagName(libc.os), @tagName(libc.abi),
|
||||||
});
|
});
|
||||||
defer allocator.free(tmp);
|
|
||||||
try libc_obj.field(tmp, .{});
|
try libc_obj.field(tmp, .{});
|
||||||
}
|
}
|
||||||
try libc_obj.end();
|
try libc_obj.end();
|
||||||
@ -64,8 +63,7 @@ pub fn cmdTargets(
|
|||||||
{
|
{
|
||||||
var glibc_obj = try root_obj.beginTupleField("glibc", .{});
|
var glibc_obj = try root_obj.beginTupleField("glibc", .{});
|
||||||
for (glibc_abi.all_versions) |ver| {
|
for (glibc_abi.all_versions) |ver| {
|
||||||
const tmp = try std.fmt.allocPrint(allocator, "{}", .{ver});
|
const tmp = try std.fmt.allocPrint(arena, "{}", .{ver});
|
||||||
defer allocator.free(tmp);
|
|
||||||
try glibc_obj.field(tmp, .{});
|
try glibc_obj.field(tmp, .{});
|
||||||
}
|
}
|
||||||
try glibc_obj.end();
|
try glibc_obj.end();
|
||||||
@ -105,21 +103,20 @@ pub fn cmdTargets(
|
|||||||
{
|
{
|
||||||
var native_obj = try root_obj.beginStructField("native", .{});
|
var native_obj = try root_obj.beginStructField("native", .{});
|
||||||
{
|
{
|
||||||
const triple = try native_target.zigTriple(allocator);
|
const triple = try host.zigTriple(arena);
|
||||||
defer allocator.free(triple);
|
|
||||||
try native_obj.field("triple", triple, .{});
|
try native_obj.field("triple", triple, .{});
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var cpu_obj = try native_obj.beginStructField("cpu", .{});
|
var cpu_obj = try native_obj.beginStructField("cpu", .{});
|
||||||
try cpu_obj.field("arch", @tagName(native_target.cpu.arch), .{});
|
try cpu_obj.field("arch", @tagName(host.cpu.arch), .{});
|
||||||
|
|
||||||
try cpu_obj.field("name", native_target.cpu.model.name, .{});
|
try cpu_obj.field("name", host.cpu.model.name, .{});
|
||||||
|
|
||||||
{
|
{
|
||||||
var features = try native_obj.beginTupleField("features", .{});
|
var features = try native_obj.beginTupleField("features", .{});
|
||||||
for (native_target.cpu.arch.allFeaturesList(), 0..) |feature, i_usize| {
|
for (host.cpu.arch.allFeaturesList(), 0..) |feature, i_usize| {
|
||||||
const index = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize));
|
const index = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize));
|
||||||
if (native_target.cpu.features.isEnabled(index)) {
|
if (host.cpu.features.isEnabled(index)) {
|
||||||
try features.field(feature.name, .{});
|
try features.field(feature.name, .{});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,14 +125,13 @@ pub fn cmdTargets(
|
|||||||
try cpu_obj.end();
|
try cpu_obj.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
try native_obj.field("os", @tagName(native_target.os.tag), .{});
|
try native_obj.field("os", @tagName(host.os.tag), .{});
|
||||||
try native_obj.field("abi", @tagName(native_target.abi), .{});
|
try native_obj.field("abi", @tagName(host.abi), .{});
|
||||||
try native_obj.end();
|
try native_obj.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
try root_obj.end();
|
try root_obj.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
try w.writeByte('\n');
|
try output.writeByte('\n');
|
||||||
return bw.flush();
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,6 @@
|
|||||||
pub fn renderToFile(zoir: Zoir, arena: Allocator, f: std.fs.File) (std.fs.File.WriteError || Allocator.Error)!void {
|
pub fn renderToWriter(zoir: Zoir, arena: Allocator, w: *std.io.BufferedWriter) anyerror!void {
|
||||||
var bw = std.io.bufferedWriter(f.writer());
|
|
||||||
try renderToWriter(zoir, arena, bw.writer());
|
|
||||||
try bw.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn renderToWriter(zoir: Zoir, arena: Allocator, w: anytype) (@TypeOf(w).Error || Allocator.Error)!void {
|
|
||||||
assert(!zoir.hasCompileErrors());
|
assert(!zoir.hasCompileErrors());
|
||||||
|
|
||||||
const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
|
|
||||||
const bytes_per_node = comptime n: {
|
const bytes_per_node = comptime n: {
|
||||||
var n: usize = 0;
|
var n: usize = 0;
|
||||||
for (@typeInfo(Zoir.Node.Repr).@"struct".fields) |f| {
|
for (@typeInfo(Zoir.Node.Repr).@"struct".fields) |f| {
|
||||||
@ -23,22 +16,22 @@ pub fn renderToWriter(zoir: Zoir, arena: Allocator, w: anytype) (@TypeOf(w).Erro
|
|||||||
|
|
||||||
// zig fmt: off
|
// zig fmt: off
|
||||||
try w.print(
|
try w.print(
|
||||||
\\# Nodes: {} ({})
|
\\# Nodes: {} ({Bi})
|
||||||
\\# Extra Data Items: {} ({})
|
\\# Extra Data Items: {} ({Bi})
|
||||||
\\# BigInt Limbs: {} ({})
|
\\# BigInt Limbs: {} ({Bi})
|
||||||
\\# String Table Bytes: {}
|
\\# String Table Bytes: {Bi}
|
||||||
\\# Total ZON Bytes: {}
|
\\# Total ZON Bytes: {Bi}
|
||||||
\\
|
\\
|
||||||
, .{
|
, .{
|
||||||
zoir.nodes.len, fmtIntSizeBin(node_bytes),
|
zoir.nodes.len, node_bytes,
|
||||||
zoir.extra.len, fmtIntSizeBin(extra_bytes),
|
zoir.extra.len, extra_bytes,
|
||||||
zoir.limbs.len, fmtIntSizeBin(limb_bytes),
|
zoir.limbs.len, limb_bytes,
|
||||||
fmtIntSizeBin(string_bytes),
|
string_bytes,
|
||||||
fmtIntSizeBin(node_bytes + extra_bytes + limb_bytes + string_bytes),
|
node_bytes + extra_bytes + limb_bytes + string_bytes,
|
||||||
});
|
});
|
||||||
// zig fmt: on
|
// zig fmt: on
|
||||||
var pz: PrintZon = .{
|
var pz: PrintZon = .{
|
||||||
.w = w.any(),
|
.w = w,
|
||||||
.arena = arena,
|
.arena = arena,
|
||||||
.zoir = zoir,
|
.zoir = zoir,
|
||||||
.indent = 0,
|
.indent = 0,
|
||||||
@ -48,7 +41,7 @@ pub fn renderToWriter(zoir: Zoir, arena: Allocator, w: anytype) (@TypeOf(w).Erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
const PrintZon = struct {
|
const PrintZon = struct {
|
||||||
w: std.io.AnyWriter,
|
w: *std.io.BufferedWriter,
|
||||||
arena: Allocator,
|
arena: Allocator,
|
||||||
zoir: Zoir,
|
zoir: Zoir,
|
||||||
indent: u32,
|
indent: u32,
|
||||||
|
|||||||
@ -5905,7 +5905,7 @@ fn parseCPrimaryExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
|
|||||||
if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) {
|
if (slice[0] != '\'' or slice[1] == '\\' or slice.len == 3) {
|
||||||
return Tag.char_literal.create(c.arena, try escapeUnprintables(c, m));
|
return Tag.char_literal.create(c.arena, try escapeUnprintables(c, m));
|
||||||
} else {
|
} else {
|
||||||
const str = try std.fmt.allocPrint(c.arena, "0x{s}", .{std.fmt.fmtSliceHexLower(slice[1 .. slice.len - 1])});
|
const str = try std.fmt.allocPrint(c.arena, "0x{x}", .{slice[1 .. slice.len - 1]});
|
||||||
return Tag.integer_literal.create(c.arena, str);
|
return Tag.integer_literal.create(c.arena, str);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user