source: doc/theses/jiada_liang_MMath/background.tex @ 292d6cf6

Last change on this file since 292d6cf6 was dcfcf368, checked in by Peter A. Buhr <pabuhr@…>, 7 weeks ago

final proofread of thesis

  • Property mode set to 100644
File size: 25.3 KB
Line 
1\chapter{Background}
2
3This chapter covers background material for C enumerations and \CFA features used in later discussions.
4
5
6\section{C}
7
8As mentioned in \VRef{s:Aliasing}, it is common for C programmers to believe there are three equivalent forms of named constants.
9\begin{clang}
10#define Mon 0
11static const int Mon = 0;
12enum { Mon };
13\end{clang}
14\begin{enumerate}[leftmargin=*]
15\item
16For @#define@, the programmer must explicitly manage the constant name and value.
17Furthermore, these C preprocessor macro names are outside the C type system and can unintentionally change program text.
18\item
19The 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{
20C 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\begin{clang}
22$\$$ nm test.o
230000000000000018 r Mon
24\end{clang}
25\item
26Only the @enum@ form is managed by the compiler, is part of the language type-system, works in all C constant-expression locations, and does not occupy storage.
27\end{enumerate}
28
29
30\subsection{C \texorpdfstring{\lstinline{const}}{const}}
31\label{s:Cconst}
32
33C can simulate the aliasing @const@ declarations \see{\VRef{s:Aliasing}}, with static and dynamic initialization.
34\begin{cquote}
35\begin{tabular}{@{}ll@{}}
36\multicolumn{1}{@{}c}{\textbf{static initialization}} &  \multicolumn{1}{c@{}}{\textbf{dynamic initialization}} \\
37\begin{clang}
38static const int one = 0 + 1;
39static const void * NIL = NULL;
40static const double PI = 3.14159;
41static const char Plus = '+';
42static const char * Fred = "Fred";
43static const int Mon = 0, Tue = Mon + 1, Wed = Tue + 1,
44        Thu = Wed + 1, Fri = Thu + 1, Sat = Fri + 1, Sun = Sat + 1;
45\end{clang}
46&
47\begin{clang}
48void foo() {
49        // auto scope only
50        const int r = random() % 100;
51        int va[r];
52}
53\end{clang}
54\end{tabular}
55\end{cquote}
56However, statically initialized identifiers cannot appear in constant-expression contexts, \eg @case@.
57Dynamically initialized identifiers may appear in initialization and array dimensions, which allows variable-sized arrays on the stack.
58Again, this form of aliasing is not an enumeration.
59
60
61\subsection{C Enumeration}
62\label{s:CEnumeration}
63
64The C enumeration has the following syntax~\cite[\S~6.7.2.2]{C11}.
65\begin{clang}[identifierstyle=\linespread{0.9}\it]
66$\it enum$-specifier:
67        enum identifier$\(_{opt}\)$ { enumerator-list }
68        enum identifier$\(_{opt}\)$ { enumerator-list , }
69        enum identifier
70enumerator-list:
71        enumerator
72        enumerator-list , enumerator
73enumerator:
74        enumeration-constant
75        enumeration-constant = constant-expression
76\end{clang}
77The terms \emph{enumeration} and \emph{enumerator} used in this work \see{\VRef{s:Terminology}} come from the grammar.
78The C enumeration semantics are discussed using examples.
79
80
81\subsubsection{Type Name}
82\label{s:TypeName}
83
84An \emph{unnamed} enumeration is used to provide aliasing \see{\VRef{s:Aliasing}} exactly like a @const@ declaration in other languages.
85However, it is restricted to integral values.
86\begin{clang}
87enum { Size = 20, Max = 10, MaxPlus10 = Max + 10, @Max10Plus1@, Fred = -7 };
88\end{clang}
89Here, the aliased constants are 20, 10, 20, 21, and -7.
90Direct initialization is achieved by a compile-time expression that generates a constant value.
91Indirect 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@.
92Because multiple independent enumerators can be combined, enumerators with the same values can occur.
93The enumerators are @rvalues@, so the assignment is disallowed.
94Finally, enumerators are \newterm{unscoped}, \ie enumerators declared inside of an @enum@ are visible (projected) outside into the enclosing scope of the @enum@ type.
95This semantic is required for unnamed enumerations because there is no type name for scoped qualification.
96
97As noted, this aliasing declaration is not an enumeration, even though it is declared using an @enum@ in C.
98While the semantics is misleading, this enumeration form matches with aggregate types:
99\begin{cfa}
100typedef struct @/* unnamed */@  { ... } S;
101struct @/* unnamed */@  { ... } x, y, z;        $\C{// questionable}$
102struct S {
103        union @/* unnamed */@ {                                 $\C{// unscoped fields}$
104                int i;  double d ;  char ch;
105        };
106};
107\end{cfa}
108Hence, C programmers would expect this enumeration form to exist in harmony with the aggregate form.
109
110A \emph{named} enumeration is an enumeration:
111\begin{clang}
112enum @Week@ { Mon, Tue, Wed, Thu@ = 10@, Fri, Sat, Sun };
113\end{clang}
114and adopts the same semantics as direct and auto initialization.
115For 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@.
116As well, initialization may occur in any order.
117\begin{clang}
118enum Week {
119        Thu@ = 10@, Fri, Sat, Sun,
120        Mon@ = 0@, Tue, Wed@,@                  $\C{// terminating comma}$
121};
122\end{clang}
123Note the comma in the enumerator list can be a terminator or a separator, allowing the list to end with a dangling comma.\footnote{
124A terminating comma appears in other C syntax, \eg the initializer list.}
125This feature allows enumerator lines to be interchanged without moving a comma.
126Named enumerators are also unscoped.
127
128
129\subsubsection{Implementation}
130\label{s:CenumImplementation}
131
132Theoretically, a C enumeration \emph{variable} is an implementation-defined integral type large enough to hold all enumerator values.
133In 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).
134According to the C standard, type @int@ is defined as the following:
135\begin{quote}
136A ``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\end{quote}
138\VRef[Table]{t:IntegerStorageSizes} shows integer storage sizes.
139On UNIX systems (LP64), @int@ means 4 bytes on both 32/64-bit architectures, which does not seem like the ``natural'' size for a 64-bit architecture.
140Whereas @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.
141On Windows systems (LLP64), @int@ and @long@ mean 4 bytes on both 32/64-bit architectures, which also does not seem like the ``natural'' size for a 64-bit architecture.
142\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.
143Hence, initialization in the range @INT_MIN@..@INT_MAX@ results in a 4-byte enumerator, and outside this range, the enumerator is 8 bytes.
144Note that @sizeof( typeof( IMin ) ) != sizeof( E )@, making the size of an enumerator different than its containing enumeration type, which seems inconsistent.
145
146\begin{table}
147\centering
148\caption{Integer Storage Sizes (bytes)}
149\label{t:IntegerStorageSizes}
150\begin{tabular}{@{}rcc@{}}
151Type                            & LP64  & LLP64 \\
152@char@                          & 1             & 1             \\
153@short@ @int@           & 2             & 2             \\
154@int@                           & 4             & 4             \\
155@long@ @int@            & 8             & 4             \\
156@long@ @long@ @int@     & 8             & 8             \\
157pointer                         & 8             & 8
158\end{tabular}
159\end{table}
160
161\begin{figure}
162\begin{cfa}
163enum E { IMin = INT_MIN, IMax = INT_MAX,
164                         ILMin = LONG_MIN, ILMax = LONG_MAX,
165                         ILLMin = LLONG_MIN, ILLMax = LLONG_MAX };
166int main() {
167        printf( "%zd %zd\n%zd %zd\n%zd %d %d\n%zd %ld %ld\n%zd %ld %ld\n",
168                        sizeof(enum E), sizeof(typeof(IMin)),
169                        sizeof(int), sizeof(long int),
170                        sizeof(IMin), IMin, IMax,
171                        sizeof(ILMin), ILMin, ILMax,
172                        sizeof(ILLMin), ILLMin, ILLMax );
173}
1748 4
1754 8
1764 -2147483648 2147483647
1778 -9223372036854775808 9223372036854775807
1788 -9223372036854775808 9223372036854775807
179\end{cfa}
180\caption{\lstinline{gcc}/\lstinline{clang} Enumeration Storage Size}
181\label{f:gccEnumerationStorageSize}
182\end{figure}
183
184
185\subsubsection{Usage}
186\label{s:Usage}
187
188C proves an implicit \emph{bidirectional} conversion between an enumeration and its integral type and between different enumerations.
189\begin{clang}
190enum Week week = Mon;                           $\C{// week == 0}$
191week = Fri;                                                     $\C{// week == 11}$
192int i = Sun;                                            $\C{// implicit conversion to int, i == 13}$
193@week = 10000;@                                         $\C{// UNDEFINED! implicit conversion to Week}$
194
195enum Season { Spring, Summer, Fall, Winter };
196@week = Winter;@                                        $\C{// UNDEFINED! implicit conversion to Week}$
197\end{clang}
198While 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.
199
200Enumerators can appear in @switch@ and looping statements.
201\begin{cfa}
202enum Week { Mon, Tue, Wed, Thu, Fri, Sat, Sun };
203switch ( week ) {
204        case Mon ... Fri:                               $\C{// gcc case range}$
205                printf( "weekday\n" );
206        case Sat: case Sun:
207                printf( "weekend\n" );
208}
209for ( enum Week day = Mon; day <= Sun; day += 1 ) { $\C{// step of 1}$
210        printf( "day %d\n", day ); // 0-6
211}
212\end{cfa}
213For iterating using arithmetic to make sense, the enumerator values \emph{must} have a consecutive ordering with a fixed step between values.
214For example, a previous gap introduced by @Thu = 10@ results in iterating over the values 0--13, where values 3--9 are not @Week@ values.
215Note 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@.
216For safety, \CC does not support the bidirectional conversion, and hence, an unsafe cast is necessary to increment @day@: @day = (Week)(day + 1)@.
217
218There is a C idiom that computes the number of enumerators in an enumeration automatically.
219\begin{cfa}
220enum E { A, B, C, D, @N@ };  // N == 4
221for ( enum E e = A; e < @N@; e += 1 ) ...
222\end{cfa}
223Serendipitously, the auto-incrementing counts the number of enumerators and puts the total into the last enumerator @N@.
224This @N@ is often used as the dimension for an array associated with the enumeration.
225\begin{cfa}
226E array[@N@];
227for ( enum E e = A; e < N; e += 1 ) {
228        array[e] = e;
229}
230\end{cfa}
231However, for non-consecutive ordering and non-integral typed enumerations, \see{\VRef{f:EumeratorTyping}}, this idiom fails.
232
233This idiom is often used with another C idiom for matching companion information.
234For example, an enumeration may be linked with a companion array of printable strings.
235\begin{cfa}
236enum Integral_Type { chr, schar, uschar, sshort, ushort, sint, usint, ..., NO_OF_ITYPES };
237char * Integral_Name[@NO_OF_ITYPES@] = {
238        "char", "signed char", "unsigned char",
239        "signed short int", "unsigned short int",
240        "signed int", "unsigned int", ...
241};
242enum Integral_Type @integral_type@ = ...
243printf( "%s\n", Integral_Name[@integral_type@] ); // human readable type name
244\end{cfa}
245However, 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}.
246The requirement to harmonize is, at best, indicated by a comment before the enumeration.
247This issue is exacerbated if enumeration and companion array are in different translation units.
248
249\bigskip
250While C provides a true enumeration, it is restricted, has unsafe semantics, and does not provide helpful/advanced enumeration features in other programming languages.
251
252
253\section{\texorpdfstring{\CFA}{Cforall}}
254
255\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.
256The following sections provide short descriptions of \CFA features needed further in the thesis.
257Other \CFA features are presented in situ with short or no explanation because the feature is obvious to C programmers.
258
259
260\subsection{Overloading}
261
262Overloading allows programmers to use the most meaningful names without fear of name clashes within a program or from external sources like included files.
263\begin{quote}
264There are only two hard things in Computer Science: cache invalidation and naming things. --- Phil Karlton
265\end{quote}
266Experience 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.
267In many cases, a programmer has no idea there are name clashes, as they are silently resolved, simplifying the development process.
268Depending on the language, ambiguous cases are resolved using some form of qualification and/or casting.
269
270
271\subsection{Operator Overloading}
272
273Virtually all programming languages overload the arithmetic operators across the basic types using the number and type of parameters and returns.
274Like \CC, \CFA also allows these operators to be overloaded with user-defined types.
275The syntax for operator names uses the @'?'@ character to denote a parameter, \eg unary operators: @?++@, @++?@, binary operator @?+?@.
276\begin{cfa}
277struct S { int i, j };
278S @?+?@( S op1, S op2 ) { return (S){ op1.i + op2.i, op1.j + op2.j }; }
279S s1, s2;
280s1 = s1 @+@ s2;                 $\C[1.75in]{// infix call}$
281s1 = @?+?@( s1, s2 );   $\C{// direct call}\CRT$
282\end{cfa}
283The type system examines each call size and selects the best matching overloaded function based on the number and types of arguments.
284If 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).
285
286
287\subsection{Function Overloading}
288
289Both \CFA and \CC allow function names to be overloaded as long as their prototypes differ in the number and type of parameters and returns.
290\begin{cfa}
291void f( void );                 $\C[1.75in]{// (1): no parameter}$
292void f( char );                 $\C{// (2): overloaded on the number and parameter type}$
293void f( int, int );             $\C{// (3): overloaded on the number and parameter type}$
294f( 'A' );                               $\C{// select (2)}\CRT$
295\end{cfa}
296In this case, the name @f@ is overloaded depending on the number and parameter types.
297The type system examines each call size and selects the best match based on the number and types of arguments.
298Here, the call @f( 'A' )@ is a perfect match for the number and parameter type of function (2).
299
300Ada, Scala, and \CFA type-systems also use the return type to pinpoint the best-overloaded name in resolving a call.
301\begin{cfa}
302int f( void );                  $\C[1.75in]{// (4); overloaded on return type}$
303double f( void );               $\C{// (5); overloaded on return type}$
304int i = f();                    $\C{// select (4)}$
305double d = f();                 $\C{// select (5)}\CRT$
306\end{cfa}
307
308
309\subsection{Variable Overloading}
310Unlike almost all programming languages, \CFA has variable overloading within a scope, along with shadow overloading in nested scopes.
311\begin{cfa}
312void foo( double d );
313int v;                              $\C[1.75in]{// (1)}$
314double v;                               $\C{// (2) variable overloading}$
315foo( v );                               $\C{// select (2)}$
316{
317        int v;                          $\C{// (3) shadow overloading}$
318        double v;                       $\C{// (4) and variable overloading}$
319        foo( v );                       $\C{// select (4)}\CRT$
320}
321\end{cfa}
322The \CFA type system treats overloaded variables as an overloaded function returning a value with no parameters.
323Hence, no significant effort is required to support this feature.
324
325
326\subsection{Constructor and Destructor}
327
328While \CFA is not object-oriented, it adopts many language features commonly used in object-oriented languages;
329these features are independent of object-oriented programming.
330
331All objects in \CFA are initialized by @constructors@ \emph{after} allocation and de-initialized \emph{before} deallocation.
332\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.
333Like \CC, \CFA has multiple auto-generated constructors for every type.
334
335The prototype for the constructor/destructor are @void ?{}( T &, ... )@ and @void ^?{}( T &, ... )@, respectively.
336The first parameter is logically the \lstinline[language=C++]{this} or \lstinline[language=Python]{self} in other object-oriented languages and implicitly passed.
337\VRef[Figure]{f:CFAConstructorDestructor} shows an example of creating and using a constructor and destructor.
338Both constructor and destructor can be explicitly called to reuse a variable.
339
340\begin{figure}
341\begin{cfa}
342struct Employee {
343        char * name;
344        double salary;
345};
346void @?{}@( Employee & emp, char * nname, double nsalary ) with( emp ) { // auto qualification
347        name = aalloc( sizeof(nname) );
348        strcpy( name, nname );
349        salary = nsalary;
350}
351void @^?{}@( Employee & emp ) {
352        free( emp.name );
353}
354{
355        Employee emp = { "Sara Schmidt", 20.5 }; $\C{// initialize with implicit constructor call}$
356        ... // use emp
357        ^?{}( emp ); $\C{// explicit de-initialize}$
358        ?{}( emp, "Jack Smith", 10.5 ); $\C{// explicit re-initialize}$
359        ... // use emp
360} $\C{// de-initialize with implicit destructor call}$
361\end{cfa}
362\caption{\CFA Constructor and Destructor}
363\label{f:CFAConstructorDestructor}
364\end{figure}
365
366
367\subsection{Special Literals}
368
369The C constants @0@ and @1@ have special meaning.
370@0@ is the null pointer and is used in conditional expressions, where @if ( p )@ is rewritten @if ( p != 0 )@;
371@1@ is an additive identity in unary operators @++@ and @--@.
372Aware of their significance, \CFA provides a special type @zero_t@ and @one_t@ for custom types.
373\begin{cfa}
374struct S { int i, j; };
375void ?{}( S & this, @zero_t@ ) { this.i = 0; this.j = 0; } // zero_t, no parameter name allowed
376int ?@!=@?( S this, @zero_t@ ) { return this.i != 0 && this.j != 0; }
377S s = @0@;
378if ( s @!= 0@ ) ...
379\end{cfa}
380Similarity, for @one_t@.
381\begin{cfa}
382void ?{}( S & this, @one_t@ ) { this.i = 1; this.j = 1; } // one_t, no parameter name allowed
383S & ?++( S & this, @one_t@ ) { return (S){ this.i++, this.j++ }; }
384\end{cfa}
385
386
387\subsection{Polymorphic Functions}
388
389Polymorphic functions are the functions that apply to all types.
390\CFA provides \newterm{parametric polymorphism} written with the @forall@ clause.
391\begin{cfa}
392@forall( T )@ T identity( T v ) { return v; }
393identity( 42 );
394\end{cfa}
395The @identity@ function accepts a value from any type as an argument and returns that value.
396At the call size, the type parameter @T@ is bounded to @int@ from the argument @42@.
397
398For polymorphic functions to be useful, the @forall@ clause needs \newterm{type assertion}s that restrict the polymorphic types it accepts.
399\begin{cfa}
400forall( T @| { void foo( T ); }@ ) void bar( T t ) { @foo( t );@ }
401struct S { ... } s;
402void foo( struct S );
403bar( s );
404\end{cfa}
405The 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.
406Unlike 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.
407
408
409\subsection{Trait}
410
411A @forall@ clause can assert many restrictions on multiple types.
412A common practice is refactoring the assertions into a named \newterm{trait}, similar to other languages like Go and Rust.
413\begin{cfa}
414forall(T) trait @Bird@ {
415        int days_can_fly( T );
416        void fly( T );
417};
418forall( B | @Bird@( B ) )
419void bird_fly( int days_since_born, B bird ) {
420        if ( days_since_born > days_can_fly( bird )) fly( bird );
421}
422struct Robin {} robin;
423int days_can_fly( Robin robin ) { return 23; }
424void fly( Robin robin ) {}
425bird_fly( 23, robin );
426\end{cfa}
427Grouping type assertions into a named trait effectively creates a reusable interface for parametric polymorphic types.
428
429
430\section{Expression Resolution}
431
432Overloading poses a challenge for all expression-resolution systems.
433Multiple overloaded names give multiple candidates at a call site, and a resolver must pick a \emph{best} match, where ``best'' is defined by a series of heuristics based on safety and programmer intuition/expectation.
434When multiple best matches exist, the resolution is ambiguous.
435
436The \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.
437Finding an exact match is not discussed here, because the mechanism is fairly straightforward, even when the search space is ample;
438only finding a non-exact match is discussed in detail.
439
440
441\subsection{Conversion Cost}
442\label{s:ConversionCost}
443
444Most programming languages perform some implicit conversions among basic types to facilitate mixed-mode arithmetic;
445otherwise, the program becomes littered with many explicit casts which do not match the programmer's expectations.
446C 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@.
447C 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.
448A 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}.
449
450\CFA generalizes ``usual arithmetic conversion'' to \newterm{conversion cost}.
451In the first design by Bilson~\cite{Bilson03}, conversion cost is a 3-tuple, @(unsafe, poly, safe)@ applied between each argument/parameter type, where:
452\begin{enumerate}
453\item
454@unsafe@ is the number of precision losing (\newterm{narrowing} conversions),
455\item
456@poly@ is the number of polymorphic function parameters, and
457\item
458@safe@ is the sum of the degree of safe (widening) conversions.
459\end{enumerate}
460Sum of degree is a method to quantify C's integer and floating-point rank.
461Every pair of widening conversion types is assigned a \newterm{distance}, and the distance between the two same types is 0.
462For example, the distance from @char@ to @int@ is 2, from @int@ to @long@ is 1, and from @int@ to @long long int@ is 2.
463This distance does not mirror C's rank system.
464For example, the @char@ and @signed char@ ranks are the same in C, but the distance from @char@ to @signed char@ is assigned 1.
465@safe@ cost is summing all pairs of arguments to parameter safe conversion distances.
466Among 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.
467
468For example, assume the overloaded function @foo@ is called with two @int@ parameters.
469The cost for every overloaded @foo@ has been listed along with the following:
470\begin{cfa}
471void foo( char, char );                         $\C[2.5in]{// (1) (2, 0, 0)}$
472void foo( char, int );                          $\C{// (2) (1, 0, 0)}$
473forall( T, V ) void foo( T, V );        $\C{// (3) (0, 2, 0)}$
474forall( T ) void foo( T, T );           $\C{// (4) (0, 2, 0)}$
475forall( T ) void foo( T, int );         $\C{// (5) (0, 1, 0)}$
476void foo( long long, long );            $\C{// (6) (0, 0, 3)}$
477void foo( long, long );                         $\C{// (7) (0, 0, 2)}$
478void foo( int, long );                          $\C{// (8) (0, 0, 1)}$
479int i, j;
480foo( i, j );                                            $\C{// convert j to long and call (8)}\CRT$
481\end{cfa}
482The overloaded instances are ordered from the highest to the lowest cost, and \CFA selects the last candidate (8).
483
484In 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:
485\begin{itemize}
486\item \textit{Unsafe}
487\item \textit{Poly}
488\item \textit{Safe}
489\item \textit{Sign} is the number of sign/unsign variable conversions.
490\item \textit{Vars} is the number of polymorphic type variables.
491\item \textit{Specialization} is the negative value of the number of type assertions.
492\item \textit{Reference} is number of reference-to-rvalue conversion.
493\end{itemize}
494The extended conversion-cost model looks for candidates that are more specific and less generic.
495@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.
496A more generic type means fewer constraints on its parameter types.
497\CFA favours candidates with more restrictions on polymorphism, so @forall( T ) void foo( T, T )@ has lower cost.
498@specialization@ is an arbitrary count-down value starting at zero.
499For every type assertion in the @forall@ clause (no assertions in the above example), \CFA subtracts one from @specialization@.
500More type assertions mean more constraints on argument types, making the function less generic.
501
502\CFA defines two special cost values: 0 and @infinite@.
503A conversion cost is 0 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.
504For example, the conversion cost from @int@ to a @struct S@ is @infinite@.
505
506In \CFA, the meaning of a C-style cast is determined by its @Cast Cost@.
507For most cast-expression resolutions, a cast cost equals a conversion cost.
508Cast cost exists as an independent matrix for conversion that cannot happen implicitly while being possible with an explicit cast.
509These conversions are often defined as having an infinite conversion cost and a non-infinite cast cost.
Note: See TracBrowser for help on using the repository browser.