[a57ad8a] | 1 | \chapter{C Enumeration in \CFA}
|
---|
[dd78dbc] | 2 |
|
---|
[94643698] | 3 | \CFA supports legacy C enumeration using the same syntax for backwards compatibility.
|
---|
[a57ad8a] | 4 | A C-style enumeration in \CFA is called a \newterm{C Enum}.
|
---|
| 5 | The semantics of the C Enum is mostly consistent with C with some restrictions.
|
---|
[94643698] | 6 | The following sections detail all of my new contributions to enumerations in C.
|
---|
[a57ad8a] | 7 |
|
---|
[dd78dbc] | 8 |
|
---|
[0c51c8b4] | 9 | \section{Visibility}
|
---|
| 10 | \label{s:CVisibility}
|
---|
[dd78dbc] | 11 |
|
---|
| 12 | In C, unscoped enumerators present a \newterm{naming problem} when multiple enumeration types appear in the same scope with duplicate enumerator names.
|
---|
[a57ad8a] | 13 | \begin{cfa}
|
---|
| 14 | enum E1 { First, Second, Third, Fourth };
|
---|
| 15 | enum E2 { @Fourth@, @Third@, @Second@, @First@ }; $\C{// same enumerator names}$
|
---|
| 16 | \end{cfa}
|
---|
[dd78dbc] | 17 | There is no mechanism in C to resolve these naming conflicts other than renaming one of the duplicates, which may be impossible if the conflict comes from system include files.
|
---|
| 18 |
|
---|
| 19 | The \CFA type-system allows extensive overloading, including enumerators.
|
---|
[a57ad8a] | 20 | Hence, most ambiguities among C enumerators are implicitly resolved by the \CFA type system, possibly without any programmer knowledge of the conflict.
|
---|
| 21 | In addition, C Enum qualification is added, exactly like aggregate field-qualification, to disambiguate.
|
---|
| 22 | \VRef[Figure]{f:EnumeratorVisibility} shows how resolution, qualification, and casting are used to disambiguate situations for enumerations @E1@ and @E2@.
|
---|
[dd78dbc] | 23 |
|
---|
| 24 | \begin{figure}
|
---|
| 25 | \begin{cfa}
|
---|
[c141c09] | 26 | E1 f() { return Third; } $\C{// overload functions with different return types}$
|
---|
[dd78dbc] | 27 | E2 f() { return Fourth; }
|
---|
| 28 | void g( E1 e );
|
---|
| 29 | void h( E2 e );
|
---|
| 30 | void foo() { $\C{// different resolutions and dealing with ambiguities}$
|
---|
| 31 | E1 e1 = First; E2 e2 = First; $\C{// initialization}$
|
---|
| 32 | e1 = Second; e2 = Second; $\C{// assignment}$
|
---|
| 33 | e1 = f(); e2 = f(); $\C{// function return}$
|
---|
| 34 | g( First ); h( First ); $\C{// function argument}$
|
---|
| 35 | int i = @E1.@First + @E2.@First; $\C{// disambiguate with qualification}$
|
---|
| 36 | int j = @(E1)@First + @(E2)@First; $\C{// disambiguate with cast}$
|
---|
| 37 | }
|
---|
| 38 | \end{cfa}
|
---|
| 39 | \caption{Enumerator Visibility and Disambiguating}
|
---|
| 40 | \label{f:EnumeratorVisibility}
|
---|
| 41 | \end{figure}
|
---|
| 42 |
|
---|
| 43 |
|
---|
[0c51c8b4] | 44 | \section{Scoping}
|
---|
[dd78dbc] | 45 |
|
---|
[a57ad8a] | 46 | A C Enum can be scoped, using @'!'@, so the enumerator constants are not projected into the enclosing scope.
|
---|
[dd78dbc] | 47 | \begin{cfa}
|
---|
| 48 | enum Week @!@ { Mon, Tue, Wed, Thu = 10, Fri, Sat, Sun };
|
---|
| 49 | enum RGB @!@ { Red, Green, Blue };
|
---|
| 50 | \end{cfa}
|
---|
| 51 | Now the enumerators \emph{must} be qualified with the associated enumeration type.
|
---|
| 52 | \begin{cfa}
|
---|
| 53 | Week week = @Week.@Mon;
|
---|
| 54 | week = @Week.@Sat;
|
---|
| 55 | RGB rgb = @RGB.@Red;
|
---|
| 56 | rgb = @RGB.@Blue;
|
---|
| 57 | \end{cfa}
|
---|
[94643698] | 58 | % with feature unimplemented
|
---|
[a57ad8a] | 59 | It is possible to toggle back to unscoped using the \CFA @with@ auto-qualification clause/statement (see also \CC \lstinline[language=c++]{using enum} in Section~\ref{s:C++RelatedWork}).
|
---|
[dd78dbc] | 60 | \begin{cfa}
|
---|
| 61 | with ( @Week@, @RGB@ ) { $\C{// type names}$
|
---|
| 62 | week = @Sun@; $\C{// no qualification}$
|
---|
| 63 | rgb = @Green@;
|
---|
| 64 | }
|
---|
| 65 | \end{cfa}
|
---|
[0c51c8b4] | 66 | As in Section~\ref{s:CVisibility}, opening multiple scoped enumerations in a @with@ can result in duplicate enumeration names, but \CFA implicit type resolution and explicit qualification/casting handle this localized scenario.
|
---|
[dd78dbc] | 67 |
|
---|
[94643698] | 68 | A partially implemented extension to enumerator scoping is providing a combination of scoped and unscoped enumerators, using individual denotations, where @'^'@ means unscoped.
|
---|
| 69 | \begin{cfa}
|
---|
| 70 | enum E1 { @!@A, @^@B, C };
|
---|
| 71 | enum E2 @!@ { @!@A, @^@B, C };
|
---|
| 72 | \end{cfa}
|
---|
| 73 | For @E1@, @A@ is scoped; @B@ and @C@ are unscoped.
|
---|
| 74 | For @E2@, @A@ and @C@ are scoped; @B@ is unscoped.
|
---|
| 75 | Finding a use case is important to justify completing this extension.
|
---|
| 76 |
|
---|
[a57ad8a] | 77 |
|
---|
[dd78dbc] | 78 | \section{Type Safety}
|
---|
| 79 |
|
---|
[c141c09] | 80 | As in Section~\ref{s:Usage}, C's implicit bidirectional conversion between enumeration and integral type raises a safety concern.
|
---|
[a57ad8a] | 81 | In \CFA, the conversion is changed to unidirectional: an enumeration can be implicitly converted into an integral type, with an associated @safe@ conversion cost.
|
---|
| 82 | But an integral type cannot be implicitly converted into a C enumeration because the conversion cost is set to @infinity@.
|
---|
[dd78dbc] | 83 | \begin{cfa}
|
---|
[a57ad8a] | 84 | enum Bird { Penguin, Robin, Eagle };
|
---|
[dd78dbc] | 85 | enum Fish { Shark, Salmon, Whale };
|
---|
| 86 |
|
---|
[94643698] | 87 | int i = Robin; $\C{// allow, implicitly converts to 1}$
|
---|
| 88 | enum Bird @bird = 1;@ $\C{// disallow }$
|
---|
| 89 | enum Bird @bird = Shark;@ $\C{// disallow }$
|
---|
[a57ad8a] | 90 | \end{cfa}
|
---|
| 91 | It is now up to the programmer to insert an explicit cast to force the assignment.
|
---|
| 92 | \begin{cfa}
|
---|
| 93 | enum Bird bird = @(Bird)@1;
|
---|
[94643698] | 94 | enum Bird bird = @(Bird)@Shark
|
---|
[a57ad8a] | 95 | \end{cfa}
|
---|
| 96 |
|
---|
| 97 | Note, \CC has the same safe restriction~\cite[C.1.5.7.2]{C++} and provides the same workaround cast.
|
---|
| 98 | \begin{description}[parsep=0pt]
|
---|
| 99 | \item[Change:] \CC objects of enumeration type can only be assigned values of the same enumeration type.
|
---|
| 100 | In C, objects of enumeration type can be assigned values of any integral type.
|
---|
| 101 | Example:
|
---|
| 102 | \begin{cfa}
|
---|
| 103 | enum color { red, blue, green };
|
---|
| 104 | color c = 1; $\C{// valid C, invalid \CC}$
|
---|
[c141c09] | 105 | \end{cfa}
|
---|
[a57ad8a] | 106 | \item[Rationale:] The type-safe nature of \CC.
|
---|
| 107 | \item[Effect on original feature:] Deletion of semantically well-defined feature.
|
---|
| 108 | \item[Difficulty of converting:] Syntactic transformation. (The type error produced by the assignment can be
|
---|
| 109 | automatically corrected by applying an explicit cast.)
|
---|
| 110 | \item[How widely used:] Common.
|
---|
| 111 | \end{description}
|
---|
| 112 |
|
---|
| 113 | \begin{comment}
|
---|
| 114 | \begin{description}[parsep=0pt]
|
---|
| 115 | \item[Change:] In \CC, the type of an enumerator is its enumeration.
|
---|
| 116 | In C, the type of an enumerator is @int@.
|
---|
| 117 | Example:
|
---|
[c141c09] | 118 | \begin{cfa}
|
---|
[a57ad8a] | 119 | enum e { A };
|
---|
| 120 | sizeof(A) == sizeof(int) $\C{// in C}$
|
---|
| 121 | sizeof(A) == sizeof(e) $\C{// in \CC}$
|
---|
| 122 | /* and sizeof(int) is not necessary equal to sizeof(e) */
|
---|
| 123 | \end{cfa}
|
---|
| 124 | \item[Rationale:] In \CC, an enumeration is a distinct type.
|
---|
| 125 | \item[Effect on original feature:] Change to semantics of well-defined feature.
|
---|
| 126 | \item[Difficulty of converting:] Semantic transformation.
|
---|
| 127 | \item[How widely used:] Seldom. The only time this affects existing C code is when the size of an enumerator is
|
---|
| 128 | taken. Taking the size of an enumerator is not a common C coding practice.
|
---|
| 129 | \end{description}
|
---|
| 130 | \end{comment}
|
---|