| ... | @@ -6,7 +6,6 @@ const Allocator = std.mem.Allocator; | ... | @@ -6,7 +6,6 @@ const Allocator = std.mem.Allocator; |
| 6 | const assert = std.debug.assert; | 6 | const assert = std.debug.assert; |
| 7 | const log = std.log.scoped(.compilation); | 7 | const log = std.log.scoped(.compilation); |
| 8 | const Target = std.Target; | 8 | const Target = std.Target; |
| 9 | const debug = std.debug; | | |
| 10 | | 9 | |
| 11 | const Value = @import("value.zig").Value; | 10 | const Value = @import("value.zig").Value; |
| 12 | const Type = @import("type.zig").Type; | 11 | const Type = @import("type.zig").Type; |
| ... | @@ -267,103 +266,62 @@ pub const AllErrors = struct { | ... | @@ -267,103 +266,62 @@ pub const AllErrors = struct { |
| 267 | list: []const Message, | 266 | list: []const Message, |
| 268 | | 267 | |
| 269 | pub const Message = union(enum) { | 268 | pub const Message = union(enum) { |
| 270 | const MessageType = enum { | | |
| 271 | pub fn render(self: @This(), stderr: anytype, ttyconf: std.debug.TTY.Config) !void { | | |
| 272 | switch (self) { | | |
| 273 | .err => { | | |
| 274 | ttyconf.setColor(stderr, .Red); | | |
| 275 | try stderr.writeAll("error:"); | | |
| 276 | }, | | |
| 277 | .note => { | | |
| 278 | ttyconf.setColor(stderr, .Green); | | |
| 279 | try stderr.writeAll("note:"); | | |
| 280 | }, | | |
| 281 | } | | |
| 282 | ttyconf.setColor(stderr, .Reset); | | |
| 283 | } | | |
| 284 | err, | | |
| 285 | note | | |
| 286 | }; | | |
| 287 | | | |
| 288 | src: struct { | 269 | src: struct { |
| 289 | msg: []const u8, | 270 | msg: []const u8, |
| 290 | src_path: union(enum) { | 271 | src_path: []const u8, |
| 291 | path: []const u8, | | |
| 292 | scope: *Module.Scope.File, | | |
| 293 | }, | | |
| 294 | line: u32, | 272 | line: u32, |
| 295 | column: u32, | 273 | column: u32, |
| 296 | byte_offset: u32, | 274 | byte_offset: u32, |
| | 275 | /// Does not include the trailing newline. |
| | 276 | source_line: ?[]const u8, |
| 297 | notes: []Message = &.{}, | 277 | notes: []Message = &.{}, |
| 298 | }, | 278 | }, |
| 299 | plain: struct { | 279 | plain: struct { |
| 300 | msg: []const u8, | 280 | msg: []const u8, |
| 301 | }, | 281 | }, |
| 302 | | 282 | |
| 303 | pub fn renderToStdErr(msg: Message, mod: ?*Module) !void { | 283 | pub fn renderToStdErr(msg: Message, ttyconf: std.debug.TTY.Config) void { |
| 304 | return msg.renderToStdErrInner(.err, mod); | 284 | const stderr_mutex = std.debug.getStderrMutex(); |
| | 285 | const held = std.debug.getStderrMutex().acquire(); |
| | 286 | defer held.release(); |
| | 287 | const stderr = std.io.getStdErr(); |
| | 288 | return msg.renderToStdErrInner(ttyconf, stderr, "error", .Red) catch return; |
| 305 | } | 289 | } |
| 306 | | 290 | |
| 307 | fn renderToStdErrInner(msg: Message, kind: MessageType, mod: ?*Module) (std.fs.File.WriteError || @typeInfo(@typeInfo(@TypeOf(Module.Scope.File.getSource)).Fn.return_type.?).ErrorUnion.error_set)!void { | 291 | fn renderToStdErrInner( |
| 308 | const ttyconf = debug.detectTTYConfig(); | 292 | msg: Message, |
| 309 | const stderr = std.io.getStdErr().writer(); | 293 | ttyconf: std.debug.TTY.Config, |
| | 294 | stderr_file: std.fs.File, |
| | 295 | kind: []const u8, |
| | 296 | color: std.debug.TTY.Color, |
| | 297 | ) anyerror!void { |
| | 298 | const stderr = stderr_file.writer(); |
| 310 | switch (msg) { | 299 | switch (msg) { |
| 311 | .src => |src| { | 300 | .src => |src| { |
| 312 | switch (src.src_path) { | 301 | try stderr.print("{s}:{d}:{d}: ", .{ |
| 313 | .path => |p| { | 302 | src.src_path, |
| 314 | // TODO read the file and do pretty printing for c objects? | 303 | src.line + 1, |
| 315 | try stderr.print("{s}:{d}:{d}: ", .{ | 304 | src.column + 1, |
| 316 | p, | 305 | }); |
| 317 | src.line + 1, | 306 | ttyconf.setColor(stderr, color); |
| 318 | src.column + 1, | 307 | try stderr.writeAll(kind); |
| 319 | }); | 308 | ttyconf.setColor(stderr, .Bold); |
| 320 | try kind.render(stderr, ttyconf); | 309 | try stderr.print(" {s}\n", .{src.msg}); |
| 321 | try stderr.print(" {s}\n", .{ | 310 | ttyconf.setColor(stderr, .Reset); |
| 322 | src.msg, | 311 | if (src.source_line) |line| { |
| 323 | }); | 312 | try stderr.writeAll(line); |
| 324 | }, | 313 | try stderr.writeByte('\n'); |
| 325 | .scope => |s| { | 314 | try stderr.writeByteNTimes(' ', src.column); |
| 326 | const module = mod.?; | 315 | ttyconf.setColor(stderr, .Green); |
| 327 | try stderr.print("{s}:{d}:{d}: ", .{ | 316 | try stderr.writeAll("^\n"); |
| 328 | s.sub_file_path, | 317 | ttyconf.setColor(stderr, .Reset); |
| 329 | src.line + 1, | | |
| 330 | src.column + 1, | | |
| 331 | }); | | |
| 332 | try kind.render(stderr, ttyconf); | | |
| 333 | try stderr.print(" {s}\n", .{ | | |
| 334 | src.msg, | | |
| 335 | }); | | |
| 336 | const fsource = try s.getSource(module); | | |
| 337 | const end_pos = blk: for (fsource[src.byte_offset..]) |c, i| { | | |
| 338 | if (c == '\n') | | |
| 339 | break :blk src.byte_offset + i + 1; | | |
| 340 | if (c == 0) | | |
| 341 | break :blk fsource.len - 1; | | |
| 342 | } else unreachable; | | |
| 343 | const start_pos = blk: { | | |
| 344 | var i = src.byte_offset; | | |
| 345 | var c: u8 = fsource[i]; | | |
| 346 | while (i > 0) : ({ | | |
| 347 | i -= 1; | | |
| 348 | c = fsource[i]; | | |
| 349 | }) { | | |
| 350 | if (c == '\n') break :blk i + 1; | | |
| 351 | } | | |
| 352 | break :blk 0; | | |
| 353 | }; | | |
| 354 | try stderr.writeAll(fsource[start_pos..end_pos]); | | |
| 355 | try stderr.writeByteNTimes(' ', src.column); | | |
| 356 | ttyconf.setColor(stderr, .Cyan); | | |
| 357 | try stderr.writeAll("^\n"); | | |
| 358 | ttyconf.setColor(stderr, .Reset); | | |
| 359 | }, | | |
| 360 | } | 318 | } |
| 361 | for (src.notes) |note| { | 319 | for (src.notes) |note| { |
| 362 | try note.renderToStdErrInner(.note, mod); | 320 | try note.renderToStdErrInner(ttyconf, stderr_file, "note", .Cyan); |
| 363 | } | 321 | } |
| 364 | }, | 322 | }, |
| 365 | .plain => |plain| { | 323 | .plain => |plain| { |
| 366 | debug.print("{s}: {s}\n", .{ kind, plain.msg }); | 324 | std.debug.print("{s}: {s}\n", .{ kind, plain.msg }); |
| 367 | }, | 325 | }, |
| 368 | } | 326 | } |
| 369 | } | 327 | } |
| ... | @@ -385,30 +343,31 @@ pub const AllErrors = struct { | ... | @@ -385,30 +343,31 @@ pub const AllErrors = struct { |
| 385 | const source = try module_note.src_loc.fileScope().getSource(module); | 343 | const source = try module_note.src_loc.fileScope().getSource(module); |
| 386 | const byte_offset = try module_note.src_loc.byteOffset(); | 344 | const byte_offset = try module_note.src_loc.byteOffset(); |
| 387 | const loc = std.zig.findLineColumn(source, byte_offset); | 345 | const loc = std.zig.findLineColumn(source, byte_offset); |
| 388 | const fscope = module_note.src_loc.fileScope(); | 346 | const sub_file_path = module_note.src_loc.fileScope().sub_file_path; |
| 389 | note.* = .{ | 347 | note.* = .{ |
| 390 | .src = .{ | 348 | .src = .{ |
| 391 | // TODO this might be freed, might need to dupe the source | 349 | .src_path = try arena.allocator.dupe(u8, sub_file_path), |
| 392 | .src_path = .{ .scope = fscope }, | | |
| 393 | .msg = try arena.allocator.dupe(u8, module_note.msg), | 350 | .msg = try arena.allocator.dupe(u8, module_note.msg), |
| 394 | .byte_offset = byte_offset, | 351 | .byte_offset = byte_offset, |
| 395 | .line = @intCast(u32, loc.line), | 352 | .line = @intCast(u32, loc.line), |
| 396 | .column = @intCast(u32, loc.column), | 353 | .column = @intCast(u32, loc.column), |
| | 354 | .source_line = try arena.allocator.dupe(u8, loc.source_line), |
| 397 | }, | 355 | }, |
| 398 | }; | 356 | }; |
| 399 | } | 357 | } |
| 400 | const source = try module_err_msg.src_loc.fileScope().getSource(module); | 358 | const source = try module_err_msg.src_loc.fileScope().getSource(module); |
| 401 | const byte_offset = try module_err_msg.src_loc.byteOffset(); | 359 | const byte_offset = try module_err_msg.src_loc.byteOffset(); |
| 402 | const loc = std.zig.findLineColumn(source, byte_offset); | 360 | const loc = std.zig.findLineColumn(source, byte_offset); |
| 403 | const fscope = module_err_msg.src_loc.fileScope(); | 361 | const sub_file_path = module_err_msg.src_loc.fileScope().sub_file_path; |
| 404 | try errors.append(.{ | 362 | try errors.append(.{ |
| 405 | .src = .{ | 363 | .src = .{ |
| 406 | .src_path = .{ .scope = fscope }, | 364 | .src_path = try arena.allocator.dupe(u8, sub_file_path), |
| 407 | .msg = try arena.allocator.dupe(u8, module_err_msg.msg), | 365 | .msg = try arena.allocator.dupe(u8, module_err_msg.msg), |
| 408 | .byte_offset = byte_offset, | 366 | .byte_offset = byte_offset, |
| 409 | .line = @intCast(u32, loc.line), | 367 | .line = @intCast(u32, loc.line), |
| 410 | .column = @intCast(u32, loc.column), | 368 | .column = @intCast(u32, loc.column), |
| 411 | .notes = notes, | 369 | .notes = notes, |
| | 370 | .source_line = try arena.allocator.dupe(u8, loc.source_line), |
| 412 | }, | 371 | }, |
| 413 | }); | 372 | }); |
| 414 | } | 373 | } |
| ... | @@ -1549,13 +1508,14 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { | ... | @@ -1549,13 +1508,14 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { |
| 1549 | // C error reporting bubbling up. | 1508 | // C error reporting bubbling up. |
| 1550 | try errors.append(.{ | 1509 | try errors.append(.{ |
| 1551 | .src = .{ | 1510 | .src = .{ |
| 1552 | .src_path = .{ .path = try arena.allocator.dupe(u8, c_object.src.src_path) }, | 1511 | .src_path = try arena.allocator.dupe(u8, c_object.src.src_path), |
| 1553 | .msg = try std.fmt.allocPrint(&arena.allocator, "unable to build C object: {s}", .{ | 1512 | .msg = try std.fmt.allocPrint(&arena.allocator, "unable to build C object: {s}", .{ |
| 1554 | err_msg.msg, | 1513 | err_msg.msg, |
| 1555 | }), | 1514 | }), |
| 1556 | .byte_offset = 0, | 1515 | .byte_offset = 0, |
| 1557 | .line = err_msg.line, | 1516 | .line = err_msg.line, |
| 1558 | .column = err_msg.column, | 1517 | .column = err_msg.column, |
| | 1518 | .source_line = null, // TODO |
| 1559 | }, | 1519 | }, |
| 1560 | }); | 1520 | }); |
| 1561 | } | 1521 | } |