source: doc/theses/jiada_liang_MMath/implementation.tex @ 38e20a80

Last change on this file since 38e20a80 was 38e20a80, checked in by JiadaL <j82liang@…>, 14 hours ago

update thesis

  • Property mode set to 100644
File size: 12.0 KB
RevLine 
[38e20a80]1\chapter{Enumeration Traits}
2\label{c:trait}
[956299b]3
[38e20a80]4\section{CfaEnum and TypedEnum}
[d1276f8]5
[38e20a80]6\CFA defines attribute functions @label()@ and @posn()@ for all \CFA enumerations,
7and therefore \CFA enumerations fulfills the type assertions with the combination.
8With the observation, we define trait @CfaEnum@:
[d1276f8]9\begin{cfa}
10forall( E ) trait CfaEnum {
11        const char * @label@( E e );
12        unsigned int @posn@( E e );
13};
14\end{cfa}
15
[38e20a80]16% The trait @TypedEnum@ extends @CfaEnum@ with an additional value() assertion:
17Typed enumerations are \CFA enumeration with an additional @value@ attribute. Extending
18CfaEnum traits, TypedEnum is a subset of CFAEnum that implements attribute function @value()@,
19which includes all typed enumerations.
[d1276f8]20\begin{cfa}
21forall( E, V | CfaEnum( E ) ) trait TypedEnum {
22        V @value@( E e );
23};
24\end{cfa}
[38e20a80]25Type parameter V of TypedEnum trait binds to return type of @value()@, which is also the base
26type for typed enumerations. CfaEnum and TypedEnum triats constitues a CfaEnum function interfaces, as well a way to define functions
27over all CfaEnum enumerations.
[d1276f8]28\begin{cfa}
[38e20a80]29// for all type E that implements value() to return type T, where T is a type that convertible to string
30forall(  E, T | TypedEnum( E, T ) | { ?{}(string &, T ); } )
31string format_enum( E e ) { return label(E) + "(" + string(value(e)) + ")"; }
[d1276f8]32
[38e20a80]33// int is convertible to string; implemented in the standard library
34enum(int) RGB { Red = 0xFF0000, Green = 0x00FF00, Blue = 0x0000FF };
35
36struct color_code { int R; int G; int B };
37// Implement color_code to string conversion
38?{}(string & this, struct color_code p ) {
39        this = string(p.R) + ',' + string(p.G) + ',' + string(p.B);
[d1276f8]40}
[38e20a80]41enum(color_code) Rainbow {
42        Red = {255, 0, 0}, Orange = {255, 127, 0}, Yellow = {255, 255, 0}, Green = {0, 255, 0},
43        Blue = {0, 0, 255}, Indigo = {75, 0, 130}, Purple = {148, 0, 211}
44};
45
46format_enum(RGB.Green); // "Green(65280)"
47format_enum(Rainbow.Green); // "Green(0,255,0)"
[d1276f8]48\end{cfa}
49
[38e20a80]50
51% Not only CFA enumerations can be used with CfaEnum trait, other types that satisfy
52% CfaEnum assertions are all valid.
53Types does not need be defined as \CFA enumerations to work with CfaEnum traits. CfaEnum applies to any type
54with @label()@ and @value()@ being properly defined.
55Here is an example on how to extend a C enumeration to comply CfaEnum traits:
[d1276f8]56\begin{cfa}
[38e20a80]57enum Fruit { Apple, Banana, Cherry };                   $\C{// C enum}$
[d1276f8]58const char * label( Fruit f ) {
[38e20a80]59        choose( f ) {
[d1276f8]60                case Apple: return "Apple";
[38e20a80]61                case Banana: return "Banana";
[d1276f8]62                case Cherry: return "Cherry";
63        }
64}
[38e20a80]65unsigned posn( Fruit f ) { return f; } 
66char value( Fruit f ) { 
67        choose(f)  {
68                case Apple: return 'a';
69                case Banana: return 'b';
70                case Cherry: return 'c';
71        }
72}
[d1276f8]73
[38e20a80]74format_enum(Cherry); // "Cherry(c)"
[d1276f8]75\end{cfa}
76
[38e20a80]77\subsection{Bounded and Serial}
78A bounded type defines a lower bound and a upper bound.
[d1276f8]79\begin{cfa}
80forall( E ) trait Bounded {
[38e20a80]81        E lowerBound();
82        E lowerBound();
[d1276f8]83};
[38e20a80]84
[d1276f8]85\end{cfa}
[38e20a80]86Both Bounded functions are implement for \CFA enumerations, with @lowerBound()@ returning the first enumerator and @upperBound()@ returning
87the last enumerator.
[d1276f8]88\begin{cfa}
[38e20a80]89Workday day = lowerBound();                                     $\C{// Mon}$
90Planet outermost = upperBound();                                $\C{// NEPTUNE}$
[d1276f8]91\end{cfa}
[38e20a80]92
93The lowerBound() and upperBound() are functions overloaded on return type only, means their type resolution solely depend on the outer context,
94including expected type as a function argument, or the left hand size of an assignment expression.
95Calling either function without a context results in a type ambiguity, except in the rare case where the type environment has only one
96type overloads the functions, including \CFA enumerations, which has Bounded functions automatic defined.
[d1276f8]97\begin{cfa}
[38e20a80]98@lowerBound();@                 $\C{// ambiguous as both Workday and Planet implement Bounded}$
99sout | @lowerBound()@;
100Workday day = first();          $\C{// day provides type Workday}$
[d1276f8]101void foo( Planet p );
[38e20a80]102foo( last() );                      $\C{// argument provides type Planet}$
[d1276f8]103\end{cfa}
104
[38e20a80]105@Serial@ is a subset of @Bounded@, with functions maps elements against integers, as well implements a sequential order between members.
[d1276f8]106\begin{cfa}
107forall( E | Bounded( E ) ) trait Serial {
108        unsigned fromInstance( E e );
[38e20a80]109        E fromInt( unsigned int i );
[d1276f8]110        E succ( E e );
111        E pred( E e );
[38e20a80]112        unsigned Countof( E e );
[d1276f8]113};
114\end{cfa}
115
[38e20a80]116% A Serail type can project to an unsigned @int@ type, \ie an instance of type T has a corresponding integer value.
117Function @fromInstance()@ projects a @Bounded@ member to a number and @fromInt@ is the inverser. Function @succ()@ take an element, returns the "next"
118member in sequential order and @pred()@ returns the "last" member.
119
120A 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}.
121Calling @succ()@ on @upperBound@ or @pred()@ on @lowerBound()@ results in out of bound.
122
123\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.
124Unlike a cast, conversion between \CFA enumeration and integer with @Serial@ interface is type safe.
125Specifically for @fromInt@, \CFA abort if input i smaller than @fromInstance(lowerBound())@ or greater than @fromInstance(upperBound())@
126
127Function @Countof@ takes an object as a parameter and returns the number of elements in the Serial type, which is @fromInstance( upper ) - fromInstance( lower ) + 1@.
128@Countof@ does not use its arugment as procedural input; it needs
129an argument to anchor its polymorphic type T.
130
131\CFA has an expression @countof@ (lower case) that returns the number of enumerators defined for enumerations.
132\begin{cfa}
133enum RGB {Red, Green, Blue};
134countof( RGB ); // (1)
135countof( Red ); // (2)
136\end{cfa}
137Both expressions from the previous example are converted to constant expression @3@ with no function call at runtime.
138@countof@ also works for any type T that defines @Countof@ and @lowerBound@, for which it turns into
139a function call @Countof( T )@. The resolution step on expression @countof(e)@ works as the following with priority ordered:
140\begin{enumerate}
141\item Looks for an enumeration named e, such as @enum e {... }@.
142If such an enumeration e exists, \CFA replace @countof(e)@  with constant expression with number of enumerator of e.
143\item Looks for a non-enumeration type named e that defines @Countof@ and @lowerBound@, including e being a polymorphic type, such as @forall(e)@.
144If type e exists, \CFA replaces it with @Countof(lowerBound())@, where lowerBound() is bounded to type e. 
145\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.
146\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)@.
147\item If 1-4 fail, \CFA reports a type error on expression @countof(e)@.
148\end{enumerate}
149
150With the @Bounded@ and @Serial@, a loop over enumeration can be implemented in the following ways:
151\begin{cfa}
152enum() E { ... }
153for( unsigned i = 0; i < countof(E); i++ ) { ... }
154for( E e = lowerBound(); ; e = succ(e) ) { ...; if (e == upperBound()) break; }
155
156forall( T ) {
157        for( unsigned i = 0; i < countof(T); i++ ) { ... }
158        for( T e = lowerBound(); ; e = succ(e) ) { ...; if (e == upperBound()) break; }
159}
160\end{cfa}
[d1276f8]161
162Finally, there is an associated trait defining comparison operators among enumerators.
163\begin{cfa}
164forall( E, T | CfaEnum( E, T ) ) {
165        // comparison
166        int ?==?( E l, E r );           $\C{// true if l and r are same enumerators}$
167        int ?!=?( E l, E r );           $\C{// true if l and r are different enumerators}$
168        int ?!=?( E l, zero_t );        $\C{// true if l is not the first enumerator}$
169        int ?<?( E l, E r );            $\C{// true if l is an enumerator before r}$
170        int ?<=?( E l, E r );           $\C{// true if l before or the same as r}$
171        int ?>?( E l, E r );            $\C{// true if l is an enumerator after r}$
172        int ?>=?( E l, E r );           $\C{// true if l after or the same as r}$         
173}
174\end{cfa}
175
176As an alternative, users can define the boolean conversion for CfaEnum:
177
178\begin{cfa}
179forall(E | CfaEnum(E))
180bool ?!=?(E lhs, zero_t) {
181        return posn(lhs) != 0;
182}
183\end{cfa}
184which effectively turns the first enumeration as a logical zero and non-zero for others.
185
186\begin{cfa}
187Count variable_a = First, variable_b = Second, variable_c = Third, variable_d = Fourth;
188p(variable_a); // 0
189p(variable_b); // 1
190p(variable_c); // "Third"
191p(variable_d); // 3
192\end{cfa}
193
194
[956299b]195\section{Iteration and Range}
196
[f9da761]197It is convenient to iterate over a \CFA enumeration value, \eg:
[956299b]198\begin{cfa}[label=lst:range_functions]
199for ( Alphabet alph; Alphabet ) { sout | alph; }
200>>> A B C ... D
201\end{cfa}
202The for-loop uses the enumeration type @Alphabet@ its range, and iterates through all enumerators in the order defined in the enumeration.
203@alph@ is the iterating enumeration object, which returns the value of an @Alphabet@ in this context according to the precedence rule.
204
205\textbullet\ \CFA offers a shorthand for iterating all enumeration constants:
206\begin{cfa}[label=lst:range_functions]
207for ( Alphabet alph ) { sout | alph; }
208>>> A B C ... D
209\end{cfa}
210
211The 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.
212
213\textbullet\ H is implicit up-to exclusive range [0, H).
214\begin{cfa}[label=lst:range_function_1]
215for ( alph; Alphabet.D ) { sout | alph; }
216>>> A B C
217\end{cfa}
218
219\textbullet\ ~= H is implicit up-to inclusive range [0,H].
220\begin{cfa}[label=lst:range_function_2]
221for ( alph; ~= Alphabet.D ) { sout | alph; }
222>>> A B C D
223\end{cfa}
224
225\textbullet\ L ~ H is explicit up-to exclusive range [L,H).
226\begin{cfa}[label=lst:range_function_3]
227for ( alph; Alphabet.B ~ Alphabet.D  ) { sout | alph; }
228// for ( Alphabet alph = Alphabet.B; alph < Alphabet.D; alph += 1  ); 1 is one_t
229>>> B C
230\end{cfa}
231
232\textbullet\ L ~= H is explicit up-to inclusive range [L,H].
233\begin{cfa}[label=lst:range_function_4]
234for ( alph; Alphabet.B ~= Alphabet.D  ) { sout | alph; }
235>>> B C D
236\end{cfa}
237
238\textbullet\ L -~ H is explicit down-to exclusive range [H,L), where L and H are implicitly interchanged to make the range down-to.
239\begin{cfa}[label=lst:range_function_5]
240for ( alph; Alphabet.D -~ Alphabet.B  ) { sout | alph; }
241>>> D C
242\end{cfa}
243
244\textbullet\ L -~= H is explicit down-to exclusive range [H,L], where L and H are implicitly interchanged to make the range down-to.
245\begin{cfa}[label=lst:range_function_6]
246for ( alph; Alphabet.D -~= Alphabet.B  ) { sout | alph; }
247>>> D C B
248\end{cfa}
249
250A user can specify the ``step size'' of an iteration. There are two different stepping schemes of enumeration for-loop.
251\begin{cfa}[label=lst:range_function_stepping]
252enum(int) Sequence { A = 10, B = 12, C = 14, D = 16, D  = 18 };
253for ( s; Sequence.A ~= Sequence.D ~ 1  ) { sout | alph; }
254>>> 10 12 14 16 18
255for ( s; Sequence.A ~= Sequence.D; s+=1  ) { sout | alph; }
256>>> 10 11 12 13 14 15 16 17 18
257\end{cfa}
258The 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
259\begin{cfa}[label=lst:range_function_stepping_converted]
260for ( typeof( value(Sequence.A) ) s=value( Sequence.A ); s <= Sequence.D; s+=1  ) { sout | alph; }
261>>> 10 11 12 13 14 15 16 17 18
262\end{cfa}
263
264% \PAB{Explain what each loop does.}
265
266It is also possible to iterate over an enumeration's labels, implicitly or explicitly:
267\begin{cfa}[label=lst:range_functions_label_implicit]
268for ( char * alph; Alphabet )
269\end{cfa}
270This 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.
271If the value can also be resolved as the @char *@, you might iterate the labels explicitly with the array iteration.
272\begin{cfa}[label=lst:range_functions_label_implicit]
273for ( char * ch; labels( Alphabet ) )
274\end{cfa}
Note: See TracBrowser for help on using the repository browser.