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 {...@@ -2096,30 +2096,38 @@ const Type = enum {
2096 NotOk,2096 NotOk,
2097};2097};
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
2105// Declare a specific instance of the enum variant.2099// 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 be2102// If you want access to the ordinal value of an enum, you
2109// retrieved by a simple cast.2103// can specify the tag type.
2110// The value starts from 0, counting up for each member.2104const Value = enum(u2) {
2111const Value = enum {
2112 Zero,2105 Zero,
2113 One,2106 One,
2114 Two,2107 Two,
2115};2108};
2109
2110// Now you can cast between u2 and Value.
2111// The ordinal value starts from 0, counting up for each member.
2116test "enum ordinal value" {2112test "enum ordinal value" {
2117 assert(usize(Value.Zero) == 0);2113 assert(u2(Value.Zero) == 0);
2118 assert(usize(Value.One) == 1);2114 assert(u2(Value.One) == 1);
2119 assert(usize(Value.Two) == 2);2115 assert(u2(Value.Two) == 2);
2120}2116}
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.
2123// Enum methods are not special, they are only namespaced2131// Enum methods are not special, they are only namespaced
2124// functions that you can call with dot syntax.2132// functions that you can call with dot syntax.
2125const Suit = enum {2133const Suit = enum {
...@@ -2128,26 +2136,120 @@ const Suit = enum {...@@ -2128,26 +2136,120 @@ const Suit = enum {
2128 Diamonds,2136 Diamonds,
2129 Hearts,2137 Hearts,
21302138
2131 pub fn ordinal(self: &amp;const Suit) -&gt; u8 {2139 pub fn isClubs(self: Suit) -&gt; bool {
2132 u8(*self)2140 return self == Suit.Clubs;
2133 }2141 }
2134};2142};
2135test "enum method" {2143test "enum method" {
2136 const p = Suit.Spades;2144 const p = Suit.Spades;
2137 assert(p.ordinal() == 1);2145 assert(!p.isClubs());
2138}2146}
21392147
2140// An enum variant of different types can be switched upon.2148// 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.
2144const Foo = enum {2149const 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) {
2145 String: []const u8,2245 String: []const u8,
2146 Number: u64,2246 Number: u64,
2247
2248 // void can be omitted when inferring enum tag type.
2147 None,2249 None,
2148};2250};
2149test "enum variant switch" {2251test "union variant switch" {
2150 const p = Foo.Number { 54 };2252 const p = Foo { .Number = 54 };
2151 const what_is_it = switch (p) {2253 const what_is_it = switch (p) {
2152 // Capture by reference2254 // Capture by reference
2153 Foo.String =&gt; |*x| {2255 Foo.String =&gt; |*x| {
...@@ -2156,6 +2258,7 @@ test "enum variant switch" {...@@ -2156,6 +2258,7 @@ test "enum variant switch" {
21562258
2157 // Capture by value2259 // Capture by value
2158 Foo.Number =&gt; |x| {2260 Foo.Number =&gt; |x| {
2261 assert(x == 54);
2159 "this is a number"2262 "this is a number"
2160 },2263 },
21612264
...@@ -2163,38 +2266,50 @@ test "enum variant switch" {...@@ -2163,38 +2266,50 @@ test "enum variant switch" {
2163 "this is a none"2266 "this is a none"
2164 }2267 }
2165 };2268 };
2269 assert(mem.eql(u8, what_is_it, "this is a number"));
2166}2270}
21672271
2168// The @memberName and @memberCount builtin functions can be used to2272// TODO union methods
2169// the string representation and number of members respectively.2273
2170const BuiltinType = enum {2274
2171 A: f32,2275const Small = union {
2172 B: u32,2276 A: i32,
2173 C,2277 B: bool,
2278 C: u8,
2174};2279};
21752280
2176test "enum builtins" {2281// @memberCount tells how many fields a union has:
2177 assert(mem.eql(u8, @memberName(BuiltinType.A { 0 }), "A"));2282test "@memberCount" {
2178 assert(mem.eql(u8, @memberName(BuiltinType.C), "C"));2283 assert(@memberCount(Small) == 3);
2179 assert(@memberCount(BuiltinType) == 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"));
2180}</code></pre>2300}</code></pre>
2181 <pre><code class="sh">$ zig test enum.zig2301 <pre><code class="sh">$ zig test union.zig
2182Test 1/4 enum ordinal value...OK2302Test 1/7 simple union...OK
2183Test 2/4 enum method...OK2303Test 2/7 declare union value...OK
2184Test 3/4 enum variant switch...OK2304Test 3/7 @TagType...OK
2185Test 4/4 enum builtins...OK</code></pre>2305Test 4/7 union variant switch...OK
2186 <p>2306Test 5/7 @memberCount...OK
2187 Enums are generated as a struct with a tag field and union field. Zig2307Test 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
2188 sorts the order of the tag and union field by the largest alignment.2311 sorts the order of the tag and union field by the largest alignment.
2189 </p>2312 </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>
2198 <h2 id="switch">switch</h2>2313 <h2 id="switch">switch</h2>
2199 <pre><code class="zig">const assert = @import("std").debug.assert;2314 <pre><code class="zig">const assert = @import("std").debug.assert;
2200const builtin = @import("builtin");2315const builtin = @import("builtin");