mirror of
https://github.com/ziglang/zig.git
synced 2025-12-24 23:23:07 +00:00
* 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.
105 lines
2.0 KiB
Zig
105 lines
2.0 KiB
Zig
const std = @import("std");
|
|
const expect = std.testing.expect;
|
|
const expectEqual = std.testing.expectEqual;
|
|
const Tag = std.meta.Tag;
|
|
|
|
const Foo = union {
|
|
float: f64,
|
|
int: i32,
|
|
};
|
|
|
|
test "basic unions" {
|
|
var foo = Foo{ .int = 1 };
|
|
try expect(foo.int == 1);
|
|
foo = Foo{ .float = 12.34 };
|
|
try expect(foo.float == 12.34);
|
|
}
|
|
|
|
test "init union with runtime value" {
|
|
var foo: Foo = undefined;
|
|
|
|
setFloat(&foo, 12.34);
|
|
try expect(foo.float == 12.34);
|
|
|
|
setInt(&foo, 42);
|
|
try expect(foo.int == 42);
|
|
}
|
|
|
|
fn setFloat(foo: *Foo, x: f64) void {
|
|
foo.* = Foo{ .float = x };
|
|
}
|
|
|
|
fn setInt(foo: *Foo, x: i32) void {
|
|
foo.* = Foo{ .int = x };
|
|
}
|
|
|
|
test "comptime union field access" {
|
|
comptime {
|
|
var foo = Foo{ .int = 0 };
|
|
try expect(foo.int == 0);
|
|
|
|
foo = Foo{ .float = 42.42 };
|
|
try expect(foo.float == 42.42);
|
|
}
|
|
}
|
|
|
|
const FooExtern = extern union {
|
|
float: f64,
|
|
int: i32,
|
|
};
|
|
|
|
test "basic extern unions" {
|
|
var foo = FooExtern{ .int = 1 };
|
|
try expect(foo.int == 1);
|
|
foo.float = 12.34;
|
|
try expect(foo.float == 12.34);
|
|
}
|
|
|
|
const ExternPtrOrInt = extern union {
|
|
ptr: *u8,
|
|
int: u64,
|
|
};
|
|
test "extern union size" {
|
|
comptime try expect(@sizeOf(ExternPtrOrInt) == 8);
|
|
}
|
|
|
|
test "0-sized extern union definition" {
|
|
const U = extern union {
|
|
a: void,
|
|
const f = 1;
|
|
};
|
|
|
|
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,
|
|
}
|
|
}
|