Implement makeScopeInternal logic
This commit is contained in:
parent
5f5d6ce4ea
commit
709c1a70fd
160
src/analysis.zig
160
src/analysis.zig
@ -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);
|
||||||
|
// }
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user