Ignore:
Timestamp:
Mar 23, 2023, 12:18:39 PM (13 months ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, ast-experimental, master
Children:
c94b1f0
Parents:
1afd9ccb (diff), 18ea270 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

File:
1 edited

Legend:

Unmodified
Added
Removed
  • doc/theses/colby_parsons_MMAth/text/CFA_intro.tex

    r1afd9ccb rd800676  
    55% ======================================================================
    66
    7 % potentially discuss rebindable references, with stmt, and operators
    8 
    97\section{Overview}
     8The following serves as an introduction to \CFA. \CFA is a layer over C, is transpiled to C and is largely considered to be an extension of C. Beyond C, it adds productivity features, libraries, a type system, and many other language constructions. However, \CFA stays true to C as a language, with most code revolving around \code{struct}'s and routines, and respects the same rules as C. \CFA is not object oriented as it has no notion of \code{this} and no classes or methods, but supports some object oriented adjacent ideas including costructors, destructors, and limited inheritance. \CFA is rich with interesting features, but a subset that is pertinent to this work will be discussed.
     9
     10\section{References}
     11References in \CFA are similar to references in \CC, however in \CFA references are rebindable, and support multi-level referencing. References in \CFA are a layer of syntactic sugar over pointers to reduce the number of ref/deref operations needed with pointer usage. Some examples of references in \CFA are shown in Listing~\ref{l:cfa_ref}.
     12
     13
     14\begin{cfacode}[tabsize=3,caption={Example of \CFA references},label={l:cfa_ref}]
     15int i = 2;
     16int & ref_i = i;            // declare ref to i
     17int * ptr_i = &i;           // ptr to i
     18
     19// address of ref_i is the same as address of i
     20assert( &ref_i == ptr_i );
     21
     22int && ref_ref_i = ref_i;   // can have a ref to a ref
     23ref_i = 3;                  // set i to 3
     24int new_i = 4;
     25
     26// syntax to rebind ref_i (must cancel implicit deref)
     27&ref_i = &new_i; // (&*)ref_i = &new_i; (sets underlying ptr)
     28\end{cfacode}
     29
     30
     31\section{Overloading}
     32In \CFA routines can be overloaded on parameter type, number of parameters, and return type. Variables can also be overloaded on type, meaning that two variables can have the same name so long as they have different types. The variables will be disambiguated via type, sometimes requiring a cast. The code snippet in Listing~\ref{l:cfa_overload} contains examples of overloading.
     33
     34
     35\begin{cfacode}[tabsize=3,caption={Example of \CFA function overloading},label={l:cfa_overload}]
     36int foo() { printf("A\n");  return 0;}
     37int foo( int bar ) { printf("B\n"); return 1; }
     38int foo( double bar ) { printf("C\n"); return 2; }
     39double foo( double bar ) { printf("D\n"); return 3;}
     40void foo( double bar ) { printf("%.0f\n", bar); }
     41
     42int main() {
     43    foo();                  // prints A
     44    foo( 0 );               // prints B
     45    int a = foo( 0.0 );     // prints C
     46    double a = foo( 0.0 );  // prints D
     47    foo( a );               // prints 3
     48}
     49\end{cfacode}
     50
     51
     52\section{With Statement}
     53The with statement is a tool for exposing members of aggregate types within a scope in \CFA. It allows users to use fields of aggregate types without using their fully qualified name. This feature is also implemented in Pascal. It can exist as a stand-alone statement or it can be used on routines to expose fields in the body of the routine. An example is shown in Listing~\ref{l:cfa_with}.
     54
     55
     56\begin{cfacode}[tabsize=3,caption={Usage of \CFA with statement},label={l:cfa_with}]
     57struct obj {
     58    int a, b, c;
     59};
     60struct pair {
     61    double x, y;
     62};
     63
     64// Stand-alone with stmt:
     65pair p;
     66with( p ) {
     67    x = 6.28;
     68    y = 1.73;
     69}
     70
     71// Can be used on routines:
     72void foo( obj o, pair p ) with( o, p ) {
     73    a = 1;
     74    b = 2;
     75    c = 3;
     76    x = 3.14;
     77    y = 2.71;
     78}
     79
     80// routine foo is equivalent to routine bar:
     81void bar( obj o, pair p ) {
     82    o.a = 1;
     83    o.b = 2;
     84    o.c = 3;
     85    p.x = 3.14;
     86    p.y = 2.71;
     87}
     88\end{cfacode}
     89
     90
     91\section{Operators}
     92Operators can be overloaded in \CFA with operator routines. Operators in \CFA are named using the operator symbol and '?' to respresent operands.
     93An example is shown in Listing~\ref{l:cfa_operate}.
     94
     95
     96\begin{cfacode}[tabsize=3,caption={Example of \CFA operators},label={l:cfa_operate}]
     97struct coord {
     98    double x;
     99    double y;
     100    double z;
     101};
     102coord ++?( coord & c ) with(c) {
     103    x++;
     104    y++;
     105    z++;
     106    return c;
     107}
     108coord ?<=?( coord op1, coord op2 ) with( op1 ) {
     109    return (x*x + y*y + z*z) <=
     110        (op2.x*op2.x + op2.y*op2.y + op2.z*op2.z);
     111}
     112\end{cfacode}
     113
     114
     115\section{Constructors and Destructors}
     116Constructors and destructors in \CFA are two special operator routines that are used for creation and destruction of objects. The default constructor and destructor for a type are called implicitly upon creation and deletion respectively if they are defined. An example is shown in Listing~\ref{l:cfa_ctor}.
     117
     118
     119\begin{cfacode}[tabsize=3,caption={Example of \CFA constructors and destructors},label={l:cfa_ctor}]
     120struct discrete_point {
     121    int x;
     122    int y;
     123};
     124void ?{}( discrete_point & this ) with(this) { // ctor
     125    x = 0;
     126    y = 0;
     127}
     128void ?{}( discrete_point & this, int x, int y ) { // ctor
     129    this.x = x;
     130    this.y = y;
     131}
     132void ^?{}( discrete_point & this ) with(this) { // dtor
     133    x = 0;
     134    y = 0;
     135}
     136
     137int main() {
     138    discrete_point d; // implicit call to ?{}
     139    discrete_point p{}; // same call as line above
     140    discrete_point dp{ 2, -4 }; // specialized ctor
     141} // ^d{}, ^p{}, ^dp{} all called as they go out of scope
     142\end{cfacode}
     143
    10144
    11145\section{Polymorphism}\label{s:poly}
    12 
    13 \section{Overloading}
    14 
    15 \section{Constructors and Destructors}
    16 
    17 \section{With Statement}
    18 
    19 \section{Threading Model}\label{s:threading}
     146C does not natively support polymorphism, and requires users to implement polymorphism themselves if they want to use it. \CFA extends C with two styles of polymorphism that it supports, parametric polymorphism and nominal inheritance.
     147
     148\subsection{Parametric Polymorphism}
     149\CFA provides parametric polymorphism in the form of \code{forall}, and \code{trait}s. A \code{forall} takes in a set of types and a list of constraints. The declarations that follow the \code{forall} are parameterized over the types listed that satisfy the constraints. Sometimes the list of constraints can be long, which is where a \code{trait} can be used. A \code{trait} is a collection of constraints that is given a name and can be reused in foralls. An example of the usage of parametric polymorphism in \CFA is shown in Listing~\ref{l:cfa_poly}.
     150
     151\begin{cfacode}[tabsize=3,caption={Example of \CFA polymorphism},label={l:cfa_poly}]
     152// sized() is a trait that means the type has a size
     153forall( V & | sized(V) )        // type params for trait
     154trait vector_space {
     155    V add( V, V );              // vector addition
     156    V scalar_mult( int, V );    // scalar multiplication
     157
     158    // dtor and copy ctor needed in constraints to pass by copy
     159    void ?{}( V &, V & );       // copy ctor for return
     160    void ^?{}( V & );           // dtor
     161};
     162
     163forall( V & | vector_space( V )) {
     164    V get_inverse( V v1 ) {
     165        return scalar_mult( -1, v1 );  // can use ?*? routine defined in trait
     166    }
     167    V add_and_invert( V v1, V v2 ) {
     168        return get_inverse( add( v1, v2 ) );  // can use ?*? routine defined in trait
     169    }
     170}
     171struct Vec1 { int x; };
     172void ?{}( Vec1 & this, Vec1 & other ) { this.x = other.x; }
     173void ?{}( Vec1 & this, int x ) { this.x = x; }
     174void ^?{}( Vec1 & this ) {}
     175Vec1 add( Vec1 v1, Vec1 v2 ) { v1.x += v2.x; return v1; }
     176Vec1 scalar_mult( int c, Vec1 v1 ) { v1.x = v1.x * c; return v1; }
     177
     178struct Vec2 { int x; int y; };
     179void ?{}( Vec2 & this, Vec2 & other ) { this.x = other.x; this.y = other.y; }
     180void ?{}( Vec2 & this, int x ) { this.x = x; this.y = x; }
     181void ^?{}( Vec2 & this ) {}
     182Vec2 add( Vec2 v1, Vec2 v2 ) { v1.x += v2.x; v1.y += v2.y; return v1; }
     183Vec2 scalar_mult( int c, Vec2 v1 ) { v1.x = v1.x * c; v1.y = v1.y * c; return v1; }
     184
     185int main() {
     186    Vec1 v1{ 1 }; // create Vec1 and call ctor
     187    Vec2 v2{ 2 }; // create Vec2 and call ctor
     188
     189    // can use forall defined routines since types satisfy trait
     190    add_and_invert( get_inverse( v1 ), v1 );
     191    add_and_invert( get_inverse( v2 ), v2 );
     192}
     193
     194\end{cfacode}
     195
     196\subsection{Inheritance}
     197Inheritance in \CFA copies its style from Plan-9 C nominal inheritance. In \CFA structs can \code{inline} another struct type to gain its fields and to be able to be passed to routines that require a parameter of the inlined type. An example of \CFA inheritance is shown in Listing~\ref{l:cfa_inherit}.
     198
     199\begin{cfacode}[tabsize=3,caption={Example of \CFA inheritance},label={l:cfa_inherit}]
     200struct one_d { double x; };
     201struct two_d {
     202    inline one_d;
     203    double y;
     204};
     205struct three_d {
     206    inline two_d;
     207    double z;
     208};
     209double get_x( one_d & d ){ return d.x; }
     210
     211struct dog {};
     212struct dog_food {
     213    int count;
     214};
     215struct pet {
     216    inline dog;
     217    inline dog_food;
     218};
     219void pet_dog( dog & d ){printf("woof\n");}
     220void print_food( dog_food & f ){printf("%d\n", f.count);}
     221
     222int main() {
     223    one_d x;
     224    two_d y;
     225    three_d z;
     226    x.x = 1;
     227    y.x = 2;
     228    z.x = 3;
     229    get_x( x ); // returns 1;
     230    get_x( y ); // returns 2;
     231    get_x( z ); // returns 3;
     232    pet p;
     233    p.count = 5;
     234    pet_dog( p );    // prints woof
     235    print_food( p ); // prints 5
     236}
     237\end{cfacode}
     238
     239
Note: See TracChangeset for help on using the changeset viewer.