zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 942b250895581f01adf52b3d5addd99b7a4bc0d3 (tree)
parent 05d9f07541c8c5b788687046ad313c6cff211476
Author: Andrew Kelley <superjoe30@gmail.com>
Date:   Mon,  4 Dec 2017 01:42:02 -0500

update docs regarding enums and unions

Diffstat:
Mdoc/langref.html.in | 211+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 163 insertions(+), 48 deletions(-)

diff --git a/doc/langref.html.in b/doc/langref.html.in @@ -2096,30 +2096,38 @@ const Type = enum { NotOk, }; -// Enums are sum types, and can hold more complex data of different types. -const ComplexType = enum { - Ok: u8, - NotOk: void, -}; - // Declare a specific instance of the enum variant. -const c = ComplexType.Ok { 0 }; +const c = Type.Ok; -// The ordinal value of a simple enum with no data members can be -// retrieved by a simple cast. -// The value starts from 0, counting up for each member. -const Value = enum { +// If you want access to the ordinal value of an enum, you +// can specify the tag type. +const Value = enum(u2) { Zero, One, Two, }; + +// Now you can cast between u2 and Value. +// The ordinal value starts from 0, counting up for each member. test "enum ordinal value" { - assert(usize(Value.Zero) == 0); - assert(usize(Value.One) == 1); - assert(usize(Value.Two) == 2); + assert(u2(Value.Zero) == 0); + assert(u2(Value.One) == 1); + assert(u2(Value.Two) == 2); } -// Enums can have methods, the same as structs. +// You can override the ordinal value for an enum. +const Value2 = enum(u32) { + Hundred = 100, + Thousand = 1000, + Million = 1000000, +}; +test "set enum ordinal value" { + assert(u32(Value2.Hundred) == 100); + assert(u32(Value2.Thousand) == 1000); + assert(u32(Value2.Million) == 1000000); +} + +// Enums can have methods, the same as structs and unions. // Enum methods are not special, they are only namespaced // functions that you can call with dot syntax. const Suit = enum { @@ -2128,26 +2136,120 @@ const Suit = enum { Diamonds, Hearts, - pub fn ordinal(self: &amp;const Suit) -&gt; u8 { - u8(*self) + pub fn isClubs(self: Suit) -&gt; bool { + return self == Suit.Clubs; } }; test "enum method" { const p = Suit.Spades; - assert(p.ordinal() == 1); + assert(!p.isClubs()); } // An enum variant of different types can be switched upon. -// The associated data can be retrieved using `|...|` syntax. -// -// A void type is not required on a tag-only member. const Foo = enum { + String, + Number, + None, +}; +test "enum variant switch" { + const p = Foo.Number; + const what_is_it = switch (p) { + Foo.String =&gt; "this is a string", + Foo.Number =&gt; "this is a number", + Foo.None =&gt; "this is a none", + }; + assert(mem.eql(u8, what_is_it, "this is a number")); +} + +// @TagType can be used to access the integer tag type of an enum. +const Small = enum { + One, + Two, + Three, + Four, +}; +test "@TagType" { + assert(@TagType(Small) == u2); +} + +// @memberCount tells how many fields an enum has: +test "@memberCount" { + assert(@memberCount(Small) == 4); +} + +// @memberName tells the name of a field in an enum: +test "@memberName" { + assert(mem.eql(u8, @memberName(Small, 1), "Two")); +} + +// @tagName gives a []const u8 representation of an enum value: +test "@tagName" { + assert(mem.eql(u8, @tagName(Small.Three), "Three")); +}</code></pre> + <p>TODO extern enum</p> + <p>TODO packed enum</p> + <pre><code class="sh">$ zig test enum.zig +Test 1/8 enum ordinal value...OK +Test 2/8 set enum ordinal value...OK +Test 3/8 enum method...OK +Test 4/8 enum variant switch...OK +Test 5/8 @TagType...OK +Test 6/8 @memberCount...OK +Test 7/8 @memberName...OK +Test 8/8 @tagName...OK</code></pre> + <p>See also:</p> + <ul> + <li><a href="#builtin-memberName">@memberName</a></li> + <li><a href="#builtin-memberCount">@memberCount</a></li> + <li><a href="#builtin-tagName">@tagName</a></li> + </ul> + <h2 id="union">union</h2> + <pre><code class="zig">const assert = @import("std").debug.assert; +const mem = @import("std").mem; + +// A union has only 1 active field at a time. +const Payload = union { + Int: i64, + Float: f64, + Bool: bool, +}; +test "simple union" { + var payload = Payload {.Int = 1234}; + // payload.Float = 12.34; // ERROR! field not active + assert(payload.Int == 1234); + // You can activate another field by assigning the entire union. + payload = Payload {.Float = 12.34}; + assert(payload.Float == 12.34); +} + +// Unions can be given an enum tag type: +const ComplexTypeTag = enum { Ok, NotOk }; +const ComplexType = union(ComplexTypeTag) { + Ok: u8, + NotOk: void, +}; + +// Declare a specific instance of the union variant. +test "declare union value" { + const c = ComplexType { .Ok = 0 }; + assert(ComplexTypeTag(c) == ComplexTypeTag.Ok); +} + +// @TagType can be used to access the enum tag type of a union. +test "@TagType" { + assert(@TagType(ComplexType) == ComplexTypeTag); +} + +// Unions can be made to infer the enum tag type. +const Foo = union(enum) { String: []const u8, Number: u64, + + // void can be omitted when inferring enum tag type. None, }; -test "enum variant switch" { - const p = Foo.Number { 54 }; +test "union variant switch" { + const p = Foo { .Number = 54 }; const what_is_it = switch (p) { // Capture by reference Foo.String =&gt; |*x| { @@ -2156,6 +2258,7 @@ test "enum variant switch" { // Capture by value Foo.Number =&gt; |x| { + assert(x == 54); "this is a number" }, @@ -2163,38 +2266,50 @@ test "enum variant switch" { "this is a none" } }; + assert(mem.eql(u8, what_is_it, "this is a number")); } -// The @memberName and @memberCount builtin functions can be used to -// the string representation and number of members respectively. -const BuiltinType = enum { - A: f32, - B: u32, - C, +// TODO union methods + + +const Small = union { + A: i32, + B: bool, + C: u8, }; -test "enum builtins" { - assert(mem.eql(u8, @memberName(BuiltinType.A { 0 }), "A")); - assert(mem.eql(u8, @memberName(BuiltinType.C), "C")); - assert(@memberCount(BuiltinType) == 3); +// @memberCount tells how many fields a union has: +test "@memberCount" { + assert(@memberCount(Small) == 3); +} + +// @memberName tells the name of a field in an enum: +test "@memberName" { + assert(mem.eql(u8, @memberName(Small, 1), "B")); +} + +// @tagName gives a []const u8 representation of an enum value, +// but only if the union has an enum tag type. +const Small2 = union(enum) { + A: i32, + B: bool, + C: u8, +}; +test "@tagName" { + assert(mem.eql(u8, @tagName(Small2.C), "C")); }</code></pre> - <pre><code class="sh">$ zig test enum.zig -Test 1/4 enum ordinal value...OK -Test 2/4 enum method...OK -Test 3/4 enum variant switch...OK -Test 4/4 enum builtins...OK</code></pre> - <p> - Enums are generated as a struct with a tag field and union field. Zig + <pre><code class="sh">$ zig test union.zig +Test 1/7 simple union...OK +Test 2/7 declare union value...OK +Test 3/7 @TagType...OK +Test 4/7 union variant switch...OK +Test 5/7 @memberCount...OK +Test 6/7 @memberName...OK +Test 7/7 @tagName...OK</code></pre> + <p> + Unions with an enum tag are generated as a struct with a tag field and union field. Zig sorts the order of the tag and union field by the largest alignment. </p> - <p>See also:</p> - <ul> - <li><a href="#builtin-memberName">@memberName</a></li> - <li><a href="#builtin-memberCount">@memberCount</a></li> - <li><a href="#builtin-tagName">@tagName</a></li> - </ul> - <h2 id="union">union</h2> - <p>TODO union documentation</p> <h2 id="switch">switch</h2> <pre><code class="zig">const assert = @import("std").debug.assert; const builtin = @import("builtin");