| [38e20a80] | 1 | \chapter{Enumeration Traits} | 
|---|
|  | 2 | \label{c:trait} | 
|---|
| [956299b] | 3 |  | 
|---|
| [8cb2ff6] | 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++} | 
|---|
| [21f4dff] | 7 | #include <type_traits> | 
|---|
| [8cb2ff6] | 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. | 
|---|
| [21f4dff] | 22 |  | 
|---|
| [8cb2ff6] | 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. | 
|---|
| [21f4dff] | 24 |  | 
|---|
| [d1276f8] | 25 |  | 
|---|
| [9d3a4cc] | 26 | \section{Traits \texorpdfstring{\lstinline{CfaEnum}{CfaEnum}} and \texorpdfstring{\lstinline{TypedEnum}}{TypedEnum}} | 
|---|
| [8cb2ff6] | 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: | 
|---|
| [21f4dff] | 30 | \begin{cfa} | 
|---|
| [8cb2ff6] | 31 | forall( E ) | @CfaEnum( E )@ ) | 
|---|
|  | 32 | void f( E e ) { | 
|---|
|  | 33 | // access enumeration properties for e | 
|---|
|  | 34 | } | 
|---|
| [21f4dff] | 35 | \end{cfa} | 
|---|
|  | 36 |  | 
|---|
| [8cb2ff6] | 37 | Trait @CfaEnum@ defines attribute functions @label@ and @posn@ for all \CFA enumerations, and internally \CFA enumerations fulfills this assertion. | 
|---|
| [d1276f8] | 38 | \begin{cfa} | 
|---|
|  | 39 | forall( E ) trait CfaEnum { | 
|---|
|  | 40 | const char * @label@( E e ); | 
|---|
|  | 41 | unsigned int @posn@( E e ); | 
|---|
|  | 42 | }; | 
|---|
|  | 43 | \end{cfa} | 
|---|
| [8cb2ff6] | 44 | This trait covers opaque enumerations that do not have an explicit @value@. | 
|---|
| [d1276f8] | 45 |  | 
|---|
| [8cb2ff6] | 46 | The trait @TypedEnum@ extends @CfaEnum@ with the @value@ assertion for typed enumerations. | 
|---|
| [d1276f8] | 47 | \begin{cfa} | 
|---|
|  | 48 | forall( E, V | CfaEnum( E ) ) trait TypedEnum { | 
|---|
|  | 49 | V @value@( E e ); | 
|---|
|  | 50 | }; | 
|---|
|  | 51 | \end{cfa} | 
|---|
| [8cb2ff6] | 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. | 
|---|
| [d1276f8] | 54 |  | 
|---|
| [8cb2ff6] | 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. | 
|---|
| [38e20a80] | 59 |  | 
|---|
| [8cb2ff6] | 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 )"}$ | 
|---|
| [d1276f8] | 65 | } | 
|---|
| [8cb2ff6] | 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; }; | 
|---|
| [38e20a80] | 70 | enum(color_code) Rainbow { | 
|---|
| [8cb2ff6] | 71 | Red = {255, 0, 0}, Orange = {255, 127, 0}, Yellow = {255, 255, 0}, Green = {0, 255, 0}, // ... | 
|---|
| [38e20a80] | 72 | }; | 
|---|
| [8cb2ff6] | 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 | } | 
|---|
| [d1276f8] | 80 | \end{cfa} | 
|---|
| [8cb2ff6] | 81 | \caption{Generalized Enumeration Formatter} | 
|---|
|  | 82 | \label{f:GeneralizedEnumerationFormatter} | 
|---|
|  | 83 | \end{figure} | 
|---|
| [d1276f8] | 84 |  | 
|---|
| [8cb2ff6] | 85 | Other types may work with traits @CfaEnum@ and @TypedEnum@, by supplying appropriate @label@, @posn@, and @value@ functions. | 
|---|
| [4c63025] | 86 | For example, \VRef[Figure]{f:ExtendCEnumeration} extends a (possibly predefined) C enumeration to work with all the \CFA extensions. | 
|---|
| [38e20a80] | 87 |  | 
|---|
| [8cb2ff6] | 88 | \begin{figure} | 
|---|
| [d1276f8] | 89 | \begin{cfa} | 
|---|
| [8cb2ff6] | 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]; | 
|---|
| [d1276f8] | 94 | } | 
|---|
| [8cb2ff6] | 95 | int @posn@( Fruit f ) { return f; } | 
|---|
|  | 96 | int @value@( Fruit f ) { | 
|---|
|  | 97 | static const char values[] = { 'a', 'b', 'c' }; | 
|---|
|  | 98 | return values[f]; | 
|---|
| [38e20a80] | 99 | } | 
|---|
| [8cb2ff6] | 100 | sout | format_enum( Cherry );                           $\C{// "Cherry(c)"}$ | 
|---|
| [d1276f8] | 101 | \end{cfa} | 
|---|
| [4c63025] | 102 | \caption{Extend C Enumeration to \CFA Enumeration} | 
|---|
|  | 103 | \label{f:ExtendCEnumeration} | 
|---|
| [8cb2ff6] | 104 | \end{figure} | 
|---|
| [d1276f8] | 105 |  | 
|---|
| [6740533e] | 106 |  | 
|---|
| [8cb2ff6] | 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). | 
|---|
| [d7cb0f7] | 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. | 
|---|
| [8cb2ff6] | 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. | 
|---|
| [5fdaeab1] | 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. | 
|---|
| [6740533e] | 128 |  | 
|---|
|  | 129 |  | 
|---|
|  | 130 | \section{Bounded and Serial} | 
|---|
| [8cb2ff6] | 131 |  | 
|---|
|  | 132 | A bounded trait defines a lower and upper bound for a type. | 
|---|
| [d1276f8] | 133 | \begin{cfa} | 
|---|
|  | 134 | forall( E ) trait Bounded { | 
|---|
| [38e20a80] | 135 | E lowerBound(); | 
|---|
|  | 136 | E lowerBound(); | 
|---|
| [d1276f8] | 137 | }; | 
|---|
|  | 138 | \end{cfa} | 
|---|
| [8cb2ff6] | 139 | Both functions are necessary for the implementation of \CFA enumeration, with @lowerBound@ returning the first enumerator and @upperBound@ returning the last enumerator. | 
|---|
| [d1276f8] | 140 | \begin{cfa} | 
|---|
| [8cb2ff6] | 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}$ | 
|---|
| [d1276f8] | 145 | \end{cfa} | 
|---|
| [8cb2ff6] | 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. | 
|---|
| [d1276f8] | 148 | \begin{cfa} | 
|---|
| [8cb2ff6] | 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$ | 
|---|
| [d1276f8] | 153 | \end{cfa} | 
|---|
|  | 154 |  | 
|---|
| [8cb2ff6] | 155 | Trait @Serial@ is a subset of @Bounded@, with functions mapping enumerators to integers, and implementing a sequential order between enumerators. | 
|---|
| [d1276f8] | 156 | \begin{cfa} | 
|---|
|  | 157 | forall( E | Bounded( E ) ) trait Serial { | 
|---|
| [8cb2ff6] | 158 | int fromInstance( E e ); | 
|---|
| [38e20a80] | 159 | E fromInt( unsigned int i ); | 
|---|
| [d1276f8] | 160 | E pred( E e ); | 
|---|
| [8cb2ff6] | 161 | E succ( E e ); | 
|---|
|  | 162 | unsigned Countof( E ); | 
|---|
| [d1276f8] | 163 | }; | 
|---|
|  | 164 | \end{cfa} | 
|---|
| [8cb2ff6] | 165 | Function @fromInstance@ projects a @Bounded@ member to a number and @fromInt@ is the inverse. | 
|---|
| [92a0ee8] | 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. | 
|---|
| [38e20a80] | 168 | \begin{cfa} | 
|---|
| [8cb2ff6] | 169 | sout | fromInstance( Wed ) | fromInt( 2 ) | succ( Wed ) | pred( Wed ); | 
|---|
|  | 170 | 2 Wed Thu Tue | 
|---|
| [38e20a80] | 171 | \end{cfa} | 
|---|
| [8cb2ff6] | 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: | 
|---|
| [38e20a80] | 195 | \begin{enumerate} | 
|---|
| [8cb2ff6] | 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 )@. | 
|---|
| [38e20a80] | 205 | \end{enumerate} | 
|---|
|  | 206 |  | 
|---|
| [8cb2ff6] | 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 |  | 
|---|
| [96de72b] | 213 |  | 
|---|
|  | 214 | \subsection{For Loop} | 
|---|
| [38e20a80] | 215 |  | 
|---|
| [8cb2ff6] | 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: | 
|---|
| [96de72b] | 222 | \begin{cfa} | 
|---|
| [8cb2ff6] | 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; | 
|---|
| [38e20a80] | 230 | } | 
|---|
| [8cb2ff6] | 231 | sout | nl; | 
|---|
|  | 232 | A B C D | 
|---|
|  | 233 | A B C D | 
|---|
| [38e20a80] | 234 | \end{cfa} | 
|---|
| [d1276f8] | 235 |  | 
|---|
| [8cb2ff6] | 236 | A caveat in writing loop control using @pred@ and @succ@ is unintentionally exceeding the range. | 
|---|
| [96de72b] | 237 | \begin{cfa} | 
|---|
| [8cb2ff6] | 238 | for ( E e = upperBound(); e >= lowerBound(); e = pred( e ) ) {} | 
|---|
|  | 239 | for ( E e = lowerBound(); e <= upperBound(); e = succ( e ) ) {} | 
|---|
| [96de72b] | 240 | \end{cfa} | 
|---|
| [8cb2ff6] | 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. | 
|---|
| [96de72b] | 243 |  | 
|---|
|  | 244 |  | 
|---|
|  | 245 | \subsection{Range Loop} | 
|---|
| [8cb2ff6] | 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; | 
|---|
| [96de72b] | 253 | \end{cfa} | 
|---|
| [8cb2ff6] | 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}$ | 
|---|
| [96de72b] | 265 | \end{cfa} | 
|---|
| [8cb2ff6] | 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 |  | 
|---|
| [96de72b] | 270 |  | 
|---|
|  | 271 | \section{Overload Operators} | 
|---|
| [8cb2ff6] | 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. | 
|---|
| [d1276f8] | 275 | \begin{cfa} | 
|---|
| [8cb2ff6] | 276 | forall( E | CfaEnum( E ) | Serial( E ) ) @{@ $\C{// distribution block}$ | 
|---|
| [d1276f8] | 277 | // comparison | 
|---|
|  | 278 | int ?==?( E l, E r );           $\C{// true if l and r are same enumerators}$ | 
|---|
|  | 279 | int ?!=?( E l, E r );           $\C{// true if l and r are different enumerators}$ | 
|---|
|  | 280 | int ?<?( E l, E r );            $\C{// true if l is an enumerator before r}$ | 
|---|
|  | 281 | int ?<=?( E l, E r );           $\C{// true if l before or the same as r}$ | 
|---|
|  | 282 | int ?>?( E l, E r );            $\C{// true if l is an enumerator after r}$ | 
|---|
| [96de72b] | 283 | int ?>=?( E l, E r );           $\C{// true if l after or the same as r}$ | 
|---|
| [8cb2ff6] | 284 | @}@ | 
|---|
| [d1276f8] | 285 | \end{cfa} | 
|---|
| [8cb2ff6] | 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.) | 
|---|
| [d1276f8] | 288 |  | 
|---|
| [8cb2ff6] | 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. | 
|---|
| [96de72b] | 291 | \begin{cfa} | 
|---|
| [8cb2ff6] | 292 | forall( E | CfaEnum( E ) | Serial( E ) ) { $\C{// distribution block}$ | 
|---|
| [96de72b] | 293 | // comparison | 
|---|
|  | 294 | E ++?( E & l ); | 
|---|
|  | 295 | E --?( E & l ); | 
|---|
|  | 296 | E ?+=? ( E & l, one_t ); | 
|---|
|  | 297 | E ?-=? ( E & l, one_t ); | 
|---|
|  | 298 | E ?+=? ( E & l, int i ); | 
|---|
|  | 299 | E ?-=? ( E & l, int i ); | 
|---|
|  | 300 | E ?++( E & l ); | 
|---|
|  | 301 | E ?--( E & l ); | 
|---|
|  | 302 | } | 
|---|
|  | 303 | \end{cfa} | 
|---|
| [d1276f8] | 304 |  | 
|---|
| [8cb2ff6] | 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: | 
|---|
| [d1276f8] | 307 | \begin{cfa} | 
|---|
| [8cb2ff6] | 308 | forall( E | CfaEnum( E ) ) | 
|---|
|  | 309 | int ?!=?( E lhs, zero_t ) { | 
|---|
|  | 310 | return posn( lhs ) != 0; | 
|---|
| [d1276f8] | 311 | } | 
|---|
|  | 312 | \end{cfa} | 
|---|
| [8cb2ff6] | 313 | which effectively turns the first enumeration to a logical @false@ and @true@ for the others. | 
|---|