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