source: doc/theses/jiada_liang_MMath/CFAenum.tex @ 6c68893

Last change on this file since 6c68893 was f9da761, checked in by Peter A. Buhr <pabuhr@…>, 9 months ago

change text to use macros \eg amd \ie

  • Property mode set to 100644
File size: 11.9 KB
RevLine 
[956299b]1\chapter{\CFA-Style Enum}
2
3
4\CFA supports C-Style enumeration using the same syntax and semantics for backwards compatibility.
5\CFA also extends C-Style enumeration by adding a number of new features that bring enumerations inline with other modern programming languages.
6
7
8\section{Enumerator Name Resolution}
9\label{s:EnumeratorNameResolution}
10
11In C, unscoping of enumerators presents a \Newterm{naming problem} when multiple enumeration types appear in the same scope with duplicate enumerator names.
12There is no mechanism in C to resolve these naming conflicts other than renaming of one of the duplicates, which may be impossible.
13
14The \CFA type-system allows extensive overloading, including enumerators.
15Furthermore, \CFA uses the left-hand of assignment in type resolution to pinpoint the best overloaded name.
16Finally, qualification is provided to disambiguate any ambiguous situations.
17\begin{cfa}
18enum C1 { First, Second, Third, Fourth };
19enum C2 { @Fourth@, @Third@, @Second@, @First@ };
20C1 p() { return Third; }                                $\C{// correctly resolved duplicate names}$
21C2 p() { return Fourth; }
22void foo() {
23        C1 e1 = First;   C2 e2 = First;
24        e1 = Second;   e2 = Second;
25        e1 = p();   e2 = p();                           $\C{// correctly resolved function call}$
26        int i = @C1.@First + @C2.@First;        $\C{// ambiguous without qualification}$
27}
28\end{cfa}
29\CFA overloading allows programmers to use the most meaningful names without fear of unresolvable clashes from included files, which are correctable with qualification.
30
31
32\section{Enumerator Scoping}
33
34An enumeration can be scoped, so the enumerator constants are not projected into the enclosing scope, using @'!'@.
35\begin{cfa}
36enum Weekday @!@ { /* as above */ };
37enum( char * ) Names @!@ { /* as above */ };
38\end{cfa}
39Now the enumerators \emph{must} be qualified with the associated enumeration.
40\begin{cfa}
41Weekday weekday = @Weekday@.Monday;
42Names names = @Names.@Fred;
43names = @Names.@Jane;
44\end{cfa}
45It is possible to toggle back to unscoping using the \CFA @with@ clause/statement (see also \CC \lstinline[language=c++]{using enum} in Section~\ref{s:C++RelatedWork}).
46\begin{cfa}
47Weekday weekday;
48with ( @Weekday@, @Names@ ) {                   $\C{// type names}$
49         Names names = @Fred@;
50         names = @Jane@;
51         weekday = Saturday;
52}
53\end{cfa}
54As in Section~\ref{s:EnumeratorNameResolution}, opening multiple unscoped enumerations can result in duplicate enumeration names, but \CFA type resolution and falling back to explicit qualification handles name resolution.
55
56\section{Enumerator Typing}
57
58\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.
59Figure~\ref{f:EumeratorTyping} shows a series of examples illustrating that all \CFA types can be use with an enumeration and each type's constants used to set the enumerator constants.
60Note, the synonyms @Liz@ and @Beth@ in the last declaration.
61
62Because enumerators are constants, the enumeration type is implicitly @const@, so all the enumerator types in Figure~\ref{f:EumeratorTyping} are rewritten with @const@.
63A typed enumeration has an implicit (safe) conversion to its base type.
64\begin{cfa}
65char currency = Dollar;
66string fred = Fred;                                             $\C{// implicit conversion from char * to \CFA string type}$
67Person student = Beth;
68\end{cfa}
69
70% \begin{cfa}
71% struct S { int i, j; };
72% enum( S ) s { A = { 3,  4 }, B = { 7,  8 } };
73% enum( @char@ ) Currency { Dollar = '$\textdollar$', Euro = '$\texteuro$', Pound = '$\textsterling$'  };
74% enum( @double@ ) Planet { Venus = 4.87, Earth = 5.97, Mars = 0.642  }; // mass
75% enum( @char *@ ) Colour { Red = "red", Green = "green", Blue = "blue"  };
76% enum( @Currency@ ) Europe { Euro = '$\texteuro$', Pound = '$\textsterling$' }; // intersection
77% \end{cfa}
78
79\begin{figure}
80\begin{cfa}
81// integral
82        enum( @char@ ) Currency { Dollar = '$\textdollar$', Euro = '$\texteuro$', Pound = '$\textsterling$};
83        enum( @signed char@ ) srgb { Red = -1, Green = 0, Blue = 1 };
84        enum( @long long int@ ) BigNum { X = 123_456_789_012_345,  Y = 345_012_789_456_123 };
85// non-integral
86        enum( @double@ ) Math { PI_2 = 1.570796, PI = 3.141597, E = 2.718282 };
87        enum( @_Complex@ ) Plane { X = 1.5+3.4i, Y = 7+3i, Z = 0+0.5i };
88// pointer
89        enum( @char *@ ) Names { Fred = "FRED", Mary = "MARY", Jane = "JANE" };
90        int i, j, k;
91        enum( @int *@ ) ptr { I = &i,  J = &j,  K = &k };
92        enum( @int &@ ) ref { I = i,   J = j,   K = k };
93// tuple
94        enum( @[int, int]@ ) { T = [ 1, 2 ] }; $\C{// new \CFA type}$
95// function
96        void f() {...}   void g() {...}
97        enum( @void (*)()@ ) funs { F = f,  G = g };
98// aggregate
99        struct Person { char * name; int age, height; };
100@***@enum( @Person@ ) friends { @Liz@ = { "ELIZABETH", 22, 170 }, @Beth@ = Liz, Jon = { "JONATHAN", 35, 190 } };
101\end{cfa}
102\caption{Enumerator Typing}
103\label{f:EumeratorTyping}
104\end{figure}
105
106Typed enumerations deals with the \emph{harmonizing} problem between an enumeration and any companion data.
107The following example is from the \CFA compiler, written in \CC.
108\begin{cfa}
109enum integral_types { chr, schar, uschar, sshort, ushort, sint, usint, ..., NO_OF_ITYPES };
110char * integral_names[NO_OF_ITYPES] = {
111        "char", "signed char", "unsigned char",
112        "signed short int", "unsigned short int",
113        "signed int", "unsigned int",
114        ...
115};
116\end{cfa}
117The \emph{harmonizing} problem occurs because the enumeration declaration is in one header file and the names are declared in another translation unit.
118It is up to the programmer to ensure changes made in one location are harmonized with the other location (by identifying this requirement within a comment).
119The typed enumeration largely solves this problem by combining and managing the two data types.
120\begin{cfa}
121enum( char * ) integral_types {
122        chr = "char", schar = "signed char", uschar = "unsigned char",
123        sshort = "signed short int", ushort = "unsigned short int",
124        sint = "signed int", usint = "unsigned int",
125        ...
126};
127\end{cfa}
128Note, 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.
129
130
131\section{Pure Enumerators}
132
133An empty enumerator type, @enum()@, implies the enumerators are pure symbols without values but set properties;
134hence, there is no default conversion to @int@.
135
136\begin{cfa}
137enum() Mode { O_RDONLY, O_WRONLY, O_CREAT, O_TRUNC, O_APPEND };
138@***@Mode iomode = O_RDONLY;
139bool b = iomode == O_RDONLY || iomode < O_APPEND;
140int i = iomode;                                                 $\C{\color{red}// disallowed}$
141\end{cfa}
142
143\section{Enumerator Subset}
144
145If follows from enumerator typing that the enumerator type can be another enumerator.
146\begin{cfa}
147enum( @char@ ) Currency { Dollar = '$\textdollar$', Euro = '$\texteuro$', Pound = '$\textsterling$};
148enum( @Currency@ ) Europe { Euro = Currency.Euro, Pound = Currency.Pound }; // intersection
149enum( char ) Letter { A = 'A',  B = 'B', C = 'C', ..., Z = 'Z' };
150enum( @Letter@ ) Greek { Alph = A, Beta = B, ..., Zeta = Z }; // intersection
151\end{cfa}
152Subset enumerations may have more or less enumerators than their typed enumeration, but the enumerator values must be from the typed enumeration.
153For example, @Greek@ enumerators are a subset of type @Letter@ and are type compatible with enumeration @Letter@, but @Letter@ enumerators are not type compatible with enumeration @Greek@.
154\begin{cfa}
155Letter letter = A;
156@***@Greak greek = Beta;
157letter = Beta;                                                  $\C{// allowed, letter == B}$
158greek = A;                                                              $\C{\color{red}// disallowed}$
159\end{cfa}
160
161
162\section{Enumeration Inheritance}
163
164\CFA Plan-9 inheritance may be used with enumerations, where Plan-9 inheritance is containment inheritance with implicit unscoping (like a nested unnamed @struct@/@union@ in C).
165\begin{cfa}
166enum( char * ) Names { /* as above */ };
167enum( char * ) Names2 { @inline Names@, Jack = "JACK", Jill = "JILL" };
168@***@enum /* inferred */ Names3 { @inline Names2@, Sue = "SUE", Tom = "TOM" };
169\end{cfa}
170Enumeration @Name2@ inherits all the enumerators and their values from enumeration @Names@ by containment, and a @Names@ enumeration is a subtype of enumeration @Name2@.
171Note, enumerators must be unique in inheritance but enumerator values may be repeated.
172
173The enumeration type for the inheriting type must be the same as the inherited type;
174hence the enumeration type may be omitted for the inheriting enumeration and it is inferred from the inherited enumeration, as for @Name3@.
175% When inheriting from integral types, automatic numbering may be used, so the inheritance placement left to right is important.
176Specifically, the inheritance relationship for @Names@ is:
177\begin{cfa}
178Names $\(\subset\)$ Names2 $\(\subset\)$ Names3 $\(\subset\)$ const char * $\C{// enum type of Names}$
179\end{cfa}
180For the given function prototypes, the following calls are valid.
181\begin{cquote}
182\begin{tabular}{ll}
183\begin{cfa}
184void f( Names );
185void g( Names2 );
186void h( Names3 );
187void j( const char * );
188\end{cfa}
189&
190\begin{cfa}
191f( Fred );
192g( Fred );   g( Jill );
193h( Fred );   h( Jill );   h( Sue );
194j( Fred );   j( Jill );   j( Sue );   j( "WILL" );
195\end{cfa}
196\end{tabular}
197\end{cquote}
198Note, 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.
199
200
201\section{Enumeration Pseudo-functions}
202
[f9da761]203Pseudo-functions are function-like operators that do not result in any run-time computations, \ie like @sizeof@, @offsetof@, @typeof@.
[956299b]204Often a call to a pseudo-function is substituted with information extracted from the symbol table at compilation time, like storage size or alignment associated with the underlying architecture..
205
206The attributes of an enumerator are accessed by pseudo-functions @position@, @value@, and @label@.
207\begin{cfa}
208@***@int jane_pos = @position@( Names.Jane );   $\C{// 2}$
209@***@char * jane_value = @value@( Names.Jane ); $\C{// "JANE"}$
210@***@char * jane_label = @label@( Names.Jane ); $\C{// "Jane"}$
211sout | @label@( Names.Jane ) | @value@( Names.Jane );
212\end{cfa}
213Note the ability to print both enumerator label and value.
214
215
216\section{Enumerator Position or Value}
217
218Enumerators can be used in multiple contexts.
219In most programming languages, an enumerator is implicitly converted to its value (like a typed macro substitution).
220However, enumerator synonyms and typed enumerations make this implicit conversion to value incorrect in some contexts.
221In these contexts, a programmer's initition assumes an implicit conversion to postion.
222
223For example, an intuitive use of enumerations is with the \CFA @switch@/@choose@ statement, where @choose@ performs an implict @break@ rather than a fall-through at the end of a @case@ clause.
224\begin{cquote}
225\begin{cfa}
226enum Count { First, Second, Third, Fourth };
227Count e;
228\end{cfa}
229\begin{tabular}{ll}
230\begin{cfa}
231
232choose( e ) {
233        case @First@: ...;
234        case @Second@: ...;
235        case @Third@: ...;
236        case @Fourth@: ...;
237}
238\end{cfa}
239&
240\begin{cfa}
241// rewrite
242choose( @value@( e ) ) {
243        case @value@( First ): ...;
244        case @value@( Second ): ...;
245        case @value@( Third ): ...;
246        case @value@( Fourth ): ...;
247}
248\end{cfa}
249\end{tabular}
250\end{cquote}
251Here, the intuitive code on the left is implicitly transformed into the statndard implementation on the right, using the value of the enumeration variable and enumerators.
[f9da761]252However, this implementation is fragile, \eg if the enumeration is changed to:
[956299b]253\begin{cfa}
254enum Count { First, Second, Third @= First@, Fourth };
255\end{cfa}
256which make @Third == First@ and @Fourth == Second@, causing a compilation error because of duplicase @case@ clauses.
257To better match with programmer intuition, \CFA toggles between value and position semantics depneding on the language context.
258For conditional clauses and switch statments, \CFA uses the robust position implementation.
259\begin{cfa}
260choose( @position@( e ) ) {
261        case @position@( First ): ...;
262        case @position@( Second ): ...;
263        case @position@( Third ): ...;
264        case @position@( Fourth ): ...;
265}
266\end{cfa}
267
268\begin{cfa}
269Count variable_a = First, variable_b = Second, variable_c = Third, variable_d = Fourth;
270p(variable_a); // 0
271p(variable_b); // 1
272p(variable_c); // "Third"
273p(variable_d); // 3
274\end{cfa}
Note: See TracBrowser for help on using the repository browser.