source: doc/theses/colby_parsons_MMAth/text/CFA_intro.tex @ 678c540

ADTast-experimental
Last change on this file since 678c540 was 678c540, checked in by Peter A. Buhr <pabuhr@…>, 13 months ago

small commits before changing latex macros

  • Property mode set to 100644
File size: 8.9 KB
Line 
1% ======================================================================
2% ======================================================================
3\chapter{Introduction to \CFA}\label{s:cfa}
4% ======================================================================
5% ======================================================================
6
7\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}. Another related item to note is that the \CFA equivalent of \CC's \code{nullptr} is \code{0p}.
12
13\begin{cfacode}[caption={Example of \CFA references},label={l:cfa_ref}]
14int i = 2;
15int & ref_i = i;            // declare ref to i
16int * ptr_i = &i;           // ptr to i
17
18// address of ref_i is the same as address of i
19assert( &ref_i == ptr_i );
20
21int && ref_ref_i = ref_i;   // can have a ref to a ref
22ref_i = 3;                  // set i to 3
23int new_i = 4;
24
25// syntax to rebind ref_i (must cancel implicit deref)
26&ref_i = &new_i; // (&*)ref_i = &new_i; (sets underlying ptr)
27\end{cfacode}
28
29
30\section{Overloading}
31In \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.
32
33
34\begin{cfacode}[caption={Example of \CFA function overloading},label={l:cfa_overload}]
35int foo() { printf("A\n");  return 0;}
36int foo( int bar ) { printf("B\n"); return 1; }
37int foo( double bar ) { printf("C\n"); return 2; }
38double foo( double bar ) { printf("D\n"); return 3;}
39void foo( double bar ) { printf("%.0f\n", bar); }
40
41int main() {
42    foo();                  // prints A
43    foo( 0 );               // prints B
44    int a = foo( 0.0 );     // prints C
45    double a = foo( 0.0 );  // prints D
46    foo( a );               // prints 3
47}
48\end{cfacode}
49
50
51\section{With Statement}
52The 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}.
53
54
55\begin{cfacode}[tabsize=3,caption={Usage of \CFA with statement},label={l:cfa_with}]
56struct obj {
57    int a, b, c;
58};
59struct pair {
60    double x, y;
61};
62
63// Stand-alone with stmt:
64pair p;
65with( p ) {
66    x = 6.28;
67    y = 1.73;
68}
69
70// Can be used on routines:
71void foo( obj o, pair p ) with( o, p ) {
72    a = 1;
73    b = 2;
74    c = 3;
75    x = 3.14;
76    y = 2.71;
77}
78
79// routine foo is equivalent to routine bar:
80void bar( obj o, pair p ) {
81    o.a = 1;
82    o.b = 2;
83    o.c = 3;
84    p.x = 3.14;
85    p.y = 2.71;
86}
87\end{cfacode}
88
89
90\section{Operators}
91Operators can be overloaded in \CFA with operator routines. Operators in \CFA are named using the operator symbol and '?' to respresent operands.
92An example is shown in Listing~\ref{l:cfa_operate}.
93
94
95\begin{cfacode}[tabsize=3,caption={Example of \CFA operators},label={l:cfa_operate}]
96struct coord {
97    double x;
98    double y;
99    double z;
100};
101coord ++?( coord & c ) with(c) {
102    x++;
103    y++;
104    z++;
105    return c;
106}
107coord ?<=?( coord op1, coord op2 ) with( op1 ) {
108    return (x*x + y*y + z*z) <=
109        (op2.x*op2.x + op2.y*op2.y + op2.z*op2.z);
110}
111\end{cfacode}
112
113
114\section{Constructors and Destructors}
115Constructors 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}.
116
117
118\begin{cfacode}[tabsize=3,caption={Example of \CFA constructors and destructors},label={l:cfa_ctor}]
119struct discrete_point {
120    int x;
121    int y;
122};
123void ?{}( discrete_point & this ) with(this) { // ctor
124    x = 0;
125    y = 0;
126}
127void ?{}( discrete_point & this, int x, int y ) { // ctor
128    this.x = x;
129    this.y = y;
130}
131void ^?{}( discrete_point & this ) with(this) { // dtor
132    x = 0;
133    y = 0;
134}
135
136int main() {
137    discrete_point d; // implicit call to ?{}
138    discrete_point p{}; // same call as line above
139    discrete_point dp{ 2, -4 }; // specialized ctor
140} // ^d{}, ^p{}, ^dp{} all called as they go out of scope
141\end{cfacode}
142
143
144\section{Polymorphism}\label{s:poly}
145C 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.
146
147\subsection{Parametric Polymorphism}
148\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}.
149
150\begin{cfacode}[tabsize=3,caption={Example of \CFA polymorphism},label={l:cfa_poly}]
151// sized() is a trait that means the type has a size
152forall( V & | sized(V) )        // type params for trait
153trait vector_space {
154    V add( V, V );              // vector addition
155    V scalar_mult( int, V );    // scalar multiplication
156
157    // dtor and copy ctor needed in constraints to pass by copy
158    void ?{}( V &, V & );       // copy ctor for return
159    void ^?{}( V & );           // dtor
160};
161
162forall( V & | vector_space( V )) {
163    V get_inverse( V v1 ) {
164        return scalar_mult( -1, v1 );  // can use ?*? routine defined in trait
165    }
166    V add_and_invert( V v1, V v2 ) {
167        return get_inverse( add( v1, v2 ) );  // can use ?*? routine defined in trait
168    }
169}
170struct Vec1 { int x; };
171void ?{}( Vec1 & this, Vec1 & other ) { this.x = other.x; }
172void ?{}( Vec1 & this, int x ) { this.x = x; }
173void ^?{}( Vec1 & this ) {}
174Vec1 add( Vec1 v1, Vec1 v2 ) { v1.x += v2.x; return v1; }
175Vec1 scalar_mult( int c, Vec1 v1 ) { v1.x = v1.x * c; return v1; }
176
177struct Vec2 { int x; int y; };
178void ?{}( Vec2 & this, Vec2 & other ) { this.x = other.x; this.y = other.y; }
179void ?{}( Vec2 & this, int x ) { this.x = x; this.y = x; }
180void ^?{}( Vec2 & this ) {}
181Vec2 add( Vec2 v1, Vec2 v2 ) { v1.x += v2.x; v1.y += v2.y; return v1; }
182Vec2 scalar_mult( int c, Vec2 v1 ) { v1.x = v1.x * c; v1.y = v1.y * c; return v1; }
183
184int main() {
185    Vec1 v1{ 1 }; // create Vec1 and call ctor
186    Vec2 v2{ 2 }; // create Vec2 and call ctor
187
188    // can use forall defined routines since types satisfy trait
189    add_and_invert( get_inverse( v1 ), v1 );
190    add_and_invert( get_inverse( v2 ), v2 );
191}
192
193\end{cfacode}
194
195\subsection{Inheritance}
196Inheritance 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}.
197
198\begin{cfacode}[tabsize=3,caption={Example of \CFA inheritance},label={l:cfa_inherit}]
199struct one_d { double x; };
200struct two_d { 
201    inline one_d;
202    double y;
203};
204struct three_d { 
205    inline two_d;
206    double z;
207};
208double get_x( one_d & d ){ return d.x; }
209
210struct dog {};
211struct dog_food {
212    int count;
213};
214struct pet {
215    inline dog;
216    inline dog_food;
217};
218void pet_dog( dog & d ){printf("woof\n");}
219void print_food( dog_food & f ){printf("%d\n", f.count);}
220
221int 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 ); // returns 1;
229    get_x( y ); // returns 2;
230    get_x( z ); // returns 3;
231    pet p;
232    p.count = 5;
233    pet_dog( p );    // prints woof
234    print_food( p ); // prints 5
235}
236\end{cfacode}
237
238
Note: See TracBrowser for help on using the repository browser.