authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-04 01:42:02-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-04 01:43:06-05:00
log942b250895581f01adf52b3d5addd99b7a4bc0d3
tree465321654a64d16acc357f1555a92c92bb6e2ad3
parent05d9f07541c8c5b788687046ad313c6cff211476

update docs regarding enums and unions


1 files changed, 163 insertions(+), 48 deletions(-)

doc/langref.html.in+163-48
......@@ -2096,30 +2096,38 @@ const Type = enum {
20962096 NotOk,
20972097};
20982098
2099// Enums are sum types, and can hold more complex data of different types.
2100const ComplexType = enum {
2101 Ok: u8,
2102 NotOk: void,
2103};
2104
21052099// Declare a specific instance of the enum variant.
2106const c = ComplexType.Ok { 0 };
2100const c = Type.Ok;
21072101
2108// The ordinal value of a simple enum with no data members can be
2109// retrieved by a simple cast.
2110// The value starts from 0, counting up for each member.
2111const Value = enum {
2102// If you want access to the ordinal value of an enum, you
2103// can specify the tag type.
2104const Value = enum(u2) {
21122105 Zero,
21132106 One,
21142107 Two,
21152108};
2109
2110// Now you can cast between u2 and Value.
2111// The ordinal value starts from 0, counting up for each member.
21162112test "enum ordinal value" {
2117 assert(usize(Value.Zero) == 0);
2118 assert(usize(Value.One) == 1);
2119 assert(usize(Value.Two) == 2);
2113 assert(u2(Value.Zero) == 0);
2114 assert(u2(Value.One) == 1);
2115 assert(u2(Value.Two) == 2);
21202116}
21212117
2122// Enums can have methods, the same as structs.
2118// You can override the ordinal value for an enum.
2119const Value2 = enum(u32) {
2120 Hundred = 100,
2121 Thousand = 1000,
2122 Million = 1000000,
2123};
2124test "set enum ordinal value" {
2125 assert(u32(Value2.Hundred) == 100);
2126 assert(u32(Value2.Thousand) == 1000);
2127 assert(u32(Value2.Million) == 1000000);
2128}
2129
2130// Enums can have methods, the same as structs and unions.
21232131// Enum methods are not special, they are only namespaced
21242132// functions that you can call with dot syntax.
21252133const Suit = enum {
......@@ -2128,26 +2136,120 @@ const Suit = enum {
21282136 Diamonds,
21292137 Hearts,
21302138
2131 pub fn ordinal(self: &amp;const Suit) -&gt; u8 {
2132 u8(*self)
2139 pub fn isClubs(self: Suit) -&gt; bool {
2140 return self == Suit.Clubs;
21332141 }
21342142};
21352143test "enum method" {
21362144 const p = Suit.Spades;
2137 assert(p.ordinal() == 1);
2145 assert(!p.isClubs());
21382146}
21392147
21402148// An enum variant of different types can be switched upon.
2141// The associated data can be retrieved using `|...|` syntax.
2142//
2143// A void type is not required on a tag-only member.
21442149const Foo = enum {
2150 String,
2151 Number,
2152 None,
2153};
2154test "enum variant switch" {
2155 const p = Foo.Number;
2156 const what_is_it = switch (p) {
2157 Foo.String =&gt; "this is a string",
2158 Foo.Number =&gt; "this is a number",
2159 Foo.None =&gt; "this is a none",
2160 };
2161 assert(mem.eql(u8, what_is_it, "this is a number"));
2162}
2163
2164// @TagType can be used to access the integer tag type of an enum.
2165const Small = enum {
2166 One,
2167 Two,
2168 Three,
2169 Four,
2170};
2171test "@TagType" {
2172 assert(@TagType(Small) == u2);
2173}
2174
2175// @memberCount tells how many fields an enum has:
2176test "@memberCount" {
2177 assert(@memberCount(Small) == 4);
2178}
2179
2180// @memberName tells the name of a field in an enum:
2181test "@memberName" {
2182 assert(mem.eql(u8, @memberName(Small, 1), "Two"));
2183}
2184
2185// @tagName gives a []const u8 representation of an enum value:
2186test "@tagName" {
2187 assert(mem.eql(u8, @tagName(Small.Three), "Three"));
2188}</code></pre>
2189 <p>TODO extern enum</p>
2190 <p>TODO packed enum</p>
2191 <pre><code class="sh">$ zig test enum.zig
2192Test 1/8 enum ordinal value...OK
2193Test 2/8 set enum ordinal value...OK
2194Test 3/8 enum method...OK
2195Test 4/8 enum variant switch...OK
2196Test 5/8 @TagType...OK
2197Test 6/8 @memberCount...OK
2198Test 7/8 @memberName...OK
2199Test 8/8 @tagName...OK</code></pre>
2200 <p>See also:</p>
2201 <ul>
2202 <li><a href="#builtin-memberName">@memberName</a></li>
2203 <li><a href="#builtin-memberCount">@memberCount</a></li>
2204 <li><a href="#builtin-tagName">@tagName</a></li>
2205 </ul>
2206 <h2 id="union">union</h2>
2207 <pre><code class="zig">const assert = @import("std").debug.assert;
2208const mem = @import("std").mem;
2209
2210// A union has only 1 active field at a time.
2211const Payload = union {
2212 Int: i64,
2213 Float: f64,
2214 Bool: bool,
2215};
2216test "simple union" {
2217 var payload = Payload {.Int = 1234};
2218 // payload.Float = 12.34; // ERROR! field not active
2219 assert(payload.Int == 1234);
2220 // You can activate another field by assigning the entire union.
2221 payload = Payload {.Float = 12.34};
2222 assert(payload.Float == 12.34);
2223}
2224
2225// Unions can be given an enum tag type:
2226const ComplexTypeTag = enum { Ok, NotOk };
2227const ComplexType = union(ComplexTypeTag) {
2228 Ok: u8,
2229 NotOk: void,
2230};
2231
2232// Declare a specific instance of the union variant.
2233test "declare union value" {
2234 const c = ComplexType { .Ok = 0 };
2235 assert(ComplexTypeTag(c) == ComplexTypeTag.Ok);
2236}
2237
2238// @TagType can be used to access the enum tag type of a union.
2239test "@TagType" {
2240 assert(@TagType(ComplexType) == ComplexTypeTag);
2241}
2242
2243// Unions can be made to infer the enum tag type.
2244const Foo = union(enum) {
21452245 String: []const u8,
21462246 Number: u64,
2247
2248 // void can be omitted when inferring enum tag type.
21472249 None,
21482250};
2149test "enum variant switch" {
2150 const p = Foo.Number { 54 };
2251test "union variant switch" {
2252 const p = Foo { .Number = 54 };
21512253 const what_is_it = switch (p) {
21522254 // Capture by reference
21532255 Foo.String =&gt; |*x| {
......@@ -2156,6 +2258,7 @@ test "enum variant switch" {
21562258
21572259 // Capture by value
21582260 Foo.Number =&gt; |x| {
2261 assert(x == 54);
21592262 "this is a number"
21602263 },
21612264
......@@ -2163,38 +2266,50 @@ test "enum variant switch" {
21632266 "this is a none"
21642267 }
21652268 };
2269 assert(mem.eql(u8, what_is_it, "this is a number"));
21662270}
21672271
2168// The @memberName and @memberCount builtin functions can be used to
2169// the string representation and number of members respectively.
2170const BuiltinType = enum {
2171 A: f32,
2172 B: u32,
2173 C,
2272// TODO union methods
2273
2274
2275const Small = union {
2276 A: i32,
2277 B: bool,
2278 C: u8,
21742279};
21752280
2176test "enum builtins" {
2177 assert(mem.eql(u8, @memberName(BuiltinType.A { 0 }), "A"));
2178 assert(mem.eql(u8, @memberName(BuiltinType.C), "C"));
2179 assert(@memberCount(BuiltinType) == 3);
2281// @memberCount tells how many fields a union has:
2282test "@memberCount" {
2283 assert(@memberCount(Small) == 3);
2284}
2285
2286// @memberName tells the name of a field in an enum:
2287test "@memberName" {
2288 assert(mem.eql(u8, @memberName(Small, 1), "B"));
2289}
2290
2291// @tagName gives a []const u8 representation of an enum value,
2292// but only if the union has an enum tag type.
2293const Small2 = union(enum) {
2294 A: i32,
2295 B: bool,
2296 C: u8,
2297};
2298test "@tagName" {
2299 assert(mem.eql(u8, @tagName(Small2.C), "C"));
21802300}</code></pre>
2181 <pre><code class="sh">$ zig test enum.zig
2182Test 1/4 enum ordinal value...OK
2183Test 2/4 enum method...OK
2184Test 3/4 enum variant switch...OK
2185Test 4/4 enum builtins...OK</code></pre>
2186 <p>
2187 Enums are generated as a struct with a tag field and union field. Zig
2301 <pre><code class="sh">$ zig test union.zig
2302Test 1/7 simple union...OK
2303Test 2/7 declare union value...OK
2304Test 3/7 @TagType...OK
2305Test 4/7 union variant switch...OK
2306Test 5/7 @memberCount...OK
2307Test 6/7 @memberName...OK
2308Test 7/7 @tagName...OK</code></pre>
2309 <p>
2310 Unions with an enum tag are generated as a struct with a tag field and union field. Zig
21882311 sorts the order of the tag and union field by the largest alignment.
21892312 </p>
2190 <p>See also:</p>
2191 <ul>
2192 <li><a href="#builtin-memberName">@memberName</a></li>
2193 <li><a href="#builtin-memberCount">@memberCount</a></li>
2194 <li><a href="#builtin-tagName">@tagName</a></li>
2195 </ul>
2196 <h2 id="union">union</h2>
2197 <p>TODO union documentation</p>
21982313 <h2 id="switch">switch</h2>
21992314 <pre><code class="zig">const assert = @import("std").debug.assert;
22002315const builtin = @import("builtin");