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\footnote{Source to source translator.} to C, and is largely considered to be an extension of C.
|
---|
10 | Beyond C, it adds productivity features, extended libraries, an advanced type-system, and many control-flow/concurrency constructions.
|
---|
11 | However, \CFA stays true to the C programming style, with most code revolving around @struct@s and routines, and respects the same rules as C.
|
---|
12 | \CFA is not object oriented as it has no notion of @this@ (receiver) and no structures with methods, but supports some object oriented ideas including constructors, destructors, and limited nominal inheritance.
|
---|
13 | While \CFA is rich with interesting features, only the subset pertinent to this work is discussed here.
|
---|
14 |
|
---|
15 | \section{References}
|
---|
16 | References in \CFA are similar to references in \CC; however \CFA references are \emph{rebindable}, and support multi-level referencing.
|
---|
17 | References in \CFA are a layer of syntactic sugar over pointers to reduce the number of syntactic ref/deref operations needed with pointer usage.
|
---|
18 | Pointers in \CFA differ from C and \CC in their use of @0p@ instead of C's @NULL@ or \CC's @nullptr@.
|
---|
19 | References can contain 0p in \CFA, which is the equivalent of a null reference.
|
---|
20 | Examples of references are shown in \VRef[Listing]{l:cfa_ref}.
|
---|
21 |
|
---|
22 | \begin{cfa}[caption={Example of \CFA references},label={l:cfa_ref}]
|
---|
23 | int i = 2;
|
---|
24 | int & ref_i = i; $\C{// declare ref to i}$
|
---|
25 | int * ptr_i = &i; $\C{// ptr to i}$
|
---|
26 |
|
---|
27 | // address of ref_i is the same as address of i
|
---|
28 | assert( &ref_i == ptr_i );
|
---|
29 |
|
---|
30 | int && ref_ref_i = ref_i; $\C{// can have a ref to a ref}$
|
---|
31 | ref_i = 3; $\C{// set i to 3}$
|
---|
32 | int new_i = 4;
|
---|
33 |
|
---|
34 | // syntax to rebind ref_i (must cancel implicit deref)
|
---|
35 | &ref_i = &new_i; $\C{// (\&*)ref\_i = \&new\_i; (sets underlying ptr)}$
|
---|
36 | \end{cfa}
|
---|
37 |
|
---|
38 |
|
---|
39 | \section{Overloading}\label{s:Overloading}
|
---|
40 | \CFA routines can be overloaded on parameter type, number of parameters, and \emph{return type}.
|
---|
41 | Variables can also be overloaded on type, meaning that two variables can have the same name so long as they have different types.
|
---|
42 | A routine or variable is disambiguated at each usage site via its type and surrounding expression context.
|
---|
43 | A cast is used to disambiguate any conflicting usage.
|
---|
44 | Examples of overloading are shown in \VRef[Listing]{l:cfa_overload}.
|
---|
45 |
|
---|
46 | \begin{cfa}[caption={Example of \CFA overloading},label={l:cfa_overload}]
|
---|
47 | int foo() { sout | "A"; return 0;}
|
---|
48 | int foo( int bar ) { sout | "B"; return 1; }
|
---|
49 | int foo( double bar ) { sout | "C"; return 2; }
|
---|
50 | double foo( double bar ) { sout | "D"; return 3; }
|
---|
51 | void foo( double bar ) { sout | bar; }
|
---|
52 |
|
---|
53 | int main() {
|
---|
54 | foo(); $\C{// prints A}$
|
---|
55 | foo( 0 ); $\C{// prints B}$
|
---|
56 | int foo = foo( 0.0 ); $\C{// prints C}$
|
---|
57 | double foo = foo( 0.0 ); $\C{// prints D}$
|
---|
58 | foo( foo ); $\C{// prints 3., where left-hand side of expression is void}$
|
---|
59 | }
|
---|
60 | \end{cfa}
|
---|
61 |
|
---|
62 |
|
---|
63 | \section{\lstinline{with} Statement}\label{s:with}
|
---|
64 | The \CFA @with@ statement is for exposing fields of an aggregate type within a scope, allowing field names without qualification.
|
---|
65 | This feature is also implemented in Pascal~\cite{Pascal}.
|
---|
66 | It can exist as a stand-alone statement or wrap a routine body to expose aggregate fields.
|
---|
67 | If exposed fields share a name, the type system will attempt to disambiguate them based on type.
|
---|
68 | If the type system is unable to disambiguate the fields then the user must qualify those names to avoid a compilation error.
|
---|
69 | Examples of the @with@ statement are shown in \VRef[Listing]{l:cfa_with}.
|
---|
70 |
|
---|
71 | \begin{cfa}[caption={Example of \CFA \lstinline{with} statement},label={l:cfa_with}]
|
---|
72 | struct pair { double x, y; };
|
---|
73 | struct triple { int a, b, c; };
|
---|
74 | pair p;
|
---|
75 |
|
---|
76 | @with( p )@ { $\C{// stand-alone with}$
|
---|
77 | p.x = 6.28; p.y = 1.73; $\C{// long form}$
|
---|
78 | x = 6.28; y = 1.73; $\C{// short form}$
|
---|
79 | }
|
---|
80 | void foo( triple t, pair p ) @with( t, p )@ { $\C{// routine with}$
|
---|
81 | t.a = 1; t.b = 2; t.c = 3; p.x = 3.14; p.y = 2.71; $\C{// long form}$
|
---|
82 | a = 1; b = 2; c = 3; x = 3.14; y = 2.71; $\C{// short form}$
|
---|
83 | }
|
---|
84 | \end{cfa}
|
---|
85 |
|
---|
86 |
|
---|
87 | \section{Operators}\label{s:Operators}
|
---|
88 | Operators can be overloaded in \CFA with operator routines.
|
---|
89 | Operators in \CFA are named using an operator symbol and '@?@' to represent operands.
|
---|
90 | Examples of \CFA operators are shown in \VRef[Listing]{l:cfa_operate}.
|
---|
91 |
|
---|
92 | \begin{cfa}[caption={Example of \CFA operators},label={l:cfa_operate}]
|
---|
93 | struct coord {
|
---|
94 | double x, y, z;
|
---|
95 | };
|
---|
96 | coord ++@?@( coord & c ) with( c ) { $\C{// post increment}$
|
---|
97 | x++; y++; z++;
|
---|
98 | return c;
|
---|
99 | }
|
---|
100 | coord @?@<=@?@( coord op1, coord op2 ) with( op1 ) { $\C{// ambiguous with both parameters}$
|
---|
101 | return (x * x + y * y + z * z) <= (op2.x * op2.x + op2.y * op2.y + op2.z * op2.z);
|
---|
102 | }
|
---|
103 | \end{cfa}
|
---|
104 |
|
---|
105 | The operator '@|@' is used for \CFA stream I/O, similar to how \CC, uses operators '@<<@' and '@>>@' \VRef[Listing]{l:cfa_stream}.
|
---|
106 |
|
---|
107 | \begin{cfa}[caption={Example of \CFA stream I/O},label={l:cfa_stream}]
|
---|
108 | char c; int i; double d;
|
---|
109 | sin | c | i | d; $\C{ // read into c, i, and d }$
|
---|
110 | sout | c | i | d; $\C{ // output c, i, and d }$
|
---|
111 | x 27 2.3 $\C{ // implicit separation between values and auto newline }$
|
---|
112 | \end{cfa}
|
---|
113 |
|
---|
114 |
|
---|
115 | \section{Constructors and Destructors}
|
---|
116 | Constructors and destructors in \CFA are special operator routines used for creation and destruction of objects.
|
---|
117 | The default constructor and destructor for a type are called implicitly upon creation and deletion, respectively.
|
---|
118 | Examples of \CFA constructors and destructors are shown in \VRef[Listing]{l:cfa_ctor}.
|
---|
119 |
|
---|
120 | \begin{cfa}[caption={Example of \CFA constructors and destructors},label={l:cfa_ctor}]
|
---|
121 | struct discrete_point {
|
---|
122 | int x, y;
|
---|
123 | };
|
---|
124 | void ?{}( discrete_point & this ) with(this) { $\C{// default constructor}$
|
---|
125 | [x, y] = 0;
|
---|
126 | }
|
---|
127 | void ?{}( discrete_point & this, int x, int y ) { $\C{// explicit constructor}$
|
---|
128 | this.[x, y] = [x, y];
|
---|
129 | }
|
---|
130 | void ^?{}( discrete_point & this ) with(this) { $\C{// destructor}$
|
---|
131 | ?{}( this ); $\C{// reset by calling default constructor}$
|
---|
132 | }
|
---|
133 | int main() {
|
---|
134 | discrete_point x, y{}; $\C{// implicit call to default ctor, ?\{\}}$
|
---|
135 | discrete_point s = { 2, -4 }, t{ 4, 2 }; $\C{// explicit call to specialized ctor}$
|
---|
136 | } // ^t{}, ^s{}, ^y{}, ^x{} implicit calls in reverse allocation order
|
---|
137 | \end{cfa}
|
---|
138 |
|
---|
139 |
|
---|
140 | \section{Polymorphism}\label{s:poly}
|
---|
141 | C supports limited polymorphism, often requiring users to implement polymorphism using a @void *@ (explicit type erasure) approach.
|
---|
142 | \CFA extends C with generalized overloading polymorphism (see \VRef{s:Overloading}), as well as parametric polymorphism and limited inclusion polymorphism (nominal inheritance).
|
---|
143 |
|
---|
144 | \subsection{Parametric Polymorphism}
|
---|
145 | \CFA provides parametric polymorphism in the form of @forall@, and @trait@s.
|
---|
146 | A @forall@ takes in a set of types and a list of constraints.
|
---|
147 | The declarations that follow the @forall@ are parameterized over the types listed that satisfy the constraints.
|
---|
148 | A list of @forall@ constraints can be refactored into a named @trait@ and reused in @forall@s.
|
---|
149 | Examples of \CFA parametric polymorphism are shown in \VRef[Listing]{l:cfa_poly}.
|
---|
150 |
|
---|
151 | \begin{cfa}[caption={Example of \CFA parametric polymorphism},label={l:cfa_poly}]
|
---|
152 | // sized() is a trait that means the type has a size
|
---|
153 | forall( V & | sized(V) ) $\C{// type params for trait}$
|
---|
154 | trait vector_space {
|
---|
155 | // dtor and copy ctor needed in constraints to pass by copy
|
---|
156 | void ?{}( V &, V & ); $\C{// copy ctor for return}$
|
---|
157 | void ^?{}( V & ); $\C{// dtor}$
|
---|
158 | V ?+?( V, V ); $\C{// vector addition}$
|
---|
159 | V ?*?( int, V ); $\C{// scalar multiplication}$
|
---|
160 | };
|
---|
161 |
|
---|
162 | forall( V & | vector_space( V ) ) {
|
---|
163 | V get_inverse( V v1 ) {
|
---|
164 | return -1 * v1; $\C{// can use ?*? routine defined in trait}$
|
---|
165 | }
|
---|
166 | V add_and_invert( V v1, V v2 ) {
|
---|
167 | return get_inverse( v1 + v2 ); $\C{// can use ?+? routine defined in trait}$
|
---|
168 | }
|
---|
169 | }
|
---|
170 | struct Vec1 { int x; };
|
---|
171 | void ?{}( Vec1 & this, Vec1 & other ) { this.x = other.x; }
|
---|
172 | void ?{}( Vec1 & this, int x ) { this.x = x; }
|
---|
173 | void ^?{}( Vec1 & this ) {}
|
---|
174 | Vec1 ?+?( Vec1 v1, Vec1 v2 ) { v1.x += v2.x; return v1; }
|
---|
175 | Vec1 ?*?( int c, Vec1 v1 ) { v1.x = v1.x * c; return v1; }
|
---|
176 |
|
---|
177 | struct Vec2 { int x; int y; };
|
---|
178 | void ?{}( Vec2 & this, Vec2 & other ) { this.x = other.x; this.y = other.y; }
|
---|
179 | void ?{}( Vec2 & this, int x ) { this.x = x; this.y = x; }
|
---|
180 | void ^?{}( Vec2 & this ) {}
|
---|
181 | Vec2 ?+?( Vec2 v1, Vec2 v2 ) { v1.x += v2.x; v1.y += v2.y; return v1; }
|
---|
182 | Vec2 ?*?( int c, Vec2 v1 ) { v1.x = v1.x * c; v1.y = v1.y * c; return v1; }
|
---|
183 |
|
---|
184 | int main() {
|
---|
185 | Vec1 v1{ 1 }; $\C{// create Vec1 and call ctor}$
|
---|
186 | Vec2 v2{ 2 }; $\C{// create Vec2 and call ctor}$
|
---|
187 | // can use forall defined routines since types satisfy trait
|
---|
188 | add_and_invert( get_inverse( v1 ), v1 );
|
---|
189 | add_and_invert( get_inverse( v2 ), v2 );
|
---|
190 | }
|
---|
191 | \end{cfa}
|
---|
192 |
|
---|
193 | \subsection{Inheritance}\label{s:Inheritance}
|
---|
194 | Inheritance in \CFA is taken from Plan-9 C's nominal inheritance.
|
---|
195 | In \CFA, @struct@s can @inline@ another struct type to gain its fields and masquerade as that type.
|
---|
196 | Examples of \CFA nominal inheritance are shown in \VRef[Listing]{l:cfa_inherit}.
|
---|
197 |
|
---|
198 | \begin{cfa}[caption={Example of \CFA nominal inheritance},label={l:cfa_inherit}]
|
---|
199 | struct one_d { double x; };
|
---|
200 | struct two_d {
|
---|
201 | @inline@ one_d;
|
---|
202 | double y;
|
---|
203 | };
|
---|
204 | struct three_d {
|
---|
205 | @inline@ two_d;
|
---|
206 | double z;
|
---|
207 | };
|
---|
208 | double get_x( one_d & d ){ return d.x; }
|
---|
209 |
|
---|
210 | struct dog {};
|
---|
211 | struct dog_food {
|
---|
212 | int count;
|
---|
213 | };
|
---|
214 | struct pet {
|
---|
215 | @inline@ dog;
|
---|
216 | @inline@ dog_food;
|
---|
217 | };
|
---|
218 | void pet_dog( dog & d ) { sout | "woof"; }
|
---|
219 | void print_food( dog_food & f ) { sout | f.count; }
|
---|
220 |
|
---|
221 | int main() {
|
---|
222 | one_d x;
|
---|
223 | two_d y;
|
---|
224 | three_d z;
|
---|
225 | x.x = 1;
|
---|
226 | y.x = 2;
|
---|
227 | z.x = 3;
|
---|
228 | get_x( x ); $\C{// returns 1;}$
|
---|
229 | get_x( y ); $\C{// returns 2;}$
|
---|
230 | get_x( z ); $\C{// returns 3;}$
|
---|
231 | pet p;
|
---|
232 | p.count = 5;
|
---|
233 | pet_dog( p ); $\C{// prints woof}$
|
---|
234 | print_food( p ); $\C{// prints 5}$
|
---|
235 | }
|
---|
236 | \end{cfa}
|
---|
237 |
|
---|
238 | % Local Variables: %
|
---|
239 | % tab-width: 4 %
|
---|
240 | % End: %
|
---|