source: doc/theses/jiada_liang_MMath/implementation.tex @ d1276f8

Last change on this file since d1276f8 was d1276f8, checked in by Peter A. Buhr <pabuhr@…>, 4 months ago

move enumeration trait material into implementation chapter

  • Property mode set to 100644
File size: 35.2 KB
Line 
1\chapter{Enumeration Implementation}
2
3
4
5\section{Enumeration Traits}
6
7\CFA defines a set of traits containing operators and helper functions for @enum@.
8A \CFA enumeration satisfies all of these traits allowing it to interact with runtime features in \CFA.
9Each trait is discussed in detail.
10
11The trait @CfaEnum@:
12\begin{cfa}
13forall( E ) trait CfaEnum {
14        const char * @label@( E e );
15        unsigned int @posn@( E e );
16};
17\end{cfa}
18asserts an enumeration type @E@ has named enumerator constants (@label@) with positions (@posn@).
19
20The trait @TypedEnum@ extends @CfaEnum@:
21\begin{cfa}
22forall( E, V | CfaEnum( E ) ) trait TypedEnum {
23        V @value@( E e );
24};
25\end{cfa}
26asserting an enumeration type @E@ can have homogeneous enumerator values of type @V@.
27
28The declarative syntax
29\begin{cfa}
30enum(T) E { A = ..., B = ..., C = ... };
31\end{cfa}
32creates an enumerated type E with @label@, @posn@ and @value@ implemented automatically.
33\begin{cfa}
34void foo( T t ) { ... }
35void bar(E e) {
36        choose ( e ) {
37                case A: printf( "\%d", posn( e) );
38                case B: printf( "\%s", label( e ) );
39                case C: foo( value( e ) );
40        } 
41}
42\end{cfa}
43
44Implementing general functions across all enumeration types is possible by asserting @CfaEnum( E, T )@, \eg:
45\begin{cfa}
46#include <string.hfa>
47forall( E, T | CfaEnum( E, T ) | {unsigned int toUnsigned(T)} )
48string formatEnum( E e ) {
49        unsigned int v = toUnsigned( value( e ) );
50        string out = label(e) + '(' + v +')';
51        return out;
52}
53formatEnum( Week.Mon );
54formatEnum( RGB.Green );
55\end{cfa}
56
57\CFA does not define attribute functions for C-style enumeration.
58But it is possible for users to explicitly implement enumeration traits for C enum and any other types.
59\begin{cfa}
60enum Fruit { Apple, Pear, Cherry };                     $\C{// C enum}$
61const char * label( Fruit f ) {
62        choose ( f ) {
63                case Apple: return "Apple";
64                case Bear: return "Pear";
65                case Cherry: return "Cherry";
66        }
67}
68unsigned posn( Fruit f ) { return f; }
69const char * value( Fruit f ) { return ""; } $\C{// value can return any non void type}$
70formatEnum( Apple );                                            $\C{// Fruit is now a \CFA enum}$
71\end{cfa}
72
73A type that implements trait @CfaEnum@, \ie, a type has no @value@, is called an opaque enum.
74
75% \section{Enumerator Opaque Type}
76
77% \CFA provides a special opaque enumeration type, where the internal representation is chosen by the compiler and only equality operations are available.
78\begin{cfa}
79enum@()@ Planets { MERCURY, VENUS, EARTH, MARS, JUPITER, SATURN, URANUS, NEPTUNE };
80\end{cfa}
81
82
83In addition, \CFA implements @Bound@ and @Serial@ for \CFA enumerations.
84\begin{cfa}
85forall( E ) trait Bounded {
86        E first();
87        E last();
88};
89\end{cfa}
90The function @first()@ and @last()@ of enumerated type E return the first and the last enumerator declared in E, respectively. \eg:
91\begin{cfa}
92Workday day = first();                                  $\C{// Mon}$
93Planet outermost = last();                              $\C{// NEPTUNE}$
94\end{cfa}
95@first()@ and @last()@ are overloaded with return types only, so in the example, the enumeration type is found on the left-hand side of the assignment.
96Calling either functions without a context results in a type ambiguity, except in the rare case where the type environment has only one enumeration.
97\begin{cfa}
98@first();@                                                              $\C{// ambiguous because both Workday and Planet implement Bounded}$
99sout | @last()@;
100Workday day = first();                                  $\C{// day provides type Workday}$
101void foo( Planet p );
102foo( last() );                                                  $\C{// argument provides type Planet}$
103\end{cfa}
104
105The trait @Serial@:
106\begin{cfa}
107forall( E | Bounded( E ) ) trait Serial {
108        unsigned fromInstance( E e );
109        E fromInt( unsigned int posn );
110        E succ( E e );
111        E pred( E e );
112};
113\end{cfa}
114is a @Bounded@ trait, where elements can be mapped to an integer sequence.
115A type @T@ matching @Serial@ can project to an unsigned @int@ type, \ie an instance of type T has a corresponding integer value.
116%However, the inverse may not be possible, and possible requires a bound check.
117The mapping from a serial type to integer is defined by @fromInstance@, which returns the enumerator's position.
118The inverse operation is @fromInt@, which performs a bound check using @first()@ and @last()@ before casting the integer into an enumerator.
119Specifically, for enumerator @E@ declaring $N$ enumerators, @fromInt( i )@ returns the $i-1_{th}$ enumerator, if $0 \leq i < N$, or raises the exception @enumBound@.
120
121The @succ( E e )@ and @pred( E e )@ imply the enumeration positions are consecutive and ordinal.
122Specifically, if @e@ is the $i_{th}$ enumerator, @succ( e )@ returns the $i+1_{th}$ enumerator when $e \ne last()$, and @pred( e )@ returns the $i-1_{th}$ enumerator when $e \ne first()$.
123The exception @enumRange@ is raised if the result of either operation is outside the range of type @E@.
124
125Finally, there is an associated trait defining comparison operators among enumerators.
126\begin{cfa}
127forall( E, T | CfaEnum( E, T ) ) {
128        // comparison
129        int ?==?( E l, E r );           $\C{// true if l and r are same enumerators}$
130        int ?!=?( E l, E r );           $\C{// true if l and r are different enumerators}$
131        int ?!=?( E l, zero_t );        $\C{// true if l is not the first enumerator}$
132        int ?<?( E l, E r );            $\C{// true if l is an enumerator before r}$
133        int ?<=?( E l, E r );           $\C{// true if l before or the same as r}$
134        int ?>?( E l, E r );            $\C{// true if l is an enumerator after r}$
135        int ?>=?( E l, E r );           $\C{// true if l after or the same as r}$         
136}
137\end{cfa}
138
139As an alternative, users can define the boolean conversion for CfaEnum:
140
141\begin{cfa}
142forall(E | CfaEnum(E))
143bool ?!=?(E lhs, zero_t) {
144        return posn(lhs) != 0;
145}
146\end{cfa}
147which effectively turns the first enumeration as a logical zero and non-zero for others.
148
149\begin{cfa}
150Count variable_a = First, variable_b = Second, variable_c = Third, variable_d = Fourth;
151p(variable_a); // 0
152p(variable_b); // 1
153p(variable_c); // "Third"
154p(variable_d); // 3
155\end{cfa}
156
157
158\section{Enumeration Variable}
159
160Although \CFA enumeration captures three different attributes, an enumeration instance does not store all this information.
161The @sizeof@ a \CFA enumeration instance is always 4 bytes, the same size as a C enumeration instance (@sizeof( int )@).
162It comes from the fact that:
163\begin{enumerate}
164\item
165a \CFA enumeration is always statically typed;
166\item
167it is always resolved as one of its attributes regarding real usage.
168\end{enumerate}
169When creating an enumeration instance @colour@ and assigning it with the enumerator @Color.Green@, the compiler allocates an integer variable and stores the position 1.
170The invocations of $positions()$, $value()$, and $label()$ turn into calls to special functions defined in the prelude:
171\begin{cfa}
172position( green );
173>>> position( Colour, 1 ) -> int
174value( green );
175>>> value( Colour, 1 ) -> T
176label( green );
177>>> label( Colour, 1) -> char *
178\end{cfa}
179@T@ represents the type declared in the \CFA enumeration defined and @char *@ in the example.
180These generated functions are $Companion Functions$, they take an $companion$ object and the position as parameters.
181
182
183\section{Enumeration Data}
184
185\begin{cfa}
186enum(T) E { ... };
187// backing data
188T * E_values;
189char ** E_labels;
190\end{cfa}
191Storing values and labels as arrays can sometimes help support enumeration features.
192However, the data structures are the overhead for the programs. We want to reduce the memory usage for enumeration support by:
193\begin{itemize}
194        \item Only generates the data array if necessary
195        \item The compilation units share the data structures.
196        No extra overhead if the data structures are requested multiple times.
197\end{itemize}
198
199
200\section{Unification}
201
202\section{Enumeration as Value}
203\label{section:enumeration_as_value}
204An \CFA enumeration with base type T can be used seamlessly as T, without explicitly calling the pseudo-function value.
205\begin{cfa}
206char * green_value = Colour.Green; // "G"
207// Is equivalent to
208// char * green_value = value( Color.Green ); "G"
209\end{cfa}
210
211
212\section{Unification Distance}
213
214\begin{cfa}
215T_2 Foo(T1);
216\end{cfa}
217The @Foo@ function expects a parameter with type @T1@. In C, only a value with the exact type T1 can be used as a parameter for @Foo@. In \CFA, @Foo@ accepts value with some type @T3@ as long as @distance(T1, T3)@ is not @Infinite@.
218
219@path(A, B)@ is a compiler concept that returns one of the following:
220\begin{itemize}
221        \item Zero or 0, if and only if $A == B$.
222        \item Safe, if B can be used as A without losing its precision, or B is a subtype of A.
223        \item Unsafe, if B loses its precision when used as A, or A is a subtype of B.
224        \item Infinite, if B cannot be used as A. A is not a subtype of B and B is not a subtype of A.
225\end{itemize}
226
227For example, @path(int, int)==Zero@, @path(int, char)==Safe@, @path(int, double)==Unsafe@, @path(int, struct S)@ is @Infinite@ for @struct S{}@.
228@distance(A, C)@ is the minimum sum of paths from A to C. For example, if @path(A, B)==i@, @path(B, C)==j@, and @path(A, C)=k@, then $$distance(A,C)==min(path(A,B), path(B,C))==i+j$$.
229
230(Skip over the distance matrix here because it is mostly irrelevant for enumeration discussion. In the actual implementation, distance( E, T ) is 1.)
231
232The arithmetic of distance is the following:
233\begin{itemize}
234        \item $Zero + v= v$, for some value v.
235        \item $Safe * k <  Unsafe$, for finite k.
236        \item $Unsafe * k < Infinite$, for finite k.
237        \item $Infinite + v = Infinite$, for some value v.
238\end{itemize}
239
240For @enum(T) E@, @path(T, E)==Safe@ and @path(E,T)==Infinite@. In other words, enumeration type E can be @safely@ used as type T, but type T cannot be used when the resolution context expects a variable with enumeration type @E@.
241
242
243\section{Variable Overloading and Parameter Unification}
244
245\CFA allows variable names to be overloaded. It is possible to overload a variable that has type T and an enumeration with type T.
246\begin{cfa}
247char * green = "Green";
248Colour green = Colour.Green; // "G"
249
250void bar(char * s) { return s; }
251void foo(Colour c) { return value( c ); }
252
253foo( green ); // "G"
254bar( green ); // "Green"
255\end{cfa}
256\CFA's conversion distance helps disambiguation in this overloading. For the function @bar@ which expects the parameter s to have type @char *@, $distance(char *,char *) == Zero$ while $distance(char *, Colour) == Safe$, the path from @char *@ to the enumeration with based type @char *@, \CFA chooses the @green@ with type @char *@ unambiguously. On the other hand, for the function @foo@, @distance(Colour, char *)@ is @Infinite@, @foo@ picks the @green@ with type @char *@.
257
258\section{Function Overloading}
259Similarly, functions can be overloaded with different signatures. \CFA picks the correct function entity based on the distance between parameter types and the arguments.
260\begin{cfa}
261Colour green = Colour.Green;
262void foo(Colour c) { sout | "It is an enum"; } // First foo
263void foo(char * s) { sout | "It is a string"; } // Second foo
264foo( green ); // "It is an enum"
265\end{cfa}
266Because @distance(Colour, Colour)@ is @Zero@ and @distance(char *, Colour)@ is @Safe@, \CFA determines the @foo( green )@ is a call to the first foo.
267
268\section{Attributes Functions}
269The pseudo-function @value()@ "unboxes" the enumeration and the type of the expression is the underlying type. Therefore, in the section~\ref{section:enumeration_as_value} when assigning @Colour.Green@ to variable typed @char *@, the resolution distance is @Safe@, while assigning @value(Color.Green) to @char *) has resolution distance @Zero@.
270
271\begin{cfa}
272int s1;
273\end{cfa}
274The generated code for an enumeration instance is simply an int. It is to hold the position of an enumeration. And usage of variable @s1@ will be converted to return one of its attributes: label, value, or position, concerning the @Unification@ rule
275
276% \section{Unification and Resolution (this implementation will probably not be used, safe as reference for now)}
277
278% \begin{cfa}
279% enum Colour( char * ) { Red = "R", Green = "G", Blue = "B"  };
280% \end{cfa}
281% The @EnumInstType@ is convertible to other types.
282% A \CFA enumeration expression is implicitly \emph{overloaded} with its three different attributes: value, position, and label.
283% The \CFA compilers need to resolve an @EnumInstType@ as one of its attributes based on the current context.
284
285% \begin{cfa}[caption={Null Context}, label=lst:null_context]
286% {
287%       Colour.Green;
288% }
289% \end{cfa}
290% In example~\ref{lst:null_context}, the environment gives no information to help with the resolution of @Colour.Green@.
291% In this case, any of the attributes is resolvable.
292% According to the \textit{precedence rule}, the expression with @EnumInstType@ resolves as @value( Colour.Green )@.
293% The @EnumInstType@ is converted to the type of the value, which is statically known to the compiler as @char *@.
294% When the compilation reaches the code generation, the compiler outputs code for type @char *@ with the value @"G"@.
295% \begin{cfa}[caption={Null Context Generated Code}, label=lst:null_context]
296% {
297%       "G";
298% }
299% \end{cfa}
300% \begin{cfa}[caption={int Context}, label=lst:int_context]
301% {
302%       int g = Colour.Green;
303% }
304% \end{cfa}
305% The assignment expression gives a context for the EnumInstType resolution.
306% The EnumInstType is used as an @int@, and \CFA needs to determine which of the attributes can be resolved as an @int@ type.
307% The functions $Unify( T1, T2 ): bool$ take two types as parameters and determine if one type can be used as another.
308% In example~\ref{lst:int_context}, the compiler is trying to unify @int@ and @EnumInstType@ of @Colour@.
309% $$Unification( int, EnumInstType<Colour> )$$ which turns into three Unification call
310% \begin{cfa}[label=lst:attr_resolution_1]
311% {
312%       Unify( int, char * ); // unify with the type of value
313%       Unify( int, int ); // unify with the type of position
314%       Unify( int, char * ); // unify with the type of label
315% }
316% \end{cfa}
317% \begin{cfa}[label=lst:attr_resolution_precedence]
318% {
319%       Unification( T1, EnumInstType<T2> ) {
320%               if ( Unify( T1, T2 ) ) return T2;
321%               if ( Unify( T1, int ) ) return int;
322%               if ( Unify( T1, char * ) ) return char *;
323%               Error: Cannot Unify T1 with EnumInstType<T2>;
324%       }
325% }
326% \end{cfa}
327% After the unification, @EnumInstType@ is replaced by its attributes.
328
329% \begin{cfa}[caption={Unification Functions}, label=lst:unification_func_call]
330% {
331%       T2 foo ( T1 ); // function take variable with T1 as a parameter
332%       foo( EnumInstType<T3> ); // Call foo with a variable has type EnumInstType<T3>
333%       >>>> Unification( T1, EnumInstType<T3> )
334% }
335% \end{cfa}
336% % The conversion can work backward: in restrictive cases, attributes of can be implicitly converted back to the EnumInstType.
337% Backward conversion:
338% \begin{cfa}[caption={Unification Functions}, label=lst:unification_func_call]
339% {
340%       enum Colour colour = 1;
341% }
342% \end{cfa}
343
344% \begin{cfa}[caption={Unification Functions}, label=lst:unification_func_call]
345% {
346%       Unification( EnumInstType<Colour>, int ) >>> label
347% }
348% \end{cfa}
349% @int@ can be unified with the label of Colour.
350% @5@ is a constant expression $\Rightarrow$ Compiler knows the value during the compilation $\Rightarrow$ turns it into
351% \begin{cfa}
352% {
353%       enum Colour colour = Colour.Green;
354% }
355% \end{cfa}
356% Steps:
357% \begin{enumerate}
358% \item
359% identify @1@ as a constant expression with type @int@, and the value is statically known as @1@
360% \item
361% @unification( EnumInstType<Colour>, int )@: @position( EnumInstType< Colour > )@
362% \item
363% return the enumeration constant at position 1
364% \end{enumerate}
365% \begin{cfa}
366% {
367%       enum T (int) { ... } // Declaration
368%       enum T t = 1;
369% }
370% \end{cfa}
371% Steps:
372% \begin{enumerate}
373% \item
374% identify @1@ as a constant expression with type @int@, and the value is statically known as @1@
375% \item
376% @unification( EnumInstType<Colour>, int )@: @value( EnumInstType< Colour > )@
377% \item
378% return the FIRST enumeration constant that has the value 1, by searching through the values array
379% \end{enumerate}
380% The downside of the precedence rule: @EnumInstType@ $\Rightarrow$ @int ( value )@ $\Rightarrow$ @EnumInstType@ may return a different @EnumInstType@ because the value can be repeated and there is no way to know which one is expected $\Rightarrow$ want uniqueness
381
382% \section{Casting}
383% Casting an EnumInstType to some other type T works similarly to unify the EnumInstType with T. For example:
384% \begin{cfa}
385% enum( int ) Foo { A = 10, B = 100, C = 1000 };
386% (int) Foo.A;
387% \end{cfa}
388% The \CFA-compiler unifies @EnumInstType<int>@ with int, with returns @value( Foo.A )@, which has statically known value 10. In other words, \CFA-compiler is aware of a cast expression, and it forms the context for EnumInstType resolution. The expression with type @EnumInstType<int>@ can be replaced by the compile with a constant expression 10, and optionally discard the cast expression.
389
390% \section{Value Conversion}
391% As discussed in section~\ref{lst:var_declaration}, \CFA only saves @position@ as the necessary information. It is necessary for \CFA to generate intermediate code to retrieve other attributes.
392
393% \begin{cfa}
394% Foo a; // int a;
395% int j = a;
396% char * s = a;
397% \end{cfa}
398% Assume stores a value x, which cannot be statically determined. When assigning a to j in line 2, the compiler @Unify@ j with a, and returns @value( a )@. The generated code for the second line will be
399% \begin{cfa}
400% int j = value( Foo, a )
401% \end{cfa}
402% Similarly, the generated code for the third line is
403% \begin{cfa}
404% char * j = label( Foo, a )
405% \end{cfa}
406
407
408\section{Enumerator Initialization}
409
410An enumerator must have a deterministic immutable value, either be explicitly initialized in the enumeration definition, or implicitly initialized by rules.
411
412
413\section{C Enumeration Rule}
414
415A C enumeration has an integral type. If not initialized, the first enumerator implicitly has the integral value 0, and other enumerators have a value equal to its $predecessor + 1$.
416
417
418\section{Auto Initialization}
419
420C auto-initialization works for the integral type @int@ with constant expressions.
421\begin{cfa}
422enum Alphabet ! {
423        A = 'A', B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
424        a = 'a', b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
425};
426\end{cfa}
427The complexity of the constant expression depends on the level of runtime 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.
428
429The notion of auto-initialization can be generalized in \CFA through the trait @AutoInitializable@.
430\begin{cfa}
431forall(T) @trait@ AutoInitializable {
432        void ?{}( T & o, T v );                         $\C{// initialization}$
433        void ?{}( T & t, zero_t );                      $\C{// 0}$
434        T ?++( T & t);                                          $\C{// increment}$
435};
436\end{cfa}
437In addition, there is an implicit enumeration counter, @ecnt@ of type @T@, managed by the compiler.
438For example, the type @Odd@ satisfies @AutoInitializable@:
439\begin{cfa}
440struct Odd { int i; };
441void ?{}( Odd & o, int v ) { if ( v & 1 ) o.i = v; else /* error not odd */ ; };
442void ?{}( Odd & o, zero_t ) { o.i = 1; };
443Odd ?++( Odd o ) { return (Odd){ o.i + 2 }; };
444\end{cfa}
445and implicit initialization is available.
446\begin{cfa}
447enum( Odd ) { A, B, C = 7, D };                 $\C{// 1, 3, 7, 9}$
448\end{cfa}
449where the compiler performs the following transformation and runs the code.
450\begin{cfa}
451enum( Odd ) {
452        ?{}( ecnt, @0@ }  ?{}( A, ecnt },       ?++( ecnt )  ?{}( B, ecnt ),
453        ?{}( ecnt, 7 )  ?{}( C, ecnt ), ?++( ecnt )  ?{}( D, ecnt )
454};
455\end{cfa}
456
457Unfortunately, auto-initialization is not implemented because \CFA is only a transpiler, relying on generated C code to perform the detail work.
458C does not have the equivalent of \CC \lstinline[language={[GNU]C++}]{constexpr}, and it is currently beyond the scope of the \CFA project to implement a complex runtime interpreter in the transpiler.
459Nevertheless, the necessary language concepts exist to support this feature.
460
461
462\section{Enumeration Features}
463
464
465\section{Iteration and Range}
466
467It is convenient to iterate over a \CFA enumeration value, \eg:
468\begin{cfa}[label=lst:range_functions]
469for ( Alphabet alph; Alphabet ) { sout | alph; }
470>>> A B C ... D
471\end{cfa}
472The for-loop uses the enumeration type @Alphabet@ its range, and iterates through all enumerators in the order defined in the enumeration.
473@alph@ is the iterating enumeration object, which returns the value of an @Alphabet@ in this context according to the precedence rule.
474
475\textbullet\ \CFA offers a shorthand for iterating all enumeration constants:
476\begin{cfa}[label=lst:range_functions]
477for ( Alphabet alph ) { sout | alph; }
478>>> A B C ... D
479\end{cfa}
480
481The 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.
482
483\textbullet\ H is implicit up-to exclusive range [0, H).
484\begin{cfa}[label=lst:range_function_1]
485for ( alph; Alphabet.D ) { sout | alph; }
486>>> A B C
487\end{cfa}
488
489\textbullet\ ~= H is implicit up-to inclusive range [0,H].
490\begin{cfa}[label=lst:range_function_2]
491for ( alph; ~= Alphabet.D ) { sout | alph; }
492>>> A B C D
493\end{cfa}
494
495\textbullet\ L ~ H is explicit up-to exclusive range [L,H).
496\begin{cfa}[label=lst:range_function_3]
497for ( alph; Alphabet.B ~ Alphabet.D  ) { sout | alph; }
498// for ( Alphabet alph = Alphabet.B; alph < Alphabet.D; alph += 1  ); 1 is one_t
499>>> B C
500\end{cfa}
501
502\textbullet\ L ~= H is explicit up-to inclusive range [L,H].
503\begin{cfa}[label=lst:range_function_4]
504for ( alph; Alphabet.B ~= Alphabet.D  ) { sout | alph; }
505>>> B C D
506\end{cfa}
507
508\textbullet\ L -~ H is explicit down-to exclusive range [H,L), where L and H are implicitly interchanged to make the range down-to.
509\begin{cfa}[label=lst:range_function_5]
510for ( alph; Alphabet.D -~ Alphabet.B  ) { sout | alph; }
511>>> D C
512\end{cfa}
513
514\textbullet\ L -~= H is explicit down-to exclusive range [H,L], where L and H are implicitly interchanged to make the range down-to.
515\begin{cfa}[label=lst:range_function_6]
516for ( alph; Alphabet.D -~= Alphabet.B  ) { sout | alph; }
517>>> D C B
518\end{cfa}
519
520A user can specify the ``step size'' of an iteration. There are two different stepping schemes of enumeration for-loop.
521\begin{cfa}[label=lst:range_function_stepping]
522enum(int) Sequence { A = 10, B = 12, C = 14, D = 16, D  = 18 };
523for ( s; Sequence.A ~= Sequence.D ~ 1  ) { sout | alph; }
524>>> 10 12 14 16 18
525for ( s; Sequence.A ~= Sequence.D; s+=1  ) { sout | alph; }
526>>> 10 11 12 13 14 15 16 17 18
527\end{cfa}
528The 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
529\begin{cfa}[label=lst:range_function_stepping_converted]
530for ( typeof( value(Sequence.A) ) s=value( Sequence.A ); s <= Sequence.D; s+=1  ) { sout | alph; }
531>>> 10 11 12 13 14 15 16 17 18
532\end{cfa}
533
534% \PAB{Explain what each loop does.}
535
536It is also possible to iterate over an enumeration's labels, implicitly or explicitly:
537\begin{cfa}[label=lst:range_functions_label_implicit]
538for ( char * alph; Alphabet )
539\end{cfa}
540This 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.
541If the value can also be resolved as the @char *@, you might iterate the labels explicitly with the array iteration.
542\begin{cfa}[label=lst:range_functions_label_implicit]
543for ( char * ch; labels( Alphabet ) )
544\end{cfa}
545
546
547% \section{Non-uniform Type}
548% TODO: Working in Progress, might need to change other sections. Conflict with the resolution right now.
549
550% \begin{cfa}
551% enum T( int, char * ) {
552%        a=42, b="Hello World"
553% };
554% \end{cfa}
555% The enum T declares two different types: int and char *. The enumerators of T hold values of one of the declared types.
556
557\section{Enumeration Inheritance}
558
559\begin{cfa}[label=lst:EnumInline]
560enum( char * ) Name { Jack = "Jack", Jill = "Jill" };
561enum /* inferred */ Name2 { inline Name, Sue = "Sue", Tom = "Tom" };
562\end{cfa}
563\lstinline{Inline} allows Enumeration Name2 to inherit enumerators from Name1 by containment, and a Name enumeration is a subtype of enumeration Name2. An enumeration instance of type Name can be used where an instance of Name2 is expected.
564\begin{cfa}[label=lst:EnumInline]
565Name Fred;
566void f( Name2 );
567f( Fred );
568\end{cfa}
569If enumeration A declares @inline B@ in its enumeration body, enumeration A is the "inlining enum" and enumeration B is the "inlined enum".
570
571An enumeration can inline at most one other enumeration. The inline declaration must be placed before the first enumerator of the inlining enum. The inlining enum has all the enumerators from the inlined enum, with the same labels, values, and position.
572\begin{cfa}[label=lst:EnumInline]
573enum /* inferred */ Name2 { inline Name, Sue = "Sue", Tom = "Tom" };
574// is equivalent to enum Name2 { Jack = "Jack", Jill="Jill", Sue = "Sue", Tom = "Tom" };
575\end{cfa}
576Name.Jack is equivalent to Name2.Jack. Their attributes are all identical. Opening both Name and Name2 in the same scope will not introduce ambiguity.
577\begin{cfa}[label=lst:EnumInline]
578with( Name, Name2 ) { Jack; } // Name.Jack and Name2.Jack are equivalent. No ambiguity
579\end{cfa}
580
581\section{Implementation}
582
583\section{Static Attribute Expression}
584\begin{cfa}[label=lst:static_attr]
585enum( char * ) Colour {
586        Red = "red", Blue = "blue", Green = "green"
587};
588\end{cfa}
589An enumerator expression returns its enumerator value as a constant expression with no runtime cost. For example, @Colour.Red@ is equivalent to the constant expression "red", and \CFA finishes the expression evaluation before generating the corresponding C code. Applying a pseudo-function to a constant enumerator expression results in a constant expression as well. @value( Colour.Red )@, @position( Colour. Red )@, and @label( Colour.Red )@ are equivalent to constant expression with char * value "red", int value 0, and char * value "Red", respectively.
590
591\section{Runtime Attribute Expression and Weak Referenced Data}
592\begin{cfa}[label=lst:dynamic_attr]
593Colour c;
594...
595value( c ); // or c
596\end{cfa}
597An enumeration variable c is equivalent to an integer variable with the value of @position( c )@ In Example~\ref{lst:dynamic_attr}, the value of enumeration variable c is unknown at compile time. In this case, the pseudo-function calls are reduced to expression that returns the enumerator values at runtime.
598
599\CFA stores the variables and labels in @const@ arrays to provide runtime lookup for enumeration information.
600
601\begin{cfa}[label=lst:attr_array]
602const char * Colour_labels [3] = { "Red", "Blue", "Green" };
603const char * Colour_values [3] = { "red", "blue", "green" };
604\end{cfa}
605The \CFA compiles transforms the attribute expressions into array access.
606\begin{cfa}[label=lst:attr_array_access]
607position( c ) // c; an integer
608value( c ); // Colour_values[c]
609label( c ); // Colour_labels[c]
610\end{cfa}
611
612To avoid unnecessary memory usage, the labels and values array are only generated as needed, and only generate once across all compilation units. By default, \CFA defers the declaration of the label and value arrays until an call to attribute function with a dynamic value. If an attribute function is never called on a dynamic value of an enumerator, the array will never be allocated. Once the arrays are created, all compilation units share a weak reference to the allocation array.
613
614\section{Enum Prelude}
615
616\begin{cfa}[label=lst:enum_func_dec]
617forall( T ) {
618        unsigned position( unsigned );
619        T value( unsigned );
620        char * label( unsigned );
621}
622\end{cfa}
623\CFA loads the declaration of enumeration function from the enum.hfa.
624
625\section{Internal Representation}
626
627The definition of an enumeration is represented by an internal type called @EnumDecl@. At the minimum, it stores all the information needed to construct the companion object. Therefore, an @EnumDecl@ can be represented as the following:
628\begin{cfa}[label=lst:EnumDecl]
629forall(T)
630class EnumDecl {
631        T* values;
632        char** label;
633};
634\end{cfa}
635
636The internal representation of an enumeration constant is @EnumInstType@.
637An @EnumInstType@ has a reference to the \CFA-enumeration declaration and the position of the enumeration constant.
638\begin{cfa}[label=lst:EnumInstType]
639class EnumInstType {
640        EnumDecl enumDecl;
641        int position;
642};
643\end{cfa}
644In the later discussion, we will use @EnumDecl<T>@ to symbolize a @EnumDecl@ parameterized by type T, and @EnumInstType<T>@ is a declared instance of @EnumDecl<T>@.
645
646\begin{cfa}[caption={Enum Type Functions}, label=lst:cforall_enum_data]
647const T * const values;
648const char * label;
649int length;
650\end{cfa}
651Companion data are necessary information to represent an enumeration. They are stored as standalone pieces, rather than a structure. Those data will be loaded "on demand".
652Companion data are needed only if the according pseudo-functions are called. For example, the value of the enumeration Workday is loaded only if there is at least one compilation that has call $value(Workday)$. Once the values are loaded, all compilations share these values array to reduce memory usage.
653
654
655% \section{(Rework) Companion Object and Companion Function}
656
657% \begin{cfa}[caption={Enum Type Functions}, label=lst:cforall_enum_functions]
658% forall( T )
659% struct Companion {
660%       const T * const values;
661%                const char * label;
662%       int length;
663% };
664% \end{cfa}
665% \CFA generates companion objects, an instance of structure that encloses @necessary@ data to represent an enumeration. The size of the companion is unknown at the compilation time, and it "grows" in size to compensate for the @usage@.
666
667% The companion object is singleton across the compilation (investigation).
668
669% \CFA generates the definition of companion functions.
670% Because \CFA implicitly stores an enumeration instance as its position, the companion function @position@ does nothing but return the position it is passed.
671% Companions function @value@ and @label@ return the array item at the given position of @values@ and @labels@, respectively.
672% \begin{cfa}[label=lst:companion_definition]
673% int position( Companion o, int pos ) { return pos; }
674% T value( Companion o, int pos ) { return o.values[ pos ]; }
675% char * label( Companion o, int pos ) { return o.labels[ pos ]; }
676% \end{cfa}
677% Notably, the @Companion@ structure definition, and all companion objects, are visible to users.
678% A user can retrieve values and labels defined in an enumeration by accessing the values and labels directly, or indirectly by calling @Companion@ functions @values@ and @labels@
679% \begin{cfa}[label=lst:companion_definition_values_labels]
680% Colour.values; // read the Companion's values
681% values( Colour ); // same as Colour.values
682% \end{cfa}
683
684\section{Companion Traits (experimental)}
685Not sure its semantics yet, and it might replace a companion object.
686\begin{cfa}[label=lst:companion_trait]
687forall(T1) {
688        trait Companion(otype T2<otype T1>) {
689                T1 value((otype T2<otype T1> const &);
690                int position(otype T2<otype T1> const &);
691                char * label(otype T2<otype T1> const &);
692        }
693}
694\end{cfa}
695All enumerations implicitly implement the Companion trait, an interface to access attributes. The Companion can be a data type because it fulfills to requirements to have concrete instances, which are:
696
697\begin{enumerate}
698  \item The instance of enumeration has a single polymorphic type.
699  \item Each assertion should use the type once as a parameter.
700\end{enumerate}
701
702\begin{cfa}
703enum(int) Weekday {
704        Mon = 10, Tue, ...
705};
706
707T value( enum Weekday<T> & this);
708int position( enum Weekday<T> & this )
709char * label( enum Weekday<T> & this )
710
711trait Companion obj = (enum(int)) Workday.Weekday;
712value(obj); // 10
713\end{cfa}
714The enumeration comes with default implementation to the Companion traits functions. The usage of Companion functions would make \CFA allocates and initializes the necessary companion arrays, and return the data at the position represented by the enumeration.
715(...)
716
717\section{User Define Enumeration Functions}
718
719Companion objects make extending features for \CFA enumeration easy.
720\begin{cfa}[label=lst:companion_user_definition]
721char * charastic_string( Companion o, int position ) {
722        return sprintf( "Label: %s; Value: %s", label( o, position ), value( o, position) );
723}
724printf( charactic_string ( Color, 1 ) );
725>>> Label: Green; Value: G
726\end{cfa}
727Defining a function takes a Companion object effectively defines functions for all \CFA enumeration.
728
729The \CFA compiler turns a function call that takes an enumeration instance as a parameter into a function call with a companion object plus a position.
730Therefore, a user can use the syntax with a user-defined enumeration function call:
731\begin{cfa}[label=lst:companion_user_definition]
732charactic_string( Color.Green ); // equivalent to charactic_string( Color, 1 )
733>>> Label: Green; Value: G
734\end{cfa}
735Similarly, the user can work with the enumeration type itself: (see section ref...)
736\begin{cfa}[ label=lst:companion_user_definition]
737void print_enumerators ( Companion o ) {
738        for ( c : Companion o ) {
739                sout | label (c) | value( c ) ;
740        }
741}
742print_enumerators( Colour );
743\end{cfa}
744
745
746\section{Declaration}
747
748The qualified enumeration syntax is dedicated to \CFA enumeration.
749\begin{cfa}[label=lst:range_functions]
750enum (type_declaration) name { enumerator = const_expr, enumerator = const_expr, ... }
751\end{cfa}
752A compiler stores the name, the underlying type, and all enumerators in an @enumeration table@.
753During the $Validation$ pass, the compiler links the type declaration to the type's definition.
754It ensures that the name of an enumerator is unique within the enumeration body, and checks if all values of the enumerator have the declaration type.
755If the declared type is not @AutoInitializable@, \CFA rejects the enumeration definition.
756Otherwise, it attempts to initialize enumerators with the enumeration initialization pattern. (a reference to a future initialization pattern section)
757
758\begin{cfa}[label=lst:init]
759struct T { ... };
760void ?{}( T & t, zero_t ) { ... };
761void ?{}( T & t, one_t ) { ... };
762T ?+?( T & lhs, T & rhs ) { ... };
763
764enum (T) Sample {
765        Zero: 0 /* zero_t */,
766        One: Zero + 1 /* ?+?( Zero, one_t ) */ , ...
767};
768\end{cfa}
769Challenge: \\
770The value of an enumerator, or the initializer, requires @const_expr@.
771While previously getting around the issue by pushing it to the C compiler, it might not work anymore because of the user-defined types, user-defined @zero_t@, @one_t@, and addition operation.
772Might not be able to implement a \emph{correct} static check.
773
774\CFA $autogens$ a Companion object for the declared enumeration.
775\begin{cfa}[label=lst:companion]
776Companion( T ) Sample {
777        .values: { 0, 0+1, 0+1+1, 0+1+1+1, ... }, /* 0: zero_t, 1: one_t, +: ?+?{} */
778        .labels: { "Zero", "One", "Two", "Three", ...},
779        .length: /* number of enumerators */
780};
781\end{cfa}
782\CFA stores values as intermediate expressions because the result of the function call to the function @?+?{}(T&, T&)@ is statically unknown to \CFA.
783But the result is computed at run time, and the compiler ensures the @values@ are not changed.
784
785\section{Qualified Expression}
786
787\CFA uses qualified expression to address the scoping of \CFA-enumeration.
788\begin{cfa}[label=lst:qualified_expression]
789aggregation_name.field;
790\end{cfa}
791The qualified expression is not dedicated to \CFA enumeration.
792It is a feature that is supported by other aggregation in \CFA as well, including a C enumeration.
793When C enumerations are unscoped, the qualified expression syntax still helps to disambiguate names in the context.
794\CFA recognizes if the expression references a \CFA aggregation by searching the presence of @aggregation_name@ in the \CFA enumeration table.
795If the @aggregation_name@ is identified as a \CFA enumeration, the compiler checks if @field@ presents in the declared \CFA enumeration.
796
797\section{Instance Declaration}
798
799
800\begin{cfa}[label=lst:var_declaration]
801enum Sample s1;
802\end{cfa}
803
804The declaration \CFA-enumeration variable has the same syntax as the C-enumeration. Internally, such a variable will be represented as an EnumInstType.
Note: See TracBrowser for help on using the repository browser.