source: doc/proposals/enums.md

Last change on this file was 80018f5, checked in by Andrew Beach <ajbeach@…>, 40 hours ago

Attempted to inject some examples (and some other pieces I had missed) into the enum proposal.

  • Property mode set to 100644
File size: 7.0 KB
Line 
1Enumeration Type Proposals
2==========================
3With Jiada's recent work on enumerations (see doc/theses/jiada_liang_MMath/),
4this is a collection point for some remaining issues with and ideas to
5further improve enumerations.
6
7Fixed Encoding
8--------------
9Because Cforall enumerations are encoded using their position, it can be
10difficult to give them a stable encoding, this is important in seperate
11compilation.
12
13The example (provided by Gregor Richards), is a system header that defines
14any type that has to be stable across versions. Let's say error codes.
15
16```cfa
17enum() BigLibError! {
18        BadArgument,
19        ...
20        MissingConfig,
21        LastStartupError = MissingConfig,
22        NoMemory,
23        Timeout,
24        ...
25};
26```
27
28The actual errors are not important, but note that "LastStartupError" has
29to be in a particular location relative to some others. If a new version of
30the header wants to add a new startup error, it should go before the
31LastStartupError, but that will change the position, and hence the encoding,
32of all the remaining
33
34The most obvious example in an existing lanuage I could find is that Rust
35usually treats its enum types as opaques algebraic data types, but in certain
36cases allows you to fix the encoding of enumerations.
37(Although the motivation seems to be optimization of enumerations that
38have a lot of common options.)
39
40Enumerated Arrays
41-----------------
42Arrays that use an enumeration as their index. The entire enumeration type
43(instead of a subset of int) is used in the index operation.
44
45```cfa
46enum() Colour {
47  Red,
48  Violet,
49  Blue,
50  Green
51  Yellow,
52  Orange,
53};
54
55// Declare an array with an index of an enumeration:
56int jarsOfPaint[Colour] = {0};
57
58// Index the array:
59printf("I have %d jars of blue paint.\n", jarsOfPaint[Blue]);
60jarsOfPaint[Green] = 3;
61jarsOfPaint[Red] += 1;
62
63// Use the function for higher order programming:
64int (*lookup)(int collection[Colour], Colour key) = ?[?];
65
66// ERROR! Use the enumeration index for safety:
67jarsOfPaint[0] = 0;
68```
69
70Although described differently, this is actually a generalization of typed
71enumerations, as it can be used to safely represent a constant of any type
72for each possible enumeration value.
73
74```cfa
75extern string colourNames[Colour];
76```
77
78This example is a forward declaration that declares the symbol but does not
79give the values or allocate any storage. This is used in header files.
80The type of colourNames would be a new type `string[Colour]`.
81
82In implementation tiles it is safe to give the array's values;
83whether it the array has been previously forward declared or not.
84```cfa
85string colourNames[Colour] = {
86  "red",
87  "violet",
88  "blue",
89  // Or without worrying about ordering:
90  [Green] = "green",
91  [Orange] = "orange",
92  [Yellow] = "yellow",
93};
94```
95
96The forward declaration and full definition variants allow the user to manage
97memory themselves, following the same rules as `extern` variables.
98The user can use `const` to fix the values in the array.
99These arrays can also be nested `BlendInfo blend[Colour][Colour]` or used
100locally.
101
102Except for the index type (and that the size of the array is fixed per
103index type, as it always covers the whole enumeration) it should be the same
104as a traditional array.
105
106Or one of the new safer Cforall arrays, as the features could be combined.
107
108(Previously, a combined declaration to declare both an enumeration and
109an enumerated array was proposed. That only covers the simple case that
110typed enumerations already cover.)
111
112Enumeration Ranges
113------------------
114We have the simplest iterate over a range of enumerations (can only be used
115directly in a for loop, always covers the entire type) but it could be
116generalized to work with the other features of ranges, such as going over
117just part of the enumeration (see Ranges in doc/proposals/iterators.md).
118
119This will work best with some alias labels that mark out the beginning of
120ranges. That is the ranges within the enum will often have to be an
121intended part of the interface.
122
123```cfa
124for ( kind : DataKind.BeginIntegers +~ DataKind.EndIntegers ) { ... }
125```
126
127Writing the declaration is a bit tricker, because of the lack of aliasing,
128but this should echo a common C pattern.
129
130Flag Set Enumerations
131---------------------
132Another common use of enumerations is as a named bitset.
133
134This doesn't actually follow from the logical definition of enumerations, but
135is something that various implementation of "enum" have commonly been used to
136recreate. This would formalize that, providing an easy way to create typesafe
137implementations of this pattern.
138
139```cfa
140enum Directions flag {
141  Up,
142  Down,
143  Left,
144  Right,
145  Upwards = Up,
146  Vertical = Up | Down,
147};
148```
149
150Some example usages:
151```cfa
152// If it is exactly Up/Upwards, then set exactly Down
153if ( Upwards == dirs ) {
154  dirs = Down
155// Otherwise, if a vertical is set, unset them:
156} else if ( Vertical & dirs ) {
157  dirs = dirs & ~Vertical;
158// Otherwise, if any direction is set then also set Up:
159} else if ( dirs ) {
160  dirs |= Up;
161}
162```
163
164Uses the existing enumeration syntax, except that all initializers must be
165bitwise expressions, using only the operators |, & and ~ and, as leaf values,
166other labels from the enumeration (no cycles) and 0.
167
168Each uninitialized label creates a new flag. Every instance of the
169enumeration will have each flag be set or unset. The labels act as instances
170of the enumeration with only that flag set.
171
172A type created this way automatically supports: default construction,
173from zero_t construction, copy construction, copy assignment, destruction,
174equality, inequality and bitwise and (&), or (|) and not (~).
175Default construction and from zero_t construction create an instance with no
176flags set. Two instances are the same if the same flags are set.
177Bitwise operations act on the individual flags in the set.
178
179In addition the type can be converted to a Boolean.
180An flag set is truthy if any flags are set and falsy if no flags are set.
181This is not a primitive operation, but comes from combining the zero_t
182constructor and inequality.
183
184Note: Scoping rules are also waiting on the namespacing and module system.
185
186Feature (and Storage) Control
187-----------------------------
188Right now features are very coursely grouped. You have exactly three options
189for your enumeration. However since there are more than two features this
190means there are some combinations you cannot have.
191
192For instance, labels (which are mostly useful for generating debug output)
193are not available for C style enum, but for both of the new Cforall enums,
194opaque and typed. However, there is no innate connection between the
195additional type safety of the opaque enum or the associated values/payloads
196of the typed enums.
197
198Enumerations do interact with on feature that shows this orthagonality,
199and that is the scoping "no export" marker, that can be applied to any
200enumeration to change the visibility rules of the enumeration and does not
201change anything else.
202
203This is not urgent, just not using the features you don't want is almost as
204clear and the compile-time, binary-size and runtime costs are all good enough
205for now (and some day all of those may have to be improved even when the
206feature is being used). Isolating independent features is just good design.
Note: See TracBrowser for help on using the repository browser.