1 | \chapter{C Enumeration in \CFA} |
---|
2 | |
---|
3 | \CFA supports legacy C enumeration using the same syntax for backwards compatibility. |
---|
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. |
---|
6 | The following sections detail all of my new contributions to enumerations in C. |
---|
7 | |
---|
8 | |
---|
9 | \section{Enumerator Visibility} |
---|
10 | \label{s:EnumeratorVisibility} |
---|
11 | |
---|
12 | In C, unscoped enumerators present a \newterm{naming problem} when multiple enumeration types appear in the same scope with duplicate enumerator names. |
---|
13 | \begin{cfa} |
---|
14 | enum E1 { First, Second, Third, Fourth }; |
---|
15 | enum E2 { @Fourth@, @Third@, @Second@, @First@ }; $\C{// same enumerator names}$ |
---|
16 | \end{cfa} |
---|
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. |
---|
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@. |
---|
23 | |
---|
24 | \begin{figure} |
---|
25 | \begin{cfa} |
---|
26 | E1 f() { return Third; } $\C{// overload functions with different return types}$ |
---|
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 | |
---|
44 | \section{Enumerator Scoping} |
---|
45 | |
---|
46 | A C Enum can be scoped, using @'!'@, so the enumerator constants are not projected into the enclosing scope. |
---|
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} |
---|
58 | % with feature unimplemented |
---|
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}). |
---|
60 | \begin{cfa} |
---|
61 | with ( @Week@, @RGB@ ) { $\C{// type names}$ |
---|
62 | week = @Sun@; $\C{// no qualification}$ |
---|
63 | rgb = @Green@; |
---|
64 | } |
---|
65 | \end{cfa} |
---|
66 | As in Section~\ref{s:EnumeratorVisibility}, 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. |
---|
67 | |
---|
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 | |
---|
77 | |
---|
78 | \section{Type Safety} |
---|
79 | |
---|
80 | As in Section~\ref{s:Usage}, C's implicit bidirectional conversion between enumeration and integral type raises a safety concern. |
---|
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@. |
---|
83 | \begin{cfa} |
---|
84 | enum Bird { Penguin, Robin, Eagle }; |
---|
85 | enum Fish { Shark, Salmon, Whale }; |
---|
86 | |
---|
87 | int i = Robin; $\C{// allow, implicitly converts to 1}$ |
---|
88 | enum Bird @bird = 1;@ $\C{// disallow }$ |
---|
89 | enum Bird @bird = Shark;@ $\C{// disallow }$ |
---|
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; |
---|
94 | enum Bird bird = @(Bird)@Shark |
---|
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}$ |
---|
105 | \end{cfa} |
---|
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: |
---|
118 | \begin{cfa} |
---|
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} |
---|