authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-14 21:26:01+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-14 22:18:58+03:00
logb5a838247bd7d66037ba48378c34ba4460747deb
tree353926c424c6d6d8153e23b50862cfb9c3a7088b
parenta4559271501670b39305fc3575ae8d87fa03d35e

stage2: point to error location using spans


4 files changed, 128 insertions(+), 150 deletions(-)

src/Compilation.zig+31-28
...@@ -338,7 +338,7 @@ pub const AllErrors = struct {...@@ -338,7 +338,7 @@ pub const AllErrors = struct {
338 src_path: []const u8,338 src_path: []const u8,
339 line: u32,339 line: u32,
340 column: u32,340 column: u32,
341 byte_offset: u32,341 span: Module.SrcLoc.Span,
342 /// Usually one, but incremented for redundant messages.342 /// Usually one, but incremented for redundant messages.
343 count: u32 = 1,343 count: u32 = 1,
344 /// Does not include the trailing newline.344 /// Does not include the trailing newline.
...@@ -429,7 +429,10 @@ pub const AllErrors = struct {...@@ -429,7 +429,10 @@ pub const AllErrors = struct {
429 try stderr.writeByte('\n');429 try stderr.writeByte('\n');
430 try stderr.writeByteNTimes(' ', src.column);430 try stderr.writeByteNTimes(' ', src.column);
431 ttyconf.setColor(stderr, .Green);431 ttyconf.setColor(stderr, .Green);
432 try stderr.writeAll("^\n");432 try stderr.writeByte('^');
433 // TODO basic unicode code point monospace width
434 try stderr.writeByteNTimes('~', src.span.end - src.span.start - 1);
435 try stderr.writeByte('\n');
433 ttyconf.setColor(stderr, .Reset);436 ttyconf.setColor(stderr, .Reset);
434 }437 }
435 }438 }
...@@ -469,7 +472,8 @@ pub const AllErrors = struct {...@@ -469,7 +472,8 @@ pub const AllErrors = struct {
469 hasher.update(src.src_path);472 hasher.update(src.src_path);
470 std.hash.autoHash(&hasher, src.line);473 std.hash.autoHash(&hasher, src.line);
471 std.hash.autoHash(&hasher, src.column);474 std.hash.autoHash(&hasher, src.column);
472 std.hash.autoHash(&hasher, src.byte_offset);475 std.hash.autoHash(&hasher, src.span.start);
476 std.hash.autoHash(&hasher, src.span.end);
473 },477 },
474 .plain => |plain| {478 .plain => |plain| {
475 hasher.update(plain.msg);479 hasher.update(plain.msg);
...@@ -488,7 +492,8 @@ pub const AllErrors = struct {...@@ -488,7 +492,8 @@ pub const AllErrors = struct {
488 mem.eql(u8, a_src.src_path, b_src.src_path) and492 mem.eql(u8, a_src.src_path, b_src.src_path) and
489 a_src.line == b_src.line and493 a_src.line == b_src.line and
490 a_src.column == b_src.column and494 a_src.column == b_src.column and
491 a_src.byte_offset == b_src.byte_offset;495 a_src.span.start == b_src.span.start and
496 a_src.span.end == b_src.span.end;
492 },497 },
493 .plain => return false,498 .plain => return false,
494 },499 },
...@@ -527,20 +532,20 @@ pub const AllErrors = struct {...@@ -527,20 +532,20 @@ pub const AllErrors = struct {
527 std.hash_map.default_max_load_percentage,532 std.hash_map.default_max_load_percentage,
528 ).init(allocator);533 ).init(allocator);
529 const err_source = try module_err_msg.src_loc.file_scope.getSource(module.gpa);534 const err_source = try module_err_msg.src_loc.file_scope.getSource(module.gpa);
530 const err_byte_offset = try module_err_msg.src_loc.byteOffset(module.gpa);535 const err_span = try module_err_msg.src_loc.span(module.gpa);
531 const err_loc = std.zig.findLineColumn(err_source.bytes, err_byte_offset);536 const err_loc = std.zig.findLineColumn(err_source.bytes, err_span.start);
532537
533 for (module_err_msg.notes) |module_note| {538 for (module_err_msg.notes) |module_note| {
534 const source = try module_note.src_loc.file_scope.getSource(module.gpa);539 const source = try module_note.src_loc.file_scope.getSource(module.gpa);
535 const byte_offset = try module_note.src_loc.byteOffset(module.gpa);540 const span = try module_note.src_loc.span(module.gpa);
536 const loc = std.zig.findLineColumn(source.bytes, byte_offset);541 const loc = std.zig.findLineColumn(source.bytes, span.start);
537 const file_path = try module_note.src_loc.file_scope.fullPath(allocator);542 const file_path = try module_note.src_loc.file_scope.fullPath(allocator);
538 const note = &notes_buf[note_i];543 const note = &notes_buf[note_i];
539 note.* = .{544 note.* = .{
540 .src = .{545 .src = .{
541 .src_path = file_path,546 .src_path = file_path,
542 .msg = try allocator.dupe(u8, module_note.msg),547 .msg = try allocator.dupe(u8, module_note.msg),
543 .byte_offset = byte_offset,548 .span = span,
544 .line = @intCast(u32, loc.line),549 .line = @intCast(u32, loc.line),
545 .column = @intCast(u32, loc.column),550 .column = @intCast(u32, loc.column),
546 .source_line = if (err_loc.eql(loc)) null else try allocator.dupe(u8, loc.source_line),551 .source_line = if (err_loc.eql(loc)) null else try allocator.dupe(u8, loc.source_line),
...@@ -566,7 +571,7 @@ pub const AllErrors = struct {...@@ -566,7 +571,7 @@ pub const AllErrors = struct {
566 .src = .{571 .src = .{
567 .src_path = file_path,572 .src_path = file_path,
568 .msg = try allocator.dupe(u8, module_err_msg.msg),573 .msg = try allocator.dupe(u8, module_err_msg.msg),
569 .byte_offset = err_byte_offset,574 .span = err_span,
570 .line = @intCast(u32, err_loc.line),575 .line = @intCast(u32, err_loc.line),
571 .column = @intCast(u32, err_loc.column),576 .column = @intCast(u32, err_loc.column),
572 .notes = notes_buf[0..note_i],577 .notes = notes_buf[0..note_i],
...@@ -593,16 +598,15 @@ pub const AllErrors = struct {...@@ -593,16 +598,15 @@ pub const AllErrors = struct {
593 while (item_i < items_len) : (item_i += 1) {598 while (item_i < items_len) : (item_i += 1) {
594 const item = file.zir.extraData(Zir.Inst.CompileErrors.Item, extra_index);599 const item = file.zir.extraData(Zir.Inst.CompileErrors.Item, extra_index);
595 extra_index = item.end;600 extra_index = item.end;
596 const err_byte_offset = blk: {601 const err_span = blk: {
597 const token_starts = file.tree.tokens.items(.start);
598 if (item.data.node != 0) {602 if (item.data.node != 0) {
599 const main_tokens = file.tree.nodes.items(.main_token);603 break :blk Module.SrcLoc.nodeToSpan(&file.tree, item.data.node);
600 const main_token = main_tokens[item.data.node];
601 break :blk token_starts[main_token];
602 }604 }
603 break :blk token_starts[item.data.token] + item.data.byte_offset;605 const token_starts = file.tree.tokens.items(.start);
606 const start = token_starts[item.data.token] + item.data.byte_offset;
607 break :blk Module.SrcLoc.Span{ .start = start, .end = start + 1 };
604 };608 };
605 const err_loc = std.zig.findLineColumn(file.source, err_byte_offset);609 const err_loc = std.zig.findLineColumn(file.source, err_span.start);
606610
607 var notes: []Message = &[0]Message{};611 var notes: []Message = &[0]Message{};
608 if (item.data.notes != 0) {612 if (item.data.notes != 0) {
...@@ -612,22 +616,21 @@ pub const AllErrors = struct {...@@ -612,22 +616,21 @@ pub const AllErrors = struct {
612 for (notes) |*note, i| {616 for (notes) |*note, i| {
613 const note_item = file.zir.extraData(Zir.Inst.CompileErrors.Item, body[i]);617 const note_item = file.zir.extraData(Zir.Inst.CompileErrors.Item, body[i]);
614 const msg = file.zir.nullTerminatedString(note_item.data.msg);618 const msg = file.zir.nullTerminatedString(note_item.data.msg);
615 const byte_offset = blk: {619 const span = blk: {
616 const token_starts = file.tree.tokens.items(.start);
617 if (note_item.data.node != 0) {620 if (note_item.data.node != 0) {
618 const main_tokens = file.tree.nodes.items(.main_token);621 break :blk Module.SrcLoc.nodeToSpan(&file.tree, note_item.data.node);
619 const main_token = main_tokens[note_item.data.node];
620 break :blk token_starts[main_token];
621 }622 }
622 break :blk token_starts[note_item.data.token] + note_item.data.byte_offset;623 const token_starts = file.tree.tokens.items(.start);
624 const start = token_starts[note_item.data.token] + note_item.data.byte_offset;
625 break :blk Module.SrcLoc.Span{ .start = start, .end = start + 1 };
623 };626 };
624 const loc = std.zig.findLineColumn(file.source, byte_offset);627 const loc = std.zig.findLineColumn(file.source, span.start);
625628
626 note.* = .{629 note.* = .{
627 .src = .{630 .src = .{
628 .src_path = try file.fullPath(arena),631 .src_path = try file.fullPath(arena),
629 .msg = try arena.dupe(u8, msg),632 .msg = try arena.dupe(u8, msg),
630 .byte_offset = byte_offset,633 .span = span,
631 .line = @intCast(u32, loc.line),634 .line = @intCast(u32, loc.line),
632 .column = @intCast(u32, loc.column),635 .column = @intCast(u32, loc.column),
633 .notes = &.{}, // TODO rework this function to be recursive636 .notes = &.{}, // TODO rework this function to be recursive
...@@ -642,7 +645,7 @@ pub const AllErrors = struct {...@@ -642,7 +645,7 @@ pub const AllErrors = struct {
642 .src = .{645 .src = .{
643 .src_path = try file.fullPath(arena),646 .src_path = try file.fullPath(arena),
644 .msg = try arena.dupe(u8, msg),647 .msg = try arena.dupe(u8, msg),
645 .byte_offset = err_byte_offset,648 .span = err_span,
646 .line = @intCast(u32, err_loc.line),649 .line = @intCast(u32, err_loc.line),
647 .column = @intCast(u32, err_loc.column),650 .column = @intCast(u32, err_loc.column),
648 .notes = notes,651 .notes = notes,
...@@ -688,7 +691,7 @@ pub const AllErrors = struct {...@@ -688,7 +691,7 @@ pub const AllErrors = struct {
688 .src_path = try arena.dupe(u8, src.src_path),691 .src_path = try arena.dupe(u8, src.src_path),
689 .line = src.line,692 .line = src.line,
690 .column = src.column,693 .column = src.column,
691 .byte_offset = src.byte_offset,694 .span = src.span,
692 .source_line = if (src.source_line) |s| try arena.dupe(u8, s) else null,695 .source_line = if (src.source_line) |s| try arena.dupe(u8, s) else null,
693 .notes = try dupeList(src.notes, arena),696 .notes = try dupeList(src.notes, arena),
694 } },697 } },
...@@ -2662,7 +2665,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {...@@ -2662,7 +2665,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
2662 .msg = try std.fmt.allocPrint(arena_allocator, "unable to build C object: {s}", .{2665 .msg = try std.fmt.allocPrint(arena_allocator, "unable to build C object: {s}", .{
2663 err_msg.msg,2666 err_msg.msg,
2664 }),2667 }),
2665 .byte_offset = 0,2668 .span = .{ .start = 0, .end = 1 },
2666 .line = err_msg.line,2669 .line = err_msg.line,
2667 .column = err_msg.column,2670 .column = err_msg.column,
2668 .source_line = null, // TODO2671 .source_line = null, // TODO
src/Module.zig+86-115
...@@ -2082,60 +2082,62 @@ pub const SrcLoc = struct {...@@ -2082,60 +2082,62 @@ pub const SrcLoc = struct {
2082 return @bitCast(Ast.Node.Index, offset + @bitCast(i32, src_loc.parent_decl_node));2082 return @bitCast(Ast.Node.Index, offset + @bitCast(i32, src_loc.parent_decl_node));
2083 }2083 }
20842084
2085 pub fn byteOffset(src_loc: SrcLoc, gpa: Allocator) !u32 {2085 pub const Span = struct {
2086 start: u32,
2087 end: u32,
2088 };
2089
2090 pub fn span(src_loc: SrcLoc, gpa: Allocator) !Span {
2086 switch (src_loc.lazy) {2091 switch (src_loc.lazy) {
2087 .unneeded => unreachable,2092 .unneeded => unreachable,
2088 .entire_file => return 0,2093 .entire_file => return Span{ .start = 0, .end = 1 },
20892094
2090 .byte_abs => |byte_index| return byte_index,2095 .byte_abs => |byte_index| return Span{ .start = byte_index, .end = byte_index + 1 },
20912096
2092 .token_abs => |tok_index| {2097 .token_abs => |tok_index| {
2093 const tree = try src_loc.file_scope.getTree(gpa);2098 const tree = try src_loc.file_scope.getTree(gpa);
2094 const token_starts = tree.tokens.items(.start);2099 const start = tree.tokens.items(.start)[tok_index];
2095 return token_starts[tok_index];2100 const end = start + @intCast(u32, tree.tokenSlice(tok_index).len);
2101 return Span{ .start = start, .end = end };
2096 },2102 },
2097 .node_abs => |node| {2103 .node_abs => |node| {
2098 const tree = try src_loc.file_scope.getTree(gpa);2104 const tree = try src_loc.file_scope.getTree(gpa);
2099 const token_starts = tree.tokens.items(.start);2105 return nodeToSpan(tree, node);
2100 const tok_index = tree.firstToken(node);
2101 return token_starts[tok_index];
2102 },2106 },
2103 .byte_offset => |byte_off| {2107 .byte_offset => |byte_off| {
2104 const tree = try src_loc.file_scope.getTree(gpa);2108 const tree = try src_loc.file_scope.getTree(gpa);
2105 const token_starts = tree.tokens.items(.start);2109 const tok_index = src_loc.declSrcToken();
2106 return token_starts[src_loc.declSrcToken()] + byte_off;2110 const start = tree.tokens.items(.start)[tok_index] + byte_off;
2111 const end = start + @intCast(u32, tree.tokenSlice(tok_index).len);
2112 return Span{ .start = start, .end = end };
2107 },2113 },
2108 .token_offset => |tok_off| {2114 .token_offset => |tok_off| {
2109 const tree = try src_loc.file_scope.getTree(gpa);2115 const tree = try src_loc.file_scope.getTree(gpa);
2110 const tok_index = src_loc.declSrcToken() + tok_off;2116 const tok_index = src_loc.declSrcToken() + tok_off;
2111 const token_starts = tree.tokens.items(.start);2117 const start = tree.tokens.items(.start)[tok_index];
2112 return token_starts[tok_index];2118 const end = start + @intCast(u32, tree.tokenSlice(tok_index).len);
2119 return Span{ .start = start, .end = end };
2113 },2120 },
2114 .node_offset => |traced_off| {2121 .node_offset => |traced_off| {
2115 const node_off = traced_off.x;2122 const node_off = traced_off.x;
2116 const tree = try src_loc.file_scope.getTree(gpa);2123 const tree = try src_loc.file_scope.getTree(gpa);
2117 const node = src_loc.declRelativeToNodeIndex(node_off);2124 const node = src_loc.declRelativeToNodeIndex(node_off);
2118 assert(src_loc.file_scope.tree_loaded);2125 assert(src_loc.file_scope.tree_loaded);
2119 const main_tokens = tree.nodes.items(.main_token);2126 return nodeToSpan(tree, node);
2120 const tok_index = main_tokens[node];
2121 const token_starts = tree.tokens.items(.start);
2122 return token_starts[tok_index];
2123 },2127 },
2124 .node_offset_bin_op => |node_off| {2128 .node_offset_bin_op => |node_off| {
2125 const tree = try src_loc.file_scope.getTree(gpa);2129 const tree = try src_loc.file_scope.getTree(gpa);
2126 const node = src_loc.declRelativeToNodeIndex(node_off);2130 const node = src_loc.declRelativeToNodeIndex(node_off);
2127 assert(src_loc.file_scope.tree_loaded);2131 assert(src_loc.file_scope.tree_loaded);
2128 const main_tokens = tree.nodes.items(.main_token);2132 return nodeToSpan(tree, node);
2129 const tok_index = main_tokens[node];
2130 const token_starts = tree.tokens.items(.start);
2131 return token_starts[tok_index];
2132 },2133 },
2133 .node_offset_back2tok => |node_off| {2134 .node_offset_back2tok => |node_off| {
2134 const tree = try src_loc.file_scope.getTree(gpa);2135 const tree = try src_loc.file_scope.getTree(gpa);
2135 const node = src_loc.declRelativeToNodeIndex(node_off);2136 const node = src_loc.declRelativeToNodeIndex(node_off);
2136 const tok_index = tree.firstToken(node) - 2;2137 const tok_index = tree.firstToken(node) - 2;
2137 const token_starts = tree.tokens.items(.start);2138 const start = tree.tokens.items(.start)[tok_index];
2138 return token_starts[tok_index];2139 const end = start + @intCast(u32, tree.tokenSlice(tok_index).len);
2140 return Span{ .start = start, .end = end };
2139 },2141 },
2140 .node_offset_var_decl_ty => |node_off| {2142 .node_offset_var_decl_ty => |node_off| {
2141 const tree = try src_loc.file_scope.getTree(gpa);2143 const tree = try src_loc.file_scope.getTree(gpa);
...@@ -2154,8 +2156,9 @@ pub const SrcLoc = struct {...@@ -2154,8 +2156,9 @@ pub const SrcLoc = struct {
2154 } else blk: {2156 } else blk: {
2155 break :blk full.ast.mut_token + 1; // the name token2157 break :blk full.ast.mut_token + 1; // the name token
2156 };2158 };
2157 const token_starts = tree.tokens.items(.start);2159 const start = tree.tokens.items(.start)[tok_index];
2158 return token_starts[tok_index];2160 const end = start + @intCast(u32, tree.tokenSlice(tok_index).len);
2161 return Span{ .start = start, .end = end };
2159 },2162 },
2160 .node_offset_builtin_call_arg0 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 0),2163 .node_offset_builtin_call_arg0 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 0),
2161 .node_offset_builtin_call_arg1 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 1),2164 .node_offset_builtin_call_arg1 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 1),
...@@ -2167,10 +2170,7 @@ pub const SrcLoc = struct {...@@ -2167,10 +2170,7 @@ pub const SrcLoc = struct {
2167 const tree = try src_loc.file_scope.getTree(gpa);2170 const tree = try src_loc.file_scope.getTree(gpa);
2168 const node_datas = tree.nodes.items(.data);2171 const node_datas = tree.nodes.items(.data);
2169 const node = src_loc.declRelativeToNodeIndex(node_off);2172 const node = src_loc.declRelativeToNodeIndex(node_off);
2170 const main_tokens = tree.nodes.items(.main_token);2173 return nodeToSpan(tree, node_datas[node].rhs);
2171 const tok_index = main_tokens[node_datas[node].rhs];
2172 const token_starts = tree.tokens.items(.start);
2173 return token_starts[tok_index];
2174 },2174 },
2175 .node_offset_slice_ptr,2175 .node_offset_slice_ptr,
2176 .node_offset_slice_start,2176 .node_offset_slice_start,
...@@ -2187,7 +2187,7 @@ pub const SrcLoc = struct {...@@ -2187,7 +2187,7 @@ pub const SrcLoc = struct {
2187 else => unreachable,2187 else => unreachable,
2188 };2188 };
2189 const main_tokens = tree.nodes.items(.main_token);2189 const main_tokens = tree.nodes.items(.main_token);
2190 const tok_index = main_tokens[2190 const part_node = main_tokens[
2191 switch (src_loc.lazy) {2191 switch (src_loc.lazy) {
2192 .node_offset_slice_ptr => full.ast.sliced,2192 .node_offset_slice_ptr => full.ast.sliced,
2193 .node_offset_slice_start => full.ast.start,2193 .node_offset_slice_start => full.ast.start,
...@@ -2196,8 +2196,7 @@ pub const SrcLoc = struct {...@@ -2196,8 +2196,7 @@ pub const SrcLoc = struct {
2196 else => unreachable,2196 else => unreachable,
2197 }2197 }
2198 ];2198 ];
2199 const token_starts = tree.tokens.items(.start);2199 return nodeToSpan(tree, part_node);
2200 return token_starts[tok_index];
2201 },2200 },
2202 .node_offset_call_func => |node_off| {2201 .node_offset_call_func => |node_off| {
2203 const tree = try src_loc.file_scope.getTree(gpa);2202 const tree = try src_loc.file_scope.getTree(gpa);
...@@ -2219,10 +2218,7 @@ pub const SrcLoc = struct {...@@ -2219,10 +2218,7 @@ pub const SrcLoc = struct {
22192218
2220 else => unreachable,2219 else => unreachable,
2221 };2220 };
2222 const main_tokens = tree.nodes.items(.main_token);2221 return nodeToSpan(tree, full.ast.fn_expr);
2223 const tok_index = main_tokens[full.ast.fn_expr];
2224 const token_starts = tree.tokens.items(.start);
2225 return token_starts[tok_index];
2226 },2222 },
2227 .node_offset_field_name => |node_off| {2223 .node_offset_field_name => |node_off| {
2228 const tree = try src_loc.file_scope.getTree(gpa);2224 const tree = try src_loc.file_scope.getTree(gpa);
...@@ -2233,16 +2229,14 @@ pub const SrcLoc = struct {...@@ -2233,16 +2229,14 @@ pub const SrcLoc = struct {
2233 .field_access => node_datas[node].rhs,2229 .field_access => node_datas[node].rhs,
2234 else => tree.firstToken(node) - 2,2230 else => tree.firstToken(node) - 2,
2235 };2231 };
2236 const token_starts = tree.tokens.items(.start);2232 const start = tree.tokens.items(.start)[tok_index];
2237 return token_starts[tok_index];2233 const end = start + @intCast(u32, tree.tokenSlice(tok_index).len);
2234 return Span{ .start = start, .end = end };
2238 },2235 },
2239 .node_offset_deref_ptr => |node_off| {2236 .node_offset_deref_ptr => |node_off| {
2240 const tree = try src_loc.file_scope.getTree(gpa);2237 const tree = try src_loc.file_scope.getTree(gpa);
2241 const node_datas = tree.nodes.items(.data);
2242 const node = src_loc.declRelativeToNodeIndex(node_off);2238 const node = src_loc.declRelativeToNodeIndex(node_off);
2243 const tok_index = node_datas[node].lhs;2239 return nodeToSpan(tree, node);
2244 const token_starts = tree.tokens.items(.start);
2245 return token_starts[tok_index];
2246 },2240 },
2247 .node_offset_asm_source => |node_off| {2241 .node_offset_asm_source => |node_off| {
2248 const tree = try src_loc.file_scope.getTree(gpa);2242 const tree = try src_loc.file_scope.getTree(gpa);
...@@ -2253,10 +2247,7 @@ pub const SrcLoc = struct {...@@ -2253,10 +2247,7 @@ pub const SrcLoc = struct {
2253 .@"asm" => tree.asmFull(node),2247 .@"asm" => tree.asmFull(node),
2254 else => unreachable,2248 else => unreachable,
2255 };2249 };
2256 const main_tokens = tree.nodes.items(.main_token);2250 return nodeToSpan(tree, full.ast.template);
2257 const tok_index = main_tokens[full.ast.template];
2258 const token_starts = tree.tokens.items(.start);
2259 return token_starts[tok_index];
2260 },2251 },
2261 .node_offset_asm_ret_ty => |node_off| {2252 .node_offset_asm_ret_ty => |node_off| {
2262 const tree = try src_loc.file_scope.getTree(gpa);2253 const tree = try src_loc.file_scope.getTree(gpa);
...@@ -2269,11 +2260,7 @@ pub const SrcLoc = struct {...@@ -2269,11 +2260,7 @@ pub const SrcLoc = struct {
2269 };2260 };
2270 const asm_output = full.outputs[0];2261 const asm_output = full.outputs[0];
2271 const node_datas = tree.nodes.items(.data);2262 const node_datas = tree.nodes.items(.data);
2272 const ret_ty_node = node_datas[asm_output].lhs;2263 return nodeToSpan(tree, node_datas[asm_output].lhs);
2273 const main_tokens = tree.nodes.items(.main_token);
2274 const tok_index = main_tokens[ret_ty_node];
2275 const token_starts = tree.tokens.items(.start);
2276 return token_starts[tok_index];
2277 },2264 },
22782265
2279 .node_offset_for_cond, .node_offset_if_cond => |node_off| {2266 .node_offset_for_cond, .node_offset_if_cond => |node_off| {
...@@ -2290,41 +2277,26 @@ pub const SrcLoc = struct {...@@ -2290,41 +2277,26 @@ pub const SrcLoc = struct {
2290 .@"for" => tree.forFull(node).ast.cond_expr,2277 .@"for" => tree.forFull(node).ast.cond_expr,
2291 else => unreachable,2278 else => unreachable,
2292 };2279 };
2293 const main_tokens = tree.nodes.items(.main_token);2280 return nodeToSpan(tree, src_node);
2294 const tok_index = main_tokens[src_node];
2295 const token_starts = tree.tokens.items(.start);
2296 return token_starts[tok_index];
2297 },2281 },
2298 .node_offset_bin_lhs => |node_off| {2282 .node_offset_bin_lhs => |node_off| {
2299 const tree = try src_loc.file_scope.getTree(gpa);2283 const tree = try src_loc.file_scope.getTree(gpa);
2300 const node = src_loc.declRelativeToNodeIndex(node_off);2284 const node = src_loc.declRelativeToNodeIndex(node_off);
2301 const node_datas = tree.nodes.items(.data);2285 const node_datas = tree.nodes.items(.data);
2302 const src_node = node_datas[node].lhs;2286 return nodeToSpan(tree, node_datas[node].lhs);
2303 const main_tokens = tree.nodes.items(.main_token);
2304 const tok_index = main_tokens[src_node];
2305 const token_starts = tree.tokens.items(.start);
2306 return token_starts[tok_index];
2307 },2287 },
2308 .node_offset_bin_rhs => |node_off| {2288 .node_offset_bin_rhs => |node_off| {
2309 const tree = try src_loc.file_scope.getTree(gpa);2289 const tree = try src_loc.file_scope.getTree(gpa);
2310 const node = src_loc.declRelativeToNodeIndex(node_off);2290 const node = src_loc.declRelativeToNodeIndex(node_off);
2311 const node_datas = tree.nodes.items(.data);2291 const node_datas = tree.nodes.items(.data);
2312 const src_node = node_datas[node].rhs;2292 return nodeToSpan(tree, node_datas[node].rhs);
2313 const main_tokens = tree.nodes.items(.main_token);
2314 const tok_index = main_tokens[src_node];
2315 const token_starts = tree.tokens.items(.start);
2316 return token_starts[tok_index];
2317 },2293 },
23182294
2319 .node_offset_switch_operand => |node_off| {2295 .node_offset_switch_operand => |node_off| {
2320 const tree = try src_loc.file_scope.getTree(gpa);2296 const tree = try src_loc.file_scope.getTree(gpa);
2321 const node = src_loc.declRelativeToNodeIndex(node_off);2297 const node = src_loc.declRelativeToNodeIndex(node_off);
2322 const node_datas = tree.nodes.items(.data);2298 const node_datas = tree.nodes.items(.data);
2323 const src_node = node_datas[node].lhs;2299 return nodeToSpan(tree, node_datas[node].lhs);
2324 const main_tokens = tree.nodes.items(.main_token);
2325 const tok_index = main_tokens[src_node];
2326 const token_starts = tree.tokens.items(.start);
2327 return token_starts[tok_index];
2328 },2300 },
23292301
2330 .node_offset_switch_special_prong => |node_off| {2302 .node_offset_switch_special_prong => |node_off| {
...@@ -2347,9 +2319,7 @@ pub const SrcLoc = struct {...@@ -2347,9 +2319,7 @@ pub const SrcLoc = struct {
2347 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"));2319 mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_"));
2348 if (!is_special) continue;2320 if (!is_special) continue;
23492321
2350 const tok_index = main_tokens[case_node];2322 return nodeToSpan(tree, case_node);
2351 const token_starts = tree.tokens.items(.start);
2352 return token_starts[tok_index];
2353 } else unreachable;2323 } else unreachable;
2354 },2324 },
23552325
...@@ -2375,9 +2345,7 @@ pub const SrcLoc = struct {...@@ -2375,9 +2345,7 @@ pub const SrcLoc = struct {
23752345
2376 for (case.ast.values) |item_node| {2346 for (case.ast.values) |item_node| {
2377 if (node_tags[item_node] == .switch_range) {2347 if (node_tags[item_node] == .switch_range) {
2378 const tok_index = main_tokens[item_node];2348 return nodeToSpan(tree, item_node);
2379 const token_starts = tree.tokens.items(.start);
2380 return token_starts[tok_index];
2381 }2349 }
2382 }2350 }
2383 } else unreachable;2351 } else unreachable;
...@@ -2403,10 +2371,7 @@ pub const SrcLoc = struct {...@@ -2403,10 +2371,7 @@ pub const SrcLoc = struct {
2403 },2371 },
2404 else => unreachable,2372 else => unreachable,
2405 };2373 };
2406 const main_tokens = tree.nodes.items(.main_token);2374 return nodeToSpan(tree, full.ast.callconv_expr);
2407 const tok_index = main_tokens[full.ast.callconv_expr];
2408 const token_starts = tree.tokens.items(.start);
2409 return token_starts[tok_index];
2410 },2375 },
24112376
2412 .node_offset_fn_type_ret_ty => |node_off| {2377 .node_offset_fn_type_ret_ty => |node_off| {
...@@ -2421,21 +2386,14 @@ pub const SrcLoc = struct {...@@ -2421,21 +2386,14 @@ pub const SrcLoc = struct {
2421 .fn_proto => tree.fnProto(node),2386 .fn_proto => tree.fnProto(node),
2422 else => unreachable,2387 else => unreachable,
2423 };2388 };
2424 const main_tokens = tree.nodes.items(.main_token);2389 return nodeToSpan(tree, full.ast.return_type);
2425 const tok_index = main_tokens[full.ast.return_type];
2426 const token_starts = tree.tokens.items(.start);
2427 return token_starts[tok_index];
2428 },2390 },
24292391
2430 .node_offset_anyframe_type => |node_off| {2392 .node_offset_anyframe_type => |node_off| {
2431 const tree = try src_loc.file_scope.getTree(gpa);2393 const tree = try src_loc.file_scope.getTree(gpa);
2432 const node_datas = tree.nodes.items(.data);2394 const node_datas = tree.nodes.items(.data);
2433 const parent_node = src_loc.declRelativeToNodeIndex(node_off);2395 const parent_node = src_loc.declRelativeToNodeIndex(node_off);
2434 const node = node_datas[parent_node].rhs;2396 return nodeToSpan(tree, node_datas[parent_node].rhs);
2435 const main_tokens = tree.nodes.items(.main_token);
2436 const tok_index = main_tokens[node];
2437 const token_starts = tree.tokens.items(.start);
2438 return token_starts[tok_index];
2439 },2397 },
24402398
2441 .node_offset_lib_name => |node_off| {2399 .node_offset_lib_name => |node_off| {
...@@ -2462,8 +2420,9 @@ pub const SrcLoc = struct {...@@ -2462,8 +2420,9 @@ pub const SrcLoc = struct {
2462 else => unreachable,2420 else => unreachable,
2463 };2421 };
2464 const tok_index = full.lib_name.?;2422 const tok_index = full.lib_name.?;
2465 const token_starts = tree.tokens.items(.start);2423 const start = tree.tokens.items(.start)[tok_index];
2466 return token_starts[tok_index];2424 const end = start + @intCast(u32, tree.tokenSlice(tok_index).len);
2425 return Span{ .start = start, .end = end };
2467 },2426 },
24682427
2469 .node_offset_array_type_len => |node_off| {2428 .node_offset_array_type_len => |node_off| {
...@@ -2476,11 +2435,7 @@ pub const SrcLoc = struct {...@@ -2476,11 +2435,7 @@ pub const SrcLoc = struct {
2476 .array_type_sentinel => tree.arrayTypeSentinel(parent_node),2435 .array_type_sentinel => tree.arrayTypeSentinel(parent_node),
2477 else => unreachable,2436 else => unreachable,
2478 };2437 };
2479 const node = full.ast.elem_count;2438 return nodeToSpan(tree, full.ast.elem_count);
2480 const main_tokens = tree.nodes.items(.main_token);
2481 const tok_index = main_tokens[node];
2482 const token_starts = tree.tokens.items(.start);
2483 return token_starts[tok_index];
2484 },2439 },
2485 .node_offset_array_type_sentinel => |node_off| {2440 .node_offset_array_type_sentinel => |node_off| {
2486 const tree = try src_loc.file_scope.getTree(gpa);2441 const tree = try src_loc.file_scope.getTree(gpa);
...@@ -2492,11 +2447,7 @@ pub const SrcLoc = struct {...@@ -2492,11 +2447,7 @@ pub const SrcLoc = struct {
2492 .array_type_sentinel => tree.arrayTypeSentinel(parent_node),2447 .array_type_sentinel => tree.arrayTypeSentinel(parent_node),
2493 else => unreachable,2448 else => unreachable,
2494 };2449 };
2495 const node = full.ast.sentinel;2450 return nodeToSpan(tree, full.ast.sentinel);
2496 const main_tokens = tree.nodes.items(.main_token);
2497 const tok_index = main_tokens[node];
2498 const token_starts = tree.tokens.items(.start);
2499 return token_starts[tok_index];
2500 },2451 },
2501 .node_offset_array_type_elem => |node_off| {2452 .node_offset_array_type_elem => |node_off| {
2502 const tree = try src_loc.file_scope.getTree(gpa);2453 const tree = try src_loc.file_scope.getTree(gpa);
...@@ -2508,21 +2459,14 @@ pub const SrcLoc = struct {...@@ -2508,21 +2459,14 @@ pub const SrcLoc = struct {
2508 .array_type_sentinel => tree.arrayTypeSentinel(parent_node),2459 .array_type_sentinel => tree.arrayTypeSentinel(parent_node),
2509 else => unreachable,2460 else => unreachable,
2510 };2461 };
2511 const node = full.ast.elem_type;2462 return nodeToSpan(tree, full.ast.elem_type);
2512 const main_tokens = tree.nodes.items(.main_token);
2513 const tok_index = main_tokens[node];
2514 const token_starts = tree.tokens.items(.start);
2515 return token_starts[tok_index];
2516 },2463 },
2517 .node_offset_un_op => |node_off| {2464 .node_offset_un_op => |node_off| {
2518 const tree = try src_loc.file_scope.getTree(gpa);2465 const tree = try src_loc.file_scope.getTree(gpa);
2519 const node_datas = tree.nodes.items(.data);2466 const node_datas = tree.nodes.items(.data);
2520 const node = src_loc.declRelativeToNodeIndex(node_off);2467 const node = src_loc.declRelativeToNodeIndex(node_off);
25212468
2522 const main_tokens = tree.nodes.items(.main_token);2469 return nodeToSpan(tree, node_datas[node].lhs);
2523 const tok_index = main_tokens[node_datas[node].lhs];
2524 const token_starts = tree.tokens.items(.start);
2525 return token_starts[tok_index];
2526 },2470 },
2527 }2471 }
2528 }2472 }
...@@ -2532,7 +2476,7 @@ pub const SrcLoc = struct {...@@ -2532,7 +2476,7 @@ pub const SrcLoc = struct {
2532 gpa: Allocator,2476 gpa: Allocator,
2533 node_off: i32,2477 node_off: i32,
2534 arg_index: u32,2478 arg_index: u32,
2535 ) !u32 {2479 ) !Span {
2536 const tree = try src_loc.file_scope.getTree(gpa);2480 const tree = try src_loc.file_scope.getTree(gpa);
2537 const node_datas = tree.nodes.items(.data);2481 const node_datas = tree.nodes.items(.data);
2538 const node_tags = tree.nodes.items(.tag);2482 const node_tags = tree.nodes.items(.tag);
...@@ -2546,10 +2490,33 @@ pub const SrcLoc = struct {...@@ -2546,10 +2490,33 @@ pub const SrcLoc = struct {
2546 .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + arg_index],2490 .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + arg_index],
2547 else => unreachable,2491 else => unreachable,
2548 };2492 };
2549 const main_tokens = tree.nodes.items(.main_token);2493 return nodeToSpan(tree, param);
2550 const tok_index = main_tokens[param];2494 }
2495
2496 pub fn nodeToSpan(tree: *const Ast, node: u32) Span {
2551 const token_starts = tree.tokens.items(.start);2497 const token_starts = tree.tokens.items(.start);
2552 return token_starts[tok_index];2498 const start = tree.firstToken(node);
2499 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 }
2505
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 };
2516 }
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 };
2553 }2520 }
2554};2521};
25552522
...@@ -3313,7 +3280,11 @@ pub fn astGenFile(mod: *Module, file: *File) !void {...@@ -3313,7 +3280,11 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
3313 .src_loc = .{3280 .src_loc = .{
3314 .file_scope = file,3281 .file_scope = file,
3315 .parent_decl_node = 0,3282 .parent_decl_node = 0,
3316 .lazy = .{ .byte_abs = token_starts[parse_err.token] + extra_offset },3283 .lazy = if (extra_offset == 0) .{
3284 .token_abs = parse_err.token,
3285 } else .{
3286 .byte_abs = token_starts[parse_err.token],
3287 },
3317 },3288 },
3318 .msg = msg.toOwnedSlice(),3289 .msg = msg.toOwnedSlice(),
3319 };3290 };
...@@ -3336,7 +3307,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {...@@ -3336,7 +3307,7 @@ pub fn astGenFile(mod: *Module, file: *File) !void {
3336 .src_loc = .{3307 .src_loc = .{
3337 .file_scope = file,3308 .file_scope = file,
3338 .parent_decl_node = 0,3309 .parent_decl_node = 0,
3339 .lazy = .{ .byte_abs = token_starts[note.token] },3310 .lazy = .{ .token_abs = note.token },
3340 },3311 },
3341 .msg = msg.toOwnedSlice(),3312 .msg = msg.toOwnedSlice(),
3342 };3313 };
src/main.zig+5-3
...@@ -4381,7 +4381,7 @@ fn printErrsMsgToStdErr(...@@ -4381,7 +4381,7 @@ fn printErrsMsgToStdErr(
4381 .msg = try std.fmt.allocPrint(arena, "invalid byte: '{'}'", .{4381 .msg = try std.fmt.allocPrint(arena, "invalid byte: '{'}'", .{
4382 std.zig.fmtEscapes(tree.source[byte_offset..][0..1]),4382 std.zig.fmtEscapes(tree.source[byte_offset..][0..1]),
4383 }),4383 }),
4384 .byte_offset = byte_offset,4384 .span = .{ .start = byte_offset, .end = byte_offset + 1 },
4385 .line = @intCast(u32, start_loc.line),4385 .line = @intCast(u32, start_loc.line),
4386 .column = @intCast(u32, start_loc.column) + bad_off,4386 .column = @intCast(u32, start_loc.column) + bad_off,
4387 .source_line = source_line,4387 .source_line = source_line,
...@@ -4396,11 +4396,12 @@ fn printErrsMsgToStdErr(...@@ -4396,11 +4396,12 @@ fn printErrsMsgToStdErr(
4396 text_buf.items.len = 0;4396 text_buf.items.len = 0;
4397 try tree.renderError(note, writer);4397 try tree.renderError(note, writer);
4398 const note_loc = tree.tokenLocation(0, note.token);4398 const note_loc = tree.tokenLocation(0, note.token);
4399 const byte_offset = @intCast(u32, note_loc.line_start);
4399 notes_buffer[notes_len] = .{4400 notes_buffer[notes_len] = .{
4400 .src = .{4401 .src = .{
4401 .src_path = path,4402 .src_path = path,
4402 .msg = try arena.dupe(u8, text_buf.items),4403 .msg = try arena.dupe(u8, text_buf.items),
4403 .byte_offset = @intCast(u32, note_loc.line_start),4404 .span = .{ .start = byte_offset, .end = byte_offset + @intCast(u32, tree.tokenSlice(note.token).len) },
4404 .line = @intCast(u32, note_loc.line),4405 .line = @intCast(u32, note_loc.line),
4405 .column = @intCast(u32, note_loc.column),4406 .column = @intCast(u32, note_loc.column),
4406 .source_line = tree.source[note_loc.line_start..note_loc.line_end],4407 .source_line = tree.source[note_loc.line_start..note_loc.line_end],
...@@ -4411,11 +4412,12 @@ fn printErrsMsgToStdErr(...@@ -4411,11 +4412,12 @@ fn printErrsMsgToStdErr(
4411 }4412 }
44124413
4413 const extra_offset = tree.errorOffset(parse_error);4414 const extra_offset = tree.errorOffset(parse_error);
4415 const byte_offset = @intCast(u32, start_loc.line_start) + extra_offset;
4414 const message: Compilation.AllErrors.Message = .{4416 const message: Compilation.AllErrors.Message = .{
4415 .src = .{4417 .src = .{
4416 .src_path = path,4418 .src_path = path,
4417 .msg = text,4419 .msg = text,
4418 .byte_offset = @intCast(u32, start_loc.line_start) + extra_offset,4420 .span = .{ .start = byte_offset, .end = byte_offset + @intCast(u32, tree.tokenSlice(lok_token).len) },
4419 .line = @intCast(u32, start_loc.line),4421 .line = @intCast(u32, start_loc.line),
4420 .column = @intCast(u32, start_loc.column) + extra_offset,4422 .column = @intCast(u32, start_loc.column) + extra_offset,
4421 .source_line = source_line,4423 .source_line = source_line,
src/print_zir.zig+6-4
...@@ -2381,10 +2381,12 @@ const Writer = struct {...@@ -2381,10 +2381,12 @@ const Writer = struct {
2381 .parent_decl_node = self.parent_decl_node,2381 .parent_decl_node = self.parent_decl_node,
2382 .lazy = src,2382 .lazy = src,
2383 };2383 };
2384 const abs_byte_off = src_loc.byteOffset(self.gpa) catch unreachable;2384 const src_span = src_loc.span(self.gpa) catch unreachable;
2385 const delta_line = std.zig.findLineColumn(tree.source, abs_byte_off);2385 const start = std.zig.findLineColumn(tree.source, src_span.start);
2386 try stream.print("{s}:{d}:{d}", .{2386 const end = std.zig.findLineColumn(tree.source, src_span.end);
2387 @tagName(src), delta_line.line + 1, delta_line.column + 1,2387 try stream.print("{s}:{d}:{d} to :{d}:{d}", .{
2388 @tagName(src), start.line + 1, start.column + 1,
2389 end.line + 1, end.column + 1,
2388 });2390 });
2389 }2391 }
2390 }2392 }