Alternate Enumeration Types =========================== A proposal to rework enumeration types. This is a new design for enumerations in Cforall. They are based around extending C enumerations focusing on the logical view of enumerations, keeping the underlying representation opaque. This does replace some of the existing features of Cforall; so implementing it will require redoing some work. However, while I do think the improvement will be worth it, I have included notes about how to regain some of the functionality/ease-of-use of typed enumerations. Because many of these uses were in the area of "enums as macros", some are not even enumeration features. Note that all the new syntax and names are only examples; in addition to any functionally changes that could happen. Sequential Enumerations ---------------------- The sequential enumeration is the most basic form of enumeration. ```cfa enum Colour seq { Red, Purple, Violet = Purple, Blue, Green, Yellow, Orange, }; ``` Uses traditional enum declaration syntax, where each label is uninitialized or initialized to another label in the enumeration (no cycles, possibly limited to previous labels). Uninitialized labels introduce a new possible value into the enumeration. This value has no representation beyond the label(s) that represents it. Initialized labels are simple aliases to an existing value. A type created this way automatically supports: copy construction, copy assignment, destruction and equality, inequality and ordering with itself. Each value is equal only to itself, so labels are equal to themselves and other labels via aliasing. Values are ordered low to high by first to last appearance of the uninitialized label. They can also be used in a switch statement with the labels used in case labels. (Default construction could be added by picking one of the labels - say the first - to be the default.) Note: This does not add the enumeration labels to the enclosing scope. Use qualification to access it or write `inline enum Colour seq ...` to begin the enumeration. This is dependent on the module and namespacing system design. Enumerated Arrays ----------------- Arrays that use an enumeration as their index. The entire enumeration type (instead of a subset of int) is used in the index operation. ```cfa extern string colourNames[Colour]; ``` This example is a forward declaration that declares the symbol but does not give the values or allocate any storage. This is used in header files. The type of colourNames would be a new type `string[Colour]`. In implementation tiles it is safe to give the array's values; whether it the array has been previously forward declared or not. ```cfa string colourNames[Colour] = { "red", "violet", "blue", // Or without worrying about ordering: [Green] = "green", [Orange] = "orange", [Yellow] = "yellow", }; ``` The forward declaration and full definition variants allow the user to manage memory themselves, following the same rules as `extern` variables. The user can use `const` to fix the values in the array. Except for the index type (and that the size of the array is fixed per index type, as it always covers the whole enumeration) it should be the same as a traditional array. Or one of the new safer Cforall arrays, as the features could be combined. Combined Declaration -------------------- People have requested, as a convenience feature, the ability to declare the enumeration and the array in one go. I say "People have requested" because I'm still working on the details, from storage to syntax, but a rough sketch of the feature would look like this: ```cfa string colourNames[inline enum Colour] = { Red = "red", Purple = "violet", Blue = "blue", Green = "green", Yellow = "yellow", Orange = "orange", }; ``` This should possibly be implemented as an extension. Enumeration Iteration --------------------- Iterate through all values in a sequential enumeration. The design very dependent on the overall design of the for-each loop and iterators in general (when added to the language). However, the behaviour should just go over every value in the enumeration in order of the initial appearance in the declaration. Flag Set Enumerations --------------------- Another common use of enumerations is as a named bitset. ```cfa enum Directions flag { Up, Down, Left, Right, Upwards = Up, Vertical = Up | Down, }; ``` Uses the existing enumeration syntax, except that all initializers must be bitwise expressions, using only the operators |, & and ~ and, as leaf values, other labels from the enumeration (no cycles) and 0. Each uninitialized label creates a new flag. Every instance of the enumeration will have each flag be set or unset. The labels act as instances of the enumeration with only that flag set. A type created this way automatically supports: default construction, from zero_t construction, copy construction, copy assignment, destruction, equality, inequality and bitwise and (&), or (|) and not (~). Default construction and from zero_t construction create an instance with no flags set. Two instances are the same if the same flags are set. Bitwise operations act on the individual flags in the set. In addition the type can be converted to a Boolean. An flag set is truthy if any flags are set and falsy if no flags are set. This is not a primitive operation, but comes from combining the zero_t constructor and inequality. Note: Scoping rules are also waiting on the namespacing and module system. Named Literal ------------- (Replacing the "enum as macros" uses of typed enumerations.) A new storage class specifier called `literal`. It specifies that the value is not stored but it is inlined at each use. These can be used like a macro except they respect scoping rules and are resolved and evaluated once. A variable with literal storage allocates no memory and does not define any symbols for the linker. They must be initialized with a constant expression. All uses of a literal variable are rvalues (that is to say, they are treated as literals, you may not assign to them or get their address). ```cfa literal int two = 2; ``` To allow this, there may have to be restrictions on the types that can be used with literal storage class. Some more implementation details will have to be known to decide what those are.