Changeset d800676 for doc/theses/colby_parsons_MMAth/text/CFA_intro.tex
- Timestamp:
- Mar 23, 2023, 12:18:39 PM (13 months ago)
- 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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/colby_parsons_MMAth/text/CFA_intro.tex
r1afd9ccb rd800676 5 5 % ====================================================================== 6 6 7 % potentially discuss rebindable references, with stmt, and operators8 9 7 \section{Overview} 8 The 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} 11 References 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}] 15 int i = 2; 16 int & ref_i = i; // declare ref to i 17 int * ptr_i = &i; // ptr to i 18 19 // address of ref_i is the same as address of i 20 assert( &ref_i == ptr_i ); 21 22 int && ref_ref_i = ref_i; // can have a ref to a ref 23 ref_i = 3; // set i to 3 24 int 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} 32 In \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}] 36 int foo() { printf("A\n"); return 0;} 37 int foo( int bar ) { printf("B\n"); return 1; } 38 int foo( double bar ) { printf("C\n"); return 2; } 39 double foo( double bar ) { printf("D\n"); return 3;} 40 void foo( double bar ) { printf("%.0f\n", bar); } 41 42 int 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} 53 The 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}] 57 struct obj { 58 int a, b, c; 59 }; 60 struct pair { 61 double x, y; 62 }; 63 64 // Stand-alone with stmt: 65 pair p; 66 with( p ) { 67 x = 6.28; 68 y = 1.73; 69 } 70 71 // Can be used on routines: 72 void 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: 81 void 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} 92 Operators can be overloaded in \CFA with operator routines. Operators in \CFA are named using the operator symbol and '?' to respresent operands. 93 An 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}] 97 struct coord { 98 double x; 99 double y; 100 double z; 101 }; 102 coord ++?( coord & c ) with(c) { 103 x++; 104 y++; 105 z++; 106 return c; 107 } 108 coord ?<=?( 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} 116 Constructors 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}] 120 struct discrete_point { 121 int x; 122 int y; 123 }; 124 void ?{}( discrete_point & this ) with(this) { // ctor 125 x = 0; 126 y = 0; 127 } 128 void ?{}( discrete_point & this, int x, int y ) { // ctor 129 this.x = x; 130 this.y = y; 131 } 132 void ^?{}( discrete_point & this ) with(this) { // dtor 133 x = 0; 134 y = 0; 135 } 136 137 int 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 10 144 11 145 \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} 146 C 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 153 forall( V & | sized(V) ) // type params for trait 154 trait 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 163 forall( 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 } 171 struct Vec1 { int x; }; 172 void ?{}( Vec1 & this, Vec1 & other ) { this.x = other.x; } 173 void ?{}( Vec1 & this, int x ) { this.x = x; } 174 void ^?{}( Vec1 & this ) {} 175 Vec1 add( Vec1 v1, Vec1 v2 ) { v1.x += v2.x; return v1; } 176 Vec1 scalar_mult( int c, Vec1 v1 ) { v1.x = v1.x * c; return v1; } 177 178 struct Vec2 { int x; int y; }; 179 void ?{}( Vec2 & this, Vec2 & other ) { this.x = other.x; this.y = other.y; } 180 void ?{}( Vec2 & this, int x ) { this.x = x; this.y = x; } 181 void ^?{}( Vec2 & this ) {} 182 Vec2 add( Vec2 v1, Vec2 v2 ) { v1.x += v2.x; v1.y += v2.y; return v1; } 183 Vec2 scalar_mult( int c, Vec2 v1 ) { v1.x = v1.x * c; v1.y = v1.y * c; return v1; } 184 185 int 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} 197 Inheritance 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}] 200 struct one_d { double x; }; 201 struct two_d { 202 inline one_d; 203 double y; 204 }; 205 struct three_d { 206 inline two_d; 207 double z; 208 }; 209 double get_x( one_d & d ){ return d.x; } 210 211 struct dog {}; 212 struct dog_food { 213 int count; 214 }; 215 struct pet { 216 inline dog; 217 inline dog_food; 218 }; 219 void pet_dog( dog & d ){printf("woof\n");} 220 void print_food( dog_food & f ){printf("%d\n", f.count);} 221 222 int 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.