stage2: implement switching on unions
* AstGen: Move `refToIndex` and `indexToRef` to Zir * ZIR: the switch_block_*_* instruction tags are collapsed into one switch_block tag which uses 4 bits for flags, and reduces the scalar_cases_len field from 32 to 28 bits. This freed up more ZIR tags, 2 of which are now used for `switch_cond` and `switch_cond_ref` for producing the switch condition value. For example, for union values it returns the corresponding enum value. * switching with multiple cases and ranges is not yet supported because I want to change the ZIR encoding to store index pointers into the extra array rather than storing prong indexes. This will avoid O(N^2) iteration over prongs. * AstGen now adds a `switch_cond` on the operand and then passes the result of that to the `switch_block` instruction. * Sema: partially implement `switch_capture_*` instructions. * Sema: `unionToTag` notices if the enum type has only one possible value.
This commit is contained in:
@@ -71,3 +71,34 @@ test "0-sized extern union definition" {
|
||||
|
||||
try expect(U.f == 1);
|
||||
}
|
||||
|
||||
const Value = union(enum) {
|
||||
Int: u64,
|
||||
Array: [9]u8,
|
||||
};
|
||||
|
||||
const Agg = struct {
|
||||
val1: Value,
|
||||
val2: Value,
|
||||
};
|
||||
|
||||
const v1 = Value{ .Int = 1234 };
|
||||
const v2 = Value{ .Array = [_]u8{3} ** 9 };
|
||||
|
||||
const err = @as(anyerror!Agg, Agg{
|
||||
.val1 = v1,
|
||||
.val2 = v2,
|
||||
});
|
||||
|
||||
const array = [_]Value{ v1, v2, v1, v2 };
|
||||
|
||||
test "unions embedded in aggregate types" {
|
||||
switch (array[1]) {
|
||||
Value.Array => |arr| try expect(arr[4] == 3),
|
||||
else => unreachable,
|
||||
}
|
||||
switch ((err catch unreachable).val1) {
|
||||
Value.Int => |x| try expect(x == 1234),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,37 +3,6 @@ const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const Tag = std.meta.Tag;
|
||||
|
||||
const Value = union(enum) {
|
||||
Int: u64,
|
||||
Array: [9]u8,
|
||||
};
|
||||
|
||||
const Agg = struct {
|
||||
val1: Value,
|
||||
val2: Value,
|
||||
};
|
||||
|
||||
const v1 = Value{ .Int = 1234 };
|
||||
const v2 = Value{ .Array = [_]u8{3} ** 9 };
|
||||
|
||||
const err = @as(anyerror!Agg, Agg{
|
||||
.val1 = v1,
|
||||
.val2 = v2,
|
||||
});
|
||||
|
||||
const array = [_]Value{ v1, v2, v1, v2 };
|
||||
|
||||
test "unions embedded in aggregate types" {
|
||||
switch (array[1]) {
|
||||
Value.Array => |arr| try expect(arr[4] == 3),
|
||||
else => unreachable,
|
||||
}
|
||||
switch ((err catch unreachable).val1) {
|
||||
Value.Int => |x| try expect(x == 1234),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
const Letter = enum { A, B, C };
|
||||
const Payload = union(Letter) {
|
||||
A: i32,
|
||||
|
||||
Reference in New Issue
Block a user