Changeset a4da45e for doc/proposals/enum.tex
- Timestamp:
- Feb 26, 2024, 3:53:42 AM (21 months ago)
- Branches:
- master
- Children:
- 3f9a8d0
- Parents:
- 0522ebe (diff), 022bce0 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - File:
-
- 1 edited
-
doc/proposals/enum.tex (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
doc/proposals/enum.tex
r0522ebe ra4da45e 117 117 \end{abstract} 118 118 119 \section{ Background}119 \section{Introduction} 120 120 121 121 Naming values is a common practice in mathematics and engineering, e.g., $\pi$, $\tau$ (2$\pi$), $\phi$ (golden ratio), MHz (1E6), etc. 122 Naming is also commonly used to represent many other numerical phenomenon, such as days of the week, months of a year, floors of a building (basement), time(noon, New Years).122 Naming is also commonly used to represent many other numerical phenomenon, such as days of the week, months of a year, floors of a building (basement), specific times (noon, New Years). 123 123 Many programming languages capture this important software-engineering capability through a mechanism called an \newterm{enumeration}. 124 124 An enumeration is similar to other programming-language types by providing a set of constrained values, but adds the ability to name \emph{all} the values in its set. … … 126 126 127 127 Specifically, an enumerated type restricts its values to a fixed set of named constants. 128 Fundamentally, all types are restricted to a fixed set of values because of the underlying von Neumann architecture, and hence, to a corresponding set of constants, e.g., @3@, @3.5@, @3.5+2.1i@, @'c'@, @"abc"@, etc. 129 However, the values for basic types are not named, other than the programming-language supplied constants. 130 131 132 \section{C-Style Enum} 133 134 The C-Style enumeration has the following syntax and semantics, and is representative of enumerations in many other programming languages (see Section~\ref{s:RelatedWork}). 135 \begin{lstlisting}[label=lst:weekday] 136 enum Weekday { Monday, Tuesday, Wednesday, Thursday@ = 10@, Friday, Saturday, Sunday }; 137 $\(\uparrow\)$ $\(\uparrow\)$ 138 ${\rm \newterm{enumeration name}}$ ${\rm \newterm{enumerator names}} 139 \end{lstlisting} 140 Here, the enumeration type @Weekday@ defines the ordered \newterm{enumerator}s @Monday@, @Tuesday@, @Wednesday@, @Thursday@, @Friday@, @Saturday@ and @Sunday@. 141 By convention, the successor of @Tuesday@ is @Monday@ and the predecessor of @Tuesday@ is @Wednesday@, independent of the associated enumerator constants. 142 Because an enumerator is a constant, it cannot appear in a mutable context, e.g. @Mon = Sun@ is meaningless, and has no address, it is an rvalue\footnote{ 143 The term rvalue defines an expression that can only appear on the right-hand side of an assignment.}. 144 Enumerators without explicitly designated constants are auto-initialized by the compiler: from left to right, starting at zero or the next explicitly initialized constant, incrementing by @1@. 145 For example, @Monday@ to @Wednesday@ are implicitly assigned with constants 0--2, @Thursday@ is explicitly set to constant @10@, and @Friday@ to @Sunday@ are implicitly assigned with constants 11--13. 146 Hence, there are 3 universal enumeration attributes: \newterm{position}, \newterm{label}, and \newterm{value}: 128 While all types are restricted to a fixed set of values because of the underlying von Neumann architecture, and hence, to a corresponding set of constants, e.g., @3@, @3.5@, @3.5+2.1i@, @'c'@, @"abc"@, etc., these values are not named, other than the programming-language supplied constant names. 129 130 Fundamentally, all enumeration systems have an \newterm{enumeration} type with an associated set of \newterm{enumerator} names. 131 An enumeration has three universal attributes, \newterm{position}, \newterm{label}, and \newterm{value}, as shown by this representative enumeration, where position and value can be different. 147 132 \begin{cquote} 148 133 \small\sf\setlength{\tabcolsep}{3pt} 149 134 \begin{tabular}{rccccccccccc} 150 @enum@ Weekday \{ & Monday, & Tuesday, & Wednesday, & Thursday = 10,& Friday, & Saturday, & Sunday \}; \\ 151 \it\color{red}position & 0 & 1 & 2 & 3 & 4 & 5 & 6 \\ 152 \it\color{red}label & Monday & Tuesday & Wednesday & Thursday & Friday & Saturday & Sunday \\ 153 \it\color{red}value & 0 & 1 & 2 & {\color{red}10}& 11 & 12 & 13 135 \it\color{red}enumeration & \multicolumn{7}{c}{\it\color{red}enumerators} \\ 136 $\downarrow$\hspace*{25pt} & \multicolumn{7}{c}{$\downarrow$} \\ 137 @enum@ Weekday \{ & Monday, & Tuesday, & Wednesday, & Thursday,& Friday, & Saturday, & Sunday \}; \\ 138 \it\color{red}position & 0 & 1 & 2 & 3 & 4 & 5 & 6 \\ 139 \it\color{red}label & Monday & Tuesday & Wednesday & Thursday & Friday & Saturday & Sunday \\ 140 \it\color{red}value & 0 & 1 & 2 & 3 & 4 & 5 & 6 154 141 \end{tabular} 155 142 \end{cquote} 156 Finally, C enumerators are \newterm{unscoped}, i.e., enumerators declared inside of an @enum@ are visible in the enclosing scope of the @enum@ type. 143 Here, the \newterm{enumeration} @Weekday@ defines the ordered \newterm{enumerator}s @Monday@, @Tuesday@, @Wednesday@, @Thursday@, @Friday@, @Saturday@ and @Sunday@. 144 By convention, the successor of @Tuesday@ is @Monday@ and the predecessor of @Tuesday@ is @Wednesday@, independent of the associated enumerator constant values. 145 Because an enumerator is a constant, it cannot appear in a mutable context, e.g. @Mon = Sun@ is meaningless, and an enumerator has no address, it is an \newterm{rvalue}\footnote{ 146 The term rvalue defines an expression that can only appear on the right-hand side of an assignment.}. 147 148 149 \section{C-Style Enum} 150 151 The C-Style enumeration has the following syntax and semantics. 152 \begin{lstlisting} 153 enum Weekday { Monday, Tuesday, Wednesday, Thursday@ = 10@, Friday, Saturday, Sunday }; 154 \end{lstlisting} 155 Enumerators without an explicitly designated constant value are \newterm{auto-initialized} by the compiler: from left to right, starting at zero or the next explicitly initialized constant, incrementing by @1@. 156 For example, @Monday@ to @Wednesday@ are implicitly assigned with constants @0@--@2@, @Thursday@ is explicitly set to constant @10@, and @Friday@ to @Sunday@ are implicitly assigned with constants @11@--@13@. 157 Initialization may occur in any order. 158 \begin{lstlisting} 159 enum Weekday { Thursday@ = 10@, Friday, Saturday, Sunday, Monday@ = 0@, Tuesday, Wednesday }; 160 \end{lstlisting} 161 Note, the comma in the enumerator list can be a terminator or a separator, allowing the list to end with a dangling comma. 162 \begin{lstlisting} 163 enum Weekday { 164 Thursday = 10, Friday, Saturday, Sunday, 165 Monday = 0, Tuesday, Wednesday@,@ // terminating comma 166 }; 167 \end{lstlisting} 168 This feature allow enumerator lines to be interchanged without moving a comma.\footnote{ 169 A terminating comma appears in other C syntax, e.g., the initializer list.} 170 Finally, C enumerators are \newterm{unscoped}, i.e., enumerators declared inside of an @enum@ are visible (projected) into the enclosing scope of the @enum@ type. 157 171 158 172 In theory, a C enumeration \emph{variable} is an implementation-defined integral type large enough to hold all enumerated values. 159 In practice, since integral constants in Chave type @int@ (unless qualified with a size suffix), C uses @int@ as the underlying type for enumeration variables.160 F urthermore, there is an implicit bidirectional conversion between an enumeration and integral types.173 In practice, since integral constants are used, which have type @int@ (unless qualified with a size suffix), C uses @int@ as the underlying type for enumeration variables. 174 Finally, there is an implicit bidirectional conversion between an enumeration and integral types. 161 175 \begin{lstlisting}[label=lst:enum_scope] 162 176 { 163 enum Weekday { ... };$\C{// enumerators implicitly projected into local scope}$177 enum Weekday { /* as above */ }; $\C{// enumerators implicitly projected into local scope}$ 164 178 Weekday weekday = Monday; $\C{// weekday == 0}$ 165 179 weekday = Friday; $\C{// weekday == 11}$ 166 int i = Sunday $\C{// implicit conversion to int, i == 13}$180 int i = Sunday; $\C{// implicit conversion to int, i == 13}$ 167 181 weekday = 10000; $\C{// UNDEFINED! implicit conversion to Weekday}$ 168 182 } … … 171 185 The implicit conversion from @int@ to an enumeration type is an unnecessary source of error. 172 186 187 It is common for C programmers to ``believe'' there are 3 equivalent forms of constant enumeration. 188 \begin{lstlisting}[label=lst:enum_scope] 189 #define Monday 0 190 static const int Monday = 0; 191 enum { Monday }; 192 \end{lstlisting} 193 For @#define@, the programmer has to play compiler and explicitly manage the enumeration values; 194 furthermore, these are independent constants outside of any language type mechanism. 195 The same explicit management is true for @const@ declarations, and the @const@ variable cannot appear in constant-expression locations, like @case@ labels, array dimensions,\footnote{ 196 C allows variable-length array-declarations (VLA), so this case does work, but it fails in \CC, which does not support VLAs, unless it is \lstinline{g++}.} and immediate operands of assembler instructions. 197 Only the @enum@ form is managed by the compiler, is part of the language type-system, and works in all C constant-expression locations. 198 199 173 200 \section{\CFA-Style Enum} 174 201 … … 176 203 \CFA also extends C-Style enumeration by adding a number of new features that bring enumerations inline with other modern programming languages. 177 204 205 206 \subsection{Enumerator Name Resolution} 207 \label{s:EnumeratorNameResolution} 208 209 In C, unscoping of enumerators presents a \newterm{naming problem} when multiple enumeration types appear in the same scope with duplicate enumerator names. 210 There is no mechanism in C to resolve these naming conflicts other than renaming of one of the duplicates, which may be impossible. 211 212 The \CFA type-system allows extensive overloading, including enumerators. 213 Furthermore, \CFA uses the left-hand of assignment in type resolution to pinpoint the best overloaded name. 214 Finally, qualification is provided to disambiguate any ambiguous situations. 215 \begin{lstlisting} 216 enum C1 { First, Second, Third, Fourth }; 217 enum C2 { @Fourth@, @Third@, @Second@, @First@ }; 218 C1 p() { return Third; } $\C{// correctly resolved duplicate names}$ 219 C2 p() { return Fourth; } 220 void foo() { 221 C1 e1 = First; C2 e2 = First; 222 e1 = Second; e2 = Second; 223 e1 = p(); e2 = p(); $\C{// correctly resolved function call}$ 224 int i = @C1.@First + @C2.@First; $\C{// ambiguous without qualification}$ 225 } 226 \end{lstlisting} 227 \CFA overloading allows programmers to use the most meaningful names without fear of unresolvable clashes from included files, which are correctable with qualification. 228 229 230 \subsection{Enumerator Scoping} 231 232 An enumeration can be scoped, so the enumerator constants are not projected into the enclosing scope, using @'!'@. 233 \begin{lstlisting} 234 enum Weekday @!@ { /* as above */ }; 235 enum( char * ) Names @!@ { /* as above */ }; 236 \end{lstlisting} 237 Now the enumerators \emph{must} be qualified with the associated enumeration. 238 \begin{lstlisting} 239 Weekday weekday = @Weekday@.Monday; 240 Names names = @Names.@Fred; 241 names = @Names.@Jane; 242 \end{lstlisting} 243 It 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}). 244 \begin{lstlisting} 245 Weekday weekday; 246 with ( @Weekday@, @Names@ ) { $\C{// type names}$ 247 Names names = @Fred@; 248 names = @Jane@; 249 weekday = Saturday; 250 } 251 \end{lstlisting} 252 As 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. 253 178 254 \subsection{Enumerator Typing} 179 255 180 \CFA extends the enumeration by parameterizing the enumeration with a type for the enumerators, allowing enumerators to be assigned any values from the declared type. 181 Figure~\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 enumerators. 182 183 Typed enumerates deals with \emph{harmonizing} problem between an enumeration and its companion data. 184 The following example is from the \CFA compiler, written in \CC. 185 \begin{lstlisting} 186 enum integral_types { chr, schar, uschar, sshort, ushort, sint, usint, ..., NO_OF_ITYPES }; 187 char * integral_names[NO_OF_ITYPES] = { 188 "char", "signed char", "unsigned char", 189 "signed short int", "unsigned short int", 190 "signed int", "unsigned int", 191 ... 192 }; 193 \end{lstlisting} 194 The \emph{harmonizing} problem occurs because the enumeration declaration is in one header file and the names are declared in another translation unit. 195 It 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). 196 The typed enumeration largely solves this problem by combining and managing the two data types. 197 \begin{lstlisting} 198 enum( char * ) integral_types { 199 chr = "char", schar = "signed char", uschar = "unsigned char", 200 sshort = "signed short int", ushort = "unsigned short int", 201 sint = "signed int", usint = "unsigned int", 202 ... 203 }; 256 \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. 257 Figure~\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. 258 Note, the synonyms @Liz@ and @Beth@ in the last declaration. 259 260 Because enumerators are constants, the enumeration type is implicitly @const@, so all the enumerator types in Figure~\ref{f:EumeratorTyping} are rewritten with @const@. 261 A typed enumeration has an implicit (safe) conversion to its base type. 262 \begin{lstlisting} 263 char currency = Dollar; 264 string fred = Fred; $\C{// implicit conversion from char * to \CFA string type}$ 265 Person student = Beth; 204 266 \end{lstlisting} 205 267 … … 223 285 enum( @_Complex@ ) Plane { X = 1.5+3.4i, Y = 7+3i, Z = 0+0.5i }; 224 286 // pointer 225 enum( @char *@ ) Names { Fred = "F red", Mary = "Mary", Jane = "Jane" };287 enum( @char *@ ) Names { Fred = "FRED", Mary = "MARY", Jane = "JANE" }; 226 288 int i, j, k; 227 289 enum( @int *@ ) ptr { I = &i, J = &j, K = &k }; 228 290 enum( @int &@ ) ref { I = i, J = j, K = k }; 229 291 // tuple 230 enum( @[int, int]@ ) { T = [ 1, 2 ] }; 292 enum( @[int, int]@ ) { T = [ 1, 2 ] }; $\C{// new \CFA type}$ 231 293 // function 232 294 void f() {...} void g() {...} … … 234 296 // aggregate 235 297 struct Person { char * name; int age, height; }; 236 enum( @Person@ ) friends { Liz = { "Elizabeth", 22, 170 }, Beth = Liz, Jon = { "Jonathan", 35, 190 } };298 @***@enum( @Person@ ) friends { @Liz@ = { "ELIZABETH", 22, 170 }, @Beth@ = Liz, Jon = { "JONATHAN", 35, 190 } }; 237 299 \end{lstlisting} 238 300 \caption{Enumerator Typing} … … 240 302 \end{figure} 241 303 304 Typed enumerations deals with the \emph{harmonizing} problem between an enumeration and any companion data. 305 The following example is from the \CFA compiler, written in \CC. 306 \begin{lstlisting} 307 enum integral_types { chr, schar, uschar, sshort, ushort, sint, usint, ..., NO_OF_ITYPES }; 308 char * integral_names[NO_OF_ITYPES] = { 309 "char", "signed char", "unsigned char", 310 "signed short int", "unsigned short int", 311 "signed int", "unsigned int", 312 ... 313 }; 314 \end{lstlisting} 315 The \emph{harmonizing} problem occurs because the enumeration declaration is in one header file and the names are declared in another translation unit. 316 It 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). 317 The typed enumeration largely solves this problem by combining and managing the two data types. 318 \begin{lstlisting} 319 enum( char * ) integral_types { 320 chr = "char", schar = "signed char", uschar = "unsigned char", 321 sshort = "signed short int", ushort = "unsigned short int", 322 sint = "signed int", usint = "unsigned int", 323 ... 324 }; 325 \end{lstlisting} 326 Note, 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. 327 328 242 329 \subsection{Pure Enumerators} 243 330 244 An empty type, @enum()@, implies the enumerators are pure symbols without values;331 An empty enumerator type, @enum()@, implies the enumerators are pure symbols without values but set properties; 245 332 hence, there is no default conversion to @int@. 246 333 247 334 \begin{lstlisting} 248 335 enum() Mode { O_RDONLY, O_WRONLY, O_CREAT, O_TRUNC, O_APPEND }; 249 Mode iomode = O_RDONLY; 336 @***@Mode iomode = O_RDONLY; 337 bool b = iomode == O_RDONLY || iomode < O_APPEND; 250 338 int i = iomode; $\C{\color{red}// disallowed}$ 251 sout | O_TRUNC; $\C{\color{red}// disallowed}$252 339 \end{lstlisting} 253 340 254 341 \subsection{Enumerator Subset} 255 342 256 If follows from enumerator typing that the type of the enumerators can be another enumerator. 257 \begin{lstlisting} 343 If follows from enumerator typing that the enumerator type can be another enumerator. 344 \begin{lstlisting} 345 enum( @char@ ) Currency { Dollar = '$\textdollar$', Euro = '$\texteuro$', Pound = '$\textsterling$' }; 346 enum( @Currency@ ) Europe { Euro = Currency.Euro, Pound = Currency.Pound }; // intersection 258 347 enum( char ) Letter { A = 'A', B = 'B', C = 'C', ..., Z = 'Z' }; 259 enum( Letter ) Greek { Alph = A, Beta = B, ..., Zeta = Z }; // alphabet intersection 348 enum( @Letter@ ) Greek { Alph = A, Beta = B, ..., Zeta = Z }; // intersection 349 \end{lstlisting} 350 Subset enumerations may have more or less enumerators than their typed enumeration, but the enumerator values must be from the typed enumeration. 351 For 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@. 352 \begin{lstlisting} 260 353 Letter letter = A; 261 Greak greek = Alph;262 letter = Alph; $\C{// allowed}$354 @***@Greak greek = Beta; 355 letter = Beta; $\C{// allowed, letter == B}$ 263 356 greek = A; $\C{\color{red}// disallowed}$ 264 357 \end{lstlisting} 265 Enumeration @Greek@ may have more or less enumerators than @Letter@, but the enumerator values must be from @Letter@. 266 Therefore, @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@. 358 267 359 268 360 \subsection{Enumeration Inheritance} 269 361 270 \CFA Plan-9 inheritance may be used with enumerations. 271 \begin{lstlisting} 272 enum( char * ) Name2 { @inline Name@, Jack = "Jack", Jill = "Jill" }; 273 enum /* inferred */ Name3 { @inline Name2@, Sue = "Sue", Tom = "Tom" }; 274 \end{lstlisting} 275 Enumeration @Name2@ inherits all the enumerators and their values from enumeration @Name@ by containment, and a @Name@ enumeration is a subtype of enumeration @Name2@. 362 \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). 363 \begin{lstlisting} 364 enum( char * ) Names { /* as above */ }; 365 enum( char * ) Names2 { @inline Names@, Jack = "JACK", Jill = "JILL" }; 366 @***@enum /* inferred */ Names3 { @inline Names2@, Sue = "SUE", Tom = "TOM" }; 367 \end{lstlisting} 368 Enumeration @Name2@ inherits all the enumerators and their values from enumeration @Names@ by containment, and a @Names@ enumeration is a subtype of enumeration @Name2@. 276 369 Note, enumerators must be unique in inheritance but enumerator values may be repeated. 277 370 278 371 The enumeration type for the inheriting type must be the same as the inherited type; 279 372 hence the enumeration type may be omitted for the inheriting enumeration and it is inferred from the inherited enumeration, as for @Name3@. 280 When inheriting from integral types, automatic numbering may be used, so the inheritance placement left to right is important. 281 282 Specifically, the inheritance relationship for Names is: 283 \begin{lstlisting} 284 Name $\(\subset\)$ Name2 $\(\subset\)$ Name3 $\(\subset\)$ const char * // enum type of Name 373 % When inheriting from integral types, automatic numbering may be used, so the inheritance placement left to right is important. 374 Specifically, the inheritance relationship for @Names@ is: 375 \begin{lstlisting} 376 Names $\(\subset\)$ Names2 $\(\subset\)$ Names3 $\(\subset\)$ const char * $\C{// enum type of Names}$ 285 377 \end{lstlisting} 286 378 For the given function prototypes, the following calls are valid. … … 288 380 \begin{tabular}{ll} 289 381 \begin{lstlisting} 290 void f( Name );291 void g( Name 2 );292 void h( Name 3 );382 void f( Names ); 383 void g( Names2 ); 384 void h( Names3 ); 293 385 void j( const char * ); 294 386 \end{lstlisting} … … 298 390 g( Fred ); g( Jill ); 299 391 h( Fred ); h( Jill ); h( Sue ); 300 j( Fred ); j( Jill ); j( Sue ); j( "W ill" );392 j( Fred ); j( Jill ); j( Sue ); j( "WILL" ); 301 393 \end{lstlisting} 302 394 \end{tabular} 303 395 \end{cquote} 304 Note, 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. 305 306 \subsection{Enumerator Scoping} 307 308 A \CFA-enum can be scoped, meaning the enumerator constants are not projected into the enclosing scope. 309 \begin{lstlisting} 310 enum Weekday @!@ { /* as above */ }; 311 enum Colour( char * ) @!@ { /* as above */ }; 312 \end{lstlisting} 313 where the @'!'@ implies the enumerators are \emph{not} projected. 314 The enumerators of a scoped enumeration are accessed using qualifications, like the fields of an aggregate. 315 % The syntax of $qualified\_expression$ for \CFA-enum is the following: 316 % $$<qualified\_expression> := <enum\_type>.<enumerator>$$ 317 \begin{lstlisting} 318 Weekday weekday = @Weekday.Monday@; $\C{// qualification}$ 319 Colour colour = @Colour.@Red; 320 colour = @Colour.@Blue; 321 \end{lstlisting} 396 Note, 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. 397 322 398 323 399 \subsection{Enumeration Pseudo-functions} 324 400 325 Pseudo-functions are function-like operators that do not result in any run-time computations, i.e., like @sizeof@ .401 Pseudo-functions are function-like operators that do not result in any run-time computations, i.e., like @sizeof@, @offsetof@, @typeof@. 326 402 Often 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.. 327 403 328 \subsubsection{Enumerator Attributes}329 404 The attributes of an enumerator are accessed by pseudo-functions @position@, @value@, and @label@. 330 405 \begin{lstlisting} 331 int green_pos = @position@( Colour.Green ); $\C{// 1}$ 332 char * green_value = @value@( Colour.Green ); $\C{// "G"}$ 333 char * green_label = @label@( Colour.Green ); $\C{// "Green"}$ 334 \end{lstlisting} 335 336 Enumeration Greek may have more or less enumerators than Letter, but the enumerator values must be from Letter. 337 Therefore, 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. 338 339 % An instance of \CFA-enum (denoted as @<enum_instance>@) is a label for the defined enum name. 340 % The label can be retrieved by calling the function @label( <enum_instance> )@. 341 % Similarly, the @value()@ function returns the value used to initialize the \CFA-enum. 342 343 \subsubsection{\lstinline{enumerate()}} 344 345 \begin{lstlisting}[label=lst:c_switch] 346 enum(int) C_ENUM { First, Second, Third = First, Fourth }; 347 int v( C_ENUM e ) { 348 switch( e ) { 349 case First: return 0; break; 350 case Second: return 1; break; 351 // case Third: return 2; break; 352 // case Fourth: return 3; break; 353 }; 354 }; 355 \end{lstlisting} 356 In the @C_ENUM@ example, @Third@ is an alias of @First@ and @Fourth@ is an alias of @Second@. 357 Programmers cannot make case branches for @Third@ and @Fourth@ because the switch statement matches cases by the enumerator's value. 358 Case @First@ and @Third@, or @Second@ and @Fourth@, has duplicate case values. 359 360 @enumerate()@ is a pseudo-function that makes the switch statement match by an enumerator instead. 361 \begin{lstlisting}[label=lst:c_switch_enumerate] 362 enum(double) C_ENUM { First, Second, Third = First, Fourth }; 363 C_ENUM variable_a = First, variable_b = Second, variable_c = Third, variable_d = Fourth; 364 int v(C_ENUM e) { 365 switch( enumeratate( e ) ) { 366 case First: return e; break; 367 case Second: return value( e ); break; 368 case Third: return label( e ); break; 369 case Fourth: return position( e ); break; 370 }; 371 }; 406 @***@int jane_pos = @position@( Names.Jane ); $\C{// 2}$ 407 @***@char * jane_value = @value@( Names.Jane ); $\C{// "JANE"}$ 408 @***@char * jane_label = @label@( Names.Jane ); $\C{// "Jane"}$ 409 sout | @label@( Names.Jane ) | @value@( Names.Jane ); 410 \end{lstlisting} 411 Note the ability to print both enumerator label and value. 412 413 414 \subsection{Enumerator Position or Value} 415 416 Enumerators can be used in multiple contexts. 417 In most programming languages, an enumerator is implicitly converted to its value (like a typed macro substitution). 418 However, enumerator synonyms and typed enumerations make this implicit conversion to value incorrect in some contexts. 419 In these contexts, a programmer's initition assumes an implicit conversion to postion. 420 421 For 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. 422 \begin{cquote} 423 \begin{lstlisting} 424 enum Count { First, Second, Third, Fourth }; 425 Count e; 426 \end{lstlisting} 427 \begin{tabular}{ll} 428 \begin{lstlisting} 429 430 choose( e ) { 431 case @First@: ...; 432 case @Second@: ...; 433 case @Third@: ...; 434 case @Fourth@: ...; 435 } 436 \end{lstlisting} 437 & 438 \begin{lstlisting} 439 // rewrite 440 choose( @value@( e ) ) { 441 case @value@( First ): ...; 442 case @value@( Second ): ...; 443 case @value@( Third ): ...; 444 case @value@( Fourth ): ...; 445 } 446 \end{lstlisting} 447 \end{tabular} 448 \end{cquote} 449 Here, 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. 450 However, this implementation is fragile, e.g., if the enumeration is changed to: 451 \begin{lstlisting} 452 enum Count { First, Second, Third @= First@, Fourth }; 453 \end{lstlisting} 454 which make @Third == First@ and @Fourth == Second@, causing a compilation error because of duplicase @case@ clauses. 455 To better match with programmer intuition, \CFA toggles between value and position semantics depneding on the language context. 456 For conditional clauses and switch statments, \CFA uses the robust position implementation. 457 \begin{lstlisting} 458 choose( @position@( e ) ) { 459 case @position@( First ): ...; 460 case @position@( Second ): ...; 461 case @position@( Third ): ...; 462 case @position@( Fourth ): ...; 463 } 464 \end{lstlisting} 465 466 \begin{lstlisting} 467 Count variable_a = First, variable_b = Second, variable_c = Third, variable_d = Fourth; 372 468 p(variable_a); // 0 373 469 p(variable_b); // 1 … … 1015 1111 If the @aggregation_name@ is identified as a \CFA enumeration, the compiler checks if @field@ presents in the declared \CFA enumeration. 1016 1112 1017 \subsection{\lstinline{with} Clause/Statement}1018 1019 Instead of qualifying an enumeration expression every time, the @with@ can be used to expose enumerators to the current scope, making them directly accessible.1020 \begin{lstlisting}[label=lst:declaration]1021 enum Color( char * ) { Red="R", Green="G", Blue="B" };1022 enum Animal( int ) { Cat=10, Dog=20 };1023 with ( Color, Animal ) {1024 char * red_string = Red; // value( Color.Red )1025 int cat = Cat; // value( Animal.Cat )1026 }1027 \end{lstlisting}1028 The \lstinline{with} might introduce ambiguity to a scope. Consider the example:1029 \begin{lstlisting}[label=lst:declaration]1030 enum Color( char * ) { Red="R", Green="G", Blue="B" };1031 enum RGB( int ) { Red=0, Green=1, Blue=2 };1032 with ( Color, RGB ) {1033 // int red = Red;1034 }1035 \end{lstlisting}1036 \CFA will not try to resolve the expression with ambiguity. It would report an error. In this case, it is necessary to qualify @Red@ even inside of the \lstinline{with} clause.1037 1038 1113 \subsection{Instance Declaration} 1039 1114 … … 1218 1293 1219 1294 \subsection{\CC} 1220 1221 \CC is backwards compatible with C, so it inherited C's enumerations, except there is no implicit conversion from an integral value to an enumeration; 1222 hence, the values in a \CC enumeration can only be its enumerators (without a cast). 1223 There is no mechanism to iterate through an enumeration. 1224 1225 \CC{11} added a scoped enumeration, \lstinline[language=c++]{enum class} (or \lstinline[language=c++]{enum struct}), so the enumerators are local to the enumeration and must be accessed using type qualification, e.g., @Weekday::Monday@. 1295 \label{s:C++RelatedWork} 1296 1297 \CC is backwards compatible with C, so it inherited C's enumerations. 1298 However, the following non-backwards compatible changes have been made. 1299 \begin{quote} 1300 7.2 Change: \CC objects of enumeration type can only be assigned values of the same enumeration type. 1301 In C, objects of enumeration type can be assigned values of any integral type. \\ 1302 Example: 1303 \begin{lstlisting} 1304 enum color { red, blue, green }; 1305 color c = 1; $\C{// valid C, invalid C++}$ 1306 \end{lstlisting} 1307 \textbf{Rationale}: The type-safe nature of C++. \\ 1308 \textbf{Effect on original feature}: Deletion of semantically well-defined feature. \\ 1309 \textbf{Difficulty of converting}: Syntactic transformation. (The type error produced by the assignment can be automatically corrected by applying an explicit cast.) \\ 1310 \textbf{How widely used}: Common. 1311 \end{quote} 1312 \begin{quote} 1313 7.2 Change: In \CC, the type of an enumerator is its enumeration. 1314 In C, the type of an enumerator is @int@. \\ 1315 Example: 1316 \begin{lstlisting} 1317 enum e { A }; 1318 sizeof(A) == sizeof(int) $\C{// in C}$ 1319 sizeof(A) == sizeof(e) $\C{// in C++}$ 1320 /* and sizeof(int) is not necessary equal to sizeof(e) */ 1321 \end{lstlisting} 1322 \textbf{Rationale}: In C++, an enumeration is a distinct type. \\ 1323 \textbf{Effect on original feature}: Change to semantics of well-defined feature. \\ 1324 \textbf{Difficulty of converting}: Semantic transformation. \\ 1325 \textbf{How widely used}: Seldom. The only time this affects existing C code is when the size of an enumerator is taken. 1326 Taking the size of an enumerator is not a common C coding practice. 1327 \end{quote} 1328 Hence, the values in a \CC enumeration can only be its enumerators (without a cast). 1329 While the storage size of an enumerator is up to the compiler, there is still an implicit cast to @int@. 1330 \begin{lstlisting} 1331 enum E { A, B, C }; 1332 E e = A; 1333 int i = A; i = e; $\C{// implicit casts to int}$ 1334 \end{lstlisting} 1335 \CC{11} added a scoped enumeration, \lstinline[language=c++]{enum class} (or \lstinline[language=c++]{enum struct}), so the enumerators are local to the enumeration and must be accessed using type qualification. 1336 \begin{lstlisting}[language=c++,{moredelim=**[is][\color{red}]{@}{@}}] 1337 enum class E { A, B, C }; 1338 E e = @E::@A; $\C{// qualified enumerator}$ 1339 e = B; $\C{// B not in scope}$ 1340 \end{lstlisting} 1226 1341 \CC{20} supports unscoped access with a \lstinline[language=c++]{using enum} declaration. 1227 1228 For both unscoped and scoped enumerations, the underlying type is an implementation-defined integral type large enough to hold all enumerated values; it does not have to be the smallest possible type.1229 In \CC{11}, the underlying integral type can be explicitly specified:1230 1342 \begin{lstlisting}[language=c++,{moredelim=**[is][\color{red}]{@}{@}}] 1231 enum class RGB : @long@ { Red, Green, Blue }; 1232 enum class rgb : @char@ { Red = 'r', Green = 'g', Blue = 'b' }; 1233 enum class srgb : @signed char@ { Red = -1, Green = 0, Blue = 1 }; 1234 RGB colour1 = @RGB::@Red; 1235 rgb colour2 = @rgb::@Red; 1236 srgb colour3 = @srgb::@Red; 1237 \end{lstlisting} 1343 enum class E { A, B, C }; 1344 @using enum E;@ 1345 E e = A; $\C{// direct access}$ 1346 e = B; $\C{// direct access}$ 1347 \end{lstlisting} 1348 \CC{11} added the ability to explicitly declare the underlying integral type for \lstinline[language=c++]{enum class}. 1349 \begin{lstlisting}[language=c++,{moredelim=**[is][\color{red}]{@}{@}}] 1350 enum class RGB @: long@ { Red, Green, Blue }; 1351 enum class rgb @: char@ { Red = 'r', Green = 'g', Blue = 'b' }; 1352 enum class srgb @: signed char@ { Red = -1, Green = 0, Blue = 1 }; 1353 \end{lstlisting} 1354 There is no implicit conversion from the \lstinline[language=c++]{enum class} type and to its type. 1355 \begin{lstlisting}[language=c++,{moredelim=**[is][\color{red}]{@}{@}}] 1356 rgb crgb = rgb::Red; 1357 char ch = rgb::Red; ch = crgb; $\C{// disallowed}$ 1358 \end{lstlisting} 1359 Finally, there is no mechanism to iterate through an enumeration nor use the enumeration type to declare an array dimension. 1360 1238 1361 1239 1362 \subsection{Go}
Note:
See TracChangeset
for help on using the changeset viewer.