Enumeration Type Proposals
==========================
With Jiada's recent work on enumerations (see doc/theses/jiada_liang_MMath/),
this is a collection point for some remaining issues with and ideas to
further improve enumerations.

Fixed Encoding
--------------
Because Cforall enumerations are encoded using their position, it can be
difficult to give them a stable encoding, this is important in seperate
compilation.

The example (provided by Gregor Richards), is a system header that defines
any type that has to be stable across versions. Let's say error codes.

```cfa
enum() BigLibError! {
	BadArgument,
	...
	MissingConfig,
	LastStartupError = MissingConfig,
	NoMemory,
	Timeout,
	...
};
```

The actual errors are not important, but note that "LastStartupError" has
to be in a particular location relative to some others. If a new version of
the header wants to add a new startup error, it should go before the
LastStartupError, but that will change the position, and hence the encoding,
of all the remaining

The most obvious example in an existing lanuage I could find is that Rust
usually treats its enum types as opaques algebraic data types, but in certain
cases allows you to fix the encoding of enumerations.
(Although the motivation seems to be optimization of enumerations that
have a lot of common options.)

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
enum() Colour {
  Red,
  Violet,
  Blue,
  Green
  Yellow,
  Orange,
};

// Declare an array with an index of an enumeration:
int jarsOfPaint[Colour] = {0};

// Index the array:
printf("I have %d jars of blue paint.\n", jarsOfPaint[Blue]);
jarsOfPaint[Green] = 3;
jarsOfPaint[Red] += 1;

// Use the function for higher order programming:
int (*lookup)(int collection[Colour], Colour key) = ?[?];

// ERROR! Use the enumeration index for safety:
jarsOfPaint[0] = 0;
```

Although described differently, this is actually a generalization of typed
enumerations, as it can be used to safely represent a constant of any type
for each possible enumeration value.

```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.
These arrays can also be nested `BlendInfo blend[Colour][Colour]` or used
locally.

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.

(Previously, a combined declaration to declare both an enumeration and
an enumerated array was proposed. That only covers the simple case that
typed enumerations already cover.)

Enumeration Ranges
------------------
We have the simplest iterate over a range of enumerations (can only be used
directly in a for loop, always covers the entire type) but it could be
generalized to work with the other features of ranges, such as going over
just part of the enumeration (see Ranges in doc/proposals/iterators.md).

This will work best with some alias labels that mark out the beginning of
ranges. That is the ranges within the enum will often have to be an
intended part of the interface.

```cfa
for ( kind : DataKind.BeginIntegers +~ DataKind.EndIntegers ) { ... }
```

Writing the declaration is a bit tricker, because of the lack of aliasing,
but this should echo a common C pattern.

Flag Set Enumerations
---------------------
Another common use of enumerations is as a named bitset.

This doesn't actually follow from the logical definition of enumerations, but
is something that various implementation of "enum" have commonly been used to
recreate. This would formalize that, providing an easy way to create typesafe
implementations of this pattern.

```cfa
enum Directions flag {
  Up,
  Down,
  Left,
  Right,
  Upwards = Up,
  Vertical = Up | Down,
};
```

Some example usages:
```cfa
// If it is exactly Up/Upwards, then set exactly Down
if ( Upwards == dirs ) {
  dirs = Down
// Otherwise, if a vertical is set, unset them:
} else if ( Vertical & dirs ) {
  dirs = dirs & ~Vertical;
// Otherwise, if any direction is set then also set Up:
} else if ( dirs ) {
  dirs |= Up;
}
```

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.

Feature (and Storage) Control
-----------------------------
Right now features are very coursely grouped. You have exactly three options
for your enumeration. However since there are more than two features this
means there are some combinations you cannot have.

For instance, labels (which are mostly useful for generating debug output)
are not available for C style enum, but for both of the new Cforall enums,
opaque and typed. However, there is no innate connection between the
additional type safety of the opaque enum or the associated values/payloads
of the typed enums.

Enumerations do interact with on feature that shows this orthagonality,
and that is the scoping "no export" marker, that can be applied to any
enumeration to change the visibility rules of the enumeration and does not
change anything else.

This is not urgent, just not using the features you don't want is almost as
clear and the compile-time, binary-size and runtime costs are all good enough
for now (and some day all of those may have to be improved even when the
feature is being used). Isolating independent features is just good design.
