\chapter{\CFA Enumeration}

\CFA extends C-Style enumeration by adding a number of new features that bring enumerations inline with other modern programming languages.
Any enumeration extensions must be intuitive to C programmers both in syntax and semantics.
The following sections detail all of my new contributions to enumerations in \CFA.


\section{Syntax}

\CFA extends the C enumeration declaration \see{\VRef{s:CEnumeration}} by parameterizing with a type (like a generic type), and adding Plan-9 inheritance \see{\VRef{s:CFAInheritance}} using an @inline@ to another enumeration type.
\begin{cfa}[identifierstyle=\linespread{0.9}\it]
$\it enum$-specifier:
	enum @(type-specifier$\(_{opt}\)$)@ identifier$\(_{opt}\)$ { cfa-enumerator-list }
	enum @(type-specifier$\(_{opt}\)$)@ identifier$\(_{opt}\)$ { cfa-enumerator-list , }
	enum @(type-specifier$\(_{opt}\)$)@ identifier
cfa-enumerator-list:
	cfa-enumerator
	cfa-enumerator-list, cfa-enumerator
cfa-enumerator:
	enumeration-constant
	@inline $\color{red}enum$-type-name@
	enumeration-constant = constant-expression
\end{cfa}


\section{Operations}

\CFA enumerations have access to the three enumerations properties \see{\VRef{s:Terminology}}: label, order (position), and value via three overloaded functions @label@, @posn@, and @value@ \see{\VRef{c:trait} for details}.
\CFA auto-generates these functions for every \CFA enumeration.
\begin{cfa}
enum(int) E { A = 3 } e = A;
sout | A | @label@( A ) | @posn@( A ) | @value@( A );
sout | e | @label@( e ) | @posn@( e ) | @value@( e );
A A 0 3
A A 0 3
\end{cfa}
For output, the default is to print the label.
An alternate way to get an enumerator's position is to cast it to @int@.
\begin{cfa}
sout | A | label( A ) | @(int)A@ | value( A );
sout | A | label( A ) | @(int)A@ | value( A );
A A @0@ 3
A A @0@ 3
\end{cfa}
Finally, there is an additional enumeration pseudo-function @countof@ (like @sizeof@, @typeof@) that returns the number of enumerators in an enumeration.
\begin{cfa}
enum(int) E { A, B, C, D } e;
countof( E );  // 4, type argument
countof( e );  // 4, variable argument
\end{cfa}
This buildin function replaces the C idiom for automatically computing the number of enumerators \see{\VRef{s:Usage}}.
\begin{cfa}
enum E { A, B, C, D, @N@ };  // N == 4
\end{cfa}

The underlying representation of \CFA enumeration object is its position, saved as an integral type.
Therefore, the size of a \CFA enumeration is consistent with a C enumeration.
Attribute function @posn@ performs type substitution on an expression from \CFA type to integral type.
The label and value of an enumerator is stored in a global data structure for each enumeration, where attribute functions @label@/@value@ map an \CFA enumeration object to the corresponding data.
These operations do not apply to C Enums because backwards compatibility means the necessary backing data structures cannot be supplied.


\section{Opaque Enumeration}
\label{s:OpaqueEnum}

When an enumeration type is empty is it an \newterm{opaque} enumeration.
\begin{cfa}
enum@()@ Mode { O_RDONLY, O_WRONLY, O_CREAT, O_TRUNC, O_APPEND };
\end{cfa}
Here, the internal representation is chosen by the compiler and hidden, so the enumerators cannot be initialized.
Compared to the C enum, opaque enums are more restrictive in terms of typing and cannot be implicitly converted to integers.
\begin{cfa}
Mode mode = O_RDONLY;
int www @=@ mode;						$\C{// disallowed}$
\end{cfa}
Opaque enumerations have only two attribute properties @label@ and @posn@.
\begin{cfa}
char * s = label( O_TRUNC );			$\C{// "O\_TRUNC"}$
int open = posn( O_WRONLY );			$\C{// 1}$
\end{cfa}
The equality and relational operations are available.
\begin{cfa}
if ( mode @==@ O_CREAT ) ...
bool b = mode @<@ O_APPEND;
\end{cfa}


\section{Typed Enumeration}
\label{s:EnumeratorTyping}

When an enumeration type is specified, all enumerators have that type and can be initialized with constants of that type or compile-time convertable to that type.
Figure~\ref{f:EumeratorTyping} shows a series of examples illustrating that all \CFA types can be use with an enumeration and each type's values used to set the enumerator constants.
Note, the use of the synonyms @Liz@ and @Beth@ in the last declaration.
Because enumerators are constants, the enumeration type is implicitly @const@, so all the enumerator types in Figure~\ref{f:EumeratorTyping} are logically rewritten with @const@.

\begin{figure}
\begin{cfa}
// integral
	enum( @char@ ) Currency { Dollar = '$\textdollar$', Cent = '$\textcent$', Yen = '$\textyen$', Pound = '$\textsterling$', Euro = 'E' };
	enum( @signed char@ ) srgb { Red = -1, Green = 0, Blue = 1 };
	enum( @long long int@ ) BigNum { X = 123_456_789_012_345,  Y = 345_012_789_456_123 };
// non-integral
	enum( @double@ ) Math { PI_2 = 1.570796, PI = 3.141597, E = 2.718282 };
	enum( @_Complex@ ) Plane { X = 1.5+3.4i, Y = 7+3i, Z = 0+0.5i };
// pointer
	enum( @char *@ ) Name { Fred = "FRED", Mary = "MARY", Jane = "JANE" };
	int i, j, k;
	enum( @int *@ ) ptr { I = &i,  J = &j,  K = &k };
	enum( @int &@ ) ref { I = i,   J = j,   K = k };
// tuple
	enum( @[int, int]@ ) { T = [ 1, 2 ] }; $\C{// new \CFA type}$
// function
	void f() {...}   void g() {...}
	enum( @void (*)()@ ) funs { F = f,  G = g };
// aggregate
	struct Person { char * name; int age, height; };
	enum( @Person@ ) friends { @Liz@ = { "ELIZABETH", 22, 170 }, @Beth@ = Liz,
									Jon = { "JONATHAN", 35, 190 } };
\end{cfa}
% synonym feature unimplemented
\caption{Enumerator Typing}
\label{f:EumeratorTyping}
\end{figure}

An advantage of the typed enumerations is eliminating the \emph{harmonizing} problem between an enumeration and companion data \see{\VRef{s:Usage}}:
\begin{cfa}
enum( char * ) integral_types {
	chr = "char", schar = "signed char", uschar = "unsigned char",
	sshort = "signed short int", ushort = "unsigned short int",
	sint = "signed int", usint = "unsigned int",
	...
};
\end{cfa}
Note, the enumeration type can be a structure (see @Person@ in Figure~\ref{f:EumeratorTyping}), so it is possible to have the equivalent of multiple arrays of companion data using an array of structures.

While the enumeration type can be any C aggregate, the aggregate's \CFA constructors are \emph{not} used to evaluate an enumerator's value.
\CFA enumeration constants are compile-time values (static);
calling constructors happens at runtime (dynamic).


\section{Value Conversion}

C has an implicit type conversion from an enumerator to its base type @int@.
Correspondingly, \CFA has an implicit conversion from a typed enumerator to its base type, allowing typed enumeration to be seamlessly used as the value of its base type
For example, using type @Currency@ in \VRef[Figure]{f:EumeratorTyping}:
\begin{cfa}
char currency = Dollar; 	$\C{// implicit conversion to base type}$
void foo( char );
foo( Dollar ); 				$\C{// implicit conversion to base type}$
\end{cfa}
The implicit conversion induces a \newterm{value cost}, which is a new category (8 tuple) in \CFA's conversion cost model \see{\VRef{s:ConversionCost}} to disambiguate function overloading over a \CFA enumeration and its base type.
\begin{cfa}
void baz( char ch );		$\C{// (1)}$
void baz( Currency cu );	$\C{// (2)}$
baz( Dollar );
\end{cfa}
While both @baz@ functions are applicable to the enumerator @Dollar@, @candidate (1)@ comes with a @value@ cost for the conversion to the enumeration's base type, while @candidate (2)@ has @zero@ cost.
Hence, \CFA chooses the exact match.
Value cost is defined to be a more significant factor than an @unsafe@ but less than the other conversion costs: @(unsafe,@ {\color{red}@value@}@, poly, safe, sign, vars, specialization,@ @reference)@.
\begin{cfa}
void bar( @int@ );
Math x = PI;				$\C{// (1)}$
double x = 5.5;				$\C{// (2)}$
bar( x );					$\C{// costs (1, 0, 0, 0, 0, 0, 0, 0) or (0, 1, 0, 0, 0, 0, 0, 0)}$
\end{cfa}
Here, candidate (1) has a value conversion cost to convert to the base type, while candidate (2) has an unsafe conversion from @double@ to @int@.
Hence, @bar( x )@ resolves @x@ as type @Math@.

% \begin{cfa}
% forall(T | @CfaEnum(T)@) void bar(T);
% 
% bar(a);					$\C{// (3), with cost (0, 0, 1, 0, 0, 0, 0, 0)}$
% \end{cfa}
% % @Value@ is designed to be less significant than @poly@ to allow function being generic over \CFA enumeration (see ~\ref{c:trait}).
% Being generic over @CfaEnum@ traits (a pre-defined interface for \CFA enums) is a practice in \CFA to implement functions over \CFA enumerations, as will see in chapter~\ref{c:trait}.
% @Value@ is a being a more significant cost than @poly@ implies if a overloaeded function defined for @CfaEnum@ (and other generic type), \CFA always try to resolve it as a @CfaEnum@, rather to insert a @value@ conversion.


\section{Auto Initialization}

A partially implemented feature is auto-initialization, which works for the C integral type with constant expressions.
\begin{cfa}
enum Week { Mon, Tue, Wed, Thu@ = 10@, Fri, Sat, Sun }; // 0-2, 10-13
\end{cfa}
The complexity of the constant expression depends on the level of computation the compiler implements, \eg \CC \lstinline[language={[GNU]C++}]{constexpr} provides complex compile-time computation across multiple types, which blurs the compilation/runtime boundary.

If \CFA had powerful compilation expression evaluation, auto initialization would be implemented as follows.
\begin{cfa}
enum E(T) { A, B, C };
\end{cfa}
\begin{enumerate}
\item the first enumerator, @A@, is initialized with @T@'s @zero_t@.
\item otherwise, the next enumerator is initialized with the previous enumerator's value using operator @?++@, where @?++( T )@ can be overloaded for any type @T@.
\end{enumerate}

Unfortunately, constant expressions in C are not powerful and \CFA is only a transpiler, relying on generated C code to perform the detail work.
It is currently beyond the scope of the \CFA project to implement a complex runtime interpreter in the transpiler to evaluate complex expressions across multiple builtin and user-defined type. 
Nevertheless, the necessary language concepts exist to support this feature.


\section{Subset}

An enumeration's type can be another enumeration.
\begin{cfa}
enum( char ) Letter { A = 'A', ..., Z = 'Z' };
enum( @Letter@ ) Greek { Alph = @A@, Beta = @B@, Gamma = @G@, ..., Zeta = @Z@ }; // alphabet intersection
\end{cfa}
Enumeration @Greek@ may have more or less enumerators than @Letter@, but its enumerator values \emph{must} be from @Letter@.
Therefore, the set of @Greek@ enumerator values in a subset of the @Letter@ enumerator values. 
@Letter@ is type compatible with enumeration @Letter@ because value conversions are inserted whenever @Letter@ is used in place of @Greek@.
\begin{cfa}
Letter l = A;						$\C{// allowed}$
Greek g = Alph;						$\C{// allowed}$
l = Alph;							$\C{// allowed, conversion to base type}$
g = A;								$\C{// {\color{red}disallowed}}$
void foo( Letter );
foo( Beta );						$\C{// allowed, conversion to base type}$
void bar( Greek );
bar( A );							$\C{// {\color{red}disallowed}}$
\end{cfa}
Hence, @Letter@ enumerators are not type compatible with the @Greek@ enumeration but the reverse is true.


\section{Inheritance}
\label{s:CFAInheritance}

\CFA Plan-9 inheritance may be used with \CFA enumerations, where Plan-9 inheritance is containment inheritance with implicit unscoping (like a nested unnamed @struct@/@union@ in C).
Containment is nominative: an enumeration inherits all enumerators from another enumeration by declaring an @inline statement@ in its enumerator lists.
\begin{cfa}
enum( char * ) Names { /* $\see{\VRef[Figure]{f:EumeratorTyping}}$ */  };
enum( char * ) Names2 { @inline Names@, Jack = "JACK", Jill = "JILL" };
enum( char * ) Names3 { @inline Names2@, Sue = "SUE", Tom = "TOM" };
\end{cfa}
In the preceding example, @Names2@ is defined with five enumerators, three of which are from @Name@ through containment, and two are self-declared.
@Names3@ inherits all five members from @Names2@ and declares two additional enumerators.
Hence, enumeration inheritance forms a subset relationship.
Specifically, the inheritance relationship for the example above is:
\begin{cfa}
Names $\(\subset\)$ Names2 $\(\subset\)$ Names3 $\C{// enum type of Names}$
\end{cfa}

Inheritance can be nested, and a \CFA enumeration can inline enumerators from more than one \CFA enumeration, forming a tree-like hierarchy.
However, the uniqueness of enumeration name applies to enumerators, including those from supertypes, meaning an enumeration cannot name enumerator with the same label as its subtype's members, or inherits
from multiple enumeration that has overlapping enumerator label. As a consequence, a new type cannot inherits from both an enumeration and its supertype, or two enumerations with a
common supertype (the diamond problem), since such would unavoidably introduce duplicate enumerator labels.

The base type must be consistent between subtype and supertype.
When an enumeration inherits enumerators from another enumeration, it copies the enumerators' @value@ and @label@, even if the @value@ is auto initialized.
However, the position of the underlying representation is the order of the enumerator in the new enumeration.
\begin{cfa}
enum() E1 { B };									$\C{// B}$						
enum() E2 { C, D };						$\C{// C D}$
enum() E3 { inline E1, inline E2, E };	$\C{// {\color{red}[\(_{E1}\)} B {\color{red}]} {\color{red}[\(_{E2}\)} C D {\color{red}]} E}$
enum() E4 { A, inline E3, F};			$\C{// A {\color{blue}[\(_{E3}\)} {\color{red}[\(_{E1}\)} B {\color{red}]} {\color{red}[\(_{E2}\)} C D {\color{red}]} E {\color{blue}]} F}$
\end{cfa}
In the example, @B@ is at position 0 in @E1@ and @E3@, but position 1 in @E4@ as @A@ takes position 0 in @E4@.
@C@ is at position 0 in @E2@, 1 in @E3@, and 2 in @E4@.
@D@ is at position 1 in @E2@, 2 in @E3@, and 3 in @E4@. 

A subtype enumeration can be casted, or implicitly converted into its supertype, with a @safe@ cost, called \newterm{enumeration conversion}. 
\begin{cfa}
enum E2 e2 = C;
posn( e2 );			$\C[1.75in]{// 0}$
enum E3 e3 = e2;
posn( e2 );			$\C{// 1 cost}$
void foo( E3 e );
foo( e2 );
posn( (E3)e2 );		$\C{// 1 cost}$
E3 e31 = B;
posn( e31 );		$\C{// 0 cost}\CRT$
\end{cfa}
The last expression is unambiguous.
While both @E2.B@ and @E3.B@ are valid candidates, @E2.B@ has an associated safe cost, so \CFA selects the zero cost candidate.

For the given function prototypes, the following calls are valid.
\begin{cquote}
\begin{tabular}{ll}
\begin{cfa}
void f( Names );
void g( Names2 );
void h( Names3 );
void j( const char * );
\end{cfa}
&
\begin{cfa}
f( Fred );
g( Fred );   g( Jill );
h( Fred );   h( Jill );   h( Sue );
j( Fred );    j( Jill );    j( Sue );    j( "WILL" );
\end{cfa}
\end{tabular}
\end{cquote}
Note, the validity of calls is the same for call-by-reference as for call-by-value, and @const@ restrictions are the same as for other types.


\subsection{Offset Calculation}

As discussed in \VRef{s:OpaqueEnum}, \CFA chooses position as a representation of a \CFA enumeration variable.
When a cast or implicit conversion moves an enumeration from subtype to supertype, the position can be unchanged or increase.
\CFA determines the position offset with an \newterm{offset calculation} function.

\begin{figure}
\begin{cfa}
struct Enumerator;
struct CFAEnum { vector<variant<CFAEnum, Enumerator>> members; string name; };
inline static bool operator==(CFAEnum& lhs, CFAEnum& rhs) { return lhs.name == rhs.name; }
pair<bool, int> calculateEnumOffset(CFAEnum src, CFAEnum dst) {
	int offset = 0;
	if ( src == dst ) return make_pair(true, 0);
	for ( auto v : dst.members ) {
		if ( holds_alternative<Enumerator>(v) ) {
			offset++;
		} else {
			auto m = get<CFAEnum>(v);
			if ( m == src ) @return@ make_pair( true, offset );
			auto dist = calculateEnumOffset( src, m );
			if ( dist.first ) {
				@return@ make_pair( true, offset + dist.second );
			} else {
				offset += dist.second;
			}
		}
	}
	@return@ make_pair( false, offset );
}
\end{cfa}
\caption{Compute Offset from Subtype Enumeration to a Supertype}
\label{s:OffsetSubtypeSuperType}
\end{figure}

Figure~\ref{s:OffsetSubtypeSuperType} shows an outline of the offset calculation in \CC.
Structure @CFAEnum@ represents the \CFA enumeration with a vector of variants of @CFAEnum@ or @Enumerator@.
The algorithm takes two @CFAEnums@ parameters, @src@ and @dst@, with @src@ being the type of expression the conversion applies to, and @dst@ being the type the expression is cast to.
The algorithm iterates over the members in @dst@ to find @src@.
If a member is an enumerator of @dst@, the positions of all subsequent members is increment by one.
If the current member is @dst@, the function returns true indicating \emph{found} and the accumulated offset.
Otherwise, the algorithm recurses into the current @CFAEnum@ @m@ to check if its @src@ is convertible to @m@.
If @src@ is convertible to the current member @m@, this means @src@ is a subtype-of-subtype of @dst@.
The offset between @src@ and @dst@ is the sum of the offset of @m@ in @dst@ and the offset of @src@ in @m@.
If @src@ is not a subtype of @m@, the loop continues but with the offset shifted by the size of @m@.
If the loop ends, than @src@ is not convertible to @dst@, and false is returned.


\section{Control Structures}

Enumerators can be used in multiple contexts.
In most programming languages, an enumerator is implicitly converted to its value (like a typed macro substitution).
However, enumerator synonyms and typed enumerations make this implicit conversion to value incorrect in some contexts.
In these contexts, a programmer's intuition assumes an implicit conversion to position.

For example, an intuitive use of enumerations is with the \CFA @switch@/@choose@ statement, where @choose@ performs an implicit @break@ rather than a fall-through at the end of a @case@ clause.
(For this discussion, ignore the fact that @case@ requires a compile-time constant.)
\begin{cfa}[belowskip=0pt]
enum Count { First, Second, Third, Fourth };
Count e;
\end{cfa}
\begin{cquote}
\setlength{\tabcolsep}{15pt}
\noindent
\begin{tabular}{@{}ll@{}}
\begin{cfa}[aboveskip=0pt]

choose( e ) {
	case @First@: ...;
	case @Second@: ...;
	case @Third@: ...;
	case @Fourth@: ...;
}
\end{cfa}
&
\begin{cfa}[aboveskip=0pt]
// rewrite
choose( @value@( e ) ) {
	case @value@( First ): ...;
	case @value@( Second ): ...;
	case @value@( Third ): ...;
	case @value@( Fourth ): ...;
}
\end{cfa}
\end{tabular}
\end{cquote}
Here, the intuitive code on the left is implicitly transformed into the standard implementation on the right, using the value of the enumeration variable and enumerators.
However, this implementation is fragile, \eg if the enumeration is changed to:
\begin{cfa}
enum Count { First, Second, Third @= First@, Fourth };
\end{cfa}
making @Third == First@ and @Fourth == Second@, causing a compilation error because of duplicate @case@ clauses.
To better match with programmer intuition, \CFA toggles between value and position semantics depending on the language context.
For conditional clauses and switch statements, \CFA uses the robust position implementation.
\begin{cfa}
if ( @posn@( e ) < posn( Third ) ) ...
choose( @posn@( e ) ) {
	case @posn@( First ): ...;
	case @posn@( Second ): ...;
	case @posn@( Third ): ...;
	case @posn@( Fourth ): ...;
}
\end{cfa}

\CFA provides a special form of for-control for enumerating through an enumeration, where the range is a type.
\begin{cfa}
for ( cx; @Count@ ) { sout | cx | nonl; } sout | nl;
for ( cx; ~= Count ) { sout | cx | nonl; } sout | nl;
for ( cx; -~= Count ) { sout | cx | nonl; } sout | nl;
First Second Third Fourth
First Second Third Fourth
Fourth Third Second First
\end{cfa}
The enumeration type is syntax sugar for looping over all enumerators and assigning each enumerator to the loop index, whose type is inferred from the range type.
The prefix @+~=@ or @-~=@ iterate forward or backwards through the inclusive enumeration range, where no prefix defaults to @+~=@.

C has an idiom for @if@ and loop predicates of comparing the predicate result ``not equal to 0''.
\begin{cfa}
if ( x + y /* != 0 */  ) ...
while ( p /* != 0 */  ) ...
\end{cfa}
This idiom extends to enumerations because there is a boolean conversion in terms of the enumeration value, if and only if such a conversion is available.
For example, such a conversion exists for all numerical types (integral and floating-point).
It is possible to explicitly extend this idiom to any typed enumeration by overloading the @!=@ operator.
\begin{cfa}
bool ?!=?( Name n, zero_t ) { return n != Fred; }
Name n = Mary;
if ( n ) ... // result is true
\end{cfa}
Specialize meanings are also possible.
\begin{cfa}
enum(int) ErrorCode { Normal = 0, Slow = 1, Overheat = 1000, OutOfResource = 1001 };
bool ?!=?( ErrorCode ec, zero_t ) { return ec >= Overheat; }
ErrorCode code = ...;
if ( code ) { problem(); }
\end{cfa}


\section{Dimension}

\VRef{s:EnumeratorTyping} introduces the harmonizing problem between an enumeration and secondary information.
When possible, using a typed enumeration for the secondary information is the best approach.
However, there are times when combining these two types is not possible.
For example, the secondary information might precede the enumeration and/or its type is needed directly to declare parameters of functions.
In these cases, having secondary arrays of the enumeration size are necessary.

To support some level of harmonizing in these cases, an array dimension can be defined using an enumerator type, and the enumerators used as subscripts.
\begin{cfa}
enum E1 { A, B, C, N }; // possibly predefined
enum(int) E2 { A, B, C };
float H1[N] = { [A] :$\footnotemark$ 3.4, [B] : 7.1, [C] : 0.01 }; // C
float H2[@E2@] = { [A] : 3.4, [B] : 7.1, [C] : 0.01 }; // CFA
\end{cfa}
\footnotetext{C uses symbol \lstinline{'='} for designator initialization, but \CFA changes it to \lstinline{':'} because of problems with tuple syntax.}
This approach is also necessary for a predefined typed enumeration (unchangeable), when additional secondary-information need to be added.

The array subscript operator, namely @?[?]@, is overloaded so that when a \CFA enumerator is used as an array index, it implicitly converts to its position over value to sustain data harmonization.
This behaviour can be reverted by explicit overloading:
\begin{cfa}
float ?[?]( float * arr, E2 index ) { return arr[ value( index ) ]; }
\end{cfa}
When an enumeration type is being used as an array dimension, \CFA adds the enumeration type to the initializer's context.
As a result, @H2@'s array destinators @A@, @B@ and @C@ are resolved unambiguously to type @E2@.
(@H1@'s destinators are also resolved unambiguously to @E1@ because @E2@ has a @value@ cost.)


\section{I/O}

As seen in multiple examples, enumerations can be printed and the default property printed is the enumerator's label, which is similar in other programming languages.
However, very few programming languages provide a mechanism to read in enumerator values.
Even the @boolean@ type in many languages does not have a mechanism for input using the enumerators @true@ or @false@.
\VRef[Figure]{f:EnumerationI/O} show \CFA enumeration input based on the enumerator labels.
When the enumerator labels are packed together in the input stream, the input algorithm scans for the longest matching string.
For basic types in \CFA, the rule is that the same constants used to initialize a variable in a program are available to initialize a variable using input, where strings constants can be quoted or unquoted.

\begin{figure}
\begin{cquote}
\setlength{\tabcolsep}{15pt}
\begin{tabular}{@{}ll@{}}
\begin{cfa}
int main() {
	enum(int ) E { BBB = 3, AAA, AA, AB, B };
	E e;

	for () {
		try {
			@sin | e@;
		} catch( missing_data * ) {
			sout | "missing data";
			continue; // try again
		}
	  if ( eof( sin ) ) break;
		sout | e | "= " | value( e );
	}
}
\end{cfa}
&
\begin{cfa}
$\rm input$
BBBABAAAAB
BBB AAA AA AB B

$\rm output$
BBB = 3
AB = 6
AAA = 4
AB = 6
BBB = 3
AAA = 4
AA = 5
AB = 6
B = 7

\end{cfa}
\end{tabular}
\end{cquote}
\caption{Enumeration I/O}
\label{f:EnumerationI/O}
\end{figure}


\section{Planet Example}

\VRef[Figure]{f:PlanetExample} shows an archetypal enumeration example illustrating most of the \CFA enumeration features.
@Planet@ is an enumeration of type @MR@.
Each planet enumerator is initialized to a specific mass/radius, @MR@, value.
The unnamed enumeration provides the gravitational-constant enumerator @G@.
Function @surfaceGravity@ uses the @with@ clause to remove @p@ qualification from fields @mass@ and @radius@.
The program main uses the pseudo function @countof@ to obtain the number of enumerators in @Planet@, and safely converts the random value into a @Planet@ enumerator using @fromInt@.
The resulting random orbital-body is used in a @choose@ statement.
The enumerators in the @case@ clause use the enumerator position for testing.
The prints use @label@ to print an enumerator's name.
Finally, a loop enumerates through the planets computing the weight on each planet for a given earth mass.
The print statement does an equality comparison with an enumeration variable and enumerator (@p == MOON@).

\begin{figure}
\small
\begin{cfa}
struct MR { double mass, radius; };			$\C[3.5in]{// planet definition}$
enum( @MR@ ) Planet {						$\C{// typed enumeration}$
	//                      mass (kg)   radius (km)
	MERCURY = { 0.330_E24, 2.4397_E6 },
	VENUS      = { 4.869_E24, 6.0518_E6 },
	EARTH       = { 5.976_E24, 6.3781_E6 },
	MOON        = { 7.346_E22, 1.7380_E6 },	$\C{// not a planet}$
	MARS         = { 0.642_E24, 3.3972_E6 },
	JUPITER    = { 1898._E24, 71.492_E6 },
	SATURN     = { 568.8_E24, 60.268_E6 },
	URANUS    = { 86.86_E24, 25.559_E6 },
	NEPTUNE  = { 102.4_E24, 24.746_E6 },
	PLUTO       = { 1.303_E22, 1.1880_E6 },	$\C{// not a planet}$
};
enum( double ) { G = 6.6743_E-11 };			$\C{// universal gravitational constant (m3 kg-1 s-2)}$
static double surfaceGravity( Planet p ) @with( p )@ {
	return G * mass / ( radius @\@ 2 );		$\C{// no qualification, exponentiation}$
}
static double surfaceWeight( Planet p, double otherMass ) {
	return otherMass * surfaceGravity( p );
}
int main( int argc, char * argv[] ) {
	if ( argc != 2 ) @exit@ | "Usage: " | argv[0] | "earth-weight";  // terminate program
	double earthWeight = convert( argv[1] );
	double earthMass = earthWeight / surfaceGravity( EARTH );
	Planet rp = @fromInt@( prng( @countof@( Planet ) ) ); $\C{// select random orbiting body}$
	@choose( rp )@ {						$\C{// implicit breaks}$
	  case MERCURY, VENUS, EARTH, MARS:
		sout | @rp@ | "is a rocky planet";
	  case JUPITER, SATURN, URANUS, NEPTUNE:
		sout | rp | "is a gas-giant planet";
	  default:
		sout | rp | "is not a planet";
	}
	for ( @p; Planet@ ) {					$\C{// enumerate}\CRT$
		sout | "Your weight on" | ( @p == MOON@ ? "the" : " " ) | p
			   | "is" | wd( 1,1,  surfaceWeight( p, earthMass ) ) | "kg";
	}
}
$\$$ planet 100
JUPITER is a gas-giant planet
Your weight on MERCURY is 37.7 kg
Your weight on VENUS is 90.5 kg
Your weight on EARTH is 100.0 kg
Your weight on the MOON is 16.6 kg
Your weight on MARS is 37.9 kg
Your weight on JUPITER is 252.8 kg
Your weight on SATURN is 106.6 kg
Your weight on URANUS is 90.5 kg
Your weight on NEPTUNE is 113.8 kg
Your weight on PLUTO is 6.3 kg
\end{cfa}
\caption{Planet Example}
\label{f:PlanetExample}
\end{figure}
