Merge pull request #5378 from ziglang/speed-up-stage2-parsing

improve std.zig.parse performance using flat arrays for AST nodes and tokens
master
Andrew Kelley 2020-05-24 09:44:08 -04:00 committed by GitHub
commit 2ff3995a70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 5603 additions and 4900 deletions

View File

@ -776,7 +776,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
next_tok_is_fn = false;
const token = tokenizer.next();
try writeEscaped(out, src[index..token.start]);
try writeEscaped(out, src[index..token.loc.start]);
switch (token.id) {
.Eof => break,
@ -827,13 +827,13 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
.Keyword_while,
=> {
try out.writeAll("<span class=\"tok-kw\">");
try writeEscaped(out, src[token.start..token.end]);
try writeEscaped(out, src[token.loc.start..token.loc.end]);
try out.writeAll("</span>");
},
.Keyword_fn => {
try out.writeAll("<span class=\"tok-kw\">");
try writeEscaped(out, src[token.start..token.end]);
try writeEscaped(out, src[token.loc.start..token.loc.end]);
try out.writeAll("</span>");
next_tok_is_fn = true;
},
@ -844,7 +844,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
.Keyword_false,
=> {
try out.writeAll("<span class=\"tok-null\">");
try writeEscaped(out, src[token.start..token.end]);
try writeEscaped(out, src[token.loc.start..token.loc.end]);
try out.writeAll("</span>");
},
@ -853,13 +853,13 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
.CharLiteral,
=> {
try out.writeAll("<span class=\"tok-str\">");
try writeEscaped(out, src[token.start..token.end]);
try writeEscaped(out, src[token.loc.start..token.loc.end]);
try out.writeAll("</span>");
},
.Builtin => {
try out.writeAll("<span class=\"tok-builtin\">");
try writeEscaped(out, src[token.start..token.end]);
try writeEscaped(out, src[token.loc.start..token.loc.end]);
try out.writeAll("</span>");
},
@ -869,34 +869,34 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
.ShebangLine,
=> {
try out.writeAll("<span class=\"tok-comment\">");
try writeEscaped(out, src[token.start..token.end]);
try writeEscaped(out, src[token.loc.start..token.loc.end]);
try out.writeAll("</span>");
},
.Identifier => {
if (prev_tok_was_fn) {
try out.writeAll("<span class=\"tok-fn\">");
try writeEscaped(out, src[token.start..token.end]);
try writeEscaped(out, src[token.loc.start..token.loc.end]);
try out.writeAll("</span>");
} else {
const is_int = blk: {
if (src[token.start] != 'i' and src[token.start] != 'u')
if (src[token.loc.start] != 'i' and src[token.loc.start] != 'u')
break :blk false;
var i = token.start + 1;
if (i == token.end)
var i = token.loc.start + 1;
if (i == token.loc.end)
break :blk false;
while (i != token.end) : (i += 1) {
while (i != token.loc.end) : (i += 1) {
if (src[i] < '0' or src[i] > '9')
break :blk false;
}
break :blk true;
};
if (is_int or isType(src[token.start..token.end])) {
if (is_int or isType(src[token.loc.start..token.loc.end])) {
try out.writeAll("<span class=\"tok-type\">");
try writeEscaped(out, src[token.start..token.end]);
try writeEscaped(out, src[token.loc.start..token.loc.end]);
try out.writeAll("</span>");
} else {
try writeEscaped(out, src[token.start..token.end]);
try writeEscaped(out, src[token.loc.start..token.loc.end]);
}
}
},
@ -905,7 +905,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
.FloatLiteral,
=> {
try out.writeAll("<span class=\"tok-number\">");
try writeEscaped(out, src[token.start..token.end]);
try writeEscaped(out, src[token.loc.start..token.loc.end]);
try out.writeAll("</span>");
},
@ -963,7 +963,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
.AngleBracketAngleBracketRight,
.AngleBracketAngleBracketRightEqual,
.Tilde,
=> try writeEscaped(out, src[token.start..token.end]),
=> try writeEscaped(out, src[token.loc.start..token.loc.end]),
.Invalid, .Invalid_ampersands => return parseError(
docgen_tokenizer,
@ -972,7 +972,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
.{},
),
}
index = token.end;
index = token.loc.end;
}
try out.writeAll("</code>");
}

View File

@ -46,13 +46,9 @@ pub const ArenaAllocator = struct {
}
fn createNode(self: *ArenaAllocator, prev_len: usize, minimum_size: usize) !*BufNode {
const actual_min_size = minimum_size + @sizeOf(BufNode);
var len = prev_len;
while (true) {
len += len / 2;
len += mem.page_size - @rem(len, mem.page_size);
if (len >= actual_min_size) break;
}
const actual_min_size = minimum_size + (@sizeOf(BufNode) + 16);
const big_enough_len = prev_len + actual_min_size;
const len = big_enough_len + big_enough_len / 2;
const buf = try self.child_allocator.alignedAlloc(u8, @alignOf(BufNode), len);
const buf_node_slice = mem.bytesAsSlice(BufNode, buf[0..@sizeOf(BufNode)]);
const buf_node = &buf_node_slice[0];

View File

@ -21,6 +21,8 @@ pub fn SinglyLinkedList(comptime T: type) type {
next: ?*Node = null,
data: T,
pub const Data = T;
pub fn init(data: T) Node {
return Node{
.data = data,
@ -47,29 +49,30 @@ pub fn SinglyLinkedList(comptime T: type) type {
node.next = next_node.next;
return next_node;
}
/// Iterate over the singly-linked list from this node, until the final node is found.
/// This operation is O(N).
pub fn findLast(node: *Node) *Node {
var it = node;
while (true) {
it = it.next orelse return it;
}
}
/// Iterate over each next node, returning the count of all nodes except the starting one.
/// This operation is O(N).
pub fn countChildren(node: *const Node) usize {
var count: usize = 0;
var it: ?*const Node = node;
while (it) |n| : (it = n.next) {
count += 1;
}
return count;
}
};
first: ?*Node = null,
/// Initialize a linked list.
///
/// Returns:
/// An empty linked list.
pub fn init() Self {
return Self{
.first = null,
};
}
/// Insert a new node after an existing one.
///
/// Arguments:
/// node: Pointer to a node in the list.
/// new_node: Pointer to the new node to insert.
pub fn insertAfter(list: *Self, node: *Node, new_node: *Node) void {
node.insertAfter(new_node);
}
/// Insert a new node at the head.
///
/// Arguments:
@ -105,64 +108,33 @@ pub fn SinglyLinkedList(comptime T: type) type {
return first;
}
/// Allocate a new node.
///
/// Arguments:
/// allocator: Dynamic memory allocator.
///
/// Returns:
/// A pointer to the new node.
pub fn allocateNode(list: *Self, allocator: *Allocator) !*Node {
return allocator.create(Node);
}
/// Deallocate a node.
///
/// Arguments:
/// node: Pointer to the node to deallocate.
/// allocator: Dynamic memory allocator.
pub fn destroyNode(list: *Self, node: *Node, allocator: *Allocator) void {
allocator.destroy(node);
}
/// Allocate and initialize a node and its data.
///
/// Arguments:
/// data: The data to put inside the node.
/// allocator: Dynamic memory allocator.
///
/// Returns:
/// A pointer to the new node.
pub fn createNode(list: *Self, data: T, allocator: *Allocator) !*Node {
var node = try list.allocateNode(allocator);
node.* = Node.init(data);
return node;
/// Iterate over all nodes, returning the count.
/// This operation is O(N).
pub fn len(list: Self) usize {
if (list.first) |n| {
return 1 + n.countChildren();
} else {
return 0;
}
}
};
}
test "basic SinglyLinkedList test" {
const allocator = testing.allocator;
var list = SinglyLinkedList(u32).init();
const L = SinglyLinkedList(u32);
var list = L{};
var one = try list.createNode(1, allocator);
var two = try list.createNode(2, allocator);
var three = try list.createNode(3, allocator);
var four = try list.createNode(4, allocator);
var five = try list.createNode(5, allocator);
defer {
list.destroyNode(one, allocator);
list.destroyNode(two, allocator);
list.destroyNode(three, allocator);
list.destroyNode(four, allocator);
list.destroyNode(five, allocator);
}
var one = L.Node{.data = 1};
var two = L.Node{.data = 2};
var three = L.Node{.data = 3};
var four = L.Node{.data = 4};
var five = L.Node{.data = 5};
list.prepend(two); // {2}
list.insertAfter(two, five); // {2, 5}
list.prepend(one); // {1, 2, 5}
list.insertAfter(two, three); // {1, 2, 3, 5}
list.insertAfter(three, four); // {1, 2, 3, 4, 5}
list.prepend(&two); // {2}
two.insertAfter(&five); // {2, 5}
list.prepend(&one); // {1, 2, 5}
two.insertAfter(&three); // {1, 2, 3, 5}
three.insertAfter(&four); // {1, 2, 3, 4, 5}
// Traverse forwards.
{
@ -175,7 +147,7 @@ test "basic SinglyLinkedList test" {
}
_ = list.popFirst(); // {2, 3, 4, 5}
_ = list.remove(five); // {2, 3, 4}
_ = list.remove(&five); // {2, 3, 4}
_ = two.removeNext(); // {2, 4}
testing.expect(list.first.?.data == 2);

View File

@ -658,7 +658,7 @@ pub const Xoroshiro128 = struct {
self.s[1] = s1;
}
fn seed(self: *Xoroshiro128, init_s: u64) void {
pub fn seed(self: *Xoroshiro128, init_s: u64) void {
// Xoroshiro requires 128-bits of seed.
var gen = SplitMix64.init(init_s);

View File

@ -320,10 +320,11 @@ fn printWithVisibleNewlines(source: []const u8) void {
}
fn printLine(line: []const u8) void {
switch (line[line.len - 1]) {
if (line.len != 0) switch (line[line.len - 1]) {
' ', '\t' => warn("{}⏎\n", .{line}), // Carriage return symbol,
else => warn("{}\n", .{line}),
}
else => {},
};
warn("{}\n", .{line});
}
test "" {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -3180,9 +3180,8 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b
const tree = try std.zig.parse(allocator, source);
defer tree.deinit();
var error_it = tree.errors.iterator(0);
while (error_it.next()) |parse_error| {
const token = tree.tokens.at(parse_error.loc());
for (tree.errors) |*parse_error| {
const token = tree.token_locs[parse_error.loc()];
const loc = tree.tokenLocation(0, parse_error.loc());
try stderr.print("(memory buffer):{}:{}: error: ", .{ loc.line + 1, loc.column + 1 });
try tree.renderError(parse_error, stderr);
@ -3271,8 +3270,6 @@ fn testError(source: []const u8, expected_errors: []const Error) !void {
std.testing.expect(tree.errors.len == expected_errors.len);
for (expected_errors) |expected, i| {
const err = tree.errors.at(i);
std.testing.expect(expected == err.*);
std.testing.expect(expected == tree.errors[i]);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -3,8 +3,12 @@ const mem = std.mem;
pub const Token = struct {
id: Id,
start: usize,
end: usize,
loc: Loc,
pub const Loc = struct {
start: usize,
end: usize,
};
pub const Keyword = struct {
bytes: []const u8,
@ -426,8 +430,10 @@ pub const Tokenizer = struct {
var state: State = .start;
var result = Token{
.id = .Eof,
.start = self.index,
.end = undefined,
.loc = .{
.start = self.index,
.end = undefined,
},
};
var seen_escape_digits: usize = undefined;
var remaining_code_units: usize = undefined;
@ -436,7 +442,7 @@ pub const Tokenizer = struct {
switch (state) {
.start => switch (c) {
' ', '\n', '\t', '\r' => {
result.start = self.index + 1;
result.loc.start = self.index + 1;
},
'"' => {
state = .string_literal;
@ -686,7 +692,7 @@ pub const Tokenizer = struct {
.identifier => switch (c) {
'a'...'z', 'A'...'Z', '_', '0'...'9' => {},
else => {
if (Token.getKeyword(self.buffer[result.start..self.index])) |id| {
if (Token.getKeyword(self.buffer[result.loc.start..self.index])) |id| {
result.id = id;
}
break;
@ -1313,7 +1319,7 @@ pub const Tokenizer = struct {
=> {},
.identifier => {
if (Token.getKeyword(self.buffer[result.start..self.index])) |id| {
if (Token.getKeyword(self.buffer[result.loc.start..self.index])) |id| {
result.id = id;
}
},
@ -1420,7 +1426,7 @@ pub const Tokenizer = struct {
}
}
result.end = self.index;
result.loc.end = self.index;
return result;
}
@ -1430,8 +1436,10 @@ pub const Tokenizer = struct {
if (invalid_length == 0) return;
self.pending_invalid_token = .{
.id = .Invalid,
.start = self.index,
.end = self.index + invalid_length,
.loc = .{
.start = self.index,
.end = self.index + invalid_length,
},
};
}

View File

@ -22,7 +22,7 @@ pub const struct_ZigClangCompoundStmt = @Type(.Opaque);
pub const struct_ZigClangConstantArrayType = @Type(.Opaque);
pub const struct_ZigClangContinueStmt = @Type(.Opaque);
pub const struct_ZigClangDecayedType = @Type(.Opaque);
pub const struct_ZigClangDecl = @Type(.Opaque);
pub const ZigClangDecl = @Type(.Opaque);
pub const struct_ZigClangDeclRefExpr = @Type(.Opaque);
pub const struct_ZigClangDeclStmt = @Type(.Opaque);
pub const struct_ZigClangDefaultStmt = @Type(.Opaque);
@ -63,7 +63,7 @@ pub const struct_ZigClangReturnStmt = @Type(.Opaque);
pub const struct_ZigClangSkipFunctionBodiesScope = @Type(.Opaque);
pub const struct_ZigClangSourceManager = @Type(.Opaque);
pub const struct_ZigClangSourceRange = @Type(.Opaque);
pub const struct_ZigClangStmt = @Type(.Opaque);
pub const ZigClangStmt = @Type(.Opaque);
pub const struct_ZigClangStringLiteral = @Type(.Opaque);
pub const struct_ZigClangStringRef = @Type(.Opaque);
pub const struct_ZigClangSwitchStmt = @Type(.Opaque);
@ -781,7 +781,7 @@ pub extern fn ZigClangSourceManager_getCharacterData(self: ?*const struct_ZigCla
pub extern fn ZigClangASTContext_getPointerType(self: ?*const struct_ZigClangASTContext, T: struct_ZigClangQualType) struct_ZigClangQualType;
pub extern fn ZigClangASTUnit_getASTContext(self: ?*struct_ZigClangASTUnit) ?*struct_ZigClangASTContext;
pub extern fn ZigClangASTUnit_getSourceManager(self: *struct_ZigClangASTUnit) *struct_ZigClangSourceManager;
pub extern fn ZigClangASTUnit_visitLocalTopLevelDecls(self: *struct_ZigClangASTUnit, context: ?*c_void, Fn: ?fn (?*c_void, *const struct_ZigClangDecl) callconv(.C) bool) bool;
pub extern fn ZigClangASTUnit_visitLocalTopLevelDecls(self: *struct_ZigClangASTUnit, context: ?*c_void, Fn: ?fn (?*c_void, *const ZigClangDecl) callconv(.C) bool) bool;
pub extern fn ZigClangRecordType_getDecl(record_ty: ?*const struct_ZigClangRecordType) *const struct_ZigClangRecordDecl;
pub extern fn ZigClangTagDecl_isThisDeclarationADefinition(self: *const ZigClangTagDecl) bool;
pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) *const struct_ZigClangEnumDecl;
@ -817,7 +817,7 @@ pub extern fn ZigClangEnumDecl_enumerator_end(*const ZigClangEnumDecl) ZigClangE
pub extern fn ZigClangEnumDecl_enumerator_iterator_next(ZigClangEnumDecl_enumerator_iterator) ZigClangEnumDecl_enumerator_iterator;
pub extern fn ZigClangEnumDecl_enumerator_iterator_deref(ZigClangEnumDecl_enumerator_iterator) *const ZigClangEnumConstantDecl;
pub extern fn ZigClangEnumDecl_enumerator_iterator_neq(ZigClangEnumDecl_enumerator_iterator, ZigClangEnumDecl_enumerator_iterator) bool;
pub extern fn ZigClangDecl_castToNamedDecl(decl: *const struct_ZigClangDecl) ?*const ZigClangNamedDecl;
pub extern fn ZigClangDecl_castToNamedDecl(decl: *const ZigClangDecl) ?*const ZigClangNamedDecl;
pub extern fn ZigClangNamedDecl_getName_bytes_begin(decl: ?*const struct_ZigClangNamedDecl) [*:0]const u8;
pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: struct_ZigClangSourceLocation) bool;
pub extern fn ZigClangTypedefType_getDecl(self: ?*const struct_ZigClangTypedefType) *const struct_ZigClangTypedefNameDecl;
@ -842,9 +842,9 @@ pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*
pub extern fn ZigClangType_getAsArrayTypeUnsafe(self: *const ZigClangType) *const ZigClangArrayType;
pub extern fn ZigClangType_getAsRecordType(self: *const ZigClangType) ?*const ZigClangRecordType;
pub extern fn ZigClangType_getAsUnionType(self: *const ZigClangType) ?*const ZigClangRecordType;
pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation;
pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass;
pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool;
pub extern fn ZigClangStmt_getBeginLoc(self: *const ZigClangStmt) struct_ZigClangSourceLocation;
pub extern fn ZigClangStmt_getStmtClass(self: ?*const ZigClangStmt) ZigClangStmtClass;
pub extern fn ZigClangStmt_classof_Expr(self: ?*const ZigClangStmt) bool;
pub extern fn ZigClangExpr_getStmtClass(self: *const struct_ZigClangExpr) ZigClangStmtClass;
pub extern fn ZigClangExpr_getType(self: *const struct_ZigClangExpr) struct_ZigClangQualType;
pub extern fn ZigClangExpr_getBeginLoc(self: *const struct_ZigClangExpr) struct_ZigClangSourceLocation;
@ -873,7 +873,7 @@ pub extern fn ZigClangFunctionDecl_getLocation(self: *const ZigClangFunctionDecl
pub extern fn ZigClangFunctionDecl_hasBody(self: *const ZigClangFunctionDecl) bool;
pub extern fn ZigClangFunctionDecl_getStorageClass(self: *const ZigClangFunctionDecl) ZigClangStorageClass;
pub extern fn ZigClangFunctionDecl_getParamDecl(self: *const ZigClangFunctionDecl, i: c_uint) *const struct_ZigClangParmVarDecl;
pub extern fn ZigClangFunctionDecl_getBody(self: *const ZigClangFunctionDecl) *const struct_ZigClangStmt;
pub extern fn ZigClangFunctionDecl_getBody(self: *const ZigClangFunctionDecl) *const ZigClangStmt;
pub extern fn ZigClangFunctionDecl_doesDeclarationForceExternallyVisibleDefinition(self: *const ZigClangFunctionDecl) bool;
pub extern fn ZigClangFunctionDecl_isThisDeclarationADefinition(self: *const ZigClangFunctionDecl) bool;
pub extern fn ZigClangFunctionDecl_doesThisDeclarationHaveABody(self: *const ZigClangFunctionDecl) bool;
@ -918,7 +918,6 @@ pub const ZigClangCompoundStmt = struct_ZigClangCompoundStmt;
pub const ZigClangConstantArrayType = struct_ZigClangConstantArrayType;
pub const ZigClangContinueStmt = struct_ZigClangContinueStmt;
pub const ZigClangDecayedType = struct_ZigClangDecayedType;
pub const ZigClangDecl = struct_ZigClangDecl;
pub const ZigClangDeclRefExpr = struct_ZigClangDeclRefExpr;
pub const ZigClangDeclStmt = struct_ZigClangDeclStmt;
pub const ZigClangDefaultStmt = struct_ZigClangDefaultStmt;
@ -959,7 +958,6 @@ pub const ZigClangReturnStmt = struct_ZigClangReturnStmt;
pub const ZigClangSkipFunctionBodiesScope = struct_ZigClangSkipFunctionBodiesScope;
pub const ZigClangSourceManager = struct_ZigClangSourceManager;
pub const ZigClangSourceRange = struct_ZigClangSourceRange;
pub const ZigClangStmt = struct_ZigClangStmt;
pub const ZigClangStringLiteral = struct_ZigClangStringLiteral;
pub const ZigClangStringRef = struct_ZigClangStringRef;
pub const ZigClangSwitchStmt = struct_ZigClangSwitchStmt;
@ -1016,14 +1014,14 @@ pub extern fn ZigClangLoadFromCommandLine(
) ?*ZigClangASTUnit;
pub extern fn ZigClangDecl_getKind(decl: *const ZigClangDecl) ZigClangDeclKind;
pub extern fn ZigClangDecl_getDeclKindName(decl: *const struct_ZigClangDecl) [*:0]const u8;
pub extern fn ZigClangDecl_getDeclKindName(decl: *const ZigClangDecl) [*:0]const u8;
pub const ZigClangCompoundStmt_const_body_iterator = [*]const *struct_ZigClangStmt;
pub const ZigClangCompoundStmt_const_body_iterator = [*]const *ZigClangStmt;
pub extern fn ZigClangCompoundStmt_body_begin(self: *const ZigClangCompoundStmt) ZigClangCompoundStmt_const_body_iterator;
pub extern fn ZigClangCompoundStmt_body_end(self: *const ZigClangCompoundStmt) ZigClangCompoundStmt_const_body_iterator;
pub const ZigClangDeclStmt_const_decl_iterator = [*]const *struct_ZigClangDecl;
pub const ZigClangDeclStmt_const_decl_iterator = [*]const *ZigClangDecl;
pub extern fn ZigClangDeclStmt_decl_begin(self: *const ZigClangDeclStmt) ZigClangDeclStmt_const_decl_iterator;
pub extern fn ZigClangDeclStmt_decl_end(self: *const ZigClangDeclStmt) ZigClangDeclStmt_const_decl_iterator;

View File

@ -600,8 +600,7 @@ pub fn cmdFmt(gpa: *Allocator, args: []const []const u8) !void {
};
defer tree.deinit();
var error_it = tree.errors.iterator(0);
while (error_it.next()) |parse_error| {
for (tree.errors) |parse_error| {
try printErrMsgToFile(gpa, parse_error, tree, "<stdin>", stderr_file, color);
}
if (tree.errors.len != 0) {
@ -701,8 +700,7 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {
};
defer tree.deinit();
var error_it = tree.errors.iterator(0);
while (error_it.next()) |parse_error| {
for (tree.errors) |parse_error| {
try printErrMsgToFile(fmt.gpa, parse_error, tree, file_path, std.io.getStdErr(), fmt.color);
}
if (tree.errors.len != 0) {
@ -730,7 +728,7 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {
fn printErrMsgToFile(
gpa: *mem.Allocator,
parse_error: *const ast.Error,
parse_error: ast.Error,
tree: *ast.Tree,
path: []const u8,
file: fs.File,
@ -745,15 +743,15 @@ fn printErrMsgToFile(
const span_first = lok_token;
const span_last = lok_token;
const first_token = tree.tokens.at(span_first);
const last_token = tree.tokens.at(span_last);
const start_loc = tree.tokenLocationPtr(0, first_token);
const end_loc = tree.tokenLocationPtr(first_token.end, last_token);
const first_token = tree.token_locs[span_first];
const last_token = tree.token_locs[span_last];
const start_loc = tree.tokenLocationLoc(0, first_token);
const end_loc = tree.tokenLocationLoc(first_token.end, last_token);
var text_buf = std.ArrayList(u8).init(gpa);
defer text_buf.deinit();
const out_stream = text_buf.outStream();
try parse_error.render(&tree.tokens, out_stream);
try parse_error.render(tree.token_ids, out_stream);
const text = text_buf.span();
const stream = file.outStream();

File diff suppressed because it is too large Load Diff

View File

@ -3612,6 +3612,12 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
auto entry = decls_scope->decl_table.put_unique(tld->name, tld);
if (entry) {
Tld *other_tld = entry->value;
if (other_tld->id == TldIdVar) {
ZigVar *var = reinterpret_cast<TldVar *>(other_tld)->var;
if (var != nullptr && var->var_type != nullptr && type_is_invalid(var->var_type)) {
return; // already reported compile error
}
}
ErrorMsg *msg = add_node_error(g, tld->source_node, buf_sprintf("redefinition of '%s'", buf_ptr(tld->name)));
add_error_note(g, msg, other_tld->source_node, buf_sprintf("previous definition is here"));
return;
@ -3887,9 +3893,18 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
if (search_scope != nullptr) {
Tld *tld = find_decl(g, search_scope, name);
if (tld != nullptr && tld != src_tld) {
ErrorMsg *msg = add_node_error(g, source_node,
buf_sprintf("redefinition of '%s'", buf_ptr(name)));
add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition is here"));
bool want_err_msg = true;
if (tld->id == TldIdVar) {
ZigVar *var = reinterpret_cast<TldVar *>(tld)->var;
if (var != nullptr && var->var_type != nullptr && type_is_invalid(var->var_type)) {
want_err_msg = false;
}
}
if (want_err_msg) {
ErrorMsg *msg = add_node_error(g, source_node,
buf_sprintf("redefinition of '%s'", buf_ptr(name)));
add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition is here"));
}
variable_entry->var_type = g->builtin_types.entry_invalid;
}
}

View File

@ -5300,9 +5300,18 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s
} else {
Tld *tld = find_decl(codegen, parent_scope, name);
if (tld != nullptr) {
ErrorMsg *msg = add_node_error(codegen, node,
buf_sprintf("redefinition of '%s'", buf_ptr(name)));
add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here"));
bool want_err_msg = true;
if (tld->id == TldIdVar) {
ZigVar *var = reinterpret_cast<TldVar *>(tld)->var;
if (var != nullptr && var->var_type != nullptr && type_is_invalid(var->var_type)) {
want_err_msg = false;
}
}
if (want_err_msg) {
ErrorMsg *msg = add_node_error(codegen, node,
buf_sprintf("redefinition of '%s'", buf_ptr(name)));
add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here"));
}
variable_entry->var_type = codegen->builtin_types.entry_invalid;
}
}