Trailing (starting at end):
pub const UnwrappedSwitchBlock = struct
pub const UnwrappedSwitchBlock = struct {
/// Either `catch`/`if` or `switch` operand.
main_operand: Inst.Ref,
switch_src_node_offset: Ast.Node.Offset,
catch_or_if_src_node_offset: Ast.Node.OptionalOffset,
payload_capture_placeholder: Inst.OptionalIndex,
tag_capture_placeholder: Inst.OptionalIndex,
has_continue: bool,
any_maybe_runtime_capture: bool,
non_err_case: ?Case.NonErr,
else_case: ?Case.Else,
has_under: bool,
// Refer to doc comment and `iterateCases` to access everything below correctly.
prong_infos: []const Inst.SwitchBlock.ProngInfo,
multi_case_items_lens: []const u32,
multi_case_ranges_lens: ?[]const u32,
item_infos: []const Inst.SwitchBlock.ItemInfo,
end: usize,
pub fn anyRanges(unwrapped: *const UnwrappedSwitchBlock) bool {
return unwrapped.multi_case_ranges_lens != null;
}
pub fn scalarCasesLen(unwrapped: *const UnwrappedSwitchBlock) u32 {
return @intCast(unwrapped.prong_infos.len - unwrapped.multi_case_items_lens.len);
}
pub fn multiCasesLen(unwrapped: *const UnwrappedSwitchBlock) u32 {
return @intCast(unwrapped.multi_case_items_lens.len);
}
pub fn totalItemsLen(unwrapped: *const UnwrappedSwitchBlock) u32 {
var total_items_len: u32 = @intCast(unwrapped.item_infos.len);
if (unwrapped.multi_case_ranges_lens) |ranges_lens| {
for (ranges_lens) |len| total_items_len -= len;
}
return total_items_len;
}
pub const Case = struct {
index: Case.Index,
prong_info: Inst.SwitchBlock.ProngInfo,
item_infos: []const Inst.SwitchBlock.ItemInfo,
range_infos: []const [2]Inst.SwitchBlock.ItemInfo,
pub const Index = packed struct(u32) {
kind: enum(u1) { scalar, multi },
value: u31,
pub const @"else": Case.Index = .{
.kind = .scalar,
.value = std.math.maxInt(u31),
};
};
pub const NonErr = struct {
body: []const Inst.Index,
capture: Inst.SwitchBlock.ProngInfo.Capture,
operand_is_ref: bool,
};
pub const Else = struct {
index: Case.Index,
body: []const Inst.Index,
capture: Inst.SwitchBlock.ProngInfo.Capture,
is_inline: bool,
has_tag_capture: bool,
is_simple_noreturn: bool,
};
pub const Iterator = struct {
next_idx: u32,
prong_infos: []const Inst.SwitchBlock.ProngInfo,
multi_case_items_lens: []const u32,
multi_case_ranges_lens: ?[]const u32,
item_infos: []const Inst.SwitchBlock.ItemInfo,
pub fn next(it: *Iterator) ?Case {
const idx = it.next_idx;
if (idx == it.prong_infos.len) return null;
it.next_idx += 1;
const scalar_cases_len = it.prong_infos.len - it.multi_case_items_lens.len;
return if (idx < scalar_cases_len) .{
.index = .{
.kind = .scalar,
.value = @intCast(idx),
},
.prong_info = it.prong_infos[idx],
.item_infos = it.itemInfos(1),
.range_infos = &.{},
} else .{
.index = .{
.kind = .multi,
.value = @intCast(idx - scalar_cases_len),
},
.prong_info = it.prong_infos[idx],
.item_infos = it.itemInfos(it.multi_case_items_lens[idx - scalar_cases_len]),
.range_infos = if (it.multi_case_ranges_lens) |ranges_lens| b: {
break :b @ptrCast(it.itemInfos(2 * ranges_lens[idx - scalar_cases_len]));
} else &.{},
};
}
fn itemInfos(it: *Iterator, count: u32) []const Inst.SwitchBlock.ItemInfo {
const lens = it.item_infos[0..count];
it.item_infos = it.item_infos[count..];
return lens;
}
};
};
pub fn iterateCases(unwrapped: UnwrappedSwitchBlock) Case.Iterator {
return .{
.next_idx = 0,
.prong_infos = unwrapped.prong_infos,
.multi_case_items_lens = unwrapped.multi_case_items_lens,
.multi_case_ranges_lens = unwrapped.multi_case_ranges_lens,
.item_infos = unwrapped.item_infos,
};
}
}