| ... | @@ -2096,30 +2096,38 @@ const Type = enum { | ... | @@ -2096,30 +2096,38 @@ const Type = enum { |
| 2096 | NotOk, | 2096 | NotOk, |
| 2097 | }; | 2097 | }; |
| 2098 | | 2098 | |
| 2099 | // Enums are sum types, and can hold more complex data of different types. | | |
| 2100 | const 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. |
| 2106 | const c = ComplexType.Ok { 0 }; | 2100 | const c = Type.Ok; |
| 2107 | | 2101 | |
| 2108 | // The ordinal value of a simple enum with no data members can be | 2102 | // 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. | 2104 | const Value = enum(u2) { |
| 2111 | const 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. |
| 2116 | test "enum ordinal value" { | 2112 | test "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 | } |
| 2121 | | 2117 | |
| 2122 | // Enums can have methods, the same as structs. | 2118 | // You can override the ordinal value for an enum. |
| | 2119 | const Value2 = enum(u32) { |
| | 2120 | Hundred = 100, |
| | 2121 | Thousand = 1000, |
| | 2122 | Million = 1000000, |
| | 2123 | }; |
| | 2124 | test "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 namespaced | 2131 | // 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. |
| 2125 | const Suit = enum { | 2133 | const Suit = enum { |
| ... | @@ -2128,26 +2136,120 @@ const Suit = enum { | ... | @@ -2128,26 +2136,120 @@ const Suit = enum { |
| 2128 | Diamonds, | 2136 | Diamonds, |
| 2129 | Hearts, | 2137 | Hearts, |
| 2130 | | 2138 | |
| 2131 | pub fn ordinal(self: &const Suit) -> u8 { | 2139 | pub fn isClubs(self: Suit) -> bool { |
| 2132 | u8(*self) | 2140 | return self == Suit.Clubs; |
| 2133 | } | 2141 | } |
| 2134 | }; | 2142 | }; |
| 2135 | test "enum method" { | 2143 | test "enum method" { |
| 2136 | const p = Suit.Spades; | 2144 | const p = Suit.Spades; |
| 2137 | assert(p.ordinal() == 1); | 2145 | assert(!p.isClubs()); |
| 2138 | } | 2146 | } |
| 2139 | | 2147 | |
| 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. | | |
| 2144 | const Foo = enum { | 2149 | const Foo = enum { |
| | 2150 | String, |
| | 2151 | Number, |
| | 2152 | None, |
| | 2153 | }; |
| | 2154 | test "enum variant switch" { |
| | 2155 | const p = Foo.Number; |
| | 2156 | const what_is_it = switch (p) { |
| | 2157 | Foo.String => "this is a string", |
| | 2158 | Foo.Number => "this is a number", |
| | 2159 | Foo.None => "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. |
| | 2165 | const Small = enum { |
| | 2166 | One, |
| | 2167 | Two, |
| | 2168 | Three, |
| | 2169 | Four, |
| | 2170 | }; |
| | 2171 | test "@TagType" { |
| | 2172 | assert(@TagType(Small) == u2); |
| | 2173 | } |
| | 2174 | |
| | 2175 | // @memberCount tells how many fields an enum has: |
| | 2176 | test "@memberCount" { |
| | 2177 | assert(@memberCount(Small) == 4); |
| | 2178 | } |
| | 2179 | |
| | 2180 | // @memberName tells the name of a field in an enum: |
| | 2181 | test "@memberName" { |
| | 2182 | assert(mem.eql(u8, @memberName(Small, 1), "Two")); |
| | 2183 | } |
| | 2184 | |
| | 2185 | // @tagName gives a []const u8 representation of an enum value: |
| | 2186 | test "@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 |
| | 2192 | Test 1/8 enum ordinal value...OK |
| | 2193 | Test 2/8 set enum ordinal value...OK |
| | 2194 | Test 3/8 enum method...OK |
| | 2195 | Test 4/8 enum variant switch...OK |
| | 2196 | Test 5/8 @TagType...OK |
| | 2197 | Test 6/8 @memberCount...OK |
| | 2198 | Test 7/8 @memberName...OK |
| | 2199 | Test 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; |
| | 2208 | const mem = @import("std").mem; |
| | 2209 | |
| | 2210 | // A union has only 1 active field at a time. |
| | 2211 | const Payload = union { |
| | 2212 | Int: i64, |
| | 2213 | Float: f64, |
| | 2214 | Bool: bool, |
| | 2215 | }; |
| | 2216 | test "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: |
| | 2226 | const ComplexTypeTag = enum { Ok, NotOk }; |
| | 2227 | const ComplexType = union(ComplexTypeTag) { |
| | 2228 | Ok: u8, |
| | 2229 | NotOk: void, |
| | 2230 | }; |
| | 2231 | |
| | 2232 | // Declare a specific instance of the union variant. |
| | 2233 | test "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. |
| | 2239 | test "@TagType" { |
| | 2240 | assert(@TagType(ComplexType) == ComplexTypeTag); |
| | 2241 | } |
| | 2242 | |
| | 2243 | // Unions can be made to infer the enum tag type. |
| | 2244 | const 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 | }; |
| 2149 | test "enum variant switch" { | 2251 | test "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 reference | 2254 | // 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" { |
| 2156 | | 2258 | |
| 2157 | // Capture by value | 2259 | // 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 | }, |
| 2161 | | 2264 | |
| ... | @@ -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 | } |
| 2167 | | 2271 | |
| 2168 | // The @memberName and @memberCount builtin functions can be used to | 2272 | // TODO union methods |
| 2169 | // the string representation and number of members respectively. | 2273 | |
| 2170 | const BuiltinType = enum { | 2274 | |
| 2171 | A: f32, | 2275 | const Small = union { |
| 2172 | B: u32, | 2276 | A: i32, |
| 2173 | C, | 2277 | B: bool, |
| | 2278 | C: u8, |
| 2174 | }; | 2279 | }; |
| 2175 | | 2280 | |
| 2176 | test "enum builtins" { | 2281 | // @memberCount tells how many fields a union has: |
| 2177 | assert(mem.eql(u8, @memberName(BuiltinType.A { 0 }), "A")); | 2282 | test "@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: |
| | 2287 | test "@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. |
| | 2293 | const Small2 = union(enum) { |
| | 2294 | A: i32, |
| | 2295 | B: bool, |
| | 2296 | C: u8, |
| | 2297 | }; |
| | 2298 | test "@tagName" { |
| | 2299 | assert(mem.eql(u8, @tagName(Small2.C), "C")); |
| 2180 | }</code></pre> | 2300 | }</code></pre> |
| 2181 | <pre><code class="sh">$ zig test enum.zig | 2301 | <pre><code class="sh">$ zig test union.zig |
| 2182 | Test 1/4 enum ordinal value...OK | 2302 | Test 1/7 simple union...OK |
| 2183 | Test 2/4 enum method...OK | 2303 | Test 2/7 declare union value...OK |
| 2184 | Test 3/4 enum variant switch...OK | 2304 | Test 3/7 @TagType...OK |
| 2185 | Test 4/4 enum builtins...OK</code></pre> | 2305 | Test 4/7 union variant switch...OK |
| 2186 | <p> | 2306 | Test 5/7 @memberCount...OK |
| 2187 | Enums are generated as a struct with a tag field and union field. Zig | 2307 | Test 6/7 @memberName...OK |
| | 2308 | Test 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; |
| 2200 | const builtin = @import("builtin"); | 2315 | const builtin = @import("builtin"); |