source: doc/theses/jiada_liang_MMath/CFAenum.tex @ 1d8a349

Last change on this file since 1d8a349 was 1d8a349, checked in by JiadaL <j82liang@…>, 5 weeks ago

change wording

  • Property mode set to 100644
File size: 27.3 KB
Line 
1\chapter{\CFA Enumeration}
2
3\CFA extends C-Style enumeration by adding a number of new features that bring enumerations inline with other modern programming languages.
4Any enumeration extensions must be intuitive to C programmers both in syntax and semantics.
5The following sections detail all of my new contributions to enumerations in \CFA.
6
7
8\section{Syntax}
9
10\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.
11\begin{cfa}[identifierstyle=\linespread{0.9}\it]
12$\it enum$-specifier:
13        enum @(type-specifier$\(_{opt}\)$)@ identifier$\(_{opt}\)$ { cfa-enumerator-list }
14        enum @(type-specifier$\(_{opt}\)$)@ identifier$\(_{opt}\)$ { cfa-enumerator-list , }
15        enum @(type-specifier$\(_{opt}\)$)@ identifier
16cfa-enumerator-list:
17        cfa-enumerator
18        cfa-enumerator-list, cfa-enumerator
19cfa-enumerator:
20        enumeration-constant
21        @inline $\color{red}enum$-type-name@
22        enumeration-constant = constant-expression
23\end{cfa}
24
25
26\section{Operations}
27
28\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}.
29\CFA auto-generates these functions for every \CFA enumeration.
30\begin{cfa}
31enum(int) E { A = 3 } e = A;
32sout | A | @label@( A ) | @posn@( A ) | @value@( A );
33sout | e | @label@( e ) | @posn@( e ) | @value@( e );
34A A 0 3
35A A 0 3
36\end{cfa}
37For output, the default is to print the label.
38An alternate way to get an enumerator's position is to cast it to @int@.
39\begin{cfa}
40sout | A | label( A ) | @(int)A@ | value( A );
41sout | A | label( A ) | @(int)A@ | value( A );
42A A @0@ 3
43A A @0@ 3
44\end{cfa}
45Finally, there is an additional enumeration pseudo-function @countof@ (like @sizeof@, @typeof@) that returns the number of enumerators in an enumeration.
46\begin{cfa}
47enum(int) E { A, B, C, D } e;
48countof( E )// 4, type argument
49countof( e )// 4, variable argument
50\end{cfa}
51This buildin function replaces the C idiom for automatically computing the number of enumerators \see{\VRef{s:Usage}}.
52\begin{cfa}
53enum E { A, B, C, D, @N@ };  // N == 4
54\end{cfa}
55
56The underlying representation of \CFA enumeration object is its position, saved as an integral type.
57Therefore, the size of a \CFA enumeration is consistent with a C enumeration.
58Attribute function @posn@ performs type substitution on an expression from \CFA type to integral type.
59The 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.
60These operations do not apply to C Enums because backwards compatibility means the necessary backing data structures cannot be supplied.
61
62\section{Opaque Enumeration}
63\label{s:OpaqueEnum}
64
65When an enumeration type is empty is it an \newterm{opaque} enumeration.
66\begin{cfa}
67enum@()@ Mode { O_RDONLY, O_WRONLY, O_CREAT, O_TRUNC, O_APPEND };
68\end{cfa}
69Here, the internal representation is chosen by the compiler and hidden, so the enumerators cannot be initialized.
70Compared to the C enum, opaque enums are more restrictive in terms of typing and cannot be implicitly converted to integers.
71\begin{cfa}
72Mode mode = O_RDONLY;
73int www @=@ mode;                                               $\C{// disallowed}$
74\end{cfa}
75Opaque enumerations have only two attribute properties @label@ and @posn@.
76\begin{cfa}
77char * s = label( O_TRUNC );                    $\C{// "O\_TRUNC"}$
78int open = posn( O_WRONLY );                    $\C{// 1}$
79\end{cfa}
80The equality and relational operations are available.
81\begin{cfa}
82if ( mode @==@ O_CREAT ) ...
83bool b = mode @<@ O_APPEND;
84\end{cfa}
85
86
87\section{Typed Enumeration}
88\label{s:EnumeratorTyping}
89
90When 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.
91Figure~\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.
92Note, the use of the synonyms @Liz@ and @Beth@ in the last declaration.
93Because enumerators are constants, the enumeration type is implicitly @const@, so all the enumerator types in Figure~\ref{f:EumeratorTyping} are logically rewritten with @const@.
94
95\begin{figure}
96\begin{cfa}
97// integral
98        enum( @char@ ) Currency { Dollar = '$\textdollar$', Cent = '$\textcent$', Yen = '$\textyen$', Pound = '$\textsterling$', Euro = 'E' };
99        enum( @signed char@ ) srgb { Red = -1, Green = 0, Blue = 1 };
100        enum( @long long int@ ) BigNum { X = 123_456_789_012_345,  Y = 345_012_789_456_123 };
101// non-integral
102        enum( @double@ ) Math { PI_2 = 1.570796, PI = 3.141597, E = 2.718282 };
103        enum( @_Complex@ ) Plane { X = 1.5+3.4i, Y = 7+3i, Z = 0+0.5i };
104// pointer
105        enum( @char *@ ) Name { Fred = "FRED", Mary = "MARY", Jane = "JANE" };
106        int i, j, k;
107        enum( @int *@ ) ptr { I = &i,  J = &j,  K = &k };
108        enum( @int &@ ) ref { I = i,   J = j,   K = k };
109// tuple
110        enum( @[int, int]@ ) { T = [ 1, 2 ] }; $\C{// new \CFA type}$
111// function
112        void f() {...}   void g() {...}
113        enum( @void (*)()@ ) funs { F = f,  G = g };
114// aggregate
115        struct Person { char * name; int age, height; };
116        enum( @Person@ ) friends { @Liz@ = { "ELIZABETH", 22, 170 }, @Beth@ = Liz,
117                                                                        Jon = { "JONATHAN", 35, 190 } };
118\end{cfa}
119% synonym feature unimplemented
120\caption{Enumerator Typing}
121\label{f:EumeratorTyping}
122\end{figure}
123
124An advantage of the typed enumerations is eliminating the \emph{harmonizing} problem between an enumeration and companion data \see{\VRef{s:Usage}}:
125\begin{cfa}
126enum( char * ) integral_types {
127        chr = "char", schar = "signed char", uschar = "unsigned char",
128        sshort = "signed short int", ushort = "unsigned short int",
129        sint = "signed int", usint = "unsigned int",
130        ...
131};
132\end{cfa}
133Note, 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.
134
135While the enumeration type can be any C aggregate, the aggregate's \CFA constructors are \emph{not} used to evaluate an enumerator's value.
136\CFA enumeration constants are compile-time values (static);
137calling constructors happens at runtime (dynamic).
138
139
140\section{Value Conversion}
141
142C has an implicit type conversion from an enumerator to its base type @int@.
143Correspondingly, \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
144For example, using type @Currency@ in \VRef[Figure]{f:EumeratorTyping}:
145\begin{cfa}
146char currency = Dollar;         $\C{// implicit conversion to base type}$
147void foo( char );
148foo( Dollar );                          $\C{// implicit conversion to base type}$
149\end{cfa}
150The 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.
151\begin{cfa}
152void baz( char ch );            $\C{// (1)}$
153void baz( Currency cu );        $\C{// (2)}$
154baz( Dollar );
155\end{cfa}
156While 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.
157Hence, \CFA chooses the exact match.
158Value 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)@.
159\begin{cfa}
160void bar( @int@ );
161Math x = PI;                            $\C{// (1)}$
162double x = 5.5;                         $\C{// (2)}$
163bar( x );                                       $\C{// costs (1, 0, 0, 0, 0, 0, 0, 0) or (0, 1, 0, 0, 0, 0, 0, 0)}$
164\end{cfa}
165Here, candidate (1) has a value conversion cost to convert to the base type, while candidate (2) has an unsafe conversion from @double@ to @int@.
166Hence, @bar( x )@ resolves @x@ as type @Math@.
167
168% \begin{cfa}
169% forall(T | @CfaEnum(T)@) void bar(T);
170%
171% bar(a);                                       $\C{// (3), with cost (0, 0, 1, 0, 0, 0, 0, 0)}$
172% \end{cfa}
173% % @Value@ is designed to be less significant than @poly@ to allow function being generic over \CFA enumeration (see ~\ref{c:trait}).
174% 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}.
175% @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.
176
177
178\section{Auto Initialization}
179
180A partially implemented feature is auto-initialization, which works for the C integral type with constant expressions.
181\begin{cfa}
182enum Week { Mon, Tue, Wed, Thu@ = 10@, Fri, Sat, Sun }; // 0-2, 10-13
183\end{cfa}
184The 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.
185
186If \CFA had powerful compilation expression evaluation, auto initialization would be implemented as follows.
187\begin{cfa}
188enum E(T) { A, B, C };
189\end{cfa}
190\begin{enumerate}
191\item the first enumerator, @A@, is initialized with @T@'s @zero_t@.
192\item otherwise, the next enumerator is initialized with the previous enumerator's value using operator @?++@, where @?++( T )@ can be overloaded for any type @T@.
193\end{enumerate}
194
195Unfortunately, constant expressions in C are not powerful and \CFA is only a transpiler, relying on generated C code to perform the detail work.
196It 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.
197Nevertheless, the necessary language concepts exist to support this feature.
198
199
200\section{Subset}
201
202An enumeration's type can be another enumeration.
203\begin{cfa}
204enum( char ) Letter { A = 'A', ... };
205enum( @Letter@ ) Greek { Alph = A, Beta = B, ... }; // alphabet intersection
206
207void foo(Letter l);
208foo(Beta);                      $\C{// foo(value(Beta))}$
209\end{cfa}
210Enumeration @Greek@ may have more or less enumerators than @Letter@, but the enum values \emph{must} be of a member of @Letter@.
211Therefore, the set of @Greek@ enum value in a subset of the value set of type @Letter@.
212@Letter@ is type compatible with enumeration @Letter@ thanks to \CFA inserts value conversion whenever @Letter@ be used
213in place of @Greek@. On the other hand, @Letter@ enums are not type compatible with enumeration @Greek@.
214As a result, @Greek@ becomes a logical subtype of @Letter@.
215
216Subset defines an implicit subtyping relationship between two \CFA enumerations. \CFA also has
217containment inheritance for \CFA enumerations where subtyping is explicitly structured.
218
219\section{Inheritance}
220\label{s:CFAInheritance}
221
222\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).
223Containment is nominative: an enumeration inherits all enumerators from another enumeration by declaring an @inline statement@ in its enumerator lists.
224\begin{cfa}
225enum( char * ) Names { /* $\see{\VRef[Figure]{f:EumeratorTyping}}$ */ };
226enum( char * ) Names2 { @inline Names@, Jack = "JACK", Jill = "JILL" };
227enum( char * ) Names3 { @inline Names2@, Sue = "SUE", Tom = "TOM" };
228\end{cfa}
229In the preceding example, @Names2@ is defined with five enumerators, three of which are from @Name@ through containment, and two are self-declared.
230@Names3@ inherits all five members from @Names2@ and declares two additional enumerators.
231Hence, enumeration inheritance forms a subset relationship.
232Specifically, the inheritance relationship for the example above is:
233\begin{cfa}
234Names $\(\subset\)$ Names2 $\(\subset\)$ Names3 $\C{// enum type of Names}$
235\end{cfa}
236
237Inheritance can be nested, and a \CFA enumeration can inline enumerators from more than one \CFA enumeration, forming a tree-like hierarchy.
238However, 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
239from 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
240common supertype (the diamond problem), since such would unavoidably introduce duplicate enumerator labels.
241
242The base type must be consistent between subtype and supertype.
243When an enumeration inherits enumerators from another enumeration, it copies the enumerators' @value@ and @label@, even if the @value@ is auto initialized.
244However, the position of the underlying representation is the order of the enumerator in the new enumeration.
245\begin{cfa}
246enum() E1 { B };                                                                $\C{// B}$                                             
247enum() E2 { C, D };                                                             $\C{// C D}$
248enum() E3 { inline E1, inline E2, E };                  $\C{// {\color{red}[\(_{E1}\)} B {\color{red}]} {\color{red}[\(_{E2}\)} C D {\color{red}]} E}$
249enum() 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 }$
250\end{cfa}
251In the example above, @B@ has the position 0 in @E1@ and @E3@, but it at the position 1 in @E4@ as @A@ taking the 0 in @E4@.
252@C@ is at the position 0 in @E2@, 1 in @E3@ and 2 in E4. @D@ is at the position 1 in @E2@, 2 in @E3@ and 3 in @E4@.
253
254A subtype enumeration can be casted, or implicitly converted into its supertype, with a @safe@ cost. Such conversion is an @enumeration conversion@.
255\begin{cfa}
256enum E2 e2 = C;
257posn( e2 );                     $\C[1.75in]{// 0}$
258enum E3 e3 = e2;
259posn( e2 );                     $\C{// 1}$
260void foo( E3 e );
261foo( e2 );
262posn( (E3)e2 );         $\C{// 1}$
263E3 e31 = B;
264posn( e31 );            $\C{// 0}\CRT$
265\end{cfa}
266The last expression is unambiguous.
267While both @E2.B@ and @E3.B@ are valid candidate, @E2.B@ has an associated safe cost and \CFA selects the zero cost candidate @E3.B@.
268
269For the given function prototypes, the following calls are valid.
270\begin{cquote}
271\begin{tabular}{ll}
272\begin{cfa}
273void f( Names );
274void g( Names2 );
275void h( Names3 );
276void j( const char * );
277\end{cfa}
278&
279\begin{cfa}
280f( Fred );
281g( Fred );   g( Jill );
282h( Fred );   h( Jill );   h( Sue );
283j( Fred );    j( Jill );    j( Sue );    j( "WILL" );
284\end{cfa}
285\end{tabular}
286\end{cquote}
287Note, 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.
288
289\subsection{Offset Calculation}
290As discussed in \VRef{s:OpaqueEnum}, \CFA chooses position as a representation of a \CFA enumeration variable.
291Because enumerators has different @position@ between subtype and supertype, \CFA might need to manipulate the representation whenever a cast or
292implicit conversion involves two \CFA enums. \CFA determine how a position is going to change with an @offset calculation@ function, reflects to
293enumerator as an arithmetic expression. Casting an enumeration of subtype to a supertype, the position can be unchanged or increase. The change
294of position is an @offset@. 
295
296\begin{figure}
297\begin{cfa}
298struct Enumerator;
299struct CFAEnum { vector<variant<CFAEnum, Enumerator>> members; string name; };
300inline static bool operator==(CFAEnum& lhs, CFAEnum& rhs) { return lhs.name == rhs.name; }
301pair<bool, int> calculateEnumOffset(CFAEnum src, CFAEnum dst) {
302        int offset = 0;
303        if (src == dst) return make_pair(true, 0);
304        for (auto v : dst.members) {
305                if (holds_alternative<Enumerator>(v)) {
306                        offset++;
307                } else {
308                        auto m = get<CFAEnum>(v);
309                        if (m == src) return make_pair(true, offset);
310                        auto dist = calculateEnumOffset(src, m);
311                        if (dist.first) {
312                                return make_pair(true, offset + dist.second);
313                        } else {
314                                offset += dist.second;
315                        }
316                }
317        }
318        return make_pair(false, offset);
319}
320\end{cfa}
321\caption{Compute Offset from Subtype Enumeration to a Supertype}
322\label{s:OffsetSubtypeSuperType}
323\end{figure}
324
325Figure~\ref{s:OffsetSubtypeSuperType} shows a minimum of @offset calculation@, written in \CC. CFAEnum represents \CFA enumeration
326which has a vector of variants of Enumerator or CFAEnum. Two CFAEnums are differentiable by their unquie name.
327The algorithm takes two CFAEnums as parameters @src@ and @dst@, with @src@ being type of expression the conversion applies on,
328and @dst@ being type that the expression cast into. The algorithm returns a pair of value: when @src@ is convertible to @dst@ (@src@ is a subtype of @dst@),
329it returns boolean true and the offset. Otherwise, it returns false and the size of @src@ (total number of enumerators in @src@). The offset between a type and itself is defined
330as 0.
331
332The algorithm iterates over members in @dst@ to find @src@. If a member is an enumerator of @dst@, the positions of all subsequent members
333increment by one. If the current member is @dst@, the function returns true indicating "found" and the accumulated offset. Otherwise, the algorithm recurse
334into the current CFAEnum @m@ and find out if the @src@ is convertible to @m@. The @src@ being convertible to the current member @m@ means @src@
335is 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
336@src@ in @m@. If @src@ is not a subtype of @m@, the loop continue but with offset shifted by the size of @m@. The procedure reaches the end
337of the loop proves @src@ is not convertible to @dst@. It returns size of @src@ in case it is in a recurse innvocation and size is needed for offset update.
338
339\section{Control Structures}
340
341Enumerators can be used in multiple contexts.
342In most programming languages, an enumerator is implicitly converted to its value (like a typed macro substitution).
343However, enumerator synonyms and typed enumerations make this implicit conversion to value incorrect in some contexts.
344In these contexts, a programmer's intuition assumes an implicit conversion to position.
345
346For 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.
347(For this discussion, ignore the fact that @case@ requires a compile-time constant.)
348\begin{cfa}[belowskip=0pt]
349enum Count { First, Second, Third, Fourth };
350Count e;
351\end{cfa}
352\begin{cquote}
353\setlength{\tabcolsep}{15pt}
354\noindent
355\begin{tabular}{@{}ll@{}}
356\begin{cfa}[aboveskip=0pt]
357
358choose( e ) {
359        case @First@: ...;
360        case @Second@: ...;
361        case @Third@: ...;
362        case @Fourth@: ...;
363}
364\end{cfa}
365&
366\begin{cfa}[aboveskip=0pt]
367// rewrite
368choose( @value@( e ) ) {
369        case @value@( First ): ...;
370        case @value@( Second ): ...;
371        case @value@( Third ): ...;
372        case @value@( Fourth ): ...;
373}
374\end{cfa}
375\end{tabular}
376\end{cquote}
377Here, 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.
378However, this implementation is fragile, \eg if the enumeration is changed to:
379\begin{cfa}
380enum Count { First, Second, Third @= First@, Fourth };
381\end{cfa}
382making @Third == First@ and @Fourth == Second@, causing a compilation error because of duplicate @case@ clauses.
383To better match with programmer intuition, \CFA toggles between value and position semantics depending on the language context.
384For conditional clauses and switch statements, \CFA uses the robust position implementation.
385\begin{cfa}
386if ( @posn@( e ) < posn( Third ) ) ...
387choose( @posn@( e ) ) {
388        case @posn@( First ): ...;
389        case @posn@( Second ): ...;
390        case @posn@( Third ): ...;
391        case @posn@( Fourth ): ...;
392}
393\end{cfa}
394
395\CFA provides a special form of for-control for enumerating through an enumeration, where the range is a type.
396\begin{cfa}
397for ( cx; @Count@ ) { sout | cx | nonl; } sout | nl;
398for ( cx; ~= Count ) { sout | cx | nonl; } sout | nl;
399for ( cx; -~= Count ) { sout | cx | nonl; } sout | nl;
400First Second Third Fourth
401First Second Third Fourth
402Fourth Third Second First
403\end{cfa}
404The 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.
405The prefix @+~=@ or @-~=@ iterate forward or backwards through the inclusive enumeration range, where no prefix defaults to @+~=@.
406
407C has an idiom for @if@ and loop predicates of comparing the predicate result ``not equal to 0''.
408\begin{cfa}
409if ( x + y /* != 0 */  ) ...
410while ( p /* != 0 */  ) ...
411\end{cfa}
412This 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.
413For example, such a conversion exists for all numerical types (integral and floating-point).
414It is possible to explicitly extend this idiom to any typed enumeration by overloading the @!=@ operator.
415\begin{cfa}
416bool ?!=?( Name n, zero_t ) { return n != Fred; }
417Name n = Mary;
418if ( n ) ... // result is true
419\end{cfa}
420Specialize meanings are also possible.
421\begin{cfa}
422enum(int) ErrorCode { Normal = 0, Slow = 1, Overheat = 1000, OutOfResource = 1001 };
423bool ?!=?( ErrorCode ec, zero_t ) { return ec >= Overheat; }
424ErrorCode code = ...;
425if ( code ) { problem(); }
426\end{cfa}
427
428
429\section{Dimension}
430
431\VRef{s:EnumeratorTyping} introduces the harmonizing problem between an enumeration and secondary information.
432When possible, using a typed enumeration for the secondary information is the best approach.
433However, there are times when combining these two types is not possible.
434For example, the secondary information might precede the enumeration and/or its type is needed directly to declare parameters of functions.
435In these cases, having secondary arrays of the enumeration size are necessary.
436
437To support some level of harmonizing in these cases, an array dimension can be defined using an enumerator type, and the enumerators used as subscripts.
438\begin{cfa}
439enum E1 { A, B, C, N }; // possibly predefined
440enum(int) E2 { A, B, C };
441float H1[N] = { [A] :$\footnotemark$ 3.4, [B] : 7.1, [C] : 0.01 }; // C
442float H2[@E2@] = { [A] : 3.4, [B] : 7.1, [C] : 0.01 }; // CFA
443\end{cfa}
444\footnotetext{C uses symbol \lstinline{'='} for designator initialization, but \CFA changes it to \lstinline{':'} because of problems with tuple syntax.}
445This approach is also necessary for a predefined typed enumeration (unchangeable), when additional secondary-information need to be added.
446
447The 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.
448This behaviour can be reverted by explicit overloading:
449\begin{cfa}
450float ?[?]( float * arr, E2 index ) { return arr[ value( index ) ]; }
451\end{cfa}
452When an enumeration type is being used as an array dimension, \CFA adds the enumeration type to the initializer's context.
453As a result, @H2@'s array destinators @A@, @B@ and @C@ are resolved unambiguously to type @E2@.
454(@H1@'s destinators are also resolved unambiguously to @E1@ because @E2@ has a @value@ cost.)
455
456
457\section{I/O}
458
459As 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.
460However, very few programming languages provide a mechanism to read in enumerator values.
461Even the @boolean@ type in many languages does not have a mechanism for input using the enumerators @true@ or @false@.
462\VRef[Figure]{f:EnumerationI/O} show \CFA enumeration input based on the enumerator labels.
463When the enumerator labels are packed together in the input stream, the input algorithm scans for the longest matching string.
464For 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.
465
466\begin{figure}
467\begin{cquote}
468\setlength{\tabcolsep}{15pt}
469\begin{tabular}{@{}ll@{}}
470\begin{cfa}
471int main() {
472        enum(int ) E { BBB = 3, AAA, AA, AB, B };
473        E e;
474
475        for () {
476                try {
477                        @sin | e@;
478                } catch( missing_data * ) {
479                        sout | "missing data";
480                        continue; // try again
481                }
482          if ( eof( sin ) ) break;
483                sout | e | "= " | value( e );
484        }
485}
486\end{cfa}
487&
488\begin{cfa}
489$\rm input$
490BBBABAAAAB
491BBB AAA AA AB B
492
493$\rm output$
494BBB = 3
495AB = 6
496AAA = 4
497AB = 6
498BBB = 3
499AAA = 4
500AA = 5
501AB = 6
502B = 7
503
504\end{cfa}
505\end{tabular}
506\end{cquote}
507\caption{Enumeration I/O}
508\label{f:EnumerationI/O}
509\end{figure}
510
511
512\section{Planet Example}
513
514\VRef[Figure]{f:PlanetExample} shows an archetypal enumeration example illustrating most of the \CFA enumeration features.
515@Planet@ is an enumeration of type @MR@.
516Each planet enumerator is initialized to a specific mass/radius, @MR@, value.
517The unnamed enumeration provides the gravitational-constant enumerator @G@.
518Function @surfaceGravity@ uses the @with@ clause to remove @p@ qualification from fields @mass@ and @radius@.
519The 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@.
520The resulting random orbital-body is used in a @choose@ statement.
521The enumerators in the @case@ clause use the enumerator position for testing.
522The prints use @label@ to print an enumerator's name.
523Finally, a loop enumerates through the planets computing the weight on each planet for a given earth mass.
524The print statement does an equality comparison with an enumeration variable and enumerator (@p == MOON@).
525
526\begin{figure}
527\small
528\begin{cfa}
529struct MR { double mass, radius; };                     $\C[3.5in]{// planet definition}$
530enum( @MR@ ) Planet {                                           $\C{// typed enumeration}$
531        //                      mass (kg)   radius (km)
532        MERCURY = { 0.330_E24, 2.4397_E6 },
533        VENUS      = { 4.869_E24, 6.0518_E6 },
534        EARTH       = { 5.976_E24, 6.3781_E6 },
535        MOON        = { 7.346_E22, 1.7380_E6 }, $\C{// not a planet}$
536        MARS         = { 0.642_E24, 3.3972_E6 },
537        JUPITER    = { 1898._E24, 71.492_E6 },
538        SATURN     = { 568.8_E24, 60.268_E6 },
539        URANUS    = { 86.86_E24, 25.559_E6 },
540        NEPTUNE  = { 102.4_E24, 24.746_E6 },
541        PLUTO       = { 1.303_E22, 1.1880_E6 }, $\C{// not a planet}$
542};
543enum( double ) { G = 6.6743_E-11 };                     $\C{// universal gravitational constant (m3 kg-1 s-2)}$
544static double surfaceGravity( Planet p ) @with( p )@ {
545        return G * mass / ( radius @\@ 2 );             $\C{// no qualification, exponentiation}$
546}
547static double surfaceWeight( Planet p, double otherMass ) {
548        return otherMass * surfaceGravity( p );
549}
550int main( int argc, char * argv[] ) {
551        if ( argc != 2 ) @exit@ | "Usage: " | argv[0] | "earth-weight";  // terminate program
552        double earthWeight = convert( argv[1] );
553        double earthMass = earthWeight / surfaceGravity( EARTH );
554        Planet rp = @fromInt@( prng( @countof@( Planet ) ) ); $\C{// select random orbiting body}$
555        @choose( rp )@ {                                                $\C{// implicit breaks}$
556          case MERCURY, VENUS, EARTH, MARS:
557                sout | @rp@ | "is a rocky planet";
558          case JUPITER, SATURN, URANUS, NEPTUNE:
559                sout | rp | "is a gas-giant planet";
560          default:
561                sout | rp | "is not a planet";
562        }
563        for ( @p; Planet@ ) {                                   $\C{// enumerate}\CRT$
564                sout | "Your weight on" | ( @p == MOON@ ? "the" : " " ) | p
565                           | "is" | wd( 1,1,  surfaceWeight( p, earthMass ) ) | "kg";
566        }
567}
568$\$$ planet 100
569JUPITER is a gas-giant planet
570Your weight on MERCURY is 37.7 kg
571Your weight on VENUS is 90.5 kg
572Your weight on EARTH is 100.0 kg
573Your weight on the MOON is 16.6 kg
574Your weight on MARS is 37.9 kg
575Your weight on JUPITER is 252.8 kg
576Your weight on SATURN is 106.6 kg
577Your weight on URANUS is 90.5 kg
578Your weight on NEPTUNE is 113.8 kg
579Your weight on PLUTO is 6.3 kg
580\end{cfa}
581\caption{Planet Example}
582\label{f:PlanetExample}
583\end{figure}
Note: See TracBrowser for help on using the repository browser.