Implement makeScopeInternal logic

This commit is contained in:
Luuk de Gram 2021-02-28 13:09:10 +01:00
parent 5f5d6ce4ea
commit 709c1a70fd
No known key found for this signature in database
GPG Key ID: A002B174963DBB7D

View File

@ -1601,9 +1601,9 @@ pub const Declaration = union(enum) {
array_expr: ast.full.ArrayType, array_expr: ast.full.ArrayType,
}, },
switch_payload: struct { switch_payload: struct {
node: ast.full.PtrType, node: ast.TokenIndex,
switch_expr: *ast.Node, switch_expr: ast.Node.Index,
items: []const *ast.Node, items: []const ast.Node.Index,
}, },
label_decl: ast.TokenIndex, // .id is While, For or Block (firstToken will be the label) label_decl: ast.TokenIndex, // .id is While, For or Block (firstToken will be the label)
}; };
@ -2320,7 +2320,7 @@ fn makeScopeInternal(
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
// .uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
.tests = &.{}, .tests = &.{},
.data = .{ .function = node }, .data = .{ .function = node_idx },
}; };
var scope_idx = scopes.items.len - 1; var scope_idx = scopes.items.len - 1;
errdefer scopes.items[scope_idx].decls.deinit(); errdefer scopes.items[scope_idx].decls.deinit();
@ -2352,16 +2352,16 @@ fn makeScopeInternal(
const scope = try scopes.addOne(allocator); const scope = try scopes.addOne(allocator);
scope.* = .{ scope.* = .{
.range = .{ .range = .{
.start = tree.tokenLocation(main_tokens[node_idx]).line_start, .start = tree.tokenLocation(0, main_tokens[node_idx]).line_start,
.end = tree.tokenLocation(@truncate(u32, start), last_token).line_start, .end = tree.tokenLocation(0, last_token).line_start,
}, },
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
// .uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
.tests = &[0]*ast.Node{}, .tests = &.{},
.data = .other, .data = .other,
}; };
errdefer scope.decls.deinit(); errdefer scope.decls.deinit();
try scopes.items[scope_idx].decls.putNoClobber(tree.tokenSlice(first_token), .{ .label_decl = first_token }); try scope.decls.putNoClobber(tree.tokenSlice(first_token), .{ .label_decl = first_token });
} }
(try scopes.addOne(allocator)).* = .{ (try scopes.addOne(allocator)).* = .{
@ -2382,17 +2382,22 @@ fn makeScopeInternal(
const statements: []const ast.Node.Index = switch (node) { const statements: []const ast.Node.Index = switch (node) {
.block, .block_semicolon => tree.extra_data[data[node_idx].lhs..data[node_idx].rhs], .block, .block_semicolon => tree.extra_data[data[node_idx].lhs..data[node_idx].rhs],
.block_two, .block_two_semicolon => blk: { .block_two, .block_two_semicolon => blk: {
const statements = [2]ast.Node.Index{ data[node_idx].lhs, data[node_idx].rhs }; const statements = &[_]ast.Node.Index{ data[node_idx].lhs, data[node_idx].rhs };
const len: usize = if (data[node_idx].lhs == 0) 0 else if (data[node_idx].rhs == 0) 1 else 2; const len: usize = if (data[node_idx].lhs == 0)
@as(usize, 0)
else if (data[node_idx].rhs == 0)
@as(usize, 1)
else
@as(usize, 2);
break :blk statements[0..len]; break :blk statements[0..len];
}, },
else => unreachable, else => unreachable,
}; };
for (statements[0..len]) |idx| { for (statements) |idx| {
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, idx); try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, idx);
// if (tags[ // if (tags[
if (varDecl(idx)) |var_decl| { if (varDecl(tree, idx)) |var_decl| {
const name = tree.tokenSlice(var_decl.ast.mut_token + 1); const name = tree.tokenSlice(var_decl.ast.mut_token + 1);
if (try scopes.items[scope_idx].decls.fetchPut(name, .{ .ast_node = idx })) |existing| { if (try scopes.items[scope_idx].decls.fetchPut(name, .{ .ast_node = idx })) |existing| {
// TODO record a redefinition error. // TODO record a redefinition error.
@ -2417,7 +2422,7 @@ fn makeScopeInternal(
scope.* = .{ scope.* = .{
.range = .{ .range = .{
.start = tree.tokenLocation(0, payload).line_start, .start = tree.tokenLocation(0, payload).line_start,
.end = tree.tokenLocation(@truncate(u32, start), tree.lastToken(if_node.ast.then_expr)).line_end, .end = tree.tokenLocation(0, tree.lastToken(if_node.ast.then_expr)).line_end,
}, },
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
// .uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
@ -2447,7 +2452,7 @@ fn makeScopeInternal(
scope.* = .{ scope.* = .{
.range = .{ .range = .{
.start = tree.tokenLocation(0, err_token).line_start, .start = tree.tokenLocation(0, err_token).line_start,
.end = tree.tokenLocation(@truncate(u32, start), tree.lastToken(if_node.ast.else_expr)).line_end, .end = tree.tokenLocation(0, tree.lastToken(if_node.ast.else_expr)).line_end,
}, },
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
// .uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
@ -2477,7 +2482,7 @@ fn makeScopeInternal(
scope.* = .{ scope.* = .{
.range = .{ .range = .{
.start = tree.tokenLocation(0, main_tokens[node_idx]).line_start, .start = tree.tokenLocation(0, main_tokens[node_idx]).line_start,
.end = tree.tokenLocation(@truncate(u32, start), tree.lastToken(while_node.ast.then_expr)).line_end, .end = tree.tokenLocation(0, tree.lastToken(while_node.ast.then_expr)).line_end,
}, },
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
// .uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
@ -2494,7 +2499,7 @@ fn makeScopeInternal(
scope.* = .{ scope.* = .{
.range = .{ .range = .{
.start = tree.tokenLocation(0, payload).line_start, .start = tree.tokenLocation(0, payload).line_start,
.end = tree.tokenLocation(@truncate(u32, start), tree.lastToken(while_node.ast.then_exp)).line_end, .end = tree.tokenLocation(0, tree.lastToken(while_node.ast.then_expr)).line_end,
}, },
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
// .uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
@ -2523,7 +2528,7 @@ fn makeScopeInternal(
scope.* = .{ scope.* = .{
.range = .{ .range = .{
.start = tree.tokenLocation(0, err_token).line_start, .start = tree.tokenLocation(0, err_token).line_start,
.end = tree.tokenLocation(@truncate(u32, start), tree.lastToken(if_node.ast.else_expr)).line_end, .end = tree.tokenLocation(0, tree.lastToken(while_node.ast.else_expr)).line_end,
}, },
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
// .uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
@ -2533,120 +2538,63 @@ fn makeScopeInternal(
errdefer scope.decls.deinit(); errdefer scope.decls.deinit();
const name = tree.tokenSlice(err_token); const name = tree.tokenSlice(err_token);
try scope.decls.putNoClobber(name, .{ .ast_node = if_node.ast.else_expr }); try scope.decls.putNoClobber(name, .{ .ast_node = while_node.ast.else_expr });
} }
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, while_node.ast.else_expr); try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, while_node.ast.else_expr);
} }
}, },
.For => { .switch_case, .switch_case_one => {
const for_node = node.castTag(.For).?; const switch_case: ast.full.SwitchCase = switch (node) {
if (for_node.label) |label| { .switch_case => tree.switchCase(node_idx),
std.debug.assert(tree.token_ids[label] == .Identifier); .switch_case_one => tree.switchCaseOne(node_idx),
else => unreachable,
};
if (switch_case.payload_token) |payload| {
var scope = try scopes.addOne(allocator); var scope = try scopes.addOne(allocator);
scope.* = .{ scope.* = .{
.range = .{ .range = .{
.start = tree.token_locs[for_node.for_token].start, .start = tree.tokenLocation(0, payload).line_start,
.end = tree.token_locs[for_node.lastToken()].end, .end = tree.tokenLocation(0, tree.lastToken(switch_case.ast.target_expr)).line_end,
}, },
.decls = std.StringHashMap(Declaration).init(allocator), .decls = std.StringHashMap(Declaration).init(allocator),
// .uses = &[0]*ast.Node.Use{}, // .uses = &[0]*ast.Node.Use{},
.tests = &[0]*ast.Node{}, .tests = &.{},
.data = .other, .data = .other,
}; };
errdefer scope.decls.deinit(); errdefer scope.decls.deinit();
try scope.decls.putNoClobber(tree.tokenSlice(label), .{ // if payload is *name than get next token
.label_decl = node, const name_token = payload + @boolToInt(token_tags[payload] == .asterisk);
}); const name = tree.tokenSlice(name_token);
}
std.debug.assert(for_node.payload.tag == .PointerIndexPayload);
const ptr_idx_payload = for_node.payload.castTag(.PointerIndexPayload).?;
std.debug.assert(ptr_idx_payload.value_symbol.tag == .Identifier);
var scope = try scopes.addOne(allocator);
scope.* = .{
.range = .{
.start = tree.token_locs[ptr_idx_payload.firstToken()].start,
.end = tree.token_locs[for_node.body.lastToken()].end,
},
.decls = std.StringHashMap(Declaration).init(allocator),
// .uses = &[0]*ast.Node.Use{},
.tests = &[0]*ast.Node{},
.data = .other,
};
errdefer scope.decls.deinit();
const value_name = tree.tokenSlice(ptr_idx_payload.value_symbol.firstToken());
try scope.decls.putNoClobber(value_name, .{
.array_payload = .{
.identifier = ptr_idx_payload.value_symbol,
.array_expr = for_node.array_expr,
},
});
if (ptr_idx_payload.index_symbol) |index_symbol| {
std.debug.assert(index_symbol.tag == .Identifier);
const index_name = tree.tokenSlice(index_symbol.firstToken());
if (try scope.decls.fetchPut(index_name, .{ .ast_node = index_symbol })) |existing| {
// TODO Record a redefinition error
}
}
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, for_node.body);
if (for_node.@"else") |else_node| {
std.debug.assert(else_node.payload == null);
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, else_node.body);
}
},
.Switch => {
const switch_node = node.castTag(.Switch).?;
for (switch_node.casesConst()) |case| {
if (case.*.castTag(.SwitchCase)) |case_node| {
if (case_node.payload) |payload| {
std.debug.assert(payload.tag == .PointerPayload);
var scope = try scopes.addOne(allocator);
scope.* = .{
.range = .{
.start = tree.token_locs[payload.firstToken()].start,
.end = tree.token_locs[case_node.expr.lastToken()].end,
},
.decls = std.StringHashMap(Declaration).init(allocator),
// .uses = &[0]*ast.Node.Use{},
.tests = &[0]*ast.Node{},
.data = .other,
};
errdefer scope.decls.deinit();
const ptr_payload = payload.castTag(.PointerPayload).?;
std.debug.assert(ptr_payload.value_symbol.tag == .Identifier);
const name = tree.tokenSlice(ptr_payload.value_symbol.firstToken());
try scope.decls.putNoClobber(name, .{ try scope.decls.putNoClobber(name, .{
.switch_payload = .{ .switch_payload = .{
.node = ptr_payload, .node = payload,
.switch_expr = switch_node.expr, .switch_expr = switch_case.ast.target_expr,
.items = case_node.itemsConst(), .items = switch_case.ast.values,
}, },
}); });
} }
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, case_node.expr);
} try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, switch_case.ast.target_expr);
}
}, },
.VarDecl => { .global_var_decl, .local_var_decl, .aligned_var_decl, .simple_var_decl => {
const var_decl = node.castTag(.VarDecl).?; const var_decl = varDecl(tree, node_idx).?;
if (var_decl.getTypeNode()) |type_node| { if (var_decl.ast.type_node != 0) {
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, type_node); try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, var_decl.ast.type_node);
} }
if (var_decl.getInitNode()) |init_node| {
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, init_node); if (var_decl.ast.init_node != 0) {
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, var_decl.ast.init_node);
} }
}, },
else => { else => {
var child_idx: usize = 0; // @TODO: Could we just do node_idx + 1 here?
while (node.iterate(child_idx)) |child_node| : (child_idx += 1) { // var child_idx: usize = 0;
try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, child_node); // while (node.iterate(child_idx)) |child_node| : (child_idx += 1) {
} // try makeScopeInternal(allocator, scopes, error_completions, enum_completions, tree, child_node);
// }
}, },
} }
} }