source: doc/theses/jiada_liang_MMath/CFAenum.tex @ b59c21a

Last change on this file since b59c21a was 1697c40, checked in by JiadaL <j82liang@…>, 4 months ago

merge local changes

  • Property mode set to 100644
File size: 27.5 KB
Line 
1\chapter{\CFA Enumeration}
2
3% \CFA supports C enumeration using the same syntax and semantics for backwards compatibility.
4% \CFA also extends C-Style enumeration by adding a number of new features that bring enumerations inline with other modern programming languages.
5% Any enumeration extensions must be intuitive to C programmers both in syntax and semantics.
6% The following sections detail all of my new contributions to enumerations in \CFA.
7\CFA extends the enumeration declaration by parameterizing with a type (like a generic type).
8
9
10\begin{cfa}[caption={CFA Enum},captionpos=b,label={l:CFAEnum}]
11$\it enum$-specifier:
12        enum @(type-specifier$\(_{opt}\)$)@ identifier$\(_{opt}\)$ { cfa-enumerator-list }
13        enum @(type-specifier$\(_{opt}\)$)@ identifier$\(_{opt}\)$ { cfa-enumerator-list , }
14        enum @(type-specifier$\(_{opt}\)$)@ identifier
15cfa-enumerator-list:
16        cfa-enumerator
17        cfa-enumerator, cfa-enumerator-list
18cfa-enumerator:
19        enumeration-constant
20        $\it inline$ identifier
21        enumeration-constant = expression
22\end{cfa}
23
24A \newterm{\CFA enumeration}, or \newterm{\CFA enum}, has an optional type declaration in the bracket next to the @enum@ keyword.
25Without optional type declarations, the syntax defines \newterm{opaque enums}.
26Otherwise, \CFA enum with type declaration are \newterm{typed enums}.
27
28\section{Opaque Enum}
29\label{s:OpaqueEnum}
30Opaque enum is a special CFA enumeration type, where the internal representation is chosen by the compiler and hidden from users.
31Compared C enum, opaque enums are more restrictive in terms of typing, and cannot be implicitly converted to integers.
32Enumerators of opaque enum cannot have initializer. Declaring initializer in the body of opaque enum results in a compile time error.
33\begin{cfa}
34enum@()@ Planets { MERCURY, VENUS, EARTH, MARS, JUPITER, SATURN, URANUS, NEPTUNE };
35
36Planet p = URANUS;
37int i = VENUS; @// Error, VENUS cannot be converted into an integral type
38\end{cfa}
39% Each opaque enum has two @attributes@: @position@ and @label@. \CFA auto-generates @attribute functions@ @posn()@ and @label()@ for every \CFA enum to returns the respective attributes.
40Opaque enumerations have two defining properties: @label@ (name) and @order@ (position), exposed to users by predefined @attribute functions@ , with the following signatures:
41\begin{cfa}
42forall( E ) {
43        unsigned posn(E e);
44        const char * s label(E e);
45};
46\end{cfa}
47With polymorphic type parameter E being substituted by enumeration types such as @Planet@.
48
49\begin{cfa}
50unsigned i = posn(VENUS); // 1
51char * s = label(MARS); // "MARS"
52\end{cfa}
53
54\subsection{Representation}
55The underlying representation of \CFA enumeration object is its order, saved as an integral type. Therefore, the size of a \CFA enumeration is consistent with C enumeration.
56Attribute function @posn@ performs type substitution on an expression from \CFA type to integral type.
57Names of enumerators are stored in a global data structure, with @label@ maps \CFA enumeration object to corresponding data.
58
59\section{Typed Enum}
60\label{s:EnumeratorTyping}
61
62\CFA extends the enumeration declaration by parameterizing with a type (like a generic type), allowing enumerators to be assigned any values from the declared type.
63Figure~\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.
64Note, the synonyms @Liz@ and @Beth@ in the last declaration.
65Because enumerators are constants, the enumeration type is implicitly @const@, so all the enumerator types in Figure~\ref{f:EumeratorTyping} are logically rewritten with @const@.
66
67\begin{figure}
68\begin{cfa}
69// integral
70        enum( @char@ ) Currency { Dollar = '$\textdollar$', Cent = '$\textcent$', Yen = '$\textyen$', Pound = '$\textsterling$', Euro = 'E' };
71        enum( @signed char@ ) srgb { Red = -1, Green = 0, Blue = 1 };
72        enum( @long long int@ ) BigNum { X = 123_456_789_012_345,  Y = 345_012_789_456_123 };
73// non-integral
74        enum( @double@ ) Math { PI_2 = 1.570796, PI = 3.141597, E = 2.718282 };
75        enum( @_Complex@ ) Plane { X = 1.5+3.4i, Y = 7+3i, Z = 0+0.5i };
76// pointer
77        enum( @char *@ ) Name { Fred = "FRED", Mary = "MARY", Jane = "JANE" };
78        int i, j, k;
79        enum( @int *@ ) ptr { I = &i,  J = &j,  K = &k };
80        enum( @int &@ ) ref { I = i,   J = j,   K = k };
81// tuple
82        enum( @[int, int]@ ) { T = [ 1, 2 ] }; $\C{// new \CFA type}$
83// function
84        void f() {...}   void g() {...}
85        enum( @void (*)()@ ) funs { F = f,  G = g };
86// aggregate
87        struct Person { char * name; int age, height; };
88@***@enum( @Person@ ) friends { @Liz@ = { "ELIZABETH", 22, 170 }, @Beth@ = Liz,
89                                                                        Jon = { "JONATHAN", 35, 190 } };
90\end{cfa}
91\caption{Enumerator Typing}
92\label{f:EumeratorTyping}
93\end{figure}
94
95An advantage of the typed enumerations is eliminating the \emph{harmonizing} problem between an enumeration and companion data \see{\VRef{s:Usage}}:
96\begin{cfa}
97enum( char * ) integral_types {
98        chr = "char", schar = "signed char", uschar = "unsigned char",
99        sshort = "signed short int", ushort = "unsigned short int",
100        sint = "signed int", usint = "unsigned int",
101        ...
102};
103\end{cfa}
104Note, 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.
105
106While the enumeration type can be any C aggregate, the aggregate's \CFA constructors are not used to evaluate an enumerator's value.
107\CFA enumeration constants are compile-time values (static);
108calling constructors happens at runtime (dynamic).
109
110@value@ is an @attribute@ that defined for typed enum along with position and label. @values@ of a typed enum are stored in a global array of declared typed, initialized with
111value of enumerator initializers. @value()@ functions maps an enum to an elements of the array.
112
113
114\subsection{Value Conversion}
115C has an implicit type conversion from an enumerator to its base type @int@.
116Correspondingly, \CFA has an implicit conversion from a typed enumerator to its base type, allowing typed enumeration to be seemlyless used as
117a value of its base type.
118\begin{cfa}
119char currency = Dollar;
120void foo( char * );
121foo( Fred );
122\end{cfa}
123
124% During the resolution of expression e with \CFA enumeration type, \CFA adds @value(e)@ as an additional candidate with an extra \newterm{value} cost.
125% For expression @char currency = Dollar@, the is no defined conversion from Dollar (\CFA enumeration) type to basic type and the conversion cost is @infinite@,
126% thus the only valid candidate is @value(Dollar)@.
127The implicit conversion induces a \newterm{value cost}, which is a new category in \CFA's conversion cost model to disambiguate function overloading over for both \CFA enumeration and its base type.
128\begin{cfa}
129void baz( char ch );            $\C{// (1)}$
130void baz( Currency cu );        $\C{// (2)}$
131
132baz( Cent );
133\end{cfa}
134While both baz are applicable to \CFA enumeration, using Cent as a char in @candiate (1)@ comes with a @value@ cost,
135while @candidate (2)@ has @zero@ cost. \CFA always choose a overloaded candidate implemented for a \CFA enumeration itself over a candidate applies on a base type.
136
137Value cost is defined to be a more significant factor than an @unsafe@ but weight less than @poly@.
138With @value@ being an additional category, the current \CFA conversion cost is a 8-tuple:
139@@(unsafe, value, poly, safe, sign, vars, specialization, reference)@@.
140
141\begin{cfa}
142void bar(int);
143enum(int) Month !{
144        January=31, February=29, March=31, April=30, May=31, June-30,
145        July=31, August=31, September=30, October=31, November=30, December=31
146};
147
148Month a = Februrary;    $\C{// (1), with cost (0, 1, 0, 0, 0, 0, 0, 0)}$
149double a = 5.5;                 $\C{// (2), with cost (1, 0, 0, 0, 0, 0, 0, 0)}$
150
151bar(a);
152\end{cfa}
153In the previous example, candidate (1) has an value cost to parameter type int, with is lower than (2) as an unsafe conversion from double to int.
154\CFA chooses value cost over unsafe cost and therefore @a@ of @bar(a)@ is resolved as an @Month@.
155
156\begin{cfa}
157forall(T | @CfaEnum(T)@) void bar(T);
158
159bar(a);                                 $\C{// (3), with cost (0, 0, 1, 0, 0, 0, 0, 0)}$ 
160\end{cfa}
161% @Value@ is designed to be less significant than @poly@ to allow function being generic over \CFA enumeration (see ~\ref{c:trait}).
162Being 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}.
163@Value@ is a being a more significant cost than @poly@ implies if a overloaeded function defined for @CfaEnum@ (and other generic type), \CFA always
164try to resolve it as a @CfaEnum@, rather to insert a @value@ conversion.
165
166\subsection{Explicit Conversion}
167Explicit conversion is allowed on \CFA enumeration to an integral type, in which case \CFA converts \CFA enumeration into its underlying representation,
168which is its @position@.
169
170\section{Auto Initialization}
171
172C auto-initialization works for the integral type @int@ with constant expressions.
173\begin{cfa}
174enum Alphabet ! {
175        A = 'A', B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
176        a = 'a', b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
177};
178\end{cfa}
179The complexity of the constant expression depends on the level of runtime 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.
180
181% The notion of auto-initialization is generalized in \CFA enumertation E with base type T in the following way:
182When an enumerator @e@ does not have a initializer, if @e@ has enumeration type @E@ with base type @T@, \CFA auto-initialize @e@ with the following scheme:
183\begin{enumerate}
184% \item Enumerator e is the first enumerator of \CFA enumeration E with base type T. If e declares no no initializer, e is auto-initialized by the $zero\_t$ constructor of T.
185\item if e is first enumerator, e is initialized with T's @zero_t@.
186\item otherwise, if d is the enumerator defined just before e, with d has has been initialized with expression @l@ (@l@ can also be an auto-generated), e is initialized with @l++@.
187% \CFA reports a compile time error if T has no $zero\_t$ constructor.
188% Enumerator e is an enumerator of base-type T enumeration E that position i, where $i \neq 0$. And d is the enumerator with position @i-1@, e is auto-initialized with
189% the result of @value(d)++@. If operator @?++@ is not defined for type T, \CFA reports a compile time error.
190
191% Unfortunately, auto-initialization is not implemented because \CFA is only a transpiler, relying on generated C code to perform the detail work.
192% C does not have the equivalent of \CC \lstinline[language={[GNU]C++}]{constexpr}, and it is currently beyond the scope of the \CFA project to implement a complex runtime interpreter in the transpiler.
193% Nevertheless, the necessary language concepts exist to support this feature.
194\end{enumerate}
195while @?++( T )@ can be explicitly overloaded or implicitly overloaded with properly defined @one_t@ and @?+?(T, T)@.
196
197Unfortunately, auto-initialization with only constant expression is not enforced because \CFA is only a transpiler, relying on generated C code to perform the detail work.
198C does not have the equivalent of \CC \lstinline[language={[GNU]C++}]{constexpr}, and it is currently beyond the scope of the \CFA project to implement a complex runtime interpreter in the transpiler.
199Nevertheless, the necessary language concepts exist to support this feature.
200
201\section{Enumeration Inheritance}
202
203\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).
204Containment is norminative: an enumeration inherits all enumerators from another enumeration by declaring an @inline statement@ in its enumerator lists.
205\begin{cfa}
206enum( char * ) Names { /* as above */ };
207enum( char * ) Names2 { @inline Names@, Jack = "JACK", Jill = "JILL" };
208enum( char * ) Names3 { @inline Names2@, Sue = "SUE", Tom = "TOM" };
209\end{cfa}
210In the preceding example, @Names2@ is defined with five enumerators, three of which are from @Name@ through containment, and two are self-declared.
211@Names3@ inherits all five members from @Names2@ and declare two additional enumerators.
212
213Enumeration inheritance forms a subset relationship. Specifically, the inheritance relationship for the example above is:
214\begin{cfa}
215Names $\(\subset\)$ Names2 $\(\subset\)$ Names3 $\C{// enum type of Names}$
216\end{cfa}
217
218Inheritance can be nested, and a \CFA enumeration can inline enumerators from more than one \CFA enumeration, forming a tree-like hierarchy.
219However, 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
220from 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
221common supertype (the diamond problem), since such would unavoidably introduce duplicate enumerator labels.
222
223
224% Enumeration @Name2@ inherits all the enumerators and their values from enumeration @Names@ by containment, and a @Names@ enumeration is a @subtype@ of enumeration @Name2@.
225% Note, that enumerators must be unique in inheritance but enumerator values may be repeated.
226
227
228
229% The enumeration type for the inheriting type must be the same as the inherited type;
230% hence the enumeration type may be omitted for the inheriting enumeration and it is inferred from the inherited enumeration, as for @Name3@.
231% When inheriting from integral types, automatic numbering may be used, so the inheritance placement left to right is important.
232
233
234% The enumeration base for the subtype must be the same as the super type.
235The base type must be consistent between subtype and supertype.
236When an enumeration inherits enumerators from another enumeration, it copies the enumerators' @value@ and @label@, even if the @value@ was auto initialized. However, the @position@ as the underlying
237representation will be the order of the enumerator in new enumeration.
238% new enumeration @N@ copies all enumerators from @O@, including those @O@ obtains through inheritance. Enumerators inherited from @O@
239% keeps same @label@ and @value@, but @position@ may shift to the right if other enumerators or inline enumeration declared in prior of @inline A@.
240% hence the enumeration type may be omitted for the inheriting enumeration and it is inferred from the inherited enumeration, as for @Name3@.
241% When inheriting from integral types, automatic numbering may be used, so the inheritance placement left to right is important.
242
243\begin{cfa}
244enum() Phynchocephalia { Tuatara };
245enum() Squamata { Snake, Lizard };
246enum() Lepidosauromorpha { inline Phynchocephalia, inline Squamata, Kuehneosauridae };
247\end{cfa}
248Snake, for example, has the position 0 in Squamata, but 1 in Lepidosauromorpha as Tuatara inherited from Phynchocephalia is position 0 in Lepidosauromorpha.
249
250A subtype enumeration can be casted, or implicitly converted into its supertype, with a @safe@ cost.
251\begin{cfa}
252enum Squamata squamata_lizard = Lizard;
253posn(quamata_lizard); // 1
254enum Lepidosauromorpha lepidosauromorpha_lizard = squamata_lizard;
255posn(lepidosauromorpha_lizard); // 2
256void foo( Lepidosauromorpha l );
257foo( squamata_lizard );
258posn( (Lepidosauromorpha) squamata_lizard ); // 2
259
260Lepidosauromorpha s = Snake;
261\end{cfa}
262The last expression in the preceding example is unambiguous. While both @Squamata.Snake@ and @Lepidosauromorpha.Snake@ are valid candidate, @Squamata.Snake@ has
263an associated safe cost and \CFA select the zero cost candidate @Lepidosauromorpha.Snake@.
264
265As discussed in \VRef{s:OpaqueEnum}, \CFA chooses position as a representation of \CFA enum. Conversion involves both change of typing
266and possibly @position@.
267
268When converting a subtype to a supertype, the position can only be a larger value. The difference between the position in subtype and in supertype is an "offset".
269\CFA runs a the following algorithm to determine the offset for an enumerator to a super type.
270% In a summary, \CFA loops over members (include enumerators and inline enums) of the supertype.
271% If the member is the matching enumerator, the algorithm returns its position.
272% If the member is a inline enumeration, the algorithm trys to find the enumerator in the inline enumeration. If success, it returns the position of enumerator in the inline enumeration, plus
273% the position in the current enumeration. Otherwises, it increase the offset by the size of inline enumeration.
274
275\begin{cfa}
276struct Enumerator;
277struct CFAEnum {
278        vector<variant<CFAEnum, Enumerator>> members;
279};
280pair<bool, int> calculateEnumOffset( CFAEnum dst, Enumerator e ) {
281        int offset = 0;
282        for( auto v: dst.members ) {
283                if ( v.holds_alternative<Enumerator>() ) {
284                        auto m = v.get<Enumerator>();
285                        if ( m == e ) return make_pair( true, 0 );
286                        offset++;
287                } else {
288                        auto p = calculateEnumOffset( v, e );
289                        if ( p.first ) return make_pair( true, offset + p.second );
290                        offset += p.second;
291                }
292        }
293        return make_pair( false, offset );
294}
295\end{cfa}
296
297% \begin{cfa}
298% Names fred = Name.Fred;
299% (Names2) fred; (Names3) fred; (Name3) Names.Jack;  $\C{// cast to super type}$
300% Names2 fred2 = fred; Names3 fred3 = fred2; $\C{// assign to super type}$
301% \end{cfa}
302For the given function prototypes, the following calls are valid.
303\begin{cquote}
304\begin{tabular}{ll}
305\begin{cfa}
306void f( Names );
307void g( Names2 );
308void h( Names3 );
309void j( const char * );
310\end{cfa}
311&
312\begin{cfa}
313f( Fred );
314g( Fred );   g( Jill );
315h( Fred );   h( Jill );   h( Sue );
316j( Fred );    j( Jill );    j( Sue );    j( "WILL" );
317\end{cfa}
318\end{tabular}
319\end{cquote}
320Note, 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.
321
322\section{Enumerator Control Structures}
323
324Enumerators can be used in multiple contexts.
325In most programming languages, an enumerator is implicitly converted to its value (like a typed macro substitution).
326However, enumerator synonyms and typed enumerations make this implicit conversion to value incorrect in some contexts.
327In these contexts, a programmer's intuition assumes an implicit conversion to position.
328
329For 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.
330(For this discussion, ignore the fact that @case@ requires a compile-time constant.)
331\begin{cfa}[belowskip=0pt]
332enum Count { First, Second, Third, Fourth };
333Count e;
334\end{cfa}
335\begin{cquote}
336\setlength{\tabcolsep}{15pt}
337\noindent
338\begin{tabular}{@{}ll@{}}
339\begin{cfa}[aboveskip=0pt]
340
341choose( e ) {
342        case @First@: ...;
343        case @Second@: ...;
344        case @Third@: ...;
345        case @Fourth@: ...;
346}
347\end{cfa}
348&
349\begin{cfa}[aboveskip=0pt]
350// rewrite
351choose( @value@( e ) ) {
352        case @value@( First ): ...;
353        case @value@( Second ): ...;
354        case @value@( Third ): ...;
355        case @value@( Fourth ): ...;
356}
357\end{cfa}
358\end{tabular}
359\end{cquote}
360Here, 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.
361However, this implementation is fragile, \eg if the enumeration is changed to:
362\begin{cfa}
363enum Count { First, Second, Third @= First@, Fourth };
364\end{cfa}
365making @Third == First@ and @Fourth == Second@, causing a compilation error because of duplicate @case@ clauses.
366To better match with programmer intuition, \CFA toggles between value and position semantics depending on the language context.
367For conditional clauses and switch statements, \CFA uses the robust position implementation.
368\begin{cfa}
369if ( @posn@( e ) < posn( Third ) ) ...
370choose( @posn@( e ) ) {
371        case @posn@( First ): ...;
372        case @posn@( Second ): ...;
373        case @posn@( Third ): ...;
374        case @posn@( Fourth ): ...;
375}
376\end{cfa}
377
378\CFA provides a special form of for-control for enumerating through an enumeration, where the range is a type.
379\begin{cfa}
380for ( cx; @Count@ ) { sout | cx | nonl; } sout | nl;
381for ( cx; +~= Count ) { sout | cx | nonl; } sout | nl;
382for ( cx; -~= Count ) { sout | cx | nonl; } sout | nl;
383First Second Third Fourth
384First Second Third Fourth
385Fourth Third Second First
386\end{cfa}
387The 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.
388The prefix @+~=@ or @-~=@ iterate forward or backwards through the inclusive enumeration range, where no prefix defaults to @+~=@.
389
390C has an idiom for @if@ and loop predicates of comparing the predicate result ``not equal to 0''.
391\begin{cfa}
392if ( x + y /* != 0 */ ) ...
393while ( p /* != 0 */ ) ...
394\end{cfa}
395This 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.
396For example, such a conversion exists for all numerical types (integral and floating-point).
397It is possible to explicitly extend this idiom to any typed enumeration by overloading the @!=@ operator.
398\begin{cfa}
399bool ?!=?( Name n, zero_t ) { return n != Fred; }
400Name n = Mary;
401if ( n ) ... // result is true
402\end{cfa}
403Specialize meanings are also possible.
404\begin{cfa}
405enum(int) ErrorCode { Normal = 0, Slow = 1, Overheat = 1000, OutOfResource = 1001 };
406bool ?!=?( ErrorCode ec, zero_t ) { return ec >= Overheat; }
407ErrorCode code = ...;
408if ( code ) { problem(); }
409\end{cfa}
410
411
412\section{Enumeration Dimension}
413
414\VRef{s:EnumeratorTyping} introduced the harmonizing problem between an enumeration and secondary information.
415When possible, using a typed enumeration for the secondary information is the best approach.
416However, there are times when combining these two types is not possible.
417For example, the secondary information might precede the enumeration and/or its type is needed directly to declare parameters of functions.
418In these cases, having secondary arrays of the enumeration size are necessary.
419
420To support some level of harmonizing in these cases, an array dimension can be defined using an enumerator type, and the enumerators used as subscripts.
421\begin{cfa}
422enum E1 { A, B, C, N }; // possibly predefined
423enum(int) E2 { A, B, C };
424float H1[N] = { [A] :$\footnote{Note, C uses the symbol, @'='@ for designator initialization, but \CFA had to change to @':'@ because of problems with tuple syntax.}$ 3.4, [B] : 7.1, [C] : 0.01 }; // C
425float H2[@E2@] = { [A] : 3.4, [B] : 7.1, [C] : 0.01 }; // CFA
426\end{cfa}
427This approach is also necessary for a predefined typed enumeration (unchangeable), when additional secondary-information need to be added.
428
429The array subscript operator, namely ?[?], has been overloaded so that when a CFA enumerator is used as an array index, it implicitly converts
430to its position over value to sustain data hormonization. User can revert the behaviour by:
431\begin{cfa}
432float ?[?](float * arr, E2 index) { return arr[value(index)]; }
433\end{cfa}
434When an enumeration type is being used as an array dimension, \CFA add the enumeration type to initializer's context. As a result,
435@H2@'s array destinators @A@, @B@ and @C@ are resolved unambiguously to type E2. (H1's destinators are also resolved unambiguously to
436E1 because E2 has a @value@ cost to @int@).
437
438\section{Enumeration I/O}
439
440As 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.
441However, very few programming languages provide a mechanism to read in enumerator values.
442Even the @boolean@ type in many languages does not have a mechanism for input using the enumerators @true@ or @false@.
443\VRef[Figure]{f:EnumerationI/O} show \CFA enumeration input based on the enumerator labels.
444When the enumerator labels are packed together in the input stream, the input algorithm scans for the longest matching string.
445For basic types in \CFA, the constants use to initialize a variable in a program are available to initialize a variable using input, where strings constants can be quoted or unquoted.
446
447\begin{figure}
448\begin{cquote}
449\setlength{\tabcolsep}{15pt}
450\begin{tabular}{@{}ll@{}}
451\begin{cfa}
452int main() {
453        enum(int ) E { BBB = 3, AAA, AA, AB, B };
454        E e;
455
456        for () {
457                try {
458                        @sin | e@;
459                } catch( missing_data * ) {
460                        sout | "missing data";
461                        continue; // try again
462                }
463          if ( eof( sin ) ) break;
464                sout | e | "= " | value( e );
465        }
466}
467\end{cfa}
468&
469\begin{cfa}
470$\rm input$
471BBBABAAAAB
472BBB AAA AA AB B
473
474$\rm output$
475BBB = 3
476AB = 6
477AAA = 4
478AB = 6
479BBB = 3
480AAA = 4
481AA = 5
482AB = 6
483B = 7
484
485\end{cfa}
486\end{tabular}
487\end{cquote}
488\caption{Enumeration I/O}
489\label{f:EnumerationI/O}
490\end{figure}
491
492
493
494\section{Planet Example}
495
496\VRef[Figure]{f:PlanetExample} shows an archetypal enumeration example illustrating most of the \CFA enumeration features.
497@Planet@ is an enumeration of type @MR@.
498Each planet enumerator is initialized to a specific mass/radius, @MR@, value.
499The unnamed enumeration provides the gravitational-constant enumerator @G@.
500Function @surfaceGravity@ uses the @with@ clause to remove @p@ qualification from fields @mass@ and @radius@.
501The 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@.
502The resulting random orbital-body is used in a @choose@ statement.
503The enumerators in the @case@ clause use the enumerator position for testing.
504The prints use @label@ to print an enumerator's name.
505Finally, a loop enumerates through the planets computing the weight on each planet for a given earth mass.
506The print statement does an equality comparison with an enumeration variable and enumerator (@p == MOON@).
507
508\begin{figure}
509\small
510\begin{cfa}
511struct MR { double mass, radius; };                     $\C{// planet definition}$
512enum( @MR@ ) Planet {                                           $\C{// typed enumeration}$
513        //                      mass (kg)   radius (km)
514        MERCURY = { 0.330_E24, 2.4397_E6 },
515        VENUS      = { 4.869_E24, 6.0518_E6 },
516        EARTH       = { 5.976_E24, 6.3781_E6 },
517        MOON        = { 7.346_E22, 1.7380_E6 }, $\C{// not a planet}$
518        MARS         = { 0.642_E24, 3.3972_E6 },
519        JUPITER    = { 1898._E24, 71.492_E6 },
520        SATURN     = { 568.8_E24, 60.268_E6 },
521        URANUS    = { 86.86_E24, 25.559_E6 },
522        NEPTUNE  = { 102.4_E24, 24.746_E6 },
523        PLUTO       = { 1.303_E22, 1.1880_E6 }, $\C{// not a planet}$
524};
525enum( double ) { G = 6.6743_E-11 };                     $\C{// universal gravitational constant (m3 kg-1 s-2)}$
526static double surfaceGravity( Planet p ) @with( p )@ {
527        return G * mass / ( radius @\@ 2 );             $\C{// no qualification, exponentiation}$
528}
529static double surfaceWeight( Planet p, double otherMass ) {
530        return otherMass * surfaceGravity( p );
531}
532int main( int argc, char * argv[] ) {
533        if ( argc != 2 ) @exit@ | "Usage: " | argv[0] | "earth-weight";  // terminate program
534        double earthWeight = convert( argv[1] );
535        double earthMass = earthWeight / surfaceGravity( EARTH );
536        Planet rp = @fromInt@( prng( @countof@( Planet ) ) ); $\C{// select random orbiting body}$
537        @choose( rp )@ {                                                $\C{// implicit breaks}$
538          case MERCURY, VENUS, EARTH, MARS:
539                sout | @rp@ | "is a rocky planet";
540          case JUPITER, SATURN, URANUS, NEPTUNE:
541                sout | rp | "is a gas-giant planet";
542          default:
543                sout | rp | "is not a planet";
544        }
545        for ( @p; Planet@ ) {                                   $\C{// enumerate}$
546                sout | "Your weight on" | ( @p == MOON@ ? "the" : " " ) | p
547                           | "is" | wd( 1,1,  surfaceWeight( p, earthMass ) ) | "kg";
548        }
549}
550$\$$ planet 100
551JUPITER is a gas-giant planet
552Your weight on MERCURY is 37.7 kg
553Your weight on VENUS is 90.5 kg
554Your weight on EARTH is 100.0 kg
555Your weight on the MOON is 16.6 kg
556Your weight on MARS is 37.9 kg
557Your weight on JUPITER is 252.8 kg
558Your weight on SATURN is 106.6 kg
559Your weight on URANUS is 90.5 kg
560Your weight on NEPTUNE is 113.8 kg
561Your weight on PLUTO is 6.3 kg
562\end{cfa}
563\caption{Planet Example}
564\label{f:PlanetExample}
565\end{figure}
Note: See TracBrowser for help on using the repository browser.