Skip to content

Commit 027609c

Browse files
llogickTechatrix
authored andcommitted
analysis: refactor getPositionContext's stack
1 parent 7cc4341 commit 027609c

File tree

1 file changed

+61
-55
lines changed

1 file changed

+61
-55
lines changed

src/analysis.zig

Lines changed: 61 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -4852,24 +4852,51 @@ pub const PositionContext = union(enum) {
48524852
}
48534853
};
48544854

4855-
const StackState = struct {
4856-
ctx: PositionContext,
4857-
stack_id: StackId,
4855+
const Stack = struct {
4856+
states: std.ArrayList(State),
48584857

4859-
/// Indicates whether the current context is an ErrorSet definition, ie `error{...}`
4860-
pub fn isErrSetDef(self: StackState) bool {
4861-
return (self.stack_id == .brace and self.ctx == .error_access);
4858+
const State = struct {
4859+
ctx: PositionContext,
4860+
scope: State.Scope,
4861+
4862+
const Scope = enum { parens, brackets, braces, global };
4863+
4864+
/// Indicates whether the current context is an ErrorSet definition, ie `error{...}`
4865+
pub fn isErrSetDef(self: *Stack.State) bool {
4866+
return (self.scope == .braces and self.ctx == .error_access);
4867+
}
4868+
};
4869+
4870+
pub fn initCapacity(allocator: std.mem.Allocator, capacity: usize) error{OutOfMemory}!Stack {
4871+
return .{ .states = try .initCapacity(allocator, capacity) };
48624872
}
4863-
};
48644873

4865-
const StackId = enum { paren, bracket, brace, global };
4874+
pub fn deinit(self: *Stack, allocator: std.mem.Allocator) void {
4875+
self.states.deinit(allocator);
4876+
}
48664877

4867-
fn peek(allocator: std.mem.Allocator, arr: *std.ArrayList(StackState)) !*StackState {
4868-
if (arr.items.len == 0) {
4869-
try arr.append(allocator, .{ .ctx = .empty, .stack_id = .global });
4878+
pub fn push(self: *Stack, allocator: std.mem.Allocator, state: *const State) error{OutOfMemory}!void {
4879+
try self.states.append(allocator, state.*);
48704880
}
4871-
return &arr.items[arr.items.len - 1];
4872-
}
4881+
4882+
pub fn peek(self: *Stack, allocator: std.mem.Allocator) error{OutOfMemory}!*Stack.State {
4883+
if (self.states.items.len == 0) {
4884+
try self.states.append(allocator, .{ .ctx = .empty, .scope = .global });
4885+
}
4886+
return &self.states.items[self.states.items.len - 1];
4887+
}
4888+
4889+
/// Pops the last state off the stack. Sets previous state's ctx to .empty if !scopes_match
4890+
pub fn pop(
4891+
self: *Stack,
4892+
allocator: std.mem.Allocator,
4893+
/// Indicate whether the current state's scope matches the one being closed
4894+
scopes_match: bool,
4895+
) error{OutOfMemory}!void {
4896+
if (self.states.items.len != 0) self.states.items.len -= 1;
4897+
if (!scopes_match) (try self.peek(allocator)).ctx = .empty;
4898+
}
4899+
};
48734900

48744901
fn tokenLocAppend(prev: offsets.Loc, token: std.zig.Token) offsets.Loc {
48754902
return .{
@@ -4941,7 +4968,7 @@ pub fn getPositionContext(
49414968
break;
49424969
}
49434970

4944-
var stack: std.ArrayList(StackState) = try .initCapacity(allocator, 8);
4971+
var stack: Stack = try .initCapacity(allocator, 8);
49454972
defer stack.deinit(allocator);
49464973
var should_do_lookahead = lookahead;
49474974

@@ -4968,7 +4995,7 @@ pub fn getPositionContext(
49684995
// `tok` is the latter of the two.
49694996
if (!should_do_lookahead) break;
49704997
should_do_lookahead = false;
4971-
const curr_ctx = try peek(allocator, &stack);
4998+
const curr_ctx = try stack.peek(allocator);
49724999
switch (tok.tag) {
49735000
.identifier,
49745001
.builtin,
@@ -4999,7 +5026,7 @@ pub fn getPositionContext(
49995026
}
50005027

50015028
// State changes
5002-
var curr_ctx = try peek(allocator, &stack);
5029+
var curr_ctx = try stack.peek(allocator);
50035030
switch (tok.tag) {
50045031
.string_literal, .multiline_string_literal_line => string_lit_block: {
50055032
curr_ctx.ctx = .{ .string_literal = tok.loc };
@@ -5017,10 +5044,10 @@ pub fn getPositionContext(
50175044

50185045
if (source_index < content_loc.start or content_loc.end < source_index) break :string_lit_block;
50195046

5020-
if (curr_ctx.stack_id == .paren and
5021-
stack.items.len >= 2)
5047+
if (curr_ctx.scope == .parens and
5048+
stack.states.items.len >= 2)
50225049
{
5023-
const perhaps_builtin = stack.items[stack.items.len - 2];
5050+
const perhaps_builtin = stack.states.items[stack.states.items.len - 2];
50245051

50255052
switch (perhaps_builtin.ctx) {
50265053
.builtin => |loc| {
@@ -5075,41 +5102,20 @@ pub fn getPositionContext(
50755102
},
50765103
.l_paren => {
50775104
if (curr_ctx.ctx == .empty) curr_ctx.ctx = .{ .parens_expr = tok.loc };
5078-
const stack_id: StackId = switch (curr_ctx.ctx) {
5079-
.keyword => |token_index| switch (tree.tokenTag(token_index)) {
5080-
.keyword_for,
5081-
.keyword_if,
5082-
.keyword_while,
5083-
=> .global,
5084-
else => .paren,
5085-
},
5086-
else => .paren,
5087-
};
5088-
try stack.append(allocator, .{ .ctx = .empty, .stack_id = stack_id });
5089-
},
5090-
.r_paren => {
5091-
// Do this manually, as .pop() sets `stack.items[stack.items.len - 1]` to `undefined` which currently curr_ctx points to
5092-
if (stack.items.len != 0) stack.items.len -= 1;
5093-
if (curr_ctx.stack_id != .paren) {
5094-
(try peek(allocator, &stack)).ctx = .empty;
5095-
}
5096-
},
5097-
.l_bracket => try stack.append(allocator, .{ .ctx = .empty, .stack_id = .bracket }),
5098-
.r_bracket => {
5099-
// Do this manually, as .pop() sets `stack.items[stack.items.len - 1]` to `undefined` which currently curr_ctx points to
5100-
if (stack.items.len != 0) stack.items.len -= 1;
5101-
if (curr_ctx.stack_id != .bracket) {
5102-
(try peek(allocator, &stack)).ctx = .empty;
5103-
}
5104-
},
5105-
.l_brace => try stack.append(allocator, .{ .ctx = if (curr_ctx.ctx == .error_access) curr_ctx.ctx else .empty, .stack_id = .brace }),
5106-
.r_brace => {
5107-
// Do this manually, as .pop() sets `stack.items[stack.items.len - 1]` to `undefined` which currently curr_ctx points to
5108-
if (stack.items.len != 0) stack.items.len -= 1;
5109-
if (curr_ctx.stack_id != .brace) {
5110-
(try peek(allocator, &stack)).ctx = .empty;
5111-
}
5105+
const scope: Stack.State.Scope = if (curr_ctx.ctx == .keyword) switch (tree.tokenTag(curr_ctx.ctx.keyword)) {
5106+
.keyword_for,
5107+
.keyword_if,
5108+
.keyword_while,
5109+
=> .global,
5110+
else => .parens,
5111+
} else .parens;
5112+
try stack.push(allocator, &.{ .ctx = .empty, .scope = scope });
51125113
},
5114+
.r_paren => try stack.pop(allocator, curr_ctx.scope == .parens),
5115+
.l_bracket => try stack.push(allocator, &.{ .ctx = .empty, .scope = .brackets }),
5116+
.r_bracket => try stack.pop(allocator, curr_ctx.scope == .brackets),
5117+
.l_brace => try stack.push(allocator, &.{ .ctx = if (curr_ctx.ctx == .error_access) curr_ctx.ctx else .empty, .scope = .braces }),
5118+
.r_brace => try stack.pop(allocator, curr_ctx.scope == .braces),
51135119
.keyword_error => curr_ctx.ctx = .error_access,
51145120
.number_literal => {
51155121
if (tok.loc.start <= source_index and tok.loc.end >= source_index) {
@@ -5143,14 +5149,14 @@ pub fn getPositionContext(
51435149
else => curr_ctx.ctx = .empty,
51445150
}
51455151

5146-
curr_ctx = try peek(allocator, &stack);
5152+
curr_ctx = try stack.peek(allocator);
51475153
switch (curr_ctx.ctx) {
51485154
.field_access => |r| curr_ctx.ctx = .{ .field_access = tokenLocAppend(r, tok) },
51495155
else => {},
51505156
}
51515157
}
51525158

5153-
if (stack.pop()) |state| {
5159+
if (stack.states.pop()) |state| {
51545160
switch (state.ctx) {
51555161
.parens_expr => |loc| return .{ .var_access = loc },
51565162
.var_access => |loc| {

0 commit comments

Comments
 (0)