| author | |
| committer | |
| log | 1463144fc88550ba1dca3888acdcdd4903781222 |
| tree | 19aa9a5f957b04d095afc7d6009eaf26877d19a4 |
| parent | b5a838247bd7d66037ba48378c34ba4460747deb |
5 files changed, 72 insertions(+), 56 deletions(-)
src/Compilation.zig+18-14| ... | ... | @@ -427,11 +427,15 @@ pub const AllErrors = struct { |
| 427 | 427 | else => try stderr.writeByte(b), |
| 428 | 428 | }; |
| 429 | 429 | try stderr.writeByte('\n'); |
| 430 | try stderr.writeByteNTimes(' ', src.column); | |
| 430 | // TODO basic unicode code point monospace width | |
| 431 | const before_caret = src.span.main - src.span.start; | |
| 432 | // -1 since span.main includes the caret | |
| 433 | const after_caret = src.span.end - src.span.main -| 1; | |
| 434 | try stderr.writeByteNTimes(' ', src.column - before_caret); | |
| 431 | 435 | ttyconf.setColor(stderr, .Green); |
| 436 | try stderr.writeByteNTimes('~', before_caret); | |
| 432 | 437 | try stderr.writeByte('^'); |
| 433 | // TODO basic unicode code point monospace width | |
| 434 | try stderr.writeByteNTimes('~', src.span.end - src.span.start - 1); | |
| 438 | try stderr.writeByteNTimes('~', after_caret); | |
| 435 | 439 | try stderr.writeByte('\n'); |
| 436 | 440 | ttyconf.setColor(stderr, .Reset); |
| 437 | 441 | } |
| ... | ... | @@ -472,8 +476,7 @@ pub const AllErrors = struct { |
| 472 | 476 | hasher.update(src.src_path); |
| 473 | 477 | std.hash.autoHash(&hasher, src.line); |
| 474 | 478 | std.hash.autoHash(&hasher, src.column); |
| 475 | std.hash.autoHash(&hasher, src.span.start); | |
| 476 | std.hash.autoHash(&hasher, src.span.end); | |
| 479 | std.hash.autoHash(&hasher, src.span.main); | |
| 477 | 480 | }, |
| 478 | 481 | .plain => |plain| { |
| 479 | 482 | hasher.update(plain.msg); |
| ... | ... | @@ -492,8 +495,7 @@ pub const AllErrors = struct { |
| 492 | 495 | mem.eql(u8, a_src.src_path, b_src.src_path) and |
| 493 | 496 | a_src.line == b_src.line and |
| 494 | 497 | a_src.column == b_src.column and |
| 495 | a_src.span.start == b_src.span.start and | |
| 496 | a_src.span.end == b_src.span.end; | |
| 498 | a_src.span.main == b_src.span.main; | |
| 497 | 499 | }, |
| 498 | 500 | .plain => return false, |
| 499 | 501 | }, |
| ... | ... | @@ -533,12 +535,12 @@ pub const AllErrors = struct { |
| 533 | 535 | ).init(allocator); |
| 534 | 536 | const err_source = try module_err_msg.src_loc.file_scope.getSource(module.gpa); |
| 535 | 537 | const err_span = try module_err_msg.src_loc.span(module.gpa); |
| 536 | const err_loc = std.zig.findLineColumn(err_source.bytes, err_span.start); | |
| 538 | const err_loc = std.zig.findLineColumn(err_source.bytes, err_span.main); | |
| 537 | 539 | |
| 538 | 540 | for (module_err_msg.notes) |module_note| { |
| 539 | 541 | const source = try module_note.src_loc.file_scope.getSource(module.gpa); |
| 540 | 542 | const span = try module_note.src_loc.span(module.gpa); |
| 541 | const loc = std.zig.findLineColumn(source.bytes, span.start); | |
| 543 | const loc = std.zig.findLineColumn(source.bytes, span.main); | |
| 542 | 544 | const file_path = try module_note.src_loc.file_scope.fullPath(allocator); |
| 543 | 545 | const note = &notes_buf[note_i]; |
| 544 | 546 | note.* = .{ |
| ... | ... | @@ -604,9 +606,10 @@ pub const AllErrors = struct { |
| 604 | 606 | } |
| 605 | 607 | const token_starts = file.tree.tokens.items(.start); |
| 606 | 608 | const start = token_starts[item.data.token] + item.data.byte_offset; |
| 607 | break :blk Module.SrcLoc.Span{ .start = start, .end = start + 1 }; | |
| 609 | const end = start + @intCast(u32, file.tree.tokenSlice(item.data.token).len); | |
| 610 | break :blk Module.SrcLoc.Span{ .start = start, .end = end, .main = start }; | |
| 608 | 611 | }; |
| 609 | const err_loc = std.zig.findLineColumn(file.source, err_span.start); | |
| 612 | const err_loc = std.zig.findLineColumn(file.source, err_span.main); | |
| 610 | 613 | |
| 611 | 614 | var notes: []Message = &[0]Message{}; |
| 612 | 615 | if (item.data.notes != 0) { |
| ... | ... | @@ -622,9 +625,10 @@ pub const AllErrors = struct { |
| 622 | 625 | } |
| 623 | 626 | const token_starts = file.tree.tokens.items(.start); |
| 624 | 627 | const start = token_starts[note_item.data.token] + note_item.data.byte_offset; |
| 625 | break :blk Module.SrcLoc.Span{ .start = start, .end = start + 1 }; | |
| 628 | const end = start + @intCast(u32, file.tree.tokenSlice(note_item.data.token).len); | |
| 629 | break :blk Module.SrcLoc.Span{ .start = start, .end = end, .main = start }; | |
| 626 | 630 | }; |
| 627 | const loc = std.zig.findLineColumn(file.source, span.start); | |
| 631 | const loc = std.zig.findLineColumn(file.source, span.main); | |
| 628 | 632 | |
| 629 | 633 | note.* = .{ |
| 630 | 634 | .src = .{ |
| ... | ... | @@ -2665,7 +2669,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { |
| 2665 | 2669 | .msg = try std.fmt.allocPrint(arena_allocator, "unable to build C object: {s}", .{ |
| 2666 | 2670 | err_msg.msg, |
| 2667 | 2671 | }), |
| 2668 | .span = .{ .start = 0, .end = 1 }, | |
| 2672 | .span = .{ .start = 0, .end = 1, .main = 0 }, | |
| 2669 | 2673 | .line = err_msg.line, |
| 2670 | 2674 | .column = err_msg.column, |
| 2671 | 2675 | .source_line = null, // TODO |
src/Module.zig+33-38| ... | ... | @@ -2085,20 +2085,21 @@ pub const SrcLoc = struct { |
| 2085 | 2085 | pub const Span = struct { |
| 2086 | 2086 | start: u32, |
| 2087 | 2087 | end: u32, |
| 2088 | main: u32, | |
| 2088 | 2089 | }; |
| 2089 | 2090 | |
| 2090 | 2091 | pub fn span(src_loc: SrcLoc, gpa: Allocator) !Span { |
| 2091 | 2092 | switch (src_loc.lazy) { |
| 2092 | 2093 | .unneeded => unreachable, |
| 2093 | .entire_file => return Span{ .start = 0, .end = 1 }, | |
| 2094 | .entire_file => return Span{ .start = 0, .end = 1, .main = 0 }, | |
| 2094 | 2095 | |
| 2095 | .byte_abs => |byte_index| return Span{ .start = byte_index, .end = byte_index + 1 }, | |
| 2096 | .byte_abs => |byte_index| return Span{ .start = byte_index, .end = byte_index + 1, .main = byte_index }, | |
| 2096 | 2097 | |
| 2097 | 2098 | .token_abs => |tok_index| { |
| 2098 | 2099 | const tree = try src_loc.file_scope.getTree(gpa); |
| 2099 | 2100 | const start = tree.tokens.items(.start)[tok_index]; |
| 2100 | 2101 | const end = start + @intCast(u32, tree.tokenSlice(tok_index).len); |
| 2101 | return Span{ .start = start, .end = end }; | |
| 2102 | return Span{ .start = start, .end = end, .main = start }; | |
| 2102 | 2103 | }, |
| 2103 | 2104 | .node_abs => |node| { |
| 2104 | 2105 | const tree = try src_loc.file_scope.getTree(gpa); |
| ... | ... | @@ -2109,14 +2110,14 @@ pub const SrcLoc = struct { |
| 2109 | 2110 | const tok_index = src_loc.declSrcToken(); |
| 2110 | 2111 | const start = tree.tokens.items(.start)[tok_index] + byte_off; |
| 2111 | 2112 | const end = start + @intCast(u32, tree.tokenSlice(tok_index).len); |
| 2112 | return Span{ .start = start, .end = end }; | |
| 2113 | return Span{ .start = start, .end = end, .main = start }; | |
| 2113 | 2114 | }, |
| 2114 | 2115 | .token_offset => |tok_off| { |
| 2115 | 2116 | const tree = try src_loc.file_scope.getTree(gpa); |
| 2116 | 2117 | const tok_index = src_loc.declSrcToken() + tok_off; |
| 2117 | 2118 | const start = tree.tokens.items(.start)[tok_index]; |
| 2118 | 2119 | const end = start + @intCast(u32, tree.tokenSlice(tok_index).len); |
| 2119 | return Span{ .start = start, .end = end }; | |
| 2120 | return Span{ .start = start, .end = end, .main = start }; | |
| 2120 | 2121 | }, |
| 2121 | 2122 | .node_offset => |traced_off| { |
| 2122 | 2123 | const node_off = traced_off.x; |
| ... | ... | @@ -2137,7 +2138,7 @@ pub const SrcLoc = struct { |
| 2137 | 2138 | const tok_index = tree.firstToken(node) - 2; |
| 2138 | 2139 | const start = tree.tokens.items(.start)[tok_index]; |
| 2139 | 2140 | const end = start + @intCast(u32, tree.tokenSlice(tok_index).len); |
| 2140 | return Span{ .start = start, .end = end }; | |
| 2141 | return Span{ .start = start, .end = end, .main = start }; | |
| 2141 | 2142 | }, |
| 2142 | 2143 | .node_offset_var_decl_ty => |node_off| { |
| 2143 | 2144 | const tree = try src_loc.file_scope.getTree(gpa); |
| ... | ... | @@ -2158,7 +2159,7 @@ pub const SrcLoc = struct { |
| 2158 | 2159 | }; |
| 2159 | 2160 | const start = tree.tokens.items(.start)[tok_index]; |
| 2160 | 2161 | const end = start + @intCast(u32, tree.tokenSlice(tok_index).len); |
| 2161 | return Span{ .start = start, .end = end }; | |
| 2162 | return Span{ .start = start, .end = end, .main = start }; | |
| 2162 | 2163 | }, |
| 2163 | 2164 | .node_offset_builtin_call_arg0 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 0), |
| 2164 | 2165 | .node_offset_builtin_call_arg1 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 1), |
| ... | ... | @@ -2186,16 +2187,13 @@ pub const SrcLoc = struct { |
| 2186 | 2187 | .slice_sentinel => tree.sliceSentinel(node), |
| 2187 | 2188 | else => unreachable, |
| 2188 | 2189 | }; |
| 2189 | const main_tokens = tree.nodes.items(.main_token); | |
| 2190 | const part_node = main_tokens[ | |
| 2191 | switch (src_loc.lazy) { | |
| 2192 | .node_offset_slice_ptr => full.ast.sliced, | |
| 2193 | .node_offset_slice_start => full.ast.start, | |
| 2194 | .node_offset_slice_end => full.ast.end, | |
| 2195 | .node_offset_slice_sentinel => full.ast.sentinel, | |
| 2196 | else => unreachable, | |
| 2197 | } | |
| 2198 | ]; | |
| 2190 | const part_node = switch (src_loc.lazy) { | |
| 2191 | .node_offset_slice_ptr => full.ast.sliced, | |
| 2192 | .node_offset_slice_start => full.ast.start, | |
| 2193 | .node_offset_slice_end => full.ast.end, | |
| 2194 | .node_offset_slice_sentinel => full.ast.sentinel, | |
| 2195 | else => unreachable, | |
| 2196 | }; | |
| 2199 | 2197 | return nodeToSpan(tree, part_node); |
| 2200 | 2198 | }, |
| 2201 | 2199 | .node_offset_call_func => |node_off| { |
| ... | ... | @@ -2231,7 +2229,7 @@ pub const SrcLoc = struct { |
| 2231 | 2229 | }; |
| 2232 | 2230 | const start = tree.tokens.items(.start)[tok_index]; |
| 2233 | 2231 | const end = start + @intCast(u32, tree.tokenSlice(tok_index).len); |
| 2234 | return Span{ .start = start, .end = end }; | |
| 2232 | return Span{ .start = start, .end = end, .main = start }; | |
| 2235 | 2233 | }, |
| 2236 | 2234 | .node_offset_deref_ptr => |node_off| { |
| 2237 | 2235 | const tree = try src_loc.file_scope.getTree(gpa); |
| ... | ... | @@ -2422,7 +2420,7 @@ pub const SrcLoc = struct { |
| 2422 | 2420 | const tok_index = full.lib_name.?; |
| 2423 | 2421 | const start = tree.tokens.items(.start)[tok_index]; |
| 2424 | 2422 | const end = start + @intCast(u32, tree.tokenSlice(tok_index).len); |
| 2425 | return Span{ .start = start, .end = end }; | |
| 2423 | return Span{ .start = start, .end = end, .main = start }; | |
| 2426 | 2424 | }, |
| 2427 | 2425 | |
| 2428 | 2426 | .node_offset_array_type_len => |node_off| { |
| ... | ... | @@ -2495,28 +2493,25 @@ pub const SrcLoc = struct { |
| 2495 | 2493 | |
| 2496 | 2494 | pub fn nodeToSpan(tree: *const Ast, node: u32) Span { |
| 2497 | 2495 | const token_starts = tree.tokens.items(.start); |
| 2496 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 2498 | 2497 | const start = tree.firstToken(node); |
| 2499 | 2498 | const end = tree.lastToken(node); |
| 2500 | if (tree.tokensOnSameLine(start, end)) { | |
| 2501 | const start_off = token_starts[start]; | |
| 2502 | const end_off = token_starts[end] + @intCast(u32, tree.tokenSlice(end).len); | |
| 2503 | return Span{ .start = start_off, .end = end_off }; | |
| 2504 | } | |
| 2499 | var start_tok = start; | |
| 2500 | var end_tok = end; | |
| 2505 | 2501 | |
| 2506 | const main_token = tree.nodes.items(.main_token)[node]; | |
| 2507 | if (tree.tokensOnSameLine(start, main_token)) { | |
| 2508 | const start_off = token_starts[start]; | |
| 2509 | const end_off = token_starts[main_token] + @intCast(u32, tree.tokenSlice(main_token).len); | |
| 2510 | return Span{ .start = start_off, .end = end_off }; | |
| 2511 | } | |
| 2512 | if (tree.tokensOnSameLine(main_token, end)) { | |
| 2513 | const start_off = token_starts[main_token]; | |
| 2514 | const end_off = token_starts[end] + @intCast(u32, tree.tokenSlice(end).len); | |
| 2515 | return Span{ .start = start_off, .end = end_off }; | |
| 2502 | if (tree.tokensOnSameLine(start, end)) { | |
| 2503 | // do nothing | |
| 2504 | } else if (tree.tokensOnSameLine(start, main_token)) { | |
| 2505 | end_tok = main_token; | |
| 2506 | } else if (tree.tokensOnSameLine(main_token, end)) { | |
| 2507 | start_tok = main_token; | |
| 2508 | } else { | |
| 2509 | start_tok = main_token; | |
| 2510 | end_tok = main_token; | |
| 2516 | 2511 | } |
| 2517 | const start_off = token_starts[main_token]; | |
| 2518 | const end_off = token_starts[main_token] + @intCast(u32, tree.tokenSlice(main_token).len); | |
| 2519 | return Span{ .start = start_off, .end = end_off }; | |
| 2512 | const start_off = token_starts[start_tok]; | |
| 2513 | const end_off = token_starts[end_tok] + @intCast(u32, tree.tokenSlice(end_tok).len); | |
| 2514 | return Span{ .start = start_off, .end = end_off, .main = token_starts[main_token] }; | |
| 2520 | 2515 | } |
| 2521 | 2516 | }; |
| 2522 | 2517 | |
| ... | ... | @@ -3283,7 +3278,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void { |
| 3283 | 3278 | .lazy = if (extra_offset == 0) .{ |
| 3284 | 3279 | .token_abs = parse_err.token, |
| 3285 | 3280 | } else .{ |
| 3286 | .byte_abs = token_starts[parse_err.token], | |
| 3281 | .byte_abs = token_starts[parse_err.token] + extra_offset, | |
| 3287 | 3282 | }, |
| 3288 | 3283 | }, |
| 3289 | 3284 | .msg = msg.toOwnedSlice(), |
src/main.zig+11-3| ... | ... | @@ -4381,7 +4381,7 @@ fn printErrsMsgToStdErr( |
| 4381 | 4381 | .msg = try std.fmt.allocPrint(arena, "invalid byte: '{'}'", .{ |
| 4382 | 4382 | std.zig.fmtEscapes(tree.source[byte_offset..][0..1]), |
| 4383 | 4383 | }), |
| 4384 | .span = .{ .start = byte_offset, .end = byte_offset + 1 }, | |
| 4384 | .span = .{ .start = byte_offset, .end = byte_offset + 1, .main = byte_offset }, | |
| 4385 | 4385 | .line = @intCast(u32, start_loc.line), |
| 4386 | 4386 | .column = @intCast(u32, start_loc.column) + bad_off, |
| 4387 | 4387 | .source_line = source_line, |
| ... | ... | @@ -4401,7 +4401,11 @@ fn printErrsMsgToStdErr( |
| 4401 | 4401 | .src = .{ |
| 4402 | 4402 | .src_path = path, |
| 4403 | 4403 | .msg = try arena.dupe(u8, text_buf.items), |
| 4404 | .span = .{ .start = byte_offset, .end = byte_offset + @intCast(u32, tree.tokenSlice(note.token).len) }, | |
| 4404 | .span = .{ | |
| 4405 | .start = byte_offset, | |
| 4406 | .end = byte_offset + @intCast(u32, tree.tokenSlice(note.token).len), | |
| 4407 | .main = byte_offset, | |
| 4408 | }, | |
| 4405 | 4409 | .line = @intCast(u32, note_loc.line), |
| 4406 | 4410 | .column = @intCast(u32, note_loc.column), |
| 4407 | 4411 | .source_line = tree.source[note_loc.line_start..note_loc.line_end], |
| ... | ... | @@ -4417,7 +4421,11 @@ fn printErrsMsgToStdErr( |
| 4417 | 4421 | .src = .{ |
| 4418 | 4422 | .src_path = path, |
| 4419 | 4423 | .msg = text, |
| 4420 | .span = .{ .start = byte_offset, .end = byte_offset + @intCast(u32, tree.tokenSlice(lok_token).len) }, | |
| 4424 | .span = .{ | |
| 4425 | .start = byte_offset, | |
| 4426 | .end = byte_offset + @intCast(u32, tree.tokenSlice(lok_token).len), | |
| 4427 | .main = byte_offset, | |
| 4428 | }, | |
| 4421 | 4429 | .line = @intCast(u32, start_loc.line), |
| 4422 | 4430 | .column = @intCast(u32, start_loc.column) + extra_offset, |
| 4423 | 4431 | .source_line = source_line, |
src/print_zir.zig+1-1| ... | ... | @@ -2386,7 +2386,7 @@ const Writer = struct { |
| 2386 | 2386 | const end = std.zig.findLineColumn(tree.source, src_span.end); |
| 2387 | 2387 | try stream.print("{s}:{d}:{d} to :{d}:{d}", .{ |
| 2388 | 2388 | @tagName(src), start.line + 1, start.column + 1, |
| 2389 | end.line + 1, end.column + 1, | |
| 2389 | end.line + 1, end.column + 1, | |
| 2390 | 2390 | }); |
| 2391 | 2391 | } |
| 2392 | 2392 | } |
test/compile_errors.zig+9| ... | ... | @@ -174,6 +174,15 @@ pub fn addCases(ctx: *TestContext) !void { |
| 174 | 174 | }); |
| 175 | 175 | } |
| 176 | 176 | |
| 177 | { | |
| 178 | const case = ctx.obj("missing semicolon at EOF", .{}); | |
| 179 | case.addError( | |
| 180 | \\const foo = 1 | |
| 181 | , &[_][]const u8{ | |
| 182 | \\:1:14: error: expected ';' after declaration | |
| 183 | }); | |
| 184 | } | |
| 185 | ||
| 177 | 186 | // TODO test this in stage2, but we won't even try in stage1 |
| 178 | 187 | //ctx.objErrStage1("inline fn calls itself indirectly", |
| 179 | 188 | // \\export fn foo() void { |