| ... | @@ -2,6 +2,12 @@ | ... | @@ -2,6 +2,12 @@ |
| 2 | //! source lives here. These APIs are provided as-is and have absolutely no API | 2 | //! source lives here. These APIs are provided as-is and have absolutely no API |
| 3 | //! guarantees whatsoever. | 3 | //! guarantees whatsoever. |
| 4 | | 4 | |
| | 5 | const std = @import("std.zig"); |
| | 6 | const tokenizer = @import("zig/tokenizer.zig"); |
| | 7 | const assert = std.debug.assert; |
| | 8 | const Allocator = std.mem.Allocator; |
| | 9 | const Writer = std.Io.Writer; |
| | 10 | |
| 5 | pub const ErrorBundle = @import("zig/ErrorBundle.zig"); | 11 | pub const ErrorBundle = @import("zig/ErrorBundle.zig"); |
| 6 | pub const Server = @import("zig/Server.zig"); | 12 | pub const Server = @import("zig/Server.zig"); |
| 7 | pub const Client = @import("zig/Client.zig"); | 13 | pub const Client = @import("zig/Client.zig"); |
| ... | @@ -355,11 +361,6 @@ pub fn serializeCpuAlloc(ally: Allocator, cpu: std.Target.Cpu) Allocator.Error![ | ... | @@ -355,11 +361,6 @@ pub fn serializeCpuAlloc(ally: Allocator, cpu: std.Target.Cpu) Allocator.Error![ |
| 355 | return buffer.toOwnedSlice(); | 361 | return buffer.toOwnedSlice(); |
| 356 | } | 362 | } |
| 357 | | 363 | |
| 358 | const std = @import("std.zig"); | | |
| 359 | const tokenizer = @import("zig/tokenizer.zig"); | | |
| 360 | const assert = std.debug.assert; | | |
| 361 | const Allocator = std.mem.Allocator; | | |
| 362 | | | |
| 363 | /// Return a Formatter for a Zig identifier, escaping it with `@""` syntax if needed. | 364 | /// Return a Formatter for a Zig identifier, escaping it with `@""` syntax if needed. |
| 364 | /// | 365 | /// |
| 365 | /// See also `fmtIdFlags`. | 366 | /// See also `fmtIdFlags`. |
| ... | @@ -425,7 +426,7 @@ pub const FormatId = struct { | ... | @@ -425,7 +426,7 @@ pub const FormatId = struct { |
| 425 | }; | 426 | }; |
| 426 | | 427 | |
| 427 | /// Print the string as a Zig identifier, escaping it with `@""` syntax if needed. | 428 | /// Print the string as a Zig identifier, escaping it with `@""` syntax if needed. |
| 428 | fn render(ctx: FormatId, writer: *std.io.Writer) std.io.Writer.Error!void { | 429 | fn render(ctx: FormatId, writer: *Writer) Writer.Error!void { |
| 429 | const bytes = ctx.bytes; | 430 | const bytes = ctx.bytes; |
| 430 | if (isValidId(bytes) and | 431 | if (isValidId(bytes) and |
| 431 | (ctx.flags.allow_primitive or !std.zig.isPrimitive(bytes)) and | 432 | (ctx.flags.allow_primitive or !std.zig.isPrimitive(bytes)) and |
| ... | @@ -463,7 +464,7 @@ test fmtChar { | ... | @@ -463,7 +464,7 @@ test fmtChar { |
| 463 | } | 464 | } |
| 464 | | 465 | |
| 465 | /// Print the string as escaped contents of a double quoted string. | 466 | /// Print the string as escaped contents of a double quoted string. |
| 466 | pub fn stringEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!void { | 467 | pub fn stringEscape(bytes: []const u8, w: *Writer) Writer.Error!void { |
| 467 | for (bytes) |byte| switch (byte) { | 468 | for (bytes) |byte| switch (byte) { |
| 468 | '\n' => try w.writeAll("\\n"), | 469 | '\n' => try w.writeAll("\\n"), |
| 469 | '\r' => try w.writeAll("\\r"), | 470 | '\r' => try w.writeAll("\\r"), |
| ... | @@ -480,7 +481,7 @@ pub fn stringEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!vo | ... | @@ -480,7 +481,7 @@ pub fn stringEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!vo |
| 480 | } | 481 | } |
| 481 | | 482 | |
| 482 | /// Print the string as escaped contents of a single-quoted string. | 483 | /// Print the string as escaped contents of a single-quoted string. |
| 483 | pub fn charEscape(bytes: []const u8, w: *std.io.Writer) std.io.Writer.Error!void { | 484 | pub fn charEscape(bytes: []const u8, w: *Writer) Writer.Error!void { |
| 484 | for (bytes) |byte| switch (byte) { | 485 | for (bytes) |byte| switch (byte) { |
| 485 | '\n' => try w.writeAll("\\n"), | 486 | '\n' => try w.writeAll("\\n"), |
| 486 | '\r' => try w.writeAll("\\r"), | 487 | '\r' => try w.writeAll("\\r"), |
| ... | @@ -529,20 +530,18 @@ test isUnderscore { | ... | @@ -529,20 +530,18 @@ test isUnderscore { |
| 529 | try std.testing.expect(!isUnderscore("\\x5f")); | 530 | try std.testing.expect(!isUnderscore("\\x5f")); |
| 530 | } | 531 | } |
| 531 | | 532 | |
| 532 | pub fn readSourceFileToEndAlloc(gpa: Allocator, input: std.fs.File, size_hint: ?usize) ![:0]u8 { | 533 | pub fn readSourceFileToEndAlloc(gpa: Allocator, input: std.fs.File, size_hint: usize) ![:0]u8 { |
| 533 | const source_code = input.readToEndAllocOptions( | 534 | var buffer: std.ArrayListAlignedUnmanaged(u8, .@"2") = .empty; |
| 534 | gpa, | 535 | defer buffer.deinit(gpa); |
| 535 | max_src_size, | 536 | |
| 536 | size_hint, | 537 | try buffer.ensureUnusedCapacity(gpa, size_hint); |
| 537 | .of(u8), | 538 | |
| 538 | 0, | 539 | input.readIntoArrayList(gpa, .limited(max_src_size), .@"2", &buffer) catch |err| switch (err) { |
| 539 | ) catch |err| switch (err) { | | |
| 540 | error.ConnectionResetByPeer => unreachable, | 540 | error.ConnectionResetByPeer => unreachable, |
| 541 | error.ConnectionTimedOut => unreachable, | 541 | error.ConnectionTimedOut => unreachable, |
| 542 | error.NotOpenForReading => unreachable, | 542 | error.NotOpenForReading => unreachable, |
| 543 | else => |e| return e, | 543 | else => |e| return e, |
| 544 | }; | 544 | }; |
| 545 | errdefer gpa.free(source_code); | | |
| 546 | | 545 | |
| 547 | // Detect unsupported file types with their Byte Order Mark | 546 | // Detect unsupported file types with their Byte Order Mark |
| 548 | const unsupported_boms = [_][]const u8{ | 547 | const unsupported_boms = [_][]const u8{ |
| ... | @@ -551,30 +550,23 @@ pub fn readSourceFileToEndAlloc(gpa: Allocator, input: std.fs.File, size_hint: ? | ... | @@ -551,30 +550,23 @@ pub fn readSourceFileToEndAlloc(gpa: Allocator, input: std.fs.File, size_hint: ? |
| 551 | "\xfe\xff", // UTF-16 big endian | 550 | "\xfe\xff", // UTF-16 big endian |
| 552 | }; | 551 | }; |
| 553 | for (unsupported_boms) |bom| { | 552 | for (unsupported_boms) |bom| { |
| 554 | if (std.mem.startsWith(u8, source_code, bom)) { | 553 | if (std.mem.startsWith(u8, buffer.items, bom)) { |
| 555 | return error.UnsupportedEncoding; | 554 | return error.UnsupportedEncoding; |
| 556 | } | 555 | } |
| 557 | } | 556 | } |
| 558 | | 557 | |
| 559 | // If the file starts with a UTF-16 little endian BOM, translate it to UTF-8 | 558 | // If the file starts with a UTF-16 little endian BOM, translate it to UTF-8 |
| 560 | if (std.mem.startsWith(u8, source_code, "\xff\xfe")) { | 559 | if (std.mem.startsWith(u8, buffer.items, "\xff\xfe")) { |
| 561 | if (source_code.len % 2 != 0) return error.InvalidEncoding; | 560 | if (buffer.items.len % 2 != 0) return error.InvalidEncoding; |
| 562 | // TODO: after wrangle-writer-buffering branch is merged, | 561 | return std.unicode.utf16LeToUtf8AllocZ(gpa, @ptrCast(buffer.items)) catch |err| switch (err) { |
| 563 | // avoid this unnecessary allocation | | |
| 564 | const aligned_copy = try gpa.alloc(u16, source_code.len / 2); | | |
| 565 | defer gpa.free(aligned_copy); | | |
| 566 | @memcpy(std.mem.sliceAsBytes(aligned_copy), source_code); | | |
| 567 | const source_code_utf8 = std.unicode.utf16LeToUtf8AllocZ(gpa, aligned_copy) catch |err| switch (err) { | | |
| 568 | error.DanglingSurrogateHalf => error.UnsupportedEncoding, | 562 | error.DanglingSurrogateHalf => error.UnsupportedEncoding, |
| 569 | error.ExpectedSecondSurrogateHalf => error.UnsupportedEncoding, | 563 | error.ExpectedSecondSurrogateHalf => error.UnsupportedEncoding, |
| 570 | error.UnexpectedSecondSurrogateHalf => error.UnsupportedEncoding, | 564 | error.UnexpectedSecondSurrogateHalf => error.UnsupportedEncoding, |
| 571 | else => |e| return e, | 565 | else => |e| return e, |
| 572 | }; | 566 | }; |
| 573 | gpa.free(source_code); | | |
| 574 | return source_code_utf8; | | |
| 575 | } | 567 | } |
| 576 | | 568 | |
| 577 | return source_code; | 569 | return buffer.toOwnedSliceSentinel(gpa, 0); |
| 578 | } | 570 | } |
| 579 | | 571 | |
| 580 | pub fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color: Color) !void { | 572 | pub fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color: Color) !void { |
| ... | @@ -621,7 +613,7 @@ pub fn parseTargetQueryOrReportFatalError( | ... | @@ -621,7 +613,7 @@ pub fn parseTargetQueryOrReportFatalError( |
| 621 | var help_text = std.ArrayList(u8).init(allocator); | 613 | var help_text = std.ArrayList(u8).init(allocator); |
| 622 | defer help_text.deinit(); | 614 | defer help_text.deinit(); |
| 623 | for (diags.arch.?.allCpuModels()) |cpu| { | 615 | for (diags.arch.?.allCpuModels()) |cpu| { |
| 624 | help_text.writer().print(" {s}\n", .{cpu.name}) catch break :help; | 616 | help_text.print(" {s}\n", .{cpu.name}) catch break :help; |
| 625 | } | 617 | } |
| 626 | std.log.info("available CPUs for architecture '{s}':\n{s}", .{ | 618 | std.log.info("available CPUs for architecture '{s}':\n{s}", .{ |
| 627 | @tagName(diags.arch.?), help_text.items, | 619 | @tagName(diags.arch.?), help_text.items, |
| ... | @@ -634,7 +626,7 @@ pub fn parseTargetQueryOrReportFatalError( | ... | @@ -634,7 +626,7 @@ pub fn parseTargetQueryOrReportFatalError( |
| 634 | var help_text = std.ArrayList(u8).init(allocator); | 626 | var help_text = std.ArrayList(u8).init(allocator); |
| 635 | defer help_text.deinit(); | 627 | defer help_text.deinit(); |
| 636 | for (diags.arch.?.allFeaturesList()) |feature| { | 628 | for (diags.arch.?.allFeaturesList()) |feature| { |
| 637 | help_text.writer().print(" {s}: {s}\n", .{ feature.name, feature.description }) catch break :help; | 629 | help_text.print(" {s}: {s}\n", .{ feature.name, feature.description }) catch break :help; |
| 638 | } | 630 | } |
| 639 | std.log.info("available CPU features for architecture '{s}':\n{s}", .{ | 631 | std.log.info("available CPU features for architecture '{s}':\n{s}", .{ |
| 640 | @tagName(diags.arch.?), help_text.items, | 632 | @tagName(diags.arch.?), help_text.items, |
| ... | @@ -647,7 +639,7 @@ pub fn parseTargetQueryOrReportFatalError( | ... | @@ -647,7 +639,7 @@ pub fn parseTargetQueryOrReportFatalError( |
| 647 | var help_text = std.ArrayList(u8).init(allocator); | 639 | var help_text = std.ArrayList(u8).init(allocator); |
| 648 | defer help_text.deinit(); | 640 | defer help_text.deinit(); |
| 649 | inline for (@typeInfo(std.Target.ObjectFormat).@"enum".fields) |field| { | 641 | inline for (@typeInfo(std.Target.ObjectFormat).@"enum".fields) |field| { |
| 650 | help_text.writer().print(" {s}\n", .{field.name}) catch break :help; | 642 | help_text.print(" {s}\n", .{field.name}) catch break :help; |
| 651 | } | 643 | } |
| 652 | std.log.info("available object formats:\n{s}", .{help_text.items}); | 644 | std.log.info("available object formats:\n{s}", .{help_text.items}); |
| 653 | } | 645 | } |
| ... | @@ -658,7 +650,7 @@ pub fn parseTargetQueryOrReportFatalError( | ... | @@ -658,7 +650,7 @@ pub fn parseTargetQueryOrReportFatalError( |
| 658 | var help_text = std.ArrayList(u8).init(allocator); | 650 | var help_text = std.ArrayList(u8).init(allocator); |
| 659 | defer help_text.deinit(); | 651 | defer help_text.deinit(); |
| 660 | inline for (@typeInfo(std.Target.Cpu.Arch).@"enum".fields) |field| { | 652 | inline for (@typeInfo(std.Target.Cpu.Arch).@"enum".fields) |field| { |
| 661 | help_text.writer().print(" {s}\n", .{field.name}) catch break :help; | 653 | help_text.print(" {s}\n", .{field.name}) catch break :help; |
| 662 | } | 654 | } |
| 663 | std.log.info("available architectures:\n{s} native\n", .{help_text.items}); | 655 | std.log.info("available architectures:\n{s} native\n", .{help_text.items}); |
| 664 | } | 656 | } |