Changeset 6abb6dc
- Timestamp:
- Aug 10, 2024, 10:27:26 AM (5 weeks ago)
- Branches:
- master
- Children:
- 774c97e
- Parents:
- 2ca7fc2 (diff), 5ca5263 (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. - Files:
-
- 2 added
- 6 deleted
- 20 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/jiada_liang_MMath/CFAenum.tex
r2ca7fc2 r6abb6dc 1 \chapter{\ CFAEnumeration}2 3 \CFA extends C-Style enumeration by adding a number of new features that bring enumerations in line with other modern programming languages.4 Any enumeration extensions must be intuitive to C programmers bothin syntax and semantics.5 The following sections detail all ofmy new contributions to enumerations in \CFA.6 7 8 \section{ EnumerationSyntax}9 10 \CFA extends the C enumeration declaration \see{\VRef{s:CEnumeration}} by parameterizing with a type (like a generic type) , and adding Plan-9 inheritance \see{\VRef{s:EnumerationInheritance}} using an @inline@ to another enumeration type.1 \chapter{\texorpdfstring{\CFA}{Cforall} Enumeration} 2 3 \CFA extends C-Style enumeration by adding a number of new features that bring enumerations in line with other modern programming languages. 4 Any enumeration extensions must be intuitive to C programmers in syntax and semantics. 5 The following sections detail my new contributions to enumerations in \CFA. 6 7 8 \section{Syntax} 9 10 \CFA extends the C enumeration declaration \see{\VRef{s:CEnumeration}} by parameterizing with a type (like a generic type) and adding Plan-9 inheritance \see{\VRef{s:CFAInheritance}} using an @inline@ to another enumeration type. 11 11 \begin{cfa}[identifierstyle=\linespread{0.9}\it] 12 12 $\it enum$-specifier: … … 24 24 25 25 26 \section{ EnumerationOperations}26 \section{Operations} 27 27 28 28 \CFA enumerations have access to the three enumerations properties \see{\VRef{s:Terminology}}: label, order (position), and value via three overloaded functions @label@, @posn@, and @value@ \see{\VRef{c:trait} for details}. … … 43 43 A A @0@ 3 44 44 \end{cfa} 45 Finally, there is an additional enumeration routine @countof@ (like @sizeof@, @typeof@) that returns the number of enumerators in an enumeration. 46 \begin{cfa} 47 enum(int) E { A, B, C, D }; 48 countof( E ); // 4 49 \end{cfa} 50 This auto-generated function replaces the C idiom for automatically computing the number of enumerators \see{\VRef{s:Usage}}. 45 Finally, \CFA introduces an additional enumeration pseudo-function @countof@ (like @sizeof@, @typeof@) that returns the number of enumerators in an enumeration. 46 \begin{cfa} 47 enum(int) E { A, B, C, D } e; 48 countof( E ); // 4, type argument 49 countof( e ); // 4, variable argument 50 \end{cfa} 51 This built-in function replaces the C idiom for automatically computing the number of enumerators \see{\VRef{s:Usage}}. 51 52 \begin{cfa} 52 53 enum E { A, B, C, D, @N@ }; // N == 4 … … 55 56 The underlying representation of \CFA enumeration object is its position, saved as an integral type. 56 57 Therefore, the size of a \CFA enumeration is consistent with a C enumeration. 57 Attribute function @posn@ performs type substitution on an expression from \CFA type to integral type. 58 The label and value of an enumerator is stored in a global data structure for each enumeration, where attribute functions @label@/@value@ map an \CFA enumeration object to the corresponding data. 59 These operations do not apply to C Enums because backwards compatibility means the necessary backing data structures cannot be supplied. 58 Attribute function @posn@ performs type substitution on an expression from \CFA type to an integral type. 59 The label and value of an enumerator are stored in a global data structure for each enumeration, where attribute functions @label@/@value@ map an \CFA enumeration object to the corresponding data. 60 These operations do not apply to C Enums because backward compatibility means the necessary backing data structures cannot be supplied. 61 60 62 61 63 \section{Opaque Enumeration} 62 64 \label{s:OpaqueEnum} 63 65 64 When an enumeration type is empty is itan \newterm{opaque} enumeration.66 When an enumeration type is empty. it is an \newterm{opaque} enumeration. 65 67 \begin{cfa} 66 68 enum@()@ Mode { O_RDONLY, O_WRONLY, O_CREAT, O_TRUNC, O_APPEND }; 67 69 \end{cfa} 68 Here, the internal representation is chosen by the compiler andhidden, so the enumerators cannot be initialized.69 Compared to the C enum, opaque enums are more restrictive in terms oftyping and cannot be implicitly converted to integers.70 Here, the compiler chooses the internal representation, which is hidden, so the enumerators cannot be initialized. 71 Compared to the C enum, opaque enums are more restrictive regarding typing and cannot be implicitly converted to integers. 70 72 \begin{cfa} 71 73 Mode mode = O_RDONLY; 72 74 int www @=@ mode; $\C{// disallowed}$ 73 75 \end{cfa} 74 Opaque enumerations have only two attribute properties @label@ and @posn@.76 Opaque enumerations have only two attribute properties, @label@ and @posn@. 75 77 \begin{cfa} 76 78 char * s = label( O_TRUNC ); $\C{// "O\_TRUNC"}$ 77 79 int open = posn( O_WRONLY ); $\C{// 1}$ 78 80 \end{cfa} 79 The equality and relational operations are available.81 Equality and relational operations are available. 80 82 \begin{cfa} 81 83 if ( mode @==@ O_CREAT ) ... … … 87 89 \label{s:EnumeratorTyping} 88 90 89 When an enumeration type is specified, all enumerators have that type and can be initialized with constants of that type or compile-time convert able to that type.90 Figure~\ref{f:EumeratorTyping} shows a series of examples illustrating that all \CFA types can be use with an enumeration and each type's valuesused to set the enumerator constants.91 Note ,the use of the synonyms @Liz@ and @Beth@ in the last declaration.91 When an enumeration type is specified, all enumerators have that type and can be initialized with constants of that type or compile-time convertible to that type. 92 Figure~\ref{f:EumeratorTyping} shows a series of examples illustrating that all \CFA types can be used with an enumeration, and each type's values are used to set the enumerator constants. 93 Note the use of the synonyms @Liz@ and @Beth@ in the last declaration. 92 94 Because enumerators are constants, the enumeration type is implicitly @const@, so all the enumerator types in Figure~\ref{f:EumeratorTyping} are logically rewritten with @const@. 93 95 … … 130 132 }; 131 133 \end{cfa} 132 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.134 Note that 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. 133 135 134 136 While the enumeration type can be any C aggregate, the aggregate's \CFA constructors are \emph{not} used to evaluate an enumerator's value. … … 162 164 bar( x ); $\C{// costs (1, 0, 0, 0, 0, 0, 0, 0) or (0, 1, 0, 0, 0, 0, 0, 0)}$ 163 165 \end{cfa} 164 Here, candidate (1) has a value conversion cost to convert to the base type, while candidate (2) has an unsafe conversion from @double@ to @int@. 166 Here, the candidate (1) has a @value@ conversion cost to convert to the base type, while the candidate (2) has an @unsafe@ conversion from @double@ to @int@, 167 which is a more expensive conversion. 165 168 Hence, @bar( x )@ resolves @x@ as type @Math@. 166 169 … … 176 179 177 180 \section{Auto Initialization} 178 179 A partially implemented feature is auto-initialization, which works for the C integral type with constant expressions. 180 \begin{cfa} 181 enum Week { Mon, Tue, Wed, Thu@ = 10@, Fri, Sat, Sun }; // 0-2, 10-13 182 \end{cfa} 183 The complexity of the constant expression depends on the level of 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. 184 185 If \CFA had powerful compilation expression evaluation, auto initialization would be implemented as follows. 186 \begin{cfa} 187 enum E(T) { A, B, C }; 188 \end{cfa} 181 \CFA extends C's auto-initialization scheme to \CFA enumeration. For an enumeration type with base type T, the initialization scheme is the following: 189 182 \begin{enumerate} 190 \item the first enumerator , @A@,is initialized with @T@'s @zero_t@.191 \item otherwise, the next enumerator is initialized with the previous enumerator's value using operator @?++@, where @?++( T )@ can be overloaded for any type @T@.183 \item the first enumerator is initialized with @T@'s @zero_t@. 184 \item Every other enumerator is initialized with its previous enumerator's value "+1", where "+1" is defined in terms of overloaded operator @?+?(T, one_t)@. 192 185 \end{enumerate} 193 186 194 Unfortunately, constant expressions in C are not powerful and \CFA is only a transpiler, relying on generated C code to perform the detail work. 195 It is currently beyond the scope of the \CFA project to implement a complex runtime interpreter in the transpiler to evaluate complex expressions across multiple builtin and user-defined type. 196 Nevertheless, the necessary language concepts exist to support this feature. 197 198 199 \section{Enumeration Inheritance} 200 \label{s:EnumerationInheritance} 187 \begin{cfa} 188 struct S { int i; }; 189 S ?+?( S & s, one_t ) { return s.i++; } 190 void ?{}( S & s, zero_t ) { s.i = 0; } 191 enum(S) E { A, B, C, D }; 192 \end{cfa} 193 194 \section{Subset} 195 196 An enumeration's type can be another enumeration. 197 \begin{cfa} 198 enum( char ) Letter { A = 'A', ..., Z = 'Z' }; 199 enum( @Letter@ ) Greek { Alph = @A@, Beta = @B@, Gamma = @G@, ..., Zeta = @Z@ }; // alphabet intersection 200 \end{cfa} 201 Enumeration @Greek@ may have more or less enumerators than @Letter@, but its enumerator values \emph{must} be from @Letter@. 202 Therefore, the set of @Greek@ enumerator values in a subset of the @Letter@ enumerator values. 203 @Letter@ is type compatible with enumeration @Letter@ because value conversions are inserted whenever @Letter@ is used in place of @Greek@. 204 \begin{cfa} 205 Letter l = A; $\C{// allowed}$ 206 Greek g = Alph; $\C{// allowed}$ 207 l = Alph; $\C{// allowed, conversion to base type}$ 208 g = A; $\C{// {\color{red}disallowed}}$ 209 void foo( Letter ); 210 foo( Beta ); $\C{// allowed, conversion to base type}$ 211 void bar( Greek ); 212 bar( A ); $\C{// {\color{red}disallowed}}$ 213 \end{cfa} 214 Hence, @Letter@ enumerators are not type-compatible with the @Greek@ enumeration, but the reverse is true. 215 216 217 \section{Inheritance} 218 \label{s:CFAInheritance} 201 219 202 220 \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). 203 221 Containment is nominative: an enumeration inherits all enumerators from another enumeration by declaring an @inline statement@ in its enumerator lists. 204 222 \begin{cfa} 205 enum( char * ) Names { /* $\see{\VRef[Figure]{ s:EnumerationInheritance}}$ */};223 enum( char * ) Names { /* $\see{\VRef[Figure]{f:EumeratorTyping}}$ */ }; 206 224 enum( char * ) Names2 { @inline Names@, Jack = "JACK", Jill = "JILL" }; 207 225 enum( char * ) Names3 { @inline Names2@, Sue = "SUE", Tom = "TOM" }; … … 216 234 217 235 Inheritance can be nested, and a \CFA enumeration can inline enumerators from more than one \CFA enumeration, forming a tree-like hierarchy. 218 However, 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 inherits219 from 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 a220 common supertype (the diamond problem) ,since such would unavoidably introduce duplicate enumerator labels.236 However, the uniqueness of the enumeration name applies to enumerators, including those from supertypes, meaning an enumeration cannot name an enumerator with the same label as its subtype's members or inherits 237 from multiple enumeration that has overlapping enumerator labels. Consequently, a new type cannot inherit from an enumeration and its supertype or two enumerations with a 238 common supertype (the diamond problem) since such would unavoidably introduce duplicate enumerator labels. 221 239 222 240 The base type must be consistent between subtype and supertype. 223 When an enumeration inherits enumerators from another enumeration, it copies the enumerators' @value@ and @label@, even if the @value@ is auto 241 When an enumeration inherits enumerators from another enumeration, it copies the enumerators' @value@ and @label@, even if the @value@ is auto-initialized. 224 242 However, the position of the underlying representation is the order of the enumerator in the new enumeration. 225 243 \begin{cfa} 226 enum() E1 { A };227 enum() E2 { B, C };228 enum() E3 { inline E1, inline E2, D };229 \end{cfa} 230 Here, @A@ has position 0 in @E1@ and @E3@. 231 @B@ has position 0 in @E2@ and 1 in @E3@.232 @C@ has position 1 in @E2@ and position 2 in @E3@.233 @D@ has position 3 in @E3@.234 235 A subtype enumeration can be casted, or implicitly converted into its supertype, with a @safe@ cost .244 enum() E1 { B }; $\C{// B}$ 245 enum() E2 { C, D }; $\C{// C D}$ 246 enum() E3 { inline E1, inline E2, E }; $\C{// {\color{red}[\(_{E1}\)} B {\color{red}]} {\color{red}[\(_{E2}\)} C D {\color{red}]} E}$ 247 enum() E4 { A, inline E3, F}; $\C{// A {\color{blue}[\(_{E3}\)} {\color{red}[\(_{E1}\)} B {\color{red}]} {\color{red}[\(_{E2}\)} C D {\color{red}]} E {\color{blue}]} F}$ 248 \end{cfa} 249 In the example, @B@ is at position 0 in @E1@ and @E3@, but position 1 in @E4@ as @A@ takes position 0 in @E4@. 250 @C@ is at position 0 in @E2@, 1 in @E3@, and 2 in @E4@. 251 @D@ is at position 1 in @E2@, 2 in @E3@, and 3 in @E4@. 252 253 A subtype enumeration can be casted, or implicitly converted into its supertype, with a @safe@ cost, called \newterm{enumeration conversion}. 236 254 \begin{cfa} 237 255 enum E2 e2 = C; 238 posn( e2 ); $\C[1.75in]{// 1}$239 enum E3 e3 = e2; 240 posn( e2 ); $\C{// 2}$256 posn( e2 ); $\C[1.75in]{// 0}$ 257 enum E3 e3 = e2; $\C{// Assignment with enumeration conversion E2 to E3}$ 258 posn( e2 ); $\C{// 1 cost}$ 241 259 void foo( E3 e ); 242 foo( e2 ); 243 posn( (E3)e2 ); $\C{// 2}$244 E3 e31 = B; 245 posn( e31 ); $\C{// 1}\CRT$260 foo( e2 ); $\C{// Type compatible with enumeration conversion E2 to E3}$ 261 posn( (E3)e2 ); $\C{// Explicit cast with enumeration conversion E2 to E3}$ 262 E3 e31 = B; $\C{// No conversion: E3.B}$ 263 posn( e31 ); $\C{// 0 cost}\CRT$ 246 264 \end{cfa} 247 265 The last expression is unambiguous. 248 While both @E2.B@ and @E3.B@ are valid candidate, @E2.B@ has an associated safe cost and \CFA selects the zero cost candidate @E3.B@. 249 Hence, as discussed in \VRef{s:OpaqueEnum}, \CFA chooses position as a representation of the \CFA enum. 250 Therefore, conversion involves both a change of type and possibly position. 251 252 When converting a subtype to a supertype, its position can only be a larger value. 253 The difference between the position in the subtype and in the supertype is its \newterm{offset}. 254 \VRef[Figure]{s:OffsetSubtypeSuperType} show the algorithm to determine the offset for an subtype enumerator to its super type. 255 \PAB{You need to explain the algorithm.} 256 257 \begin{figure} 258 \begin{cfa} 259 struct Enumerator; 260 struct CFAEnum { 261 vector<variant<CFAEnum, Enumerator>> members; 262 }; 263 pair<bool, int> calculateEnumOffset( CFAEnum dst, Enumerator e ) { 264 int offset = 0; 265 for ( auto v: dst.members ) { 266 if ( v.holds_alternative<Enumerator>() ) { 267 auto m = v.get<Enumerator>(); 268 if ( m == e ) return make_pair( true, 0 ); 269 offset++; 270 } else { 271 auto p = calculateEnumOffset( v, e ); 272 if ( p.first ) return make_pair( true, offset + p.second ); 273 offset += p.second; 274 } 275 } 276 return make_pair( false, offset ); 277 } 278 \end{cfa} 279 \caption{Compute Offset from Subtype Enumerator to Super Type} 280 \label{s:OffsetSubtypeSuperType} 281 \end{figure} 266 While both @E2.B@ and @E3.B@ are valid candidates, @E2.B@ has an associated safe cost and @E3.B@ needs no conversion (@zero@ cost). 267 \CFA selects the lowest cost candidate @E3.B@. 282 268 283 269 For the given function prototypes, the following calls are valid. … … 302 288 303 289 304 \section{Enumerator Control Structures} 290 \subsection{Offset Calculation} 291 292 As discussed in \VRef{s:OpaqueEnum}, \CFA chooses position as a representation of a \CFA enumeration variable. 293 When a cast or implicit conversion moves an enumeration from subtype to supertype, the position can be unchanged or increase. 294 \CFA determines the position offset with an \newterm{offset calculation} function. 295 296 \begin{figure} 297 \begin{cfa} 298 struct Enumerator; 299 struct CFAEnum { vector<variant<CFAEnum, Enumerator>> members; string name; }; 300 inline static bool operator==(CFAEnum& lhs, CFAEnum& rhs) { return lhs.name == rhs.name; } 301 pair<bool, int> calculateEnumOffset(CFAEnum src, CFAEnum dst) { 302 int offset = 0; 303 if ( src == dst ) return make_pair(true, 0); 304 for ( auto v : dst.members ) { 305 if ( holds_alternative<Enumerator>(v) ) { 306 offset++; 307 } else { 308 auto m = get<CFAEnum>(v); 309 if ( m == src ) @return@ make_pair( true, offset ); 310 auto dist = calculateEnumOffset( src, m ); 311 if ( dist.first ) { 312 @return@ make_pair( true, offset + dist.second ); 313 } else { 314 offset += dist.second; 315 } 316 } 317 } 318 @return@ make_pair( false, offset ); 319 } 320 \end{cfa} 321 \caption{Compute Offset from Subtype Enumeration to a Supertype} 322 \label{s:OffsetSubtypeSuperType} 323 \end{figure} 324 325 Figure~\ref{s:OffsetSubtypeSuperType} shows an outline of the offset calculation in \CC. 326 Structure @CFAEnum@ represents the \CFA enumeration with a vector of variants of @CFAEnum@ or @Enumerator@. 327 The algorithm takes two @CFAEnums@ parameters, @src@ and @dst@, with @src@ being the type of expression the conversion applies to, and @dst@ being the type the expression is cast to. 328 The algorithm iterates over the members in @dst@ to find @src@. 329 If a member is an enumerator of @dst@, the positions of all subsequent members are incremented by one. 330 If the current member is @dst@, the function returns true indicating \emph{found} and the accumulated offset. 331 Otherwise, the algorithm recurses into the current @CFAEnum@ @m@ to check if its @src@ is convertible to @m@. 332 If @src@ is convertible to the current member @m@, this means @src@ is a subtype-of-subtype of @dst@. 333 The offset between @src@ and @dst@ is the sum of the offset of @m@ in @dst@ and the offset of @src@ in @m@. 334 If @src@ is not a subtype of @m@, the loop continues but with the offset shifted by the size of @m@. 335 If the loop ends, than @src@ is not convertible to @dst@, and false is returned. 336 337 338 \section{Control Structures} 305 339 306 340 Enumerators can be used in multiple contexts. … … 392 426 393 427 394 \section{ EnumerationDimension}428 \section{Dimension} 395 429 396 430 \VRef{s:EnumeratorTyping} introduces the harmonizing problem between an enumeration and secondary information. … … 409 443 \footnotetext{C uses symbol \lstinline{'='} for designator initialization, but \CFA changes it to \lstinline{':'} because of problems with tuple syntax.} 410 444 This approach is also necessary for a predefined typed enumeration (unchangeable), when additional secondary-information need to be added. 411 412 445 The array subscript operator, namely @?[?]@, is overloaded so that when a \CFA enumerator is used as an array index, it implicitly converts to its position over value to sustain data harmonization. 413 446 This behaviour can be reverted by explicit overloading: … … 415 448 float ?[?]( float * arr, E2 index ) { return arr[ value( index ) ]; } 416 449 \end{cfa} 417 Wh en an enumeration type is being used as an array dimension, \CFA adds the enumeration type to the initializer'scontext.418 As a result, @H2@'s array destinators @A@, @B@ and @C@ are resolved unambiguously to type @E2@.419 (@H1@'s destinators are also resolved unambiguously to @E1@ because @E2@ has a @value@ cost.) 420 421 422 \section{ EnumerationI/O}423 424 As 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.450 While enumerator labels @A@, @B@ and @C@ are being defined twice in different enumerations, they are unambiguous within the context. 451 Designators in @H1@ are unambiguous becasue @E2@ has a @value@ cost to @int@, which is more expensive than @safe@ cost from C-Enum @E1@ to @int@. 452 Designators in @H2@ are resolved as @E2@ because when a \CFA enumeration type is being used as an array dimension, \CFA adds the enumeration type to the initializer's resolution context. 453 454 455 \section{I/O} 456 457 As seen in multiple examples, \CFA enumerations can be printed and the default property printed is the enumerator's label, which is similar in other programming languages. 425 458 However, very few programming languages provide a mechanism to read in enumerator values. 426 459 Even the @boolean@ type in many languages does not have a mechanism for input using the enumerators @true@ or @false@. 427 460 \VRef[Figure]{f:EnumerationI/O} show \CFA enumeration input based on the enumerator labels. 428 461 When the enumerator labels are packed together in the input stream, the input algorithm scans for the longest matching string. 429 For basic types in \CFA, the rule is that the same constants used to initialize a variable in a program are available to initialize a variable using input, where string sconstants can be quoted or unquoted.462 For basic types in \CFA, the rule is that the same constants used to initialize a variable in a program are available to initialize a variable using input, where string constants can be quoted or unquoted. 430 463 431 464 \begin{figure} … … 473 506 \label{f:EnumerationI/O} 474 507 \end{figure} 475 476 508 477 509 -
doc/theses/jiada_liang_MMath/Cenum.tex
r2ca7fc2 r6abb6dc 1 \chapter{C Enumeration in \ CFA}1 \chapter{C Enumeration in \texorpdfstring{\CFA}{Cforall}} 2 2 3 \CFA supports legacy C enumeration using the same syntax for backward scompatibility.3 \CFA supports legacy C enumeration using the same syntax for backward compatibility. 4 4 A C-style enumeration in \CFA is called a \newterm{C Enum}. 5 5 The semantics of the C Enum is mostly consistent with C with some restrictions. … … 7 7 8 8 9 \section{ EnumeratorVisibility}10 \label{s: EnumeratorVisibility}9 \section{Visibility} 10 \label{s:CVisibility} 11 11 12 12 In C, unscoped enumerators present a \newterm{naming problem} when multiple enumeration types appear in the same scope with duplicate enumerator names. … … 15 15 enum E2 { @Fourth@, @Third@, @Second@, @First@ }; $\C{// same enumerator names}$ 16 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 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 18 19 19 The \CFA type-system allows extensive overloading, including enumerators. … … 42 42 43 43 44 \section{ EnumeratorScoping}44 \section{Scoping} 45 45 46 46 A C Enum can be scoped, using @'!'@, so the enumerator constants are not projected into the enclosing scope. … … 64 64 } 65 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. 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. 76 67 77 68 78 69 \section{Type Safety} 70 \label{s:TypeSafety} 79 71 80 72 As in Section~\ref{s:Usage}, C's implicit bidirectional conversion between enumeration and integral type raises a safety concern. 81 73 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 Butan integral type cannot be implicitly converted into a C enumeration because the conversion cost is set to @infinity@.74 However, an integral type cannot be implicitly converted into a C enumeration because the conversion cost is set to @infinity@. 83 75 \begin{cfa} 84 76 enum Bird { Penguin, Robin, Eagle }; … … 110 102 \item[How widely used:] Common. 111 103 \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 is128 taken. Taking the size of an enumerator is not a common C coding practice.129 \end{description}130 \end{comment} -
doc/theses/jiada_liang_MMath/background.tex
r2ca7fc2 r6abb6dc 1 1 \chapter{Background} 2 2 3 This chapter covers background material for C enumerations and \CFA features used in later discussion .3 This chapter covers background material for C enumerations and \CFA features used in later discussions. 4 4 5 5 … … 14 14 \begin{enumerate}[leftmargin=*] 15 15 \item 16 For @#define@, the programmer has toexplicitly manage the constant name and value.17 Furthermore, these C preprocessor macro names are outside of the C type-system and can incorrectly change random text in a program.16 For @#define@, the programmer must explicitly manage the constant name and value. 17 Furthermore, these C preprocessor macro names are outside the C type system and can incorrectly change random text in a program. 18 18 \item 19 19 The same explicit management is true for the @const@ declaration, and the @const@ variable cannot appear in constant-expression locations, like @case@ labels, array dimensions,\footnote{ 20 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++}.} immediate oper\-ands of assembler instructions,and occupies storage.20 C allows variable-length array declarations (VLA), so this case does work. Still, it fails in \CC, which does not support VLAs, unless it is \lstinline{g++}.} immediate oper\-ands of assembler instructions and occupies storage. 21 21 \begin{clang} 22 22 $\$$ nm test.o … … 28 28 29 29 30 \subsection{C \ lstinline{const}}30 \subsection{C \texorpdfstring{\lstinline{const}}{const}} 31 31 \label{s:Cconst} 32 32 … … 87 87 enum { Size = 20, Max = 10, MaxPlus10 = Max + 10, @Max10Plus1@, Fred = -7 }; 88 88 \end{clang} 89 Here, the aliased constants are :20, 10, 20, 21, and -7.90 Direct initialization is by a compile-time expression generatinga constant value.91 Indirect initialization (without initializer, @Max10Plus1@) is called \newterm{auto-initialization}, where enumerators are assigned values from left to right, starting at zero or the next explicitly initialized constant, incrementing by @1@.89 Here, the aliased constants are 20, 10, 20, 21, and -7. 90 Direct initialization is achieved by a compile-time expression that generates a constant value. 91 Indirect initialization (without an initializer, @Max10Plus1@) is called \newterm{auto-initialization}, where enumerators are assigned values from left to right, starting at zero or the next explicitly initialized constant, incrementing by @1@. 92 92 Because multiple independent enumerators can be combined, enumerators with the same values can occur. 93 The enumerators are rvalues, soassignment is disallowed.93 The enumerators are @rvalues@, so the assignment is disallowed. 94 94 Finally, enumerators are \newterm{unscoped}, \ie enumerators declared inside of an @enum@ are visible (projected) outside into the enclosing scope of the @enum@ type. 95 For unnamed enumerations, this semantic is requiredbecause there is no type name for scoped qualification.96 97 As noted, this kind ofaliasing declaration is not an enumeration, even though it is declared using an @enum@ in C.95 This semantic is required for unnamed enumerations because there is no type name for scoped qualification. 96 97 As noted, this aliasing declaration is not an enumeration, even though it is declared using an @enum@ in C. 98 98 While the semantics is misleading, this enumeration form matches with aggregate types: 99 99 \begin{cfa} … … 112 112 enum @Week@ { Mon, Tue, Wed, Thu@ = 10@, Fri, Sat, Sun }; 113 113 \end{clang} 114 and adopts the same semantics with respect to direct and auto intialization.114 and adopts the same semantics as direct and auto initialization. 115 115 For example, @Mon@ to @Wed@ are implicitly assigned with constants @0@--@2@, @Thu@ is explicitly set to constant @10@, and @Fri@ to @Sun@ are implicitly assigned with constants @11@--@13@. 116 116 As well, initialization may occur in any order. … … 121 121 }; 122 122 \end{clang} 123 Note ,the comma in the enumerator list can be a terminator or a separator, allowing the list to end with a dangling comma.\footnote{123 Note the comma in the enumerator list can be a terminator or a separator, allowing the list to end with a dangling comma.\footnote{ 124 124 A terminating comma appears in other C syntax, \eg the initializer list.} 125 This feature allow enumerator lines to be interchanged without moving a comma.125 This feature allows enumerator lines to be interchanged without moving a comma. 126 126 Named enumerators are also unscoped. 127 127 … … 130 130 \label{s:CenumImplementation} 131 131 132 In theory, a C enumeration \emph{variable} is an implementation-defined integral type large enough to hold all enumerator values.132 Theoretically, a C enumeration \emph{variable} is an implementation-defined integral type large enough to hold all enumerator values. 133 133 In practice, C defines @int@~\cite[\S~6.4.4.3]{C11} as the underlying type for enumeration variables, restricting initialization to integral constants, which have type @int@ (unless qualified with a size suffix). 134 134 However, type @int@ is defined as: … … 136 136 A ``plain'' @int@ object has the natural size suggested by the architecture of the execution environment (large enough to contain any value in the range @INT_MIN@ to @INT_MAX@ as defined in the header @<limits.h>@).~\cite[\S~6.2.5(5)]{C11} 137 137 \end{quote} 138 However, @int@ means a4 bytes on both 32/64-bit architectures, which does not seem like the ``natural'' size for a 64-bit architecture.139 Whereas ,@long int@ means 4 bytes on a 32-bit and 8 bytes on 64-bit architectures, and @long long int@ means 8 bytes on both 32/64-bit architectures, where 64-bit operations are simulated on 32-bit architectures.140 \VRef[Figure]{f:gccEnumerationStorageSize} shows both @gcc@ and @clang@ partially ignore this specification and type the integral size of an enumerator based its initialization.141 Hence, initialization in the range @INT_MIN@..@INT_MAX@ results in a 4-byte enumerator, and outside this range the enumerator is 8 bytes.138 However, @int@ means 4 bytes on both 32/64-bit architectures, which does not seem like the ``natural'' size for a 64-bit architecture. 139 Whereas @long int@ means 4 bytes on a 32-bit and 8 bytes on 64-bit architectures, and @long long int@ means 8 bytes on both 32/64-bit architectures, where 64-bit operations are simulated on 32-bit architectures. 140 \VRef[Figure]{f:gccEnumerationStorageSize} shows both @gcc@ and @clang@ partially ignore this specification and type the integral size of an enumerator based on its initialization. 141 Hence, initialization in the range @INT_MIN@..@INT_MAX@ results in a 4-byte enumerator, and outside this range, the enumerator is 8 bytes. 142 142 Note that @sizeof( typeof( IMin ) ) != sizeof( E )@, making the size of an enumerator different than is containing enumeration type, which seems inconsistent, \eg @sizeof( typeof( 3 ) ) == sizeof( int )@. 143 143 … … 168 168 \label{s:Usage} 169 169 170 C proves an implicit \emph{bidirectional} conversion between an enumeration and its integral type ,and between two different enumerations.170 C proves an implicit \emph{bidirectional} conversion between an enumeration and its integral type and between two different enumerations. 171 171 \begin{clang} 172 172 enum Week week = Mon; $\C{// week == 0}$ … … 178 178 @week = Winter;@ $\C{// UNDEFINED! implicit conversion to Week}$ 179 179 \end{clang} 180 While converting an enumerator to its underlying type is useful, the implicit conversion from the base or another enumeration type to an enumeration is a common source of error.180 While converting an enumerator to its underlying type is sound, the implicit conversion from the base or another enumeration type to an enumeration is a common source of error. 181 181 182 182 Enumerators can appear in @switch@ and looping statements. … … 194 194 \end{cfa} 195 195 For iterating using arithmetic to make sense, the enumerator values \emph{must} have a consecutive ordering with a fixed step between values. 196 For example, a previous gap introduced by @Thu = 10@ ,results in iterating over the values 0--13, where values 3--9 are not @Week@ values.197 Note , it is the bidirectional conversion thatallows incrementing @day@: @day@ is converted to @int@, integer @1@ is added, and the result is converted back to @Week@ for the assignment to @day@.196 For example, a previous gap introduced by @Thu = 10@ results in iterating over the values 0--13, where values 3--9 are not @Week@ values. 197 Note that the bidirectional conversion allows incrementing @day@: @day@ is converted to @int@, integer @1@ is added, and the result is converted back to @Week@ for the assignment to @day@. 198 198 For safety, \CC does not support the bidirectional conversion, and hence, an unsafe cast is necessary to increment @day@: @day = (Week)(day + 1)@. 199 199 200 There is a C idiom t o automatically compute the number of enumerators in an enumeration.200 There is a C idiom that computes the number of enumerators in an enumeration automatically. 201 201 \begin{cfa} 202 202 enum E { A, B, C, D, @N@ }; // N == 4 203 203 for ( enum E e = A; e < @N@; e += 1 ) ... 204 204 \end{cfa} 205 Here, serendipitouslythe auto-incrementing counts the number of enumerators and puts the total into the last enumerator @N@.206 This @N@ is often used as the dimension for an array assoc ated with the enumeration.205 Serendipitously, the auto-incrementing counts the number of enumerators and puts the total into the last enumerator @N@. 206 This @N@ is often used as the dimension for an array associated with the enumeration. 207 207 \begin{cfa} 208 208 E array[@N@]; … … 226 226 \end{cfa} 227 227 However, the companion idiom results in the \emph{harmonizing} problem because an update to the enumeration @Integral_Type@ often requires a corresponding update to the companion array \snake{Integral_Name}. 228 The requirement to harmonize is at bestindicated by a comment before the enumeration.228 The requirement to harmonize is, at best, indicated by a comment before the enumeration. 229 229 This issue is exacerbated if enumeration and companion array are in different translation units. 230 230 231 231 \bigskip 232 While C provides a true enumeration, it is restricted, has unsafe semantics, and does not provide useful/advanced enumeration features found in other programming languages. 233 234 \section{\CFA Polymorphism} 235 236 \subsection{Function Overloading} 237 Function overloading is programming languages feature wherein functions may share the same name, but with different function signatures. In both C++ and \CFA, function names can be overloaded 238 with different entities as long as they are different in terms of the number and type of parameters. 239 240 \section{\CFA} 241 242 \CFA in \emph{not} an object-oriented programming-language, \ie functions cannot be nested in aggregate types, and hence, there is no \newterm{receiver} notation for calling functions, \eg @obj.method(...)@, where the first argument proceeds the call and becomes an implicit first (\lstinline[language=C++]{this}) parameter. 232 While C provides a true enumeration, it is restricted, has unsafe semantics, and does not provide helpful/advanced enumeration features in other programming languages. 233 234 235 \section{\texorpdfstring{\CFA}{Cforall}} 236 237 \CFA in \emph{not} an object-oriented programming language, \ie functions cannot be nested in aggregate types, and hence, there is no \newterm{receiver} notation for calling functions, \eg @obj.method(...)@, where the first argument proceeds the call and becomes an implicit first (\lstinline[language=C++]{this}) parameter. 243 238 The following sections provide short descriptions of \CFA features needed further in the thesis. 244 Other \CFA features are presented in -situ with short explanations,or no explanation because the feature is obvious to C programmers.239 Other \CFA features are presented in situ with short or no explanation because the feature is obvious to C programmers. 245 240 246 241 247 242 \subsection{Overloading} 248 243 249 Overloading allows programmers to use the most meaningful names without fear of name clashes within a program or from external sources , like includefiles.244 Overloading allows programmers to use the most meaningful names without fear of name clashes within a program or from external sources like included files. 250 245 \begin{quote} 251 246 There are only two hard things in Computer Science: cache invalidation and naming things. --- Phil Karlton … … 253 248 Experience from \CC and \CFA developers is that the type system implicitly and correctly disambiguates the majority of overloaded names, \ie it is rare to get an incorrect selection or ambiguity, even among hundreds of overloaded (variables and) functions. 254 249 In many cases, a programmer has no idea there are name clashes, as they are silently resolved, simplifying the development process. 255 Depending on the language, ambiguous cases are resolved using some form of qualification or casting.250 Depending on the language, ambiguous cases are resolved using some form of qualification and/or casting. 256 251 257 252 … … 268 263 s1 = @?+?@( s1, s2 ); $\C{// direct call}\CRT$ 269 264 \end{cfa} 270 The type system examines each call size and selects the best matching overloaded function based on the number and types of thearguments.271 If there are intermixed operands, @2 + 3.5@, the type system attempts (safe) conversions changing the arguments to one or more ofthe parameter type(s).265 The type system examines each call size and selects the best matching overloaded function based on the number and types of arguments. 266 If there are mixed-mode operands, @2 + 3.5@, the type system, like in C/\CC, attempts (safe) conversions, converting the argument type(s) to the parameter type(s). 272 267 273 268 274 269 \subsection{Function Overloading} 275 270 276 Both \CFA and \CC allow function names to be overloaded ,as long as their prototypes differ in the number and type of parameters and returns.271 Both \CFA and \CC allow function names to be overloaded as long as their prototypes differ in the number and type of parameters and returns. 277 272 \begin{cfa} 278 273 void f( void ); $\C[1.75in]{// (1): no parameter}$ … … 282 277 \end{cfa} 283 278 In this case, the name @f@ is overloaded depending on the number and parameter types. 284 The type system examines each call size and selects the best match ing based on the number and types of thearguments.285 Here, the re is a perfect match for the call, @f( 'A' )@ withthe number and parameter type of function (2).286 287 Ada, Scala, and \CFA type-systems also use the return type in resolving a call, to pinpoint the best overloaded name.279 The type system examines each call size and selects the best match based on the number and types of arguments. 280 Here, the call @f( 'A' )@ is a perfect match for the number and parameter type of function (2). 281 282 Ada, Scala, and \CFA type-systems also use the return type to pinpoint the best-overloaded name in resolving a call. 288 283 \begin{cfa} 289 284 int f( void ); $\C[1.75in]{// (4); overloaded on return type}$ … … 307 302 } 308 303 \end{cfa} 309 The \CFA type system simplytreats overloaded variables as an overloaded function returning a value with no parameters.304 The \CFA type system treats overloaded variables as an overloaded function returning a value with no parameters. 310 305 Hence, no significant effort is required to support this feature. 311 306 … … 313 308 \subsection{Constructor and Destructor} 314 309 315 While \CFA i n not objectoriented, it adopts many language features commonly used in object-oriented languages;316 these features are independent fromobject-oriented programming.310 While \CFA is not object-oriented, it adopts many language features commonly used in object-oriented languages; 311 these features are independent of object-oriented programming. 317 312 318 313 All objects in \CFA are initialized by @constructors@ \emph{after} allocation and de-initialized \emph{before} deallocation. 319 \CC cannot have constructors for basic -types because they have no aggregate type \lstinline[language=C++]{struct/class} in which to insert a constructor definition.314 \CC cannot have constructors for basic types because they have no aggregate type \lstinline[language=C++]{struct/class} in which to insert a constructor definition. 320 315 Like \CC, \CFA has multiple auto-generated constructors for every type. 321 316 322 317 The prototype for the constructor/destructor are @void ?{}( T &, ... )@ and @void ^?{}( T &, ... )@, respectively. 323 The first parameter is logically , the \lstinline[language=C++]{this} or \lstinline[language=Python]{self} in other object-oriented languages,and implicitly passed.318 The first parameter is logically the \lstinline[language=C++]{this} or \lstinline[language=Python]{self} in other object-oriented languages and implicitly passed. 324 319 \VRef[Figure]{f:CFAConstructorDestructor} shows an example of creating and using a constructor and destructor. 325 320 Both constructor and destructor can be explicitly called to reuse a variable. … … 355 350 356 351 The C constants @0@ and @1@ have special meaning. 357 @0@ is the null pointer and used in conditional expressions, where @if ( p )@ is rewritten @if ( p != 0 )@;352 @0@ is the null pointer and is used in conditional expressions, where @if ( p )@ is rewritten @if ( p != 0 )@; 358 353 @1@ is an additive identity in unary operators @++@ and @--@. 359 354 Aware of their significance, \CFA provides a special type @zero_t@ and @one_t@ for custom types. … … 383 378 At the call size, the type parameter @T@ is bounded to @int@ from the argument @42@. 384 379 385 For polymorphic functions to be useful, the @forall@ clause needs \newterm{type assertion}s that restrict sthe polymorphic types it accepts.380 For polymorphic functions to be useful, the @forall@ clause needs \newterm{type assertion}s that restrict the polymorphic types it accepts. 386 381 \begin{cfa} 387 382 forall( T @| { void foo( T ); }@ ) void bar( T t ) { @foo( t );@ } … … 390 385 bar( s ); 391 386 \end{cfa} 392 The assertion on @T@ restricts the range of types that can be manipulated by @bar@ to only those that have an implementation of @foo@ with the matching signature, allowing @bar@'s call to @foo@ in its body. 387 The assertion on @T@ restricts the range of types that can be manipulated by @bar@ to only those that implement @foo@ with the matching signature, allowing @bar@'s call to @foo@ in its body. 388 Unlike templates in \CC, which are macro expansions at the call site, \CFA polymorphic functions are compiled, passing the call-site assertion functions as hidden parameters. 389 393 390 394 391 \subsection{Trait} 395 A @forall@ clause can asserts on multiple types and with multiple asserting functions. A common practice in \CFA is to group396 the asserting functions in to a named \newterm{trait}.397 398 \subsection{Trait}399 392 400 393 A @forall@ clause can assert many restrictions on multiple types. 401 A common practice is to refactor the assertions into a named \newterm{trait}.394 A common practice is refactoring the assertions into a named \newterm{trait}, similar to other languages like Go and Rust. 402 395 \begin{cfa} 403 396 forall(T) trait @Bird@ { … … 414 407 bird_fly( 23, robin ); 415 408 \end{cfa} 416 Grouping type assertions into a named trait effectively creates a reusable interface for parametric -polymorphic types.409 Grouping type assertions into a named trait effectively creates a reusable interface for parametric polymorphic types. 417 410 418 411 … … 423 416 When multiple best matches exist, the resolution is ambiguous. 424 417 425 The \CFA resolver attempts to identi ty abest candidate based on: first, the number of parameters and types, and second, when no exact match exists, the fewest implicit conversions and polymorphic variables.426 Finding an exact match is not discussed here, because the mechanism is fairly straightforward, even when the search space is large;418 The \CFA resolver attempts to identify the best candidate based on: first, the number of parameters and types, and second, when no exact match exists, the fewest implicit conversions and polymorphic variables. 419 Finding an exact match is not discussed here, because the mechanism is fairly straightforward, even when the search space is ample; 427 420 only finding a non-exact match is discussed in detail. 428 421 … … 432 425 433 426 Most programming languages perform some implicit conversions among basic types to facilitate mixed-mode arithmetic; 434 otherwise, the program becomes littered with many explicit casts , which is not match programmer expectation.435 C is an aggressive language as it provides conversions among almost all of thebasic types, even when the conversion is potentially unsafe or not meaningful, \ie @float@ to @bool@.427 otherwise, the program becomes littered with many explicit casts which do not match the programmer's expectations. 428 C is an aggressive language, providing conversions among almost all basic types, even when the conversion is potentially unsafe or not meaningful, \ie @float@ to @bool@. 436 429 C defines the resolution pattern as ``usual arithmetic conversion''~\cite[\S~6.3.1.8]{C11}, in which C looks for a \newterm{common type} between operands, and converts one or both operands to the common type. 437 Loosely defined, a common type is a the smallest type in terms ofsize of representation that both operands can be converted into without losing their precision, called a \newterm{widening} or \newterm{safe conversion}.430 A common type is the smallest type in terms of the size of representation that both operands can be converted into without losing their precision, called a \newterm{widening} or \newterm{safe conversion}. 438 431 439 432 \CFA generalizes ``usual arithmetic conversion'' to \newterm{conversion cost}. … … 445 438 @poly@ is the number of polymorphic function parameters, and 446 439 \item 447 @safe@ is sum of the degree of safe (widening) conversions.440 @safe@ is the sum of the degree of safe (widening) conversions. 448 441 \end{enumerate} 449 442 Sum of degree is a method to quantify C's integer and floating-point rank. 450 Every pair of widening conversion types is assigned a \newterm{distance}, and distance between the two same typeis 0.451 For example, the distance from @char@ to @int@ is 2, distance from @int@ to @long@ is 1, and distancefrom @int@ to @long long int@ is 2.443 Every pair of widening conversion types is assigned a \newterm{distance}, and the distance between the two same types is 0. 444 For example, the distance from @char@ to @int@ is 2, from @int@ to @long@ is 1, and from @int@ to @long long int@ is 2. 452 445 This distance does not mirror C's rank system. 453 For example, the rank of @char@ and @signed char@are the same in C, but the distance from @char@ to @signed char@ is assigned 1.454 @safe@ cost is summing all pairs of argument to parameter safe conversion distances.455 Among the three costs in Bilson's model, @unsafe@ is the most significant cost and @safe@ is the least significant, with an implication that \CFA always choosea candidate with the lowest @unsafe@, if possible.456 457 For example, assume the overloaded function @foo@ is called with two @int@ parameter .458 The cost for every overloaded @foo@ has been list along:446 For example, the @char@ and @signed char@ ranks are the same in C, but the distance from @char@ to @signed char@ is assigned 1. 447 @safe@ cost is summing all pairs of arguments to parameter safe conversion distances. 448 Among the three costs in Bilson's model, @unsafe@ is the most significant cost, and @safe@ is the least significant, implying that \CFA always chooses a candidate with the lowest @unsafe@, if possible. 449 450 For example, assume the overloaded function @foo@ is called with two @int@ parameters. 451 The cost for every overloaded @foo@ has been listed along with the following: 459 452 \begin{cfa} 460 453 void foo( char, char ); $\C[2.5in]{// (1) (2, 0, 0)}$ … … 469 462 foo( i, j ); $\C{// convert j to long and call (8)}\CRT$ 470 463 \end{cfa} 471 The overloaded instances are ordered from the highest to the lowest cost, and \CFA select the last candidate (8).464 The overloaded instances are ordered from the highest to the lowest cost, and \CFA selects the last candidate (8). 472 465 473 466 In the next iteration of \CFA, Schluntz and Aaron~\cite{Moss18} expanded conversion cost to a 7-tuple with 4 additional categories, @(unsafe, poly, safe, sign, vars, specialization, reference)@, with the following interpretations: … … 476 469 \item \textit{Poly} 477 470 \item \textit{Safe} 478 \item \textit{Sign} is the number of sign/unsign variable conversion .479 \item \textit{Vars} is the number of polymorphic s type variable.480 \item \textit{Specialization} is negative value of the number of type assertion.471 \item \textit{Sign} is the number of sign/unsign variable conversions. 472 \item \textit{Vars} is the number of polymorphic type variables. 473 \item \textit{Specialization} is the negative value of the number of type assertions. 481 474 \item \textit{Reference} is number of reference-to-rvalue conversion. 482 475 \end{itemize} 483 476 The extended conversion-cost model looks for candidates that are more specific and less generic. 484 477 @vars@ disambiguates @forall( T, V ) foo( T, V )@ and @forall( T ) void foo( T, T )@, where the extra type parameter @V@ makes is more generic. 485 A more generic type means lessconstraints on its parameter types.478 A more generic type means fewer constraints on its parameter types. 486 479 \CFA favours candidates with more restrictions on polymorphism, so @forall( T ) void foo( T, T )@ has lower cost. 487 480 @specialization@ is an arbitrary count-down value starting at zero. 488 For every type assertion in @forall@ clause (no assertions in the above example), \CFA subtracts one from @specialization@.489 More type assertions mean smore constraints on argument types, making the function less generic.481 For every type assertion in the @forall@ clause (no assertions in the above example), \CFA subtracts one from @specialization@. 482 More type assertions mean more constraints on argument types, making the function less generic. 490 483 491 484 \CFA defines two special cost values: @zero@ and @infinite@. 492 A conversion cost is @zero@ when argument and parameter has an exact match, and a conversion cost is @infinite@ when there is no defined conversion betweentwo types.485 A conversion cost is @zero@ when the argument and parameter have an exact match, and a conversion cost is @infinite@ when there is no defined conversion between the two types. 493 486 For example, the conversion cost from @int@ to a @struct S@ is @infinite@. 494 487 495 In \CFA, the meaning of a C style cast is determined by its @Cast Cost@. For most cast expression resolution, a cast cost is equal to a conversion cost. 496 Cast cost exists as an independent matrix for conversion that cannot happen implcitly, while being possible with an explicit cast. These conversions are often defined to have 497 infinite conversion cost and non-infinite cast cost. 488 In \CFA, the meaning of a C-style cast is determined by its @Cast Cost@. 489 For most cast-expression resolutions, a cast cost equals a conversion cost. 490 Cast cost exists as an independent matrix for conversion that cannot happen implicitly while being possible with an explicit cast. 491 These conversions are often defined as having an infinite conversion cost and a non-infinite cast cost. -
doc/theses/jiada_liang_MMath/conclusion.tex
r2ca7fc2 r6abb6dc 2 2 \label{c:conclusion} 3 3 4 The goal of this thesis is to adapt enumeration in \CFA to be aligned with the analogous features in 5 other languages while being backward-compatiable to C. 6 The presented features are based off on tools and techniques that widely used in 7 other languages but they were adapted to better fix \CFA's feature set. Additionally, the thesis provides 8 an improvement on safety and productivity of C enumeration, including enumerator overloading, 9 name scoping and type checking. 4 The goal of this work is to extend the simple and unsafe enumeration type in the C programming language into a complex and safe enumeration type in the \CFA programming language while maintaining backward compatibility with C. 5 Within this goal, the new \CFA enumeration should align with the analogous enumeration features in other languages to match modern programming expectations. 6 Hence, the \CFA enumeration features are borrowed from a number of programming languages, but engineered to work and play with \CFA's type system and feature set. 10 7 11 To further explores the potential of enumerated types, this thesis presents a new \CFA enumeration 12 that is independent on C enumeration. The \CFA enumeration aims to solve the data harmonization problem 13 and have natural support to \CFA generic type, along with some new features that fit with \CFA's 14 programming pattern, such as enumerator conctrol structures. 8 Strong type-checking of enumeration initialization and assignment provides additional safety, ensuring an enumeration only contains its enumerators. 9 Overloading and scoping of enumerators significantly reduces the naming problem, providing a better software-engineering environment, with fewer name clashes and the ability to disambiguate those that cannot be implicitly resolved. 10 Typed enumerations solve the data-harmonization problem increasing safety through better software engineering. 11 Moreover, integrating enumerations with existing control structures provides a consistent upgrade for programmers and a succinct and secure mechanism to enumerate with the new loop-range feature. 12 Generalization and reuse are supported by incorporating the new enumeration type using the \CFA trait system. 13 Enumeration traits define the meaning of an enumeration, allowing functions to be written that work on any enumeration, such as the reading and printing an enumeration. 14 Using advanced duck typing, existing C enumerations can be extended so they work with all of the enumeration features, providing for legacy C code to be moved forward into the modern \CFA programming domain. 15 Finally, I expanded the \CFA project's test-suite with multiple enumeration features tests with respect to implicit conversions, control structures, inheritance, interaction with the polymorphic types, and the features built on top of enumeration traits. 16 These tests ensure future \CFA work does not accidentally break the new enumeration system. 15 17 16 The \CFA project's test suite has been expanded to test the enumerations with respect to its 17 implicit conversions, inheritance, interaction with the polymorphic types, and the features 18 built on top of enumeration traits. 18 The conclusion is that the new \CFA enumeration mechanisms achieve the initial goals, providing C programmers with an intuitive enumeration mechanism for handling modern programming requirements. 19 19 20 The enumerated type is an attempt to adapt classic data types into \CFA unique type system. It brings21 valuable new feature to \CFA in its own right, but also serve as a motivation to adapt other data types22 in \CFA.23 20 24 %\section{Future Work}21 \section{Future Work} 25 22 23 The following are ideas to improve and extend the work in this thesis. 24 \begin{enumerate} 25 \item 26 There are still corner cases being found in the current \CFA enumeration implementation. 27 Fixing some of these corner cases requires changes to the \CFA resolver or extensions to \CFA. %, like compile-time constant-expression evaluation. 28 When these changes are made, it should be straightforward to update the \CFA enumeration implementation to work with them. 29 \item 30 Currently, some aspects of the enumeration trait system require explicitly including the file @enum.hfa@, which can lead to problems. 31 It should be possible to have this file included implicitly by updating the \CFA prelude. 32 \item 33 There are multiple \CFA features being developed in parallel with enumerations. 34 Two closely related features are iterator and namespace. 35 Enumerations may have to be modified to dovetail with these features. 36 For example, enumerating with range loops does not align with the current iterator design, so some changes will be necessary. 37 \item 38 C already provides @const@-style aliasing using the \emph{unnamed} enumerator \see{\VRef{s:TypeName}}, even if the name @enum@ is misleading (@const@ would be better). 39 Given the existence of this form, it is conceivable to extend it with types other than @int@. 40 \begin{cfa} 41 enum { Size = 20u, PI = 3.14159L, Jack = L"John" }; 42 \end{cfa} 43 which matches with @const@ aliasing in other programming languages. 44 Here, the type of the enumerator is the type of the initialization constant, \eg @typeof( 20u )@ for @Size@ implies @unsigned int@. 45 Auto-initialization is restricted to the case where all constants are @int@, matching with C. 46 As seen in \VRef{s:EnumeratorTyping}, this feature is just a shorthand for multiple typed-enumeration declarations. 47 \begin{cfa} 48 enum( unsigned int ) { Size = 20u }; 49 enum( long double ) { PI = 3.14159L }; 50 enum( wchar_t * ) { Jack = L"John" }; 51 \end{cfa} 52 \item 53 Currently enumeration scoping is all or nothing. In some cases, it might be useful to 54 increase the scoping granularity to individual enumerators. 55 \begin{cfa} 56 enum E1 { @!@A, @^@B, C }; 57 enum E2 @!@ { @!@A, @^@B, C }; 58 \end{cfa} 59 Here, @'!'@ means the enumerator is scoped, and @'^'@ means the enumerator is unscoped. 60 For @E1@, @A@ is scoped; @B@ and @C@ are unscoped. 61 For @E2@, @A@, and @C@ are scoped; @B@ is unscoped. 62 Finding a use case is important to justify this extension. 63 \item 64 An extension mentioned in \VRef{s:Ada} is using @typedef@ to create an enumerator alias. 65 \begin{cfa} 66 enum(int) RGB { @Red@, @Green@, Blue }; 67 enum(int) Traffic_Light { @Red@, Yellow, @Green@ }; 68 typedef RGB.Red OtherRed; // alias 69 \end{cfa} 70 \end{enumerate} -
doc/theses/jiada_liang_MMath/intro.tex
r2ca7fc2 r6abb6dc 1 1 \chapter{Introduction} 2 2 3 All basic types in a programming language have a set of constants (symbols), and these constants represent computable values, \eg integer types have constants @-1@, @17@, @0xff@ representing whole numbers, floating-point types have constants @5.3@, @2.3E-5@, @0xff.ffp0@ representing 3 All basic types in a programming language have a set of constants (symbols), and these constants represent computable values, \eg integer types have constants @-1@, @17@, @0xff@ representing whole numbers, floating-point types have constants @5.3@, @2.3E-5@, @0xff.ffp0@ representing real numbers, character types have constants @'a'@, @"abc\n"@, \mbox{\lstinline{u8"}\texttt{\guillemotleft{na\"{i}ve}\guillemotright}\lstinline{"}} representing (human readable) text, \etc. 4 4 Constants can be overloaded among types, \eg @0@ is a null pointer for all pointer types, and the value zero for integer and floating-point types. 5 5 (In \CFA, the constants @0@ and @1@ can be overloaded for any type.) … … 12 12 A constant's symbolic name is dictated by language syntax related to types, \eg @5.@ (double), @5.0f@ (float), @5l@ (long double). 13 13 In general, the representation of a constant's value is \newterm{opaque}, so the internal representation can be chosen arbitrarily, \eg two's complement, IEEE floating-point. 14 In theory, there arean infinite set of constant names per type representing an infinite set of values.14 In theory, there is an infinite set of constant names per type representing an infinite set of values. 15 15 16 16 It is common in mathematics, engineering, and computer science to alias new constants to existing constants so they have the same value, \eg $\pi$, $\tau$ (2$\pi$), $\phi$ (golden ratio), K(k), M, G, T for powers of 2\footnote{Overloaded with SI powers of 10.} often prefixing bits (b) or bytes (B), \eg Gb, MB, and in general situations, \eg specific times (noon, New Years), cities (Big Apple), flowers (Lily), \etc. … … 23 23 Because an aliased name is a constant, it cannot appear in a mutable context, \eg \mbox{$\pi$ \lstinline{= 42}} is meaningless, and a constant has no address, \ie it is an \newterm{rvalue}\footnote{ 24 24 The term rvalue defines an expression that can only appear on the right-hand side of an assignment expression.}. 25 In theory, there are an infinite set of possible aliasing,in practice, the number of aliasing per program is finite and small.25 In theory, there is an infinite set of possible aliasing; in practice, the number of aliasing per program is finite and small. 26 26 27 27 Aliased constants can form an (ordered) set, \eg days of a week, months of a year, floors of a building (basement, ground, 1st), colours in a rainbow, \etc. … … 59 59 \end{sloppypar} 60 60 \item 61 The alias names are constants, which follow stransitively from their binding to other constants.61 The alias names are constants, which follow transitively from their binding to other constants. 62 62 \item 63 63 Defines a type for generating instants (variables). … … 140 140 \end{cfa} 141 141 For these reasons, aliasing is sometimes called an enumeration. 142 However, there is no type to create a type-checked instance or iterator cursor, so there is no ability for enumerating.142 However, there is no type to create a type-checked instance or iterator cursor, so there is no ability to enumerate. 143 143 Hence, there are multiple enumeration aspects not provided by aliasing, justifying a separate enumeration type in a programming language. 144 144 … … 158 158 the ADT has three variants (constructors), @A@, @B@, @C@, with associated types @Int@, @Double@, and @S@. 159 159 The constructors create an initialized value of the specific type that is bound to the immutable variables @foo@, @bar@, and @baz@. 160 Hence, the ADT @Foo@ is like a union containing values of the associated types, and a constructor name is used to in tialize and access the value using dynamic pattern-matching.160 Hence, the ADT @Foo@ is like a union containing values of the associated types, and a constructor name is used to initialize and access the value using dynamic pattern-matching. 161 161 \begin{cquote} 162 162 \setlength{\tabcolsep}{20pt} … … 194 194 baz = Z 5; 195 195 \end{haskell} 196 Here, the constructor name gives different meaning to the values in the common \lstinline[language=Haskell]{Int} type, \eg the value @3@ has different interpretations depending on the constructor name in the pattern matching.196 Here, the constructor name gives different meanings to the values in the common \lstinline[language=Haskell]{Int} type, \eg the value @3@ has different interpretations depending on the constructor name in the pattern matching. 197 197 198 198 Note, the term \newterm{variant} is often associated with ADTs. 199 199 However, there are multiple languages with a @variant@ type that is not an ADT \see{Algol68~\cite{Algol68} or \CC \lstinline{variant}}. 200 Here, the type (and possibly the position for equivalent types) is used to discrimina ntthe specific \emph{variant} within the variant instance.200 Here, the type (and possibly the position for equivalent types) is used to discriminate the specific \emph{variant} within the variant instance. 201 201 For example, \VRef[Figure]{f:C++variant} shows the \CC equivalent of the two Haskell ADT types using variant types. 202 202 In these languages, the variant cannot be used to simulate an enumeration. … … 246 246 data Week = Mon | Tue | Wed | Thu | Fri | Sat | Sun deriving(Enum, Eq, Show) 247 247 \end{haskell} 248 the default type for each constructor is the unit type, and deriving from @Enum@ enforces no other associated types ,@Eq@ allows equality comparison, and @Show@ is for printing.249 The nullary constructors for the unit types are numbered left-to-right from $0$ to @maxBound@$- 1$, and provide senumerating operations @succ@, @pred@, @enumFrom@, @enumFromTo@.248 the default type for each constructor is the unit type, and deriving from @Enum@ enforces no other associated types. The @Eq@ allows equality comparison, and @Show@ is for printing. 249 The nullary constructors for the unit types are numbered left-to-right from $0$ to @maxBound@$- 1$, and provide enumerating operations @succ@, @pred@, @enumFrom@, @enumFromTo@. 250 250 \VRef[Figure]{f:HaskellEnumeration} shows enumeration comparison and iterating (enumerating). 251 251 … … 296 296 However, when extended with advanced features, enumerations become complex for both the type system and the runtime implementation. 297 297 298 The contribution of this work are:298 The contributions of this work are: 299 299 \begin{enumerate} 300 300 \item 301 overloading: provides a pattern to overload functions, literal, and variable for polymorphic enumerations. 302 \item 303 scoping: adds name space for enumerations. 304 \item 305 safety: defines a safe enumeration conversion scheme. 306 \item 307 harmonization: allows enumeration to be mapped with data. 308 \item 309 inheritance: implements containment inheritance for enumerations. 301 safety: Define a safe enumeration conversion scheme, both for C and \CFA, and replace ad-hoc C idioms with safer software-engineering approaches. 302 \item 303 overloading: Provide a pattern to overload functions, literals, and variables for polymorphic enumerations using the \CFA type system. 304 \item 305 scoping: Add a namespace for enumerations and qualified access into the namespace to deal with the naming problem. 306 \item 307 generalization: Support all language types for enumerators with associated values providing enumeration constants for any type. 308 \item 309 reuse: Implement subset and containment inheritance for enumerations. 310 \item 311 control flow: Extend control-flow structures making it safer and easier to enumerate over an enumeration. 312 \item 313 I/O: Provide input and output of enumerations based on enumerator names. 310 314 \end{enumerate} 311 315 -
doc/theses/jiada_liang_MMath/relatedwork.tex
r2ca7fc2 r6abb6dc 18 18 \end{comment} 19 19 20 Enumeration-like features exist in many popular programming languages, both past and present, \eg Pascal~\cite{Pascal}, Ada~\cite{Ada}, \Csharp~\cite{Csharp}, OCaml~\cite{OCaml} \CC, Go~\cite{Go}, Haskell~\cite{Haskell} , Java~\cite{Java}, Rust~\cite{Rust}, Swift~\cite{Swift}, Python~\cite{Python}.21 Among these s languages, there area large set of overlapping features, but each language has its own unique extensions and restrictions.20 Enumeration-like features exist in many popular programming languages, both past and present, \eg Pascal~\cite{Pascal}, Ada~\cite{Ada}, \Csharp~\cite{Csharp}, OCaml~\cite{OCaml} \CC, Go~\cite{Go}, Haskell~\cite{Haskell} \see{discussion in \VRef{s:AlgebraicDataType}}, Java~\cite{Java}, Rust~\cite{Rust}, Swift~\cite{Swift}, Python~\cite{Python}. 21 Among these languages, there is a large set of overlapping features, but each language has its own unique extensions and restrictions. 22 22 23 23 … … 39 39 \end{pascal} 40 40 Object initialization and assignment are restricted to the enumerators of this type. 41 Enumerators are auto-initialized from left to right, starting at zero ,incrementing by 1.41 Enumerators are auto-initialized from left to right, starting at zero and incrementing by 1. 42 42 Enumerators \emph{cannot} be explicitly initialized. 43 43 Pascal provides a predefined type \lstinline[language=Pascal]{Boolean} defined as: … … 56 56 \end{cquote} 57 57 58 Pascal provides \emph{consecutive} sub typing of an enumeration usingsubrange type.58 Pascal provides \emph{consecutive} subsetting of an enumeration using a subrange type. 59 59 \begin{pascal} 60 60 type Week = ( Mon, Tue, Wed, Thu, Fri, Sat, Sun ); 61 Weekday = @Mon..Fri@;62 61 Weekday = @Mon..Fri@; { subtype } 62 Weekend = @Sat..Sun@; 63 63 var day : Week; 64 65 64 wday : Weekday; 65 wend : Weekend; 66 66 \end{pascal} 67 67 Hence, the ordering of the enumerators is crucial to provide the necessary ranges. 68 There is bidirectional assignment between the enumeration and its subranges.68 There is a bidirectional assignment between the enumeration and its subranges. 69 69 \begin{pascal} 70 70 day := Sat; … … 77 77 day := wend; $\C{\{ no check \}}\CRT$ 78 78 \end{pascal} 79 There should be a static/dynamic range check to verifyvalues assigned to subtypes.79 A static/dynamic range check should be performed to verify the values assigned to subtypes. 80 80 (Free Pascal does not check and aborts in certain situations, like writing an invalid enumerator.) 81 81 … … 85 85 \begin{tabular}{@{}ll@{}} 86 86 \begin{pascal} 87 day := Mon; 87 88 if @day@ = wday then 88 89 Writeln( day ); 89 90 if @day@ <= Fri then 90 91 Writeln( 'weekday'); 91 92 92 Mon 93 weekday 93 94 \end{pascal} 94 95 & 95 96 \begin{pascal} 97 96 98 case @day@ of 97 99 Mon..Fri : … … 100 102 Writeln( 'weekend') 101 103 end; 104 weekday 102 105 \end{pascal} 103 106 \end{tabular} … … 107 110 \begin{tabular}{@{}ll@{}} 108 111 \begin{pascal} 109 day := Mon; 110 while day <= Sat do begin 112 while day <= Sun do begin 111 113 Write( day, ' ' ); 112 114 day := succ( day ); 113 115 end; 114 Mon Tue Wed Thu Fri Sat 116 Mon Tue Wed Thu Fri Sat Sun 115 117 \end{pascal} 116 118 & 117 119 \begin{pascal} 118 119 for day := Mon to Sat do begin 120 for day := Mon to Sun do begin 120 121 Write( day, ' ' ); 121 122 122 123 end; 123 Mon Tue Wed Thu Fri Sat 124 Mon Tue Wed Thu Fri Sat Sun 124 125 \end{pascal} 125 126 \end{tabular} 126 127 \end{cquote} 127 Note , subtype@Weekday@ and @Weekend@ cannot be used to define a case or loop range.128 Note that subtypes @Weekday@ and @Weekend@ cannot be used to define a case or loop range. 128 129 129 130 An enumeration type can be used as an array dimension and subscript. … … 149 150 \end{pascal} 150 151 151 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.152 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. 152 153 The integral size can be explicitly specified using compiler directive @$PACKENUM@~$N$, where $N$ is the number of bytes, \eg: 153 154 \begin{pascal} … … 160 161 161 162 \section{Ada} 163 \label{s:Ada} 162 164 163 165 An Ada enumeration type is a set of ordered, unscoped identifiers (enumerators) bound to \emph{unique} \newterm{literals}.\footnote{% … … 172 174 type Traffic_Light is ( @Red@, Yellow, @Green@ ); 173 175 \end{ada} 174 Like \CFA, Ada uses a type-resolution algorithm including the left-hand side of assignmenteto disambiguate among overloaded identifiers.175 \VRef[Figure]{f:AdaEnumeration} shows how ambiguity is handled using a cast, \ ie\lstinline[language=ada]{RGB'(Red)}.176 Like \CFA, Ada uses a type-resolution algorithm, including the left-hand side of the assignment, to disambiguate among overloaded identifiers. 177 \VRef[Figure]{f:AdaEnumeration} shows how ambiguity is handled using a cast, \eg \lstinline[language=ada]{RGB'(Red)}. 176 178 177 179 \begin{figure} … … 194 196 \end{ada} 195 197 \caption{Ada Enumeration Overload Resolution} 196 \label{f:AdaEnumeration} 198 \label{f:AdaEnumeration} 197 199 \end{figure} 198 200 … … 201 203 \begin{ada} 202 204 type Week is ( Mon, Tue, Wed, Thu, Fri, Sat, Sun ); 203 for Week use ( Mon => 0, Tue => 1, Wed => 2, Thu => @10@, Fri => 11, Sat => 14, Sun => 15 );204 \end{ada} 205 The enumeration operators are the equality and relational operators, @=@, @/=@, @<@, @<=@, @=@, @/=@, @>=@, @>@, where the ordering relationship is given implicitly by the sequence of a csending enumerators.205 for Week use ( Mon => 0, Tue => 1, Wed => 2, Thu => @10@, Fri => 11, Sat => 14, Sun => 15 ); 206 \end{ada} 207 The enumeration operators are the equality and relational operators, @=@, @/=@, @<@, @<=@, @=@, @/=@, @>=@, @>@, where the ordering relationship is given implicitly by the sequence of ascending enumerators. 206 208 207 209 Ada provides an alias mechanism, \lstinline[language=ada]{renames}, for aliasing types, which is useful to shorten package identifiers. … … 259 261 if @Flag@ then ... -- conditional 260 262 \end{ada} 261 Since only types derived from @Boolean@ can be a conditional, @Boolean@ is essentiallya builtin type.262 263 Ada provides \emph{consecutive} sub typing of an enumeration using \lstinline[language=ada]{range}.263 Since only types derived from @Boolean@ can be conditional, @Boolean@ is essentially a builtin type. 264 265 Ada provides \emph{consecutive} subsetting of an enumeration using \lstinline[language=ada]{range}. 264 266 \begin{ada} 265 267 type Week is ( Mon, Tue, Wed, Thu, Fri, Sat, Sun ); … … 325 327 \label{s:C++RelatedWork} 326 328 327 \CC enumeration is largely backward scompatible with C, so it inherited C's enumerations with some modifications and additions.329 \CC enumeration is largely backward compatible with C, so it inherited C's enumerations with some modifications and additions. 328 330 329 331 \CC has aliasing using @const@ declarations, like C \see{\VRef{s:Cconst}}, with type inferencing, plus static/dynamic initialization. … … 351 353 whereas C @const@ declarations without @static@ are marked @R@. 352 354 353 The following \CC non-backwards compatible changes are made \see{\cite[\S~7.2]{ANSI98:c++}}. 354 \begin{cquote} 355 Change: \CC objects of enumeration type can only be assigned values of the same enumeration type. 356 In C, objects of enumeration type can be assigned values of any integral type. \\ 357 Example: 358 \begin{c++} 359 enum color { red, blue, green }; 360 color c = 1; $\C{// valid C, invalid c++}$ 361 \end{c++} 362 \textbf{Rationale}: The type-safe nature of \CC. \\ 363 \textbf{Effect on original feature}: Deletion of semantically well-defined feature. \\ 364 \textbf{Difficulty of converting}: Syntactic transformation. (The type error produced by the assignment can be automatically corrected by applying an explicit cast.) \\ 365 \textbf{How widely used}: Common. 366 \end{cquote} 367 368 \begin{cquote} 369 Change: In \CC, the type of an enumerator is its enumeration. 370 In C, the type of an enumerator is @int@. \\ 355 The following \CC non-backward compatible change is made~\cite[C.1.5.7.2]{C++}, plus the safe-assignment change shown in~\VRef{s:TypeSafety}. 356 \begin{description}[parsep=0pt] 357 \item[Change:] In \CC, the type of an enumerator is its enumeration. 358 In C, the type of an enumerator is @int@. 371 359 Example: 372 360 \begin{c++} 373 361 enum e { A }; 374 362 sizeof(A) == sizeof(int) $\C{// in C}$ 375 sizeof(A) == sizeof(e) $\C{// in c++}$363 sizeof(A) == sizeof(e) $\C{// in \CC}$ 376 364 /* and sizeof(int) is not necessary equal to sizeof(e) */ 377 365 \end{c++} 378 \ textbf{Rationale}: In \CC, an enumeration is a distinct type. \\379 \ textbf{Effect on original feature}: Change to semantics of well-defined feature. \\380 \ textbf{Difficulty of converting}: Semantic transformation. \\381 \ textbf{How widely used}:Seldom. The only time this affects existing C code is when the size of an enumerator is taken.366 \item[Rationale:] In \CC, an enumeration is a distinct type. 367 \item[Effect on original feature:] Change to semantics of well-defined feature. 368 \item[Difficulty of converting:] Semantic transformation. 369 \item[How widely used:] Seldom. The only time this affects existing C code is when the size of an enumerator is taken. 382 370 Taking the size of an enumerator is not a common C coding practice. 383 \end{ cquote}371 \end{description} 384 372 Hence, the values in a \CC enumeration can only be its enumerators (without a cast). 373 385 374 While the storage size of an enumerator is up to the compiler, there is still an implicit cast to @int@. 386 375 \begin{c++} … … 444 433 0 1 2 @3 4 5 6 7 8 9@ 10 11 12 13 445 434 \end{c++} 435 As a consequence, there is no meaningful enumerating mechanism. 436 446 437 An enumeration type cannot declare an array dimension but an enumerator can be used as a subscript. 447 There is no mechanism to sub typeor inherit from an enumeration.448 449 450 \section{C\ raisebox{-0.7ex}{\LARGE$^\sharp$}\xspace} % latex bug: cannot use \relsize{2} so use \LARGE438 There is no mechanism to subset or inherit from an enumeration. 439 440 441 \section{C\texorpdfstring{\raisebox{-0.7ex}{\LARGE$^\sharp$}\xspace}{Csharp}} % latex bug: cannot use \relsize{2} so use \LARGE 451 442 \label{s:Csharp} 452 443 … … 455 446 % https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/enums 456 447 457 \Csharp is a dynamically-typed programming -language with a scoped, integral enumeration similar to \CC \lstinline[language=C++]{enum class}.448 \Csharp is a dynamically-typed programming language with a scoped, integral enumeration similar to \CC \lstinline[language=C++]{enum class}. 458 449 \begin{csharp} 459 enum Week : @long@ { Mon, Tue, Wed, Thu@ = 10@, Fri, Sat, Sun @,@ } // terminating comma450 enum Week : @long@ { Mon, Tue, Wed, Thu@ = 10@, Fri, Sat, Sun } 460 451 enum RGB { Red, Green, Blue } 461 452 \end{csharp} 462 The default underlying integral type is @int@ (no @char@), with auto-incrementing, implicit/explicit initialization, and terminating comma.453 The default underlying integral type is @int@, with auto-incrementing and implicit/explicit initialization. 463 454 A method cannot be defined in an enumeration type (extension methods are possible). 464 455 There is an explicit bidirectional conversion between an enumeration and its integral type, and an implicit conversion to the enumerator label in display contexts. … … 471 462 Console.WriteLine( Week.Fri ); $\C{// print label Fri}$ 472 463 \end{csharp} 473 The majority of the integral operators (relational and arithmetic) work with enumerations, except @*@ and @/@. 464 % The majority of the integral operators (relational and arithmetic) work with enumerations, except @*@ and @/@. 465 % Relational and arithmetic operators are defined in terms of its numeric value only. 466 % Therefore, enumerators are not ordered and not enumerable like \CC. 467 Like \CC, \Csharp defines enumeration relational and arithmetic operators in terms of value. 468 Enumerators have no defined positional meaning. 474 469 \begin{csharp} 475 day = day++ - 5; $\C{// unsafe}$470 day = day++ - 5; $\C{// value manipulation}$ 476 471 day = day & day; 477 472 \end{csharp} 473 \begin{csharp} 474 for ( Week d = Mon; d <= Sun; @d += 1@ ) { 475 Console.Write( d + " " ); 476 } 477 Mon Tue Wed @3 4 5 6 7 8 9@ Thu Fri Sat Sun 478 \end{csharp} 479 As a consequence, there is no direct meaningful enumerating mechanism. 478 480 479 481 An enumeration can be used in the @if@ and @switch@ statements. … … 502 504 \end{tabular} 503 505 \end{cquote} 504 However, there is no mechanism to iterate through an enumeration without an unsafe cast to increment and positions versus values is not handled. 505 \begin{csharp} 506 for ( Week d = Mon; d <= Sun; @d += 1@ ) { 507 Console.Write( d + " " ); 508 } 509 Mon Tue Wed @3 4 5 6 7 8 9@ Thu Fri Sat Sun 510 \end{csharp} 511 The @Enum.GetValues@ pseudo-method retrieves an array of the enumeration constants for looping over an enumeration type or variable (expensive operation). 506 507 To indirectly enumerate, \Csharp's Enum library has @Enum.GetValues@, a pseudo-method that retrieves an array of the enumeration constants for looping over an enumeration type or variable (expensive operation). 512 508 \begin{csharp} 513 509 foreach ( Week d in @Enum.GetValues@( typeof(Week) ) ) { … … 516 512 Mon 0, Tue 1, Wed 2, Thu 10, Fri 11, Sat 12, Sun 13, 517 513 \end{csharp} 518 Hence, enumerating is not supplied directly by the enumeration, but indirectly through another enumerable type, array.514 Hence, enumerating is not supplied directly by the enumeration, but indirectly through the enumerable array type. 519 515 520 516 An enumeration type cannot declare an array dimension but an enumerator can be used as a subscript. 521 There is no mechanism to sub typeor inherit from an enumeration.517 There is no mechanism to subset or inherit from an enumeration. 522 518 523 519 The @Flags@ attribute creates a bit-flags enumeration, making bitwise operators @&@, @|@, @~@ (complement), @^@ (xor) sensible. … … 533 529 534 530 535 \section{Go lang}536 \label{s:Go lang}537 538 Go langhas a no enumeration.531 \section{Go} 532 \label{s:Go} 533 534 Go has a no enumeration. 539 535 It has @const@ aliasing declarations, similar to \CC \see{\VRef{s:C++RelatedWork}}, for basic types with type inferencing and static initialization (constant expression). 540 536 \begin{Go} … … 545 541 const V = 3.1; const W = 3.1; 546 542 \end{Go} 547 Since these declarations are unmutable variables, they are unscoped and Golanghas no overloading.548 549 Go langprovides an enumeration-like feature to group together @const@ declaration into a block and introduces a form of auto-initialization.543 Since these declarations are immutable variables, they are unscoped and Go has no overloading. 544 545 Go provides an enumeration-like feature to group together @const@ declaration into a block and introduces a form of auto-initialization. 550 546 \begin{Go} 551 547 const ( R = 0; G; B ) $\C{// implicit initialization: 0 0 0}$ … … 574 570 \begin{Go} 575 571 const ( Mon = iota; Tue; Wed; // 0, 1, 2 576 @Thu = 10@; Fri; Sat; Sun = itoa ) // 10, 10, 10, 6572 @Thu = 10@; Fri; Sat; @Sun = itoa@ ) $\C{// 10, 10, 10, {\color{red}6}}$ 577 573 \end{Go} 578 Auto-initialization from \lstinline[language=Go]{iota} is restarted and \lstinline[language=Go]{iota} reinitialized with an expression containing a smost \emph{one} \lstinline[language=Go]{iota}.574 Auto-initialization from \lstinline[language=Go]{iota} is restarted and \lstinline[language=Go]{iota} reinitialized with an expression containing at most \emph{one} \lstinline[language=Go]{iota}. 579 575 \begin{Go} 580 576 const ( V1 = iota; V2; @V3 = 7;@ V4 = @iota@ + 1; V5 ) // 0 1 7 4 5 581 577 const ( Mon = iota; Tue; Wed; // 0, 1, 2 582 @Thu = 10;@ Fri = @iota - Wed + Thu - 1@; Sat; Sun ) // 10, 11, 12, 13578 @Thu = 10;@ Fri = @iota@ - Wed + Thu - 1; Sat; Sun ) // 10, 11, 12, 13 583 579 \end{Go} 584 Here, @V4@ and @Fri@ restart auto-incrementing from \lstinline[language=Go]{iota} and reset \lstinline[language=Go]{iota} to 4 and 11, respectively, because of the in tialization expressions containing \lstinline[language=Go]{iota}.580 Here, @V4@ and @Fri@ restart auto-incrementing from \lstinline[language=Go]{iota} and reset \lstinline[language=Go]{iota} to 4 and 11, respectively, because of the initialization expressions containing \lstinline[language=Go]{iota}. 585 581 Note, because \lstinline[language=Go]{iota} is incremented for an explicitly initialized identifier or @_@, 586 582 at @Fri@ \lstinline[language=Go]{iota} is 4 requiring the minus one to compute the value for @Fri@. … … 625 621 A basic Java enumeration is an opaque enumeration, where the enumerators are constants. 626 622 \begin{Java} 627 enum Week { 628 Mon, Tue, Wed, Thu, Fri, Sat, Sun; 629 } 623 enum Week { Mon, Tue, Wed, Thu, Fri, Sat, Sun; } 630 624 Week day = Week.Sat; 631 625 \end{Java} 632 The enumerator s members are scoped and cannot be made \lstinline[language=java]{public}, hence requirequalification.626 The enumerator's members are scoped and cannot be made \lstinline[language=java]{public}, hence requiring qualification. 633 627 The value of an enumeration instance is restricted to its enumerators. 634 628 635 The position (ordinal) and label are accessible but there is no value.629 The position (ordinal) and label (name) are accessible but there is no value property. 636 630 \begin{Java} 637 631 System.out.println( day.!ordinal()! + " " + !day! + " " + day.!name()! ); … … 639 633 \end{Java} 640 634 Since @day@ has no value, it prints its label (name). 641 The member @valueOf@ is the inverse of @name@ converting a string to enumerator.635 The member @valueOf@ is the inverse of @name@ converting a string to an enumerator. 642 636 \begin{Java} 643 637 day = Week.valueOf( "Wed" ); … … 693 687 Notice enumerators in the @switch@ statement do not require qualification. 694 688 695 There are no arith emtic operations on enumerations, so there is no arithmetic way to iterate through an enumeration without making the implementation type \lstinline[language=Java]{public}.689 There are no arithmetic operations on enumerations, so there is no arithmetic way to iterate through an enumeration without making the implementation type \lstinline[language=Java]{public}. 696 690 Like \Csharp, looping over an enumeration is done using method @values@, which returns an array of enumerator values (expensive operation). 697 691 \begin{Java} … … 782 776 #[repr(u8)] 783 777 enum ADT { 784 I(isize) @= 5@, // ???778 I(isize) @= 5@, 785 779 F(f64) @= 10@, 786 780 S(S) @= 0@, … … 791 785 Through this integral tag, it is possible to enumerate, and when all tags represent the unit type, it behaves like \CC \lstinline[language=C++]{enum class}. 792 786 When tags represent non-unit types, Rust largely precludes accessing the tag because the semantics become meaningless. 793 Hence, the two mechanisms are largely disjoint, and on y the enumeration component is discussed.794 795 In detail, the @enum@ type has an implicit integer tag (discriminant) ,with a unique value for each variant type.796 Direct initialization is by a compile-time expression generatinga constant value.787 Hence, the two mechanisms are largely disjoint, and only the enumeration component is discussed. 788 789 In detail, the @enum@ type has an implicit integer tag (discriminant) with a unique value for each variant type. 790 Direct initialization is achieved by a compile-time expression that generates a constant value. 797 791 Indirect initialization (without initialization, @Fri@/@Sun@) is auto-initialized: from left to right, starting at zero or the next explicitly initialized constant, incrementing by @1@. 798 792 There is an explicit cast from the tag to integer. … … 829 823 \end{c++} 830 824 An enumeration type cannot declare an array dimension nor as a subscript. 831 There is no mechanism to sub typeor inherit from an enumeration.825 There is no mechanism to subset or inherit from an enumeration. 832 826 833 827 … … 878 872 \end{tabular} 879 873 \end{cquote} 880 (Note, after an @adt@'s type is know, the enumerator is inferred without qualification, \eg @.I(3)@.) 874 Note, after an @adt@'s type is know, the enumerator is inferred without qualification, \eg @.I(3)@. 881 875 882 876 An enumeration is created when \emph{all} the enumerators are unit-type, which is like a scoped, opaque enumeration. 883 877 \begin{swift} 884 enum Week { 885 case Mon, Tue, Wed, Thu, Fri, Sat, Sun // unit-type 886 }; 878 enum Week { case Mon, Tue, Wed, Thu, Fri, Sat, Sun }; // unit-type 887 879 var week : Week = @Week.Mon@; 888 880 \end{swift} … … 911 903 An enumeration can have methods. 912 904 \begin{swift} 913 enum Week: Comparable{905 enum Week: @Comparable@ { 914 906 case Mon, Tue, Wed, Thu, Fri, Sat, Sun // unit-type 915 func @isWeekday() -> Bool@ { return self <= .Fri } // method916 func @isWeekend() -> Bool@ { return .Sat <= self } // method907 func @isWeekday() -> Bool@ { return self <= .Fri } // methods 908 func @isWeekend() -> Bool@ { return .Sat <= self } 917 909 }; 918 910 \end{swift} … … 938 930 \end{tabular} 939 931 \end{cquote} 940 941 932 Enumerating is accomplished by inheriting from @CaseIterable@ without any associated values. 942 933 \begin{swift} … … 944 935 case Mon, Tue, Wed, Thu, Fri, Sat, Sun // unit-type 945 936 }; 946 var weeki : Week = Week.Mon;947 if weeki <= .Fri {948 print( "weekday" );949 }950 937 for day in Week@.allCases@ { 951 938 print( day, terminator:" " ) 952 939 } 953 weekday954 940 Mon Tue Wed Thu Fri Sat Sun 955 941 \end{swift} 956 942 The @enum.allCases@ property returns a collection of all the cases for looping over an enumeration type or variable (expensive operation). 957 943 958 A typed enumeration is accomplished by inheriting from any Swift type, and accessing the underlying enumerator value is done with attribute @rawValue@.959 Type @Int@ has auto-incrementing from previous enumerator;944 A typed enumeration is accomplished by inheriting from any Swift type, and accessing the underlying enumerator value is done with the attribute @rawValue@. 945 Type @Int@ has auto-incrementing from the previous enumerator; 960 946 type @String@ has auto-incrementing of the enumerator label. 961 947 \begin{cquote} … … 986 972 \end{cquote} 987 973 988 There is a bidirectional conversion from typed enumerator to @rawValue@ and vi se versa.974 There is a bidirectional conversion from typed enumerator to @rawValue@ and vice versa. 989 975 \begin{swift} 990 976 var weekInt : WeekInt = WeekInt.Mon; … … 1002 988 1003 989 Python is a dynamically-typed reflexive programming language with multiple incompatible versions. 1004 The generality of the language makes it ispossible to extend existing or build new language features.1005 As a result, discussing Python enumerations is a moving target, because if a feature sdoes not exist, it can often be created with varying levels of complexity within the language.990 The generality of the language makes it possible to extend existing or build new language features. 991 As a result, discussing Python enumerations is a moving target, because if a feature does not exist, it can often be created with varying levels of complexity within the language. 1006 992 Therefore, the following discussion is (mostly) restricted to the core enumeration features in Python 3.13. 1007 993 1008 994 A Python enumeration is not a basic type; 1009 995 it is a @class@ inheriting from the @Enum@ class. 1010 The @Enum@ class presents a set of scoped enumerators, where each enumerator is a pair object with a \emph{constant} string name and a rbitrary value.996 The @Enum@ class presents a set of scoped enumerators, where each enumerator is a pair object with a \emph{constant} string name and an arbitrary value. 1011 997 Hence, an enumeration instance is a fixed type (enumeration pair), and its value is the type of one of the enumerator pairs. 1012 998 … … 1015 1001 class Week(!Enum!): Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5; Sat = 6; Sun = 7 1016 1002 \end{python} 1017 and/or explicitly auto 1003 and/or explicitly auto-initialized, \eg: 1018 1004 \begin{python} 1019 1005 class Week(Enum): Mon = 1; Tue = 2; Wed = 3; Thu = 10; Fri = !auto()!; Sat = 4; Sun = !auto()! 1020 1006 Mon : 1 Tue : 2 Wed : 3 Thu : 10 Fri : !11! Sat : 4 Sun : !12! 1021 1007 \end{python} 1022 where @auto@ increments by 1 from the previous @auto@ value \see{Go lang \lstinline[language=Go]{iota}, \VRef{s:Golang}}.1008 where @auto@ increments by 1 from the previous @auto@ value \see{Go \lstinline[language=Go]{iota}, \VRef{s:Go}}. 1023 1009 @auto@ is controlled by member @_generate_next_value_()@, which can be overridden: 1024 1010 \begin{python} … … 1028 1014 \end{python} 1029 1015 1030 There is no direct concept of restricting the enumerators in an enumeration \emph{instance} because thedynamic typing changes the type.1016 There is no direct concept of restricting the enumerators in an enumeration \emph{instance} because dynamic typing changes the type. 1031 1017 \begin{python} 1032 1018 class RGB(Enum): Red = 1; Green = 2; Blue = 3 … … 1086 1072 class Week(!OrderedEnum!): 1087 1073 Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5; Sat = 6; Sun = 7 1088 def !isWeekday(self)!: # method 1074 def !isWeekday(self)!: # methods 1089 1075 return Week(self.value) !<=! Week.Fri 1090 def !isWeekend(self)!: # method1076 def !isWeekend(self)!: 1091 1077 return Week.Sat !<=! Week(self.value) 1092 1078 \end{python} … … 1137 1123 class WeekEnd(WeekE): Sat = 6; Sun = 7 1138 1124 \end{python} 1139 Here, type @WeekE@ is an abstract type because thedynamic typing never uses it.1125 Here, type @WeekE@ is an abstract type because dynamic typing never uses it. 1140 1126 \begin{cquote} 1141 1127 \setlength{\tabcolsep}{25pt} … … 1165 1151 @Flag@ is the same as @IntFlag@ but cannot be combined with, nor compared against, any other @Flag@ enumeration, nor @int@. 1166 1152 Auto increment for @IntFlag@ and @Flag@ is by powers of 2. 1167 Enumerators that are a combinations of single bit enumerators are aliases, andhence, invisible.1153 Enumerators that are combinations of single-bit enumerators are aliases and, hence, invisible. 1168 1154 The following is an example for @Flag@. 1169 1155 \begin{python} … … 1248 1234 \end{cquote} 1249 1235 (Note, after an @adtv@'s type is know, the enumerator is inferred without qualification, \eg @I(3)@.) 1250 The type names are independent from the type value,and mapped to an opaque, ascending, integral tag, starting from 0, supporting relational operators @<@, @<=@, @>@, and @>=@.1236 The type names are independent of the type value and mapped to an opaque, ascending, integral tag, starting from 0, supporting relational operators @<@, @<=@, @>@, and @>=@. 1251 1237 \begin{cquote} 1252 1238 \setlength{\tabcolsep}{10pt} … … 1288 1274 As seen, a type tag can be used in the @if@ and \lstinline[language=ocaml]{match} statements, where \lstinline[language=ocaml]{match} must be exhaustive or have a default case. 1289 1275 1290 Enumerating is accomplished by deriving from @enumerate@. 1291 1292 Enumeration subtyping is allowed but inheritance is restricted to classes not types. 1276 While OCaml enumerators have an ordering following the definition order, they are not enumerable. 1277 To iterate over all enumerators, an OCaml type needs to derive from the @enumerate@ preprocessor, which appends a list of all enumerators to the program abstract syntax tree (AST). 1278 However, the list of values may not persist in the defined ordering. 1279 As a consequence, there is no meaningful enumerating mechanism. 1280 1281 Enumeration subsetting is allowed but inheritance is restricted to classes not types. 1293 1282 \begin{ocaml} 1294 1283 type weekday = Mon | Tue | Wed | Thu | Fri … … 1518 1507 \section{Comparison} 1519 1508 1520 \VRef[Table]{t:FeatureLanguageComparison} shows a comparison of enumeration features and programming languages. 1521 The features are high level and may not capture nuances within a particular language 1522 The @const@ feature is simple macros substitution and not a typed enumeration. 1509 \VRef[Table]{t:FeatureLanguageComparison} shows a comparison of enumeration features and programming languages with the explaination of categories below. 1510 The features are high-level and may not capture nuances within a particular language. 1523 1511 1524 1512 \begin{table} … … 1529 1517 \newcommand{\CM}{\checkmark} 1530 1518 \begin{tabular}{r|c|c|c|c|c|c|c|c|c|c|c|c|c} 1531 &Pascal & Ada &\Csharp& OCaml & Java &Modula-3&Golang& Rust & Swift& Python& C & \CC & \CFA \\1519 &Pascal & Ada &\Csharp & OCaml & Java &Golang & Rust & Swift & Python& C & \CC & \CFA \\ 1532 1520 \hline 1533 @const@ & \CM & & & & & & \CM & & & & & \CM &\\1521 enum &Dialect& \CM & \CM & ADT & \CM & @const@ &ADT/\CM &ADT/\CM & \CM &\CM &\CM &\CM\\ 1534 1522 \hline 1535 1523 \hline 1536 opaque & & & & & & & & && & & & \CM \\1524 opaque & \CM & & & \CM & \CM & & \CM & \CM & & & & \CM \\ 1537 1525 \hline 1538 typed & & & & & & & & & & & @int@ & integral & @T@\\1526 typed & Int & Int & Integral & H & U & H & U/H & U/H & H & Int & Integral& U \\ 1539 1527 \hline 1540 safe & & & & & & & & && & & \CM & \CM \\1528 safety & \CM & \CM & & \CM & \CM & & \CM & \CM & & & \CM & \CM \\ 1541 1529 \hline 1542 ordered & & & & & & & & & & & \CM & \CM& \CM \\1530 posn ordered & Implied & Implied & & \CM & & & & & & & & \CM \\ 1543 1531 \hline 1544 dup. values & & & & & & & & & & alias & \CM & \CM & \CM\\1532 unique values & \CM & \CM & & & & & & \CM & & & & \\ 1545 1533 \hline 1546 setable & & & & & & & & & && \CM & \CM & \CM \\1534 auto-init & \CM & all or none & \CM & & & \CM & \CM & \CM & \CM & \CM & \CM & \CM \\ 1547 1535 \hline 1548 auto-init & & & & & & & & & & & \CM & \CM & \CM\\1536 (Un)Scoped & U & U & S & S & S & U & S & S & S & U & U/S & U/S \\ 1549 1537 \hline 1550 (Un)Scoped & & & & & & & & & & & U & U/S & U/S\\1538 overload & & \CM & & & & & & & & & & \CM \\ 1551 1539 \hline 1552 overload & & \CM & & & & & & & & & & \CM& \CM \\1540 loop & \CM & \CM & & & & & & & \CM & & & \CM \\ 1553 1541 \hline 1554 switch & & & & & & & & & & & \CM & \CM & \CM\\1542 arr. dim. & \CM & \CM & & & & & & & & & & \CM \\ 1555 1543 \hline 1556 loop & & & & & & & & && & & & \CM \\1544 subset & \CM & \CM & & \CM & & & & & & & & \CM \\ 1557 1545 \hline 1558 array/subscript & & & & & & & & & & & \CM & & \CM \\ 1559 \hline 1560 subtype & & & & & & & & & & & & & \CM \\ 1561 \hline 1562 inheritance & & & & & & & & & & & & & \CM \\ 1546 superset & & & & & & & & & & & & \CM \\ 1563 1547 \end{tabular} 1564 1548 \end{table} 1549 1550 \begin{enumerate} 1551 \item opaque: an enumerator cannot be used as its underlying representation or implemented in terms of an ADT. 1552 \item typed: H $\Rightarrow$ heterogeneous, \ie enumerator values may be different types. \\ 1553 U $\Rightarrow$ homogenous, \ie enumerator values have the same type. 1554 \item safety: An enumeration variable can only hold a value from its defined enumerators. 1555 \item posn ordered: enumerators have defined ordering based on enumerator declaration order. 1556 Position ordered is implied if the enumerator values must be strictly increasingly. 1557 \item unique value: enumerators must have a unique value. 1558 \item auto-init: Values are auto-initializable by language specification, often being "+1" of the predecessor. 1559 \item (Un)Scoped: U $\Rightarrow$ enumerators are projected into the containing scope. 1560 S $\Rightarrow$ enumerators are contained in the enumeration scope and require qualification. 1561 \item overload: An enumerator label can be used without type qualification in a context where multiple enumerations have defined the label. 1562 \item loop: Enumerate without the need to convert an enumeration to another data structure. 1563 \item arr. dim: An enumeration can be used directly as an array dimension, and enumerators can be mapped to an array element (not a conversion to integer type). 1564 \item subset: Name a subset of enumerators as a new type. 1565 \item superset: Create a new enumeration that contains all enumerators from pre-defined enumerations. 1566 \end{enumerate} -
doc/theses/jiada_liang_MMath/test.adb
r2ca7fc2 r6abb6dc 2 2 -- with Ada.Standard; use Ada.Standard; 3 3 procedure test is 4 type GBR is ( Green, Blue, Red ); 4 5 type RGB is ( Red, Green, Blue ); 5 for RGB use ( Red => 10, Green => 20, Blue => 30);6 for RGB use ( Red => 10, Green => 20, Blue => 21 ); 6 7 Colour : RGB := Red; 7 8 … … 95 96 96 97 if B then null; end if; 98 99 B := False; 100 Colour := Green; 101 102 Put_Line ( Boolean'Image( B ) & " " ); 103 Put_Line ( RGB'Image( RGB'Enum_Val( 10 ) ) & " " ); 97 104 end test; 98 105 -
doc/theses/jiada_liang_MMath/test.cc
r2ca7fc2 r6abb6dc 61 61 eca[A] = EC::A; 62 62 63 enum Week { Mon, Tue, Wed, Thu = 10, Fri, Sat, Sun }; 63 enum Week { Mon, Tue, Wed, Thu = 10, Fri, Sat = 8, Sun }; 64 if ( Fri < Sat ) cout << "hmm" << endl; 65 else cout << "ahh" << std::endl; 64 66 Week day = Mon; 65 67 if ( day <= Fri ) cout << "weekday" << endl; -
doc/theses/jiada_liang_MMath/test.go
r2ca7fc2 r6abb6dc 20 20 21 21 22 const ( R = 0; G = 3; B ) // implicit: 0 0 022 const ( R = 0; G = 3; B = 3; TT = 3 ) // implicit: 0 3 3 23 23 const ( Fred = "Fred"; Mary = "Mary"; Jane = "Jane" ) // Fred Mary Jane 24 24 const ( H = 0; Jack = "Jack"; J; K = 0; I ) // type change, implicit: 0 Jack Jack 25 25 const ( C = iota + G; M = iota; Y ) 26 26 const ( Mon = iota; Tue; Wed; // 0, 1, 2 27 Thu = 10; Fri = iota - Wed + Thu - 1; Sat; Sun = iota) // 10, 11, 12, 1327 Thu = 10; Fri = iota - Wed + Thu - 1; Sat; Sun = 0 ) // 10, 11, 12, 13 28 28 const ( O1 = iota + 1; _; O3; _; O5 ) // 1, 3, 5 29 29 const ( V1 = iota; V2; V3 = 7; V4 = iota + 1; V5 ) … … 34 34 35 35 func main() { 36 fmt.Println( "Go:") 36 37 if 3 == R {}; 37 38 fmt.Println( R, G, B ) … … 45 46 46 47 day := Mon; 48 day = Sun; 49 47 50 switch day { 48 51 case Mon, Tue, Wed, Thu, Fri: 49 52 fmt.Println( "weekday" ); 50 case Sat , Sun:53 case Sat: 51 54 fmt.Println( "weekend" ); 52 55 } … … 54 57 fmt.Println( i ) 55 58 } 59 fmt.Println(B < TT); 60 } // main 56 61 57 var ar[Sun] int 58 ar[Mon] = 3 59 } // main 62 // go build test.go -
doc/theses/jiada_liang_MMath/test.pas
r2ca7fc2 r6abb6dc 4 4 Weekday = Mon..Fri; 5 5 Weekend = Sat..Sun; 6 type Count = ( Zero, One, Two, Ten = 10, Eleven ); 6 type Count = ( Zero, One, Two, Ten = 10, Eleven=10 ); 7 type RR = ( A, B, C ); 8 7 9 var day : Week; 8 10 wday : Weekday; … … 10 12 lunch : array[Week] of Integer; 11 13 cnt : Count; 14 // procedure P1(v:Week); 15 // begin 16 // Writeln('Week'); 17 // end; 18 procedure P1(v:Weekday); 19 begin 20 Writeln('Weekday'); 21 end; 22 procedure P1(v:RR); 23 begin 24 Writeln('RR'); 25 end; 12 26 begin 13 27 day := Sat; … … 40 54 Writeln(); 41 55 for day := Mon to Sat do 56 lunch[day] := ord(day) * 10; 57 for day := Mon to Sun do 42 58 Write( lunch[day], ' ' ); 43 59 Writeln(); … … 45 61 Write( ord( cnt ), ' ' ); 46 62 end; 63 day := Tue; 64 P1( day ); 47 65 Writeln(); 66 67 case (day) of 68 Mon: writeln('Excellent!' ); 69 Tue: writeln('Well done' ); 70 end; 48 71 end. 49 72 -
doc/theses/jiada_liang_MMath/test.py
r2ca7fc2 r6abb6dc 25 25 # Mon = 1; Tue = 2; Wed = 3; Thu = 10; Fri = 10; Sat = 16; Sun = 17 26 26 class Week(OrderedEnum): 27 Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5; Sat = 6; Sun = 727 Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5; Sat = 6; Sun = 0 28 28 def isWeekday(self): 29 29 return Week(self.value) <= Week.Fri … … 34 34 return cls(date.isoweekday()) 35 35 36 day : Week = Week.Tue ;36 day : Week = Week.Tue 37 37 print( "weekday:", day.isWeekday() ) 38 38 print( "weekend:", day.isWeekend() ) 39 39 print( "today:", Week.today(date.today())) 40 40 41 print( Week.Thu.value == 4 ) ;42 print( Week.Thu.name == "Thu" ) ;43 print( Week( 4 ) == Week.Thu ) ;44 print( Week["Thu"].value == 4 ) ;41 print( Week.Thu.value == 4 ) 42 print( Week.Thu.name == "Thu" ) 43 print( Week( 4 ) == Week.Thu ) 44 print( Week["Thu"].value == 4 ) 45 45 46 46 if day <= Week.Fri : 47 print( "weekday" ) ;47 print( "weekday" ) 48 48 match day: 49 49 case Week.Mon | Week.Tue | Week.Wed | Week.Thu | Week.Fri: 50 print( "weekday" ) ;50 print( "weekday" ) 51 51 case Week.Sat | Week.Sun: 52 print( "weekend" ) ;52 print( "weekend" ) 53 53 54 54 for day in Week: … … 80 80 print( isinstance(Week.Fri, Week) ) 81 81 82 class WeekE(OrderedEnum): pass ;82 class WeekE(OrderedEnum): pass 83 83 class WeekDay(WeekE): Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5; 84 84 class WeekEnd(WeekE): Sat = 6; Sun = 7 … … 121 121 Weekend = Sat | Sun 122 122 print( f"0x{repr(WeekF.Weekday.value)} 0x{repr(WeekF.Weekend.value)}" ) 123 day : WeekF = WeekF.Mon | WeekF.Tue ;123 day : WeekF = WeekF.Mon | WeekF.Tue 124 124 print( type(day) ) 125 125 for day in WeekF: … … 164 164 match diffval: 165 165 case Diff.Int: 166 print( "diffval", diffval.value ) ;166 print( "diffval", diffval.value ) 167 167 case Diff.Float: 168 print( "diffval", diffval.value ) ;168 print( "diffval", diffval.value ) 169 169 case Diff.Str: 170 print( "diffval", diffval.value ) ;170 print( "diffval", diffval.value ) 171 171 for i in Diff: 172 172 print( f"Diff type {type(i)}, {i}, {i.name}, {i.value} : " ) … … 197 197 return G * self.mass / (self.radius * self.radius) 198 198 def surfaceWeight(self, otherMass): 199 return otherMass * self.surfaceGravity(); 199 return otherMass * self.surfaceGravity() 200 201 class Cats(Enum): 202 pass 203 200 204 201 205 earthWeight : float = 100 202 earthMass : float = earthWeight / ( Planet.EARTH.surfaceGravity() ) ;206 earthMass : float = earthWeight / ( Planet.EARTH.surfaceGravity() ) 203 207 204 208 p = by_position( Planet, random.randrange(8) ) # select a random orbiting body -
doc/theses/jiada_liang_MMath/test.swift
r2ca7fc2 r6abb6dc 59 59 60 60 enum WeekInt: Int, CaseIterable { 61 case Mon, Tue, Wed, Thu = 10, Fri ,61 case Mon, Tue, Wed, Thu = 10, Fri = 14, 62 62 Sat = 4, Sun // auto-incrementing 63 63 }; -
doc/theses/jiada_liang_MMath/test1.cfa
r2ca7fc2 r6abb6dc 1 1 #include <fstream.hfa> // sout 2 2 #include <stdlib.hfa> // ato 3 #include <enum.hfa> 3 4 4 5 // integral … … 9 10 enum( Letter ) Greek { Alph = A, Beta = B, Gamma = G, /* more enums */ Zeta = Z }; // alphabet intersection 10 11 12 // integral 11 13 enum( char ) Currency { Dollar = '$', Cent = '¢', Yen = '¥', Pound = '£', Euro = 'E' }; // iso-latin-1 12 14 enum( Currency ) Europe { Euro = Currency.Euro, Pound = Currency.Pound }; … … 33 35 34 36 enum() Mode { O_RDONLY, O_WRONLY, O_CREAT, O_TRUNC, O_APPEND }; 35 Mode iomode = O_RDONLY; 36 //bool b = iomode == O_RDONLY || iomode < O_APPEND; // disallowed 37 //int www = iomode; // disallowed 37 Mode mode = O_RDONLY; 38 void opaque() { 39 bool b = mode == O_RDONLY || mode < O_APPEND; // disallowed 40 //int www = mode; // disallowed 41 } 38 42 39 43 enum( char * ) Colour { Red = "red", Green = "green", Blue = "blue" }; 44 45 enum E1 { A1, B1, C1 = A1, D1 = B1 }; 46 enum(float) E2 { A2 = 3.5, B2 = 4.5, C2 = A, D2 = B }; 40 47 41 48 void fred() { … … 45 52 //greek = A; // disallowed 46 53 47 for ( Greek l = Alph; posn(l) < =posn(Gamma); l = succ( l ) ) {54 for ( Greek l = Alph; posn(l) < posn(Gamma); l = succ( l ) ) { 48 55 printf( "%s %c %d\n", label( l ), value( l ), posn( l ) ); 49 56 } 50 for ( Currency c = Dollar; posn(c) < =posn(Currency.Euro); c = succ( c ) ) {57 for ( Currency c = Dollar; posn(c) < posn(Currency.Euro); c = succ( c ) ) { 51 58 printf( "%s %c %d\n", label( c ), value( c ), posn( c ) ); 52 59 } 53 60 } 54 61 55 56 enum( char * ) Names { Fred = "FRED", Mary = "MARY", Jane = "JANE" }; 57 enum( char * ) Names2 { inline Names, Jack = "JACK", Jill = "JILL" }; 58 enum( char * ) Names3 { inline Names2, Sue = "SUE", Tom = "TOM" }; 59 62 enum( const char * ) Names { Fred = "FRED", Mary = "MARY", Jane = "JANE" }; 63 enum( const char * ) Names2 { inline Names, Jack = "JACK", Jill = "JILL" }; 64 enum( const char * ) Names3 { inline Names2, Sue = "SUE", Tom = "TOM" }; 65 void bar() { 66 Names fred = Names.Fred; 67 (Names2)fred; (Names3)fred; (Names3)Names2.Jack; // cast to super type 68 Names2 fred2 = fred; Names3 fred3 = fred2; // assign to super type 69 const char * name = fred; 70 Names name = Fred; 71 sout | name | label( name ) | posn( name ) | value( name ); 72 } 60 73 void f( Names n ) { sout | "Name" | posn( n ); } 61 74 void g( Names2 ); … … 63 76 void j( char * ); 64 77 65 enum color { red, blue, green }; 66 //color c = 0; 67 //color c = 1; 68 color c = 2; 69 int w = red; 78 enum CColour { Red, Blue, Green }; 79 CColour c0 = 0; 80 CColour c1 = 1; 81 CColour c = 2; 82 int w = Red; 83 84 void coo() { 85 enum(int) Color { Red, Blue, Green }; 86 Colour c = Red; 87 sout | countof( Colour ) | Countof( c ); 88 // sout | Countof( Colour ); 89 sout | countof( c ); 90 } 70 91 71 92 // enum(int) Week ! { Mon, Tue, Wed, Thu = 10, Fri, Sat, Sun }; … … 79 100 // } 80 101 102 void baz() { 103 enum(int) Count { First, Second, Third/* = First*/, Fourth/* = Second*/ }; 104 enum CCount { First, Second, Third/* = First*/, Fourth/* = Second*/ }; 105 Count cnt = Second; 106 CCount ccnt = Second; 107 if ( cnt < Third ) sout | "less than Third"; 108 if ( cnt ) sout | "XXX"; 109 if ( ccnt ) sout | "YYY"; 110 enum(float) F {WWW = 0.0}; 111 F f; 112 if ( f ) sout | "FFF"; 113 bool ?!=?( Name n, zero_t ) { sout | "DDD"; return n != Fred; } 114 Name n = Mary; 115 if ( n ) sout | "NAME"; 116 choose( cnt ) { 117 case First: sout | "First"; 118 case Second: sout | "Second"; 119 case Third: sout | "Third"; 120 case Fourth: sout | "Fourth"; 121 } 122 // for (d; Week) { sout | d; } 123 // for (p; +~=Planet) { sout | p; } 124 for ( cx; Count ) { sout | cx | nonl; } sout | nl; 125 for ( cx; +~= Count ) { sout | cx | nonl; } sout | nl; 126 for ( cx; -~= Count ) { sout | cx | nonl; } sout | nl; 127 for ( Count cx = lowerBound();; ) { 128 sout | cx | nonl; 129 if ( cx == upperBound() ) break; 130 cx = succ( cx ); 131 } 132 sout | nl; 133 } 134 81 135 int main() { 82 136 fred(); 83 Names name = Fred;137 Names name = Names.Fred; 84 138 // f( name ); 85 139 86 140 int jane_pos = posn( Names.Jane ); 87 c har * jane_value = value( Names.Jane );88 c har * jane_label = label( Names.Jane );141 const char * jane_value = value( Names.Jane ); 142 const char * jane_label = label( Names.Jane ); 89 143 sout | Names.Jane | posn( Names.Jane) | label( Names.Jane ) | value( Names.Jane ); 144 145 bar(); 146 baz(); 147 coo(); 148 149 enum Ex { Ax, Bx, Cx, Nx }; 150 float H1[Nx] = { [Ax] : 3.4, [Bx] : 7.1, [Cx] : 0.01 }; // C 151 // float H2[Ex] = { [Ax] : 3.4, [Bx] : 7.1, [Cx] : 0.01 }; // CFA 152 153 enum(int) E { A = 3 } e = A; 154 sout | A | label( A ) | posn( A ) | value( A ); 155 sout | e | label( e ) | posn( e ) | value( e ); 90 156 } -
doc/theses/jiada_liang_MMath/test1.java
r2ca7fc2 r6abb6dc 3 3 public class test1 { 4 4 enum Weekday { 5 Mon(7), Tue(6), Wed(5), Thu(3), Fri( 3), Sat(3), Sun(1); // must appear first5 Mon(7), Tue(6), Wed(5), Thu(3), Fri(4), Sat(3), Sun(7); // must appear first 6 6 private long day; 7 7 private Weekday( long d ) { day = d; } … … 27 27 } 28 28 for ( Weekday icday : Weekday.values() ) { // position 29 System.out.print ( icday + " " + icday.ordinal() + " " + icday.day + " " + icday.name() + ", " ); // label29 System.out.println( icday + " " + icday.ordinal() + " " + icday.day + " " + icday.name() + ", " ); // label 30 30 } 31 31 System.out.println(); 32 33 if (Weekday.Fri == Weekday.Sat) { 34 System.out.println( "Alias "); 35 } 32 36 } 33 37 } -
doc/theses/jiada_liang_MMath/trait.tex
r2ca7fc2 r6abb6dc 2 2 \label{c:trait} 3 3 4 % Despite parametric polymorphism being a pivotal feature of \CFA, for a long time, there was not 5 % a technique to write functions being polymorphic over enumerated types. 6 \CC introduced @std::is_enum@ trait on \CC{11} and @concepts@ on \CC{20}; with the combination, users can 7 write function polymorphic over enumerated type in \CC: 8 \begin{cfa} 4 \CC introduced the @std::is_enum@ trait in \CC{11} and concept feature in \CC{20}. 5 With this combination, it is possible to write a polymorphic function over an enumerated type. 6 \begin{c++} 9 7 #include <type_traits> 10 11 template<typename T> 12 @concept Enumerable = std::is_enum<T>::value;@ 13 14 template<@Enumerable@ T> 15 void f(T) {} 16 \end{cfa} 17 The @std::is_enum@ and other \CC @traits@ are a compile-time interfaces to query type information. 18 While named the same as @trait@, it is orthogonal to \CFA trait, as the latter being defined as 19 a collection of assertion to be satisfied by a polymorphic type. 20 21 \CFA provides @CfaEnum@ and @TypedEnum@ traits to supports polymorphic functions for \CFA enumeration: 22 \begin{cfa} 23 forall(T | @CfaEnum(T)@) 24 void f(T) {} 25 \end{cfa} 26 27 \section{CfaEnum and TypedEnum} 28 \CFA defines attribute functions @label()@ and @posn()@ for all \CFA enumerations, 29 and therefore \CFA enumerations fulfills the type assertions with the combination. 30 With the observation, we define trait @CfaEnum@: 8 template<typename T> @concept Enumerable@ = std::is_enum<T>::value; 9 template<@Enumerable@ E> E f( E e ) { $\C{// constrainted type}$ 10 E w = e; $\C{// alloction and copy}$ 11 cout << e << ' ' << w << endl; $\C{// value}$ 12 return w; $\C{// copy}$ 13 } 14 int main() { 15 enum E { A = 42, B, C } e = C; 16 e = f( e ); 17 } 18 44 44 19 \end{c++} 20 The @std::is_enum@ and other \CC @traits@ are a compile-time interfaces to query type information. 21 While named the same as @trait@ in other programming languages, it is orthogonal to the \CFA trait, with the latter being defined as a collection of assertion to be satisfied by a polymorphic type. 22 23 The following sections cover the underlying implementation features I created to generalize and restrict enumerations in the \CFA type-system using the @trait@ mechanism. 24 25 26 \section{Traits \texorpdfstring{\lstinline{CfaEnum}{CfaEnum}} and \texorpdfstring{\lstinline{TypedEnum}}{TypedEnum}} 27 28 Traits @CfaEnum@ and @TypedEnum@ define the enumeration attributes: @label@, @posn@, @value@, and @Countof@. 29 These traits support polymorphic functions for \CFA enumeration, \eg: 30 \begin{cfa} 31 forall( E ) | @CfaEnum( E )@ ) 32 void f( E e ) { 33 // access enumeration properties for e 34 } 35 \end{cfa} 36 37 Trait @CfaEnum@ defines attribute functions @label@ and @posn@ for all \CFA enumerations, and internally \CFA enumerations fulfills this assertion. 31 38 \begin{cfa} 32 39 forall( E ) trait CfaEnum { … … 35 42 }; 36 43 \end{cfa} 37 38 % The trait @TypedEnum@ extends @CfaEnum@ with an additional value() assertion: 39 Typed enumerations are \CFA enumeration with an additional @value@ attribute. Extending 40 CfaEnum traits, TypedEnum is a subset of CFAEnum that implements attribute function @value()@, 41 which includes all typed enumerations. 44 This trait covers opaque enumerations that do not have an explicit @value@. 45 46 The trait @TypedEnum@ extends @CfaEnum@ with the @value@ assertion for typed enumerations. 42 47 \begin{cfa} 43 48 forall( E, V | CfaEnum( E ) ) trait TypedEnum { … … 45 50 }; 46 51 \end{cfa} 47 Type parameter V of TypedEnum trait binds to return type of @value()@, which is also the base 48 type for typed enumerations. CfaEnum and TypedEnum triats constitues a CfaEnum function interfaces, as well a way to define functions 49 over all CfaEnum enumerations. 50 \begin{cfa} 51 // for all type E that implements value() to return type T, where T is a type that convertible to string 52 forall( E, T | TypedEnum( E, T ) | { ?{}(string &, T ); } ) 53 string format_enum( E e ) { return label(E) + "(" + string(value(e)) + ")"; } 54 55 // int is convertible to string; implemented in the standard library 56 enum(int) RGB { Red = 0xFF0000, Green = 0x00FF00, Blue = 0x0000FF }; 57 58 struct color_code { int R; int G; int B }; 59 // Implement color_code to string conversion 60 ?{}(string & this, struct color_code p ) { 61 this = string(p.R) + ',' + string(p.G) + ',' + string(p.B); 62 } 52 Here, the associate type-parameter @V@ is the base type of the typed enumeration, and hence, the return type of @value@. 53 These two traits provide a way to define functions over all \CFA enumerations. 54 55 For example, \VRef[Figure]{f:GeneralizedEnumerationFormatter} shows a generalized enumeration formatter for any enumeration type. 56 The formatter prints an enumerator name and its value in the form @"label( value )"@. 57 The trait for @format_enum@ requires a function named @str@ for printing the value (payload) of the enumerator. 58 Hence, enumeration defines how its value appear and @format_enum@ displays this value within the label name. 59 60 \begin{figure} 61 \begin{cfa} 62 forall( @E, V | TypedEnum( E, V )@ | { string str( V ); } ) $\C{// format any enumeration}$ 63 string format_enum( E e ) { 64 return label( e ) + '(' + str( value( e ) ) + ')'; $\C{// "label( value )"}$ 65 } 66 enum(size_t) RGB { Red = 0xFF0000, Green = 0x00FF00, Blue = 0x0000FF }; 67 // string library has conversion function str from size_t to string 68 69 struct color_code { int R, G, B; }; 63 70 enum(color_code) Rainbow { 64 Red = {255, 0, 0}, Orange = {255, 127, 0}, Yellow = {255, 255, 0}, Green = {0, 255, 0}, 65 Blue = {0, 0, 255}, Indigo = {75, 0, 130}, Purple = {148, 0, 211} 66 }; 67 68 format_enum(RGB.Green); // "Green(65280)" 69 format_enum(Rainbow.Green); // "Green(0,255,0)" 70 \end{cfa} 71 72 73 % Not only CFA enumerations can be used with CfaEnum trait, other types that satisfy 74 % CfaEnum assertions are all valid. 75 Types does not need be defined as \CFA enumerations to work with CfaEnum traits. CfaEnum applies to any type 76 with @label()@ and @value()@ being properly defined. 77 Here is an example on how to extend a C enumeration to comply CfaEnum traits: 78 \begin{cfa} 79 enum Fruit { Apple, Banana, Cherry }; $\C{// C enum}$ 80 const char * label( Fruit f ) { 81 choose( f ) { 82 case Apple: return "Apple"; 83 case Banana: return "Banana"; 84 case Cherry: return "Cherry"; 85 } 86 } 87 unsigned posn( Fruit f ) { return f; } 88 char value( Fruit f ) { 89 choose(f) { 90 case Apple: return 'a'; 91 case Banana: return 'b'; 92 case Cherry: return 'c'; 93 } 94 } 95 96 format_enum(Cherry); // "Cherry(c)" 97 \end{cfa} 98 99 \section{Discussion: Static Type Information} 100 @CfaEnum@ and @TypedEnum@ are approximations to \CFA Enumerations and Typed Enumerations: they are not 101 assertions on a type being an enumerated type, 102 but rather types being shared an interfaces with \CFA enumerations. 103 \CC's @type_traits@ is fundamentally different than \CFA's traits: \CC's @type_traits@ are descriptions 104 of compile time type information 105 \footnote{Concepts can check if a \CC class implement a certain method, 106 but it is to probe a static type information of a class having a such member.} 107 , while \CFA's trait describe how a type can be used, 108 which is a closer paradigm to a trait system in languages such as Scala and Rust. 109 However, Scala and Rust's traits are nominative: 110 a type explicitly declare a named traits to be of its type; while in \CFA, 111 type implements all functions declares in a trait to implicitly be of the trait type. 112 113 If to support static type information, \CFA needs new piece of syntax to distinguish static type 114 query from function calls, for example: 115 \begin{cfa} 116 forall(T | { T::is_enum; }); 117 \end{cfa} 118 When to call a polymorphic function @foo(T)@ with assertions set @S@ and function call argument @a@, \CFA 119 determines if there is an overloaded name @a@ that has non-zero conversion cost to all assertions in @S@. 120 As a consequence, @is_enum@ can be a \CFA directive that immediately trim down the search space of @a@ to 121 be some enumerated types. In fact, because \CFA stores symbols maps to enumeration in a standalone data structure. 122 Limiting search space to enumeration improve on \CFA resolution speed. 123 124 While assertion on static type information seems improvement on expressivity, it is a challenge to 125 extend its capability without a fully functional pre-processsor that evaluate constant expression as \CC 126 compilers does. The described @is_enum@ manipulate compiler behaviour, which cannot be easily extended to 127 other usage cases. Therefore, \CFA currently does not support @is_enum@ and utalizes traits as a workaround. 71 Red = {255, 0, 0}, Orange = {255, 127, 0}, Yellow = {255, 255, 0}, Green = {0, 255, 0}, // ... 72 }; 73 string str( color_code cc ) with( cc ) { $\C{// format payload, "ddd,ddd,ddd"}$ 74 return str( R ) + ',' + str( G ) + ',' + str( B ); $\C{// "R,G,B"}$ 75 } 76 int main() { 77 sout | format_enum( RGB.Green ); $\C{// "Green(65280)"}$ 78 sout | format_enum( Rainbow.Green ); $\C{// "Green(0,255,0)"}$ 79 } 80 \end{cfa} 81 \caption{Generalized Enumeration Formatter} 82 \label{f:GeneralizedEnumerationFormatter} 83 \end{figure} 84 85 Other types may work with traits @CfaEnum@ and @TypedEnum@, by supplying appropriate @label@, @posn@, and @value@ functions. 86 For example, \VRef[Figure]{f:ExtendCEnumeration} extends a (possibly predefined) C enumeration to work with all the \CFA extensions. 87 88 \begin{figure} 89 \begin{cfa} 90 enum Fruit { Apple, Banana, Cherry }; $\C{// C enum}$ 91 const char * @label@( Fruit f ) { 92 static const char * labels[] = { "Apple", "Banana", "Cherry" }; 93 return labels[f]; 94 } 95 int @posn@( Fruit f ) { return f; } 96 int @value@( Fruit f ) { 97 static const char values[] = { 'a', 'b', 'c' }; 98 return values[f]; 99 } 100 sout | format_enum( Cherry ); $\C{// "Cherry(c)"}$ 101 \end{cfa} 102 \caption{Extend C Enumeration to \CFA Enumeration} 103 \label{f:ExtendCEnumeration} 104 \end{figure} 105 106 107 \section{Discussion: Genericity} 108 109 At the start of this chapter, the \CC concept is introduced to constraint template types, \eg: 110 \begin{c++} 111 concept Enumerable = std::is_enum<T>::value; 112 \end{c++} 113 Here, @concept@ is referring directly to types with kind @enum@; 114 other @concept@s can refer to all types with kind @int@ with @long@ or @long long@ qualifiers, \etc. 115 Hence, the @concept@ is a first level of restriction allowing only the specified kinds of types and rejecting others. 116 The template expansion is the second level of restriction verifying if the type passing the @concept@ test provides the necessary functionality. 117 Hence, a @concept@ is querying precise aspects of the programming language set of types. 118 119 Alternatively, languages using traits, like \CFA, Scala, Go, and Rust, are defining a restriction based on a set of operations, variables, or structure fields that must exist to match with usages in a function or aggregate type. 120 Hence, the \CFA enumeration traits never connected with the specific @enum@ kind. 121 Instead, anything that can look like the @enum@ kind is considered an enumeration (duck typing). 122 However, Scala, Go, and Rust traits are nominative: a type explicitly declares a named traits to be of its type, while in \CFA, any type implementing all requirements declared in a trait implicitly satisfy its restrictions. 123 124 One of the key differences between concepts and traits, which is leveraged heavily by \CFA, is the ability to apply new \CFA features to C legacy code. 125 For example, \VRef[Figure]{f:GeneralizedEnumerationFormatter} shows that pre-existing C enumerations can be upgraded to work and play with new \CFA enumeration facilities. 126 Another example is adding constructors and destructors to pre-existing C types by simply declaring them for the old C type. 127 \CC fails at certain levels of legacy extension because many of the new \CC features must appear \emph{within} an aggregate definition due to the object-oriented nature of he type system, where it is impossible to change legacy library types. 128 128 129 129 130 130 \section{Bounded and Serial} 131 A bounded type defines a lower bound and a upper bound. 131 132 A bounded trait defines a lower and upper bound for a type. 132 133 \begin{cfa} 133 134 forall( E ) trait Bounded { … … 135 136 E lowerBound(); 136 137 }; 137 138 \end{cfa} 139 Both Bounded functions are implement for \CFA enumerations, with @lowerBound()@ returning the first enumerator and @upperBound()@ returning 140 the last enumerator. 141 \begin{cfa} 142 Workday day = lowerBound(); $\C{// Mon}$ 143 Planet outermost = upperBound(); $\C{// NEPTUNE}$ 144 \end{cfa} 145 146 The lowerBound() and upperBound() are functions overloaded on return type only, means their type resolution solely depend on the outer context, 147 including expected type as a function argument, or the left hand size of an assignment expression. 148 Calling either function without a context results in a type ambiguity, except in the rare case where the type environment has only one 149 type overloads the functions, including \CFA enumerations, which has Bounded functions automatic defined. 150 \begin{cfa} 151 @lowerBound();@ $\C{// ambiguous as both Workday and Planet implement Bounded}$ 152 sout | @lowerBound()@; 153 Workday day = first(); $\C{// day provides type Workday}$ 154 void foo( Planet p ); 155 foo( last() ); $\C{// argument provides type Planet}$ 156 \end{cfa} 157 158 @Serial@ is a subset of @Bounded@, with functions maps elements against integers, as well implements a sequential order between members. 138 \end{cfa} 139 Both functions are necessary for the implementation of \CFA enumeration, with @lowerBound@ returning the first enumerator and @upperBound@ returning the last enumerator. 140 \begin{cfa} 141 enum(int) Week { Mon, Tue, Wed, Thu, Fri, Sat, Sun }; 142 enum(int) Fruit { Apple, Banana, Cherry }; 143 Week first_day = lowerBound(); $\C{// Mon}$ 144 Fruit last_fruit = upperBound(); $\C{// Cherry}$ 145 \end{cfa} 146 The @lowerBound@ and @upperBound@ are functions overloaded on return type only, meaning their type resolution depends solely on the call-site context, such as the parameter type for a function argument or the left hand size of an assignment expression. 147 Calling either function without a context results in a type ambiguity, unless the type environment has only one type overloading the functions. 148 \begin{cfa} 149 sout | @lowerBound()@; $\C[2.5in]{// ambiguous as Week and Fruit implement Bounded}$ 150 void foo( Fruit ); 151 foo( lowerBound() ); $\C{// parameter provides type Fruit}$ 152 Week day = upperBound(); $\C{// day provides type Week}\CRT$ 153 \end{cfa} 154 155 Trait @Serial@ is a subset of @Bounded@, with functions mapping enumerators to integers, and implementing a sequential order between enumerators. 159 156 \begin{cfa} 160 157 forall( E | Bounded( E ) ) trait Serial { 161 unsignedfromInstance( E e );158 int fromInstance( E e ); 162 159 E fromInt( unsigned int i ); 160 E pred( E e ); 163 161 E succ( E e ); 164 E pred( E e ); 165 unsigned Countof( E e ); 166 }; 167 \end{cfa} 168 169 % A Serail type can project to an unsigned @int@ type, \ie an instance of type T has a corresponding integer value. 170 Function @fromInstance()@ projects a @Bounded@ member to a number and @fromInt@ is the inverser. Function @succ()@ take an element, returns the "next" 171 member in sequential order and @pred()@ returns the "last" member. 172 173 A Serial type E may not be having a one-to-one mapping to integer because of bound. An integer that cannot be mapping to a member of E is called the member \newterm{out of bound}. 174 Calling @succ()@ on @upperBound@ or @pred()@ on @lowerBound()@ results in out of bound. 175 176 \CFA implements Serial interface for CFA enumerations with \newterm{bound check} on @fromInt()@, @succ()@ and @pred()@, and abort the program if the function call results in out of bound. 177 Unlike a cast, conversion between \CFA enumeration and integer with @Serial@ interface is type safe. 178 Specifically for @fromInt@, \CFA abort if input i smaller than @fromInstance(lowerBound())@ or greater than @fromInstance(upperBound())@ 179 180 Function @Countof@ takes an object as a parameter and returns the number of elements in the Serial type, which is @fromInstance( upper ) - fromInstance( lower ) + 1@. 181 @Countof@ does not use its arugment as procedural input; it needs 182 an argument to anchor its polymorphic type T. 183 184 \CFA has an expression @countof@ (lower case) that returns the number of enumerators defined for enumerations. 185 \begin{cfa} 186 enum RGB {Red, Green, Blue}; 187 countof( RGB ); 188 countof( Red ); 189 \end{cfa} 190 Both expressions from the previous example are converted to constant expression @3@ with no function call at runtime. 191 @countof@ also works for any type T that defines @Countof@ and @lowerBound@, for which it turns into 192 a function call @Countof( T )@. The resolution step on expression @countof(e)@ works as the following with priority ordered: 162 unsigned Countof( E ); 163 }; 164 \end{cfa} 165 Function @fromInstance@ projects a @Bounded@ member to a number and @fromInt@ is the inverse. 166 Function @pred@ and @succ@ are advancement functions: 167 @pred@ takes an enumerator and returns the previous enumerator, if there is one, in sequential order, and @succ@ returns the next enumerator. 168 \begin{cfa} 169 sout | fromInstance( Wed ) | fromInt( 2 ) | succ( Wed ) | pred( Wed ); 170 2 Wed Thu Tue 171 \end{cfa} 172 Bound checking is provided for @fromInt@, @pred@, and @succ@, and the program is terminated if the lower or upper bound is exceeded, \eg: 173 \begin{cfa} 174 fromInt( 100 ); 175 Cforall Runtime error: call to fromInt has index 100 outside of enumeration range 0-6. 176 \end{cfa} 177 Function @fromInstance@ or a position cast using @(int)@ is always safe, \ie within the enumeration range. 178 179 Function @Countof@ is the generic counterpart to the builtin pseudo-function @countof@. 180 @countof@ only works on enumeration types and instances, so it is locked into the language type system; 181 as such, @countof( enum-type)@ becomes a compile-time constant. 182 @Countof@ works on an any type that matches the @Serial@ trait. 183 Hence, @Countof@ does not use its argument; 184 only the parameter type is needed to compute the range size. 185 \begin{cfa} 186 int Countof( E ) { 187 E upper = upperBound(); 188 E lower = lowerBound(); 189 return fromInstance( upper ) + fromInstance( lower ) + 1; 190 } 191 \end{cfa} 192 193 @countof@ also works for any type @E@ that defines @Countof@ and @lowerBound@, becoming a call to @Countof( E )@. 194 The resolution step on expression @countof( E )@ are: 193 195 \begin{enumerate} 194 \item Looks for an enumeration named e, such as @enum e {... }@. 195 If such an enumeration e exists, \CFA replace @countof(e)@ with constant expression with number of enumerator of e. 196 \item Looks for a non-enumeration type named e that defines @Countof@ and @lowerBound@, including e being a polymorphic type, such as @forall(e)@. 197 If type e exists, \CFA replaces it with @Countof(lowerBound())@, where lowerBound() is bounded to type e. 198 \item Looks for an enumerator e that defined in enumeration E. If such an enumeration e exists, \CFA replace @countof(e)@ with constant expression with number of enumerator of E. 199 \item Looks for a name e in the context with expression type E. If such name e exists, \CFA replace @countof(e)@ with function call @Countof(e)@. 200 \item If 1-4 fail, \CFA reports a type error on expression @countof(e)@. 196 \item Look for an enumeration named @E@, such as @enum E {... }@. 197 If such an enumeration @E@ exists, replace @countof( E )@ with the number of enumerators. 198 \item Look for a non-enumeration type named @E@ that defines @Countof@ and @lowerBound@, including @E@ being a polymorphic type, such as @forall( E )@. 199 If type @E@ exists, replaces it with @Countof(lowerBound())@, where @lowerBound@ is defined for type @E@. 200 \item Look for an enumerator @A@ defined in enumeration @E@. 201 If such an enumerator @A@ exists, replace @countof( A )@ with the number of enumerators in @E@. 202 \item Look for a name @A@ in the lexical context with type @E@. 203 If such name @A@ exists, replace @countof( A )@ with function call @Countof( E )@. 204 \item If 1-4 fail, report a type error on expression @countof( E )@. 201 205 \end{enumerate} 202 206 203 \section{Iterating Over An Enumeration} 204 An fundamental aspect of an enumerated type is to be able to enumerate over its enumerators. \CFA supports \newterm{for} loops, 205 \newterm{while} loop, and \newterm{range} loop. This section covers @for@ loops and @range@ loops for 206 enumeration, but the concept transition to @while@ loop. 207 208 \section{Enumerating} 209 210 The fundamental aspect of an enumeration type is the ability to enumerate over its enumerators. 211 \CFA supports \newterm{for} loops, \newterm{while} loop, and \newterm{range} loop. This section covers @for@ loops and @range@ loops for enumeration, but the concept transition to @while@ loop. 212 207 213 208 214 \subsection{For Loop} 209 A for loop is constitued by a loop control and a loop body. 210 A loop control is often a 3-tuple, separated by semicolons: initializers, condition, and an expression. It is a common practice to declare 211 a variable, often in initializers, that be used in the condition and updated in the expression or loop body. Such variable is called \newterm{index}. 212 213 % With implemented @Bounded@ and @Serial@ interface for \CFA enumeration, a @for@ loop that iterates over \CFA enumeration can be implemented as the following: 214 A @for@ loop iterates an enumeration can be written with functions from @Bounded@ and @Serial@ interfaces: 215 \begin{cfa} 216 enum() Chars { A, B, C, D }; 217 for( unsigned i = 0; i < countof(E); i++ ) { sout | label(e); } $\C{// (1) A B C D}$ 218 for( Chars e = lowerBound(); ; e = succ(e) ) { $\C{// (2)}$ 219 sout |label((Chars)fromInt(i)) |' '; 220 if (e == upperBound()) break; 221 } 222 \end{cfa} 223 224 A caveat in writing loop using finite number as index is that the number can unintentionally be out the range: 225 \begin{cfa} 226 for( unsigned i = countof(Chars) - 1; i >= 0; i-- ) {} $\C{// 3}$ 227 for( Chars e = lowerBound(); e <= upperBound(); e = succ(e) ) {} $\C{// 4}$ 228 for( Chars e = upperBound(); e >= lowerBound(); e = pred(e) ) {} $\C{// 5}$ 229 \end{cfa} 230 Loop (3) is a value underflow: when @i@ reaches to @0@, decrement statement will still execute and cause 231 the @unsigned int@ value @i@ wraps to @UINT_MAX@, which fails to loop test and the loop cannot terminate. 232 233 In loop (4) and (5), when @e@ is at the @Bound@ (@upperBound@/@lowerBound@) and @succ@/@pred@ will result in @out of bounded@, \CFA 234 aborts its execution. Therefore, it is necessary to implement the condtional break within the loop body. 215 216 A for-loop consists of loop control and body. 217 The loop control is often a 3-tuple: initializers, stopping condition, and advancement. 218 It is a common practice to declare one or more loop-index variables in initializers, checked these variables for stopping iteration, and updated the variables in advancement. 219 Such a variable is called an \newterm{index} and is available for reading and writing within the loop body. 220 (Some languages make the index read-only in the loop body.) 221 This style of iteration can be written for an enumeration using functions from the @Bounded@ and @Serial@ traits: 222 \begin{cfa} 223 enum() E { A, B, C, D }; 224 for ( unsigned int i = 0; i < countof(E); i += 1 ) $\C{// (1)}$ 225 sout | label( fromInt( i ) ) | nonl; 226 sout | nl; 227 for ( E e = lowerBound(); ; e = succ(e) ) { $\C{// (2)}$ 228 sout | label(e) | nonl; 229 if (e == upperBound()) break; 230 } 231 sout | nl; 232 A B C D 233 A B C D 234 \end{cfa} 235 236 A caveat in writing loop control using @pred@ and @succ@ is unintentionally exceeding the range. 237 \begin{cfa} 238 for ( E e = upperBound(); e >= lowerBound(); e = pred( e ) ) {} 239 for ( E e = lowerBound(); e <= upperBound(); e = succ( e ) ) {} 240 \end{cfa} 241 Both of these loops look correct but fail because these is an additional bound check within the advancement \emph{before} the conditional test to stop the loop, resulting in a failure at the endpoints of the iteration. 242 These loops must be restructured by moving the loop test to the end of the loop (@do-while@), as in loop (2) above, which is safe because an enumeration always at least one enumerator. 235 243 236 244 237 245 \subsection{Range Loop} 238 Instead of specifying condition, \CFA supports @range loops@, for which a user specifies a range of values. 239 \begin{cfa}[label=lst:range_functions_2] 240 for ( Chars e; A ~= D ) { sout | label(e); } $\C{// (6)}$ 241 for ( e; A ~= D ) { sout | label(e); } $\C{// (7)}$ 242 for ( Chars e; A -~= D ) { sout | label(e); } $\C{// (8) D C B A}$ 243 for ( e; A -~=D ~ 2 ) { sout | label(e); } $\C{// (9) D B }$ 244 \end{cfa} 245 Every range loop above has an index declaration, and a @range@ bounded by \newterm{left bound} @A@ and \newterm{right bound} @D@. 246 An index declaration can have an optional type declaration, without which \CFA 247 implicitly declares index variable to be the type of the bounds (@typeof(A)@). 248 If a range is joined by @~=@ (range up equal) operator, the index variable will be initialized by 249 the @left bound@, and change incrementally until its position exceeds @right bound@. 250 On the other hand, if a range is defined with @-~=@ (range down equal) operation, the index variable will 251 have the value of the @right bound@. It change decrementally until its position is less than the @left bound@. 252 A range can be suffixed by an positive integal \newterm{step}, joined by @~@. The loop @(9)@ declares a step size of 2 so that 253 e updates @pred(pred(e))@ in every iteration. 254 255 \CFA manipulates the position of the index variable and breaks the loop if an index update can result in @out of range@. 256 257 \CFA provides a shorthand for range loop over a \CFA enumeration or a @Serial@: 258 \begin{cfa}[label=lst:range_functions_2] 259 for ( e; Chars ) { sout | label(e); } $\C{// (10) A B C D}$ 260 for ( e; E ) { $\C{// forall(E | CfaEnum(E) | Serial(E)) }$ 261 sout | label(e); 262 } 263 \end{cfa} 264 The shorthand syntax has a type name expression (@Char@ and @E@) as its range. If the range expression does not name 265 a \CFA enumeration or a @Serial@, \CFA reports a compile time error. When type name as range is a \CFA enumeration, 266 it turns into a loop that iterates all enumerators of the type. If the type name is a @Serial@, the index variable 267 will be initialized as the @lowerBound@. The loop control checks the index's position against the position of @upperBound@, 268 and terminate the loop when the index has a position greater than the @upperBound@. \CFA does not update the index with 269 @succ@ but manipulate its position directly to avoid @out of bound@. 246 247 Instead of writing the traditional 3-tuple loop control, \CFA supports a \newterm{range loop}. 248 \begin{cfa} 249 for ( @E e; A ~= D@ ) { sout | label( e ) | nonl; } sout | nl; 250 for ( @e; A ~= D@ ) { sout | label( e ) | nonl; } sout | nl; 251 for ( @E e; A -~= D@ ) { sout | label( e ) | nonl; } sout | nl; 252 for ( @e; A -~= D ~ 2@ ) { sout | label( e ) | nonl; } sout | nl; 253 \end{cfa} 254 Every range loop above has an index declaration and a @range@ bounded by \newterm{left bound} @A@ and \newterm{right bound} @D@. 255 If the index declaration-type is omitted, the index type is the type of the lower bound (@typeof( A )@). 256 If a range is joined by @~=@ (range up equal) operator, the index variable is initialized by the left bound and advanced by 1 until it is greater than the right bound. 257 If a range is joined by @-~=@ (range down equal) operator, the index variable is initialized by the right bound and advanced by -1 until it is less than the left bound. 258 (Note, functions @pred@ and @succ@ are not used for advancement, so the advancement problem does not occur.) 259 A range can be suffixed by a positive \newterm{step}, \eg @~ 2@, so advancement is incremented/decremented by step. 260 261 Finally, a shorthand for enumerating over the entire set of enumerators (the most common case) is using the enumeration type for the range. 262 \begin{cfa} 263 for ( e; @E@ ) sout | label( e ) | nonl; sout | nl; $\C{// A B C D}$ 264 for ( e; @-~= E@ ) sout | label( e ) | nonl; sout | nl; $\C{// D C B A}$ 265 \end{cfa} 266 For a \CFA enumeration, the loop enumerates over all enumerators of the enumeration. 267 For a type matching the @Serial@ trait: the index variable is initialized to @lowerBound@ and loop control checks the index's value for greater than the @upperBound@. 268 If the range type is not a \CFA enumeration or does not match trait @Serial@, it is compile-time error. 269 270 270 271 271 \section{Overload Operators} 272 % Finally, there is an associated trait defining comparison operators among enumerators. 273 \CFA preemptively overloads comparison operators for \CFA enumeration with @Serial@ and @CfaEnum@. 274 They defines that two enumerators are equal only if the are the same enumerator, and compartors are 275 define for order comparison. 276 \begin{cfa} 277 forall( E | CfaEnum( E ) | Serial( E ) ) { 272 273 \CFA overloads the comparison operators for \CFA enumeration satisfying traits @Serial@ and @CfaEnum@. 274 These definitions require the operand types be the same and the appropriate comparison is made using the the positions of the operands. 275 \begin{cfa} 276 forall( E | CfaEnum( E ) | Serial( E ) ) @{@ $\C{// distribution block}$ 278 277 // comparison 279 278 int ?==?( E l, E r ); $\C{// true if l and r are same enumerators}$ … … 283 282 int ?>?( E l, E r ); $\C{// true if l is an enumerator after r}$ 284 283 int ?>=?( E l, E r ); $\C{// true if l after or the same as r}$ 285 } 286 \end{cfa} 287 288 \CFA implements few arithmetic operators for @CfaEnum@. Unlike update functions in @Serial@, these 289 operator does not have bound checks, which rely on @upperBound@ and @lowerBound@. These operators directly manipulate 290 position, the underlying representation of a \CFA enumeration. 291 \begin{cfa} 292 forall( E | CfaEnum( E ) | Serial( E ) ) { 284 @}@ 285 \end{cfa} 286 (Note, all the function prototypes are wrapped in a distribution block, where all qualifiers preceding the block are distributed to each declaration with the block, which eliminated tedious repeated qualification. 287 Distribution blocks can be nested.) 288 289 \CFA implements a few arithmetic operators for @CfaEnum@. 290 Unlike advancement functions in @Serial@, these operators perform direct arithmetic, so there is no implicit bound checks. 291 \begin{cfa} 292 forall( E | CfaEnum( E ) | Serial( E ) ) { $\C{// distribution block}$ 293 293 // comparison 294 294 E ++?( E & l ); … … 303 303 \end{cfa} 304 304 305 Lastly, \CFA does not define @zero_t@ for \CFA enumeration. Users can define the boolean false for 306 \CFA enumerations on their own. Here is an example: 307 \begin{cfa} 308 forall(E | CfaEnum(E)) 309 bool ?!=?(E lhs, zero_t) { 310 return posn(lhs) != 0; 311 } 312 \end{cfa} 313 which effectively turns the first enumeration as a logical false and true for others. 314 315 % \begin{cfa} 316 % Count variable_a = First, variable_b = Second, variable_c = Third, variable_d = Fourth; 317 % p(variable_a); // 0 318 % p(variable_b); // 1 319 % p(variable_c); // "Third" 320 % p(variable_d); // 3 321 % \end{cfa} 322 323 324 % \section{Iteration and Range} 325 326 327 328 % % It is convenient to iterate over a \CFA enumeration value, \eg: 329 % \CFA implements \newterm{range loop} for \CFA enumeration using the enumerated traits. The most basic form of @range loop@ is the follows: 330 % \begin{cfa}[label=lst:range_functions] 331 % for ( Alphabet alph; Alphabet ) { sout | alph; } 332 % >>> A B C ... D 333 % \end{cfa} 334 % % The @range loops@ iterates through all enumerators in the order defined in the enumeration. 335 % % @alph@ is the iterating enumeration object, which returns the value of an @Alphabet@ in this context according to the precedence rule. 336 % Enumerated @range loop@ extends the \CFA grammar as it allows a type name @Alphabet@ 337 338 % \textbullet\ \CFA offers a shorthand for iterating all enumeration constants: 339 % \begin{cfa}[label=lst:range_functions] 340 % for ( Alphabet alph ) { sout | alph; } 341 % >>> A B C ... D 342 % \end{cfa} 343 344 % The following are examples for constructing for-control using an enumeration. Note that the type declaration of the iterating variable is optional, because \CFA can infer the type as EnumInstType based on the range expression, and possibly convert it to one of its attribute types. 345 346 % \textbullet\ H is implicit up-to exclusive range [0, H). 347 % \begin{cfa}[label=lst:range_function_1] 348 % for ( alph; Alphabet.D ) { sout | alph; } 349 % >>> A B C 350 % \end{cfa} 351 352 % \textbullet\ ~= H is implicit up-to inclusive range [0,H]. 353 % \begin{cfa}[label=lst:range_function_2] 354 % for ( alph; ~= Alphabet.D ) { sout | alph; } 355 % >>> A B C D 356 % \end{cfa} 357 358 % \textbullet\ L ~ H is explicit up-to exclusive range [L,H). 359 % \begin{cfa}[label=lst:range_function_3] 360 % for ( alph; Alphabet.B ~ Alphabet.D ) { sout | alph; } 361 % // for ( Alphabet alph = Alphabet.B; alph < Alphabet.D; alph += 1 ); 1 is one_t 362 % >>> B C 363 % \end{cfa} 364 365 % \textbullet\ L ~= H is explicit up-to inclusive range [L,H]. 366 % \begin{cfa}[label=lst:range_function_4] 367 % for ( alph; Alphabet.B ~= Alphabet.D ) { sout | alph; } 368 % >>> B C D 369 % \end{cfa} 370 371 % \textbullet\ L -~ H is explicit down-to exclusive range [H,L), where L and H are implicitly interchanged to make the range down-to. 372 % \begin{cfa}[label=lst:range_function_5] 373 % for ( alph; Alphabet.D -~ Alphabet.B ) { sout | alph; } 374 % >>> D C 375 % \end{cfa} 376 377 % \textbullet\ L -~= H is explicit down-to exclusive range [H,L], where L and H are implicitly interchanged to make the range down-to. 378 % \begin{cfa}[label=lst:range_function_6] 379 % for ( alph; Alphabet.D -~= Alphabet.B ) { sout | alph; } 380 % >>> D C B 381 % \end{cfa} 382 383 % A user can specify the ``step size'' of an iteration. There are two different stepping schemes of enumeration for-loop. 384 % \begin{cfa}[label=lst:range_function_stepping] 385 % enum(int) Sequence { A = 10, B = 12, C = 14, D = 16, D = 18 }; 386 % for ( s; Sequence.A ~= Sequence.D ~ 1 ) { sout | alph; } 387 % >>> 10 12 14 16 18 388 % for ( s; Sequence.A ~= Sequence.D; s+=1 ) { sout | alph; } 389 % >>> 10 11 12 13 14 15 16 17 18 390 % \end{cfa} 391 % The first syntax is stepping to the next enumeration constant, which is the default stepping scheme if not explicitly specified. The second syntax, on the other hand, is to call @operator+=@ @one_type@ on the @value( s )@. Therefore, the second syntax is equivalent to 392 % \begin{cfa}[label=lst:range_function_stepping_converted] 393 % for ( typeof( value(Sequence.A) ) s=value( Sequence.A ); s <= Sequence.D; s+=1 ) { sout | alph; } 394 % >>> 10 11 12 13 14 15 16 17 18 395 % \end{cfa} 396 397 % % \PAB{Explain what each loop does.} 398 399 % It is also possible to iterate over an enumeration's labels, implicitly or explicitly: 400 % \begin{cfa}[label=lst:range_functions_label_implicit] 401 % for ( char * alph; Alphabet ) 402 % \end{cfa} 403 % This for-loop implicitly iterates every label of the enumeration, because a label is the only valid resolution to @ch@ with type @char *@ in this case. 404 % If the value can also be resolved as the @char *@, you might iterate the labels explicitly with the array iteration. 405 % \begin{cfa}[label=lst:range_functions_label_implicit] 406 % for ( char * ch; labels( Alphabet ) ) 407 % \end{cfa} 305 Lastly, \CFA does not define @zero_t@ for \CFA enumeration. 306 Users can define the boolean @false@ for \CFA enumerations on their own, \eg: 307 \begin{cfa} 308 forall( E | CfaEnum( E ) ) 309 int ?!=?( E lhs, zero_t ) { 310 return posn( lhs ) != 0; 311 } 312 \end{cfa} 313 which effectively turns the first enumeration to a logical @false@ and @true@ for the others. -
doc/theses/jiada_liang_MMath/uw-ethesis-frontpgs.tex
r2ca7fc2 r6abb6dc 141 141 One of the key properties of an enumeration is the ability to enumerate (iterate) through the constants, and hence, access their values, if present. 142 142 C restricts an enumeration to the integral type @signed int@, while \CC extends enumerations to all integral types, meaning enumeration names must bind to integer constants. 143 Other modern programming languages provide bindings to any type and additional features to extend enumeration capabilities for better software -engineering practices.144 145 The \CFA (C-for-all) programming language is an evolutionary refinement of the C program ing language.146 One of its distinctive feature is a parametric-polymorphic generic type.147 However, legacy data types from C, such as enumerations, do not adapt well into the \CFA generic type-system.143 Other modern programming languages provide bindings to any type and additional features to extend enumeration capabilities for better software engineering practices. 144 145 The \CFA (C-for-all) programming language is an evolutionary refinement of the C programming language. 146 One of its distinctive features is a parametric-polymorphic generic type. 147 However, legacy data types from C, such as enumerations, do not adapt well to the \CFA generic type-system. 148 148 149 149 This thesis extends the simple and unsafe enumeration type in the C programming language into a complex and safe enumeration type in the \CFA programming-language, while maintaining backwards compatibility with C. 150 150 The major contribution is an adaptation of enumerated types with the \CFA type-system in a way that integrates naturally with the generic types. 151 This thesis also presents a number of smaller refinementto the \CFA overload resolution rules for enumerated types, each of which improves the intuitive nature of enumeration name resolution by the compiler.151 This thesis also presents several smaller refinements to the \CFA overload resolution rules for enumerated types, each of which improves the intuitive nature of enumeration name resolution by the compiler. 152 152 Finally, this work adds other useful features to enumerations that better support software-engineering practices and simplify program development. 153 153 … … 166 166 Thanks to Gregor Richards and Yzihou Zhang for reading my thesis. 167 167 168 Special thanks to Andrew James Beach for your insight on the theory development o nthe thesis.168 Special thanks to Andrew James Beach for your insight on the theory development of the thesis. 169 169 170 170 Thanks to Michael Brooks, Fangran Yu, Colby Parsons, Thierry Delisle, Mubeen Zulifiqar, 171 and the entire \CFA team for development of the \CFA language, making it the best language it can be.171 and the entire \CFA team for the development of the \CFA language, making it the best language it can be. 172 172 173 173 Finally, a special thank you to Huawei Canada for funding this work. -
libcfa/src/collections/string.hfa
r2ca7fc2 r6abb6dc 10 10 // Created On : Fri Sep 03 11:00:00 2021 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Aug 5 23:06:14202413 // Update Count : 1 2812 // Last Modified On : Tue Aug 6 07:49:52 2024 13 // Update Count : 130 14 14 // 15 15 … … 161 161 string ?+?( char c, const string & s ); // add a character to a copy of the string 162 162 string ?+?( const string & s, const string & s2 ); // copy and concatenate both strings 163 string ?+?( const char * s, char c ); // copy and concatenate both strings164 string ?+?( char c, const char * s ); // copy and concatenate both strings165 string ?+?( const char * s1, const char * s2 ); // copy and concatenate both strings166 string ?+?( const char * s1, string & s2 ); // copy and concatenate both strings167 string ?+?( const string & s, const char * c ); // copy and concatenatewith NULL-terminated string163 string ?+?( const char * s, char c ); // add a character to a copy of the string 164 string ?+?( char c, const char * s ); // add a character to a copy of the string 165 string ?+?( const char * c, const char * s ); // copy and add with two NULL-terminated string 166 string ?+?( const char * c, string & s ); // copy and add with NULL-terminated string 167 string ?+?( const string & s, const char * c ); // copy and add with NULL-terminated string 168 168 169 169 static inline string & strcat( string & s, const string & s2 ) { s += s2; return s; } … … 184 184 185 185 // Comparisons 186 int strcmp ( const string &, const string & );187 bool ?==?( const string &, const string & );188 bool ?!=?( const string &, const string & );189 bool ?>? ( const string &, const string & );190 bool ?>=?( const string &, const string & );191 bool ?<=?( const string &, const string & );192 bool ?<? ( const string &, const string & );193 194 int strcmp( const string &, const char * );195 bool ?==?( const string &, const char * );196 bool ?!=?( const string &, const char * );197 bool ?>? ( const string &, const char * );198 bool ?>=?( const string &, const char * );199 bool ?<=?( const string &, const char * );200 bool ?<? ( const string &, const char * );201 202 int strcmp( const char *, const string & );203 bool ?==?( const char *, const string & );204 bool ?!=?( const char *, const string & );205 bool ?>? ( const char *, const string & );206 bool ?>=?( const char *, const string & );207 bool ?<=?( const char *, const string & );208 bool ?<? ( const char *, const string & );186 int strcmp ( const string &, const string & ); 187 bool ?==?( const string &, const string & ); 188 bool ?!=?( const string &, const string & ); 189 bool ?>? ( const string &, const string & ); 190 bool ?>=?( const string &, const string & ); 191 bool ?<=?( const string &, const string & ); 192 bool ?<? ( const string &, const string & ); 193 194 int strcmp( const string &, const char * ); 195 bool ?==?( const string &, const char * ); 196 bool ?!=?( const string &, const char * ); 197 bool ?>? ( const string &, const char * ); 198 bool ?>=?( const string &, const char * ); 199 bool ?<=?( const string &, const char * ); 200 bool ?<? ( const string &, const char * ); 201 202 int strcmp( const char *, const string & ); 203 bool ?==?( const char *, const string & ); 204 bool ?!=?( const char *, const string & ); 205 bool ?>? ( const char *, const string & ); 206 bool ?>=?( const char *, const string & ); 207 bool ?<=?( const char *, const string & ); 208 bool ?<? ( const char *, const string & ); 209 209 210 210 -
libcfa/src/enum.cfa
r2ca7fc2 r6abb6dc 11 11 // It is okay to overflow as overflow will be theoretically caught by the other bound 12 12 if ( i < fromInstance( lower ) || i > fromInstance( upper ) ) 13 abort( "call to fromInt has index %d outside enumeration range %d-%d",13 abort( "call to fromInt has index %d outside of enumeration range %d-%d.", 14 14 i, fromInstance( lower ), fromInstance( upper ) ); 15 15 return fromInt_unsafe( i ); … … 19 19 E upper = upperBound(); 20 20 if ( fromInstance( e ) >= fromInstance( upper ) ) 21 abort( "call to succ() exceeds enumeration upper bound of %d ", fromInstance( upper ) );21 abort( "call to succ() exceeds enumeration upper bound of %d.", fromInstance( upper ) ); 22 22 return succ_unsafe(e); 23 23 } … … 26 26 E lower = lowerBound(); 27 27 if ( fromInstance( e ) <= fromInstance(lower ) ) 28 abort( "call to pred() exceeds enumeration lower bound of %d ", fromInstance( lower ) );28 abort( "call to pred() exceeds enumeration lower bound of %d.", fromInstance( lower ) ); 29 29 return pred_unsafe( e ); 30 30 } 31 31 32 int Countof( __attribute__((unused)) E e) {32 int Countof( E ) { 33 33 E upper = upperBound(); 34 34 E lower = lowerBound(); -
libcfa/src/enum.hfa
r2ca7fc2 r6abb6dc 19 19 E succ( E e ); 20 20 E pred( E e ); 21 int Countof( E e);21 int Countof( E ); 22 22 } 23 23 -
libcfa/src/heap.cfa
r2ca7fc2 r6abb6dc 10 10 // Created On : Tue Dec 19 21:58:35 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Apr 7 21:54:29202413 // Update Count : 164 412 // Last Modified On : Wed Aug 7 10:14:47 2024 13 // Update Count : 1646 14 14 // 15 15 … … 582 582 __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText), 583 583 "CFA warning (UNIX pid:%ld) : program terminating with %td(%#tx) bytes of storage allocated but not freed.\n" 584 "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n",584 "Possible cause is mismatched allocation/deallocation calls (malloc/free), direct constructor call without a direct destructor call, or system/library routines not freeing storage.\n", 585 585 (long int)getpid(), allocUnfreed, allocUnfreed ); // always print the UNIX pid 586 586 } // if -
src/Validate/ImplementEnumFunc.cpp
r2ca7fc2 r6abb6dc 210 210 "value", 211 211 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))}, 212 {new ast::ObjectDecl(getLocation(), "_ret", 213 ast::deepCopy(decl->base))}); 214 // else 215 // return genQuasiValueProto(); 212 {new ast::ObjectDecl(getLocation(), "_ret", decl->base)}); 216 213 } 217 214
Note: See TracChangeset
for help on using the changeset viewer.