# Changeset edc6ea2 for doc/theses/andrew_beach_MMath/existing.tex

Ignore:
Timestamp:
Apr 28, 2021, 2:02:23 PM (7 months ago)
Branches:
arm-eh, jacob/cs343-translation, master, new-ast-unique-expr
Children:
c1136c56
Parents:
df24d37
Message:

Andrew MMath: LaTeX clean-up. Went through existing to make some of the examples more managable.

File:
1 edited

### Legend:

Unmodified
 rdf24d37 mangling is: \begin{cfa} // name mangling // name mangling on by default int i; // _X1ii_1 @extern "C"@ {  // no name mangling extern "C" {  // disables name mangling int j; // j @extern "Cforall"@ {  // name mangling extern "Cforall" {  // enables name mangling int k; // _X1ki_1 } // no name mangling } // name mangling // revert to no name mangling } // revert to name mangling \end{cfa} Both forms of @extern@ affect all the declarations within their nested lexical \begin{cfa} int i, j; int @&@ ri = i, @&&@ rri = ri; int & ri = i, && rri = ri; rri = 3;  // auto-dereference assign to i @&@ri = @&@j; // rebindable &ri = &j; // rebindable ri = 5;   // assign to j \end{cfa} In general, operator names in \CFA are constructed by bracketing an operator token with @?@, which indicates the position of the arguments. For example, infixed multiplication is @?*?@ while prefix dereference is @*?@. This syntax make it easy to tell the difference between prefix operations (such as @++?@) and post-fix operations (@?++@). token with @?@, which indicates the position of the arguments. For example, infixed multiplication is @?*?@ while prefix dereference is @*?@. This syntax make it easy to tell the difference between prefix operations (such as @++?@) and post-fix operations (@?++@). The special name for a constructor is @?{}@, which comes from the initialization syntax in C. The special name for a destructor is @^{}@, where the @^@ has no special meaning. initialization syntax in C. That initialation syntax is also the operator form. \CFA will generate a constructor call each time a variable is declared, passing the initialization arguments to the constructort. \begin{cfa} struct Example { ... }; void ?{}(Example & this) { ... } { Example a; Example b = {}; } void ?{}(Example & this, char first, int num) { ... } { Example c = {'a', 2}; } \end{cfa} Both @a@ and @b@ will be initalized with the first constructor (there is no general way to skip initialation) while @c@ will be initalized with the second. % I don't like the \^{} symbol but $^\wedge$ isn't better. \begin{cfa} struct T { ... }; void ?@{}@(@T &@ this, ...) { ... }  // constructor void ?@^{}@(@T &@ this, ...) { ... } // destructor Similarly destructors use the special name @^?{}@ (the @^@ has no special meaning). They can be called explicatly as well but normally they are implicitly called on a variable when it goes out of scope. \begin{cfa} void ^?{}(Example & this) { ... } { T s = @{@ ... @}@;  // same constructor/initialization braces } // destructor call automatically generated \end{cfa} The first parameter is a reference parameter to the type for the constructor/destructor. Destructors may have multiple parameters.  The compiler implicitly matches an overloaded constructor @void ^?{}(T &, ...);@ to an object declaration with associated initialization, and generates a construction call after the object is allocated. When an object goes out of scope, the matching overloaded destructor @void ^?{}(T &);@ is called.  Without explicit definition, \CFA creates a default and copy constructor, destructor and assignment (like \Cpp). It is possible to define constructors/destructors for basic and existing types (unlike \Cpp). Example d; } // <- implicit destructor call \end{cfa} No operator name is restricted in what function signatures they may be bound to although most of the forms cannot be called in operator form. Some near-misses" will generate warnings. Whenever a type is defined, \CFA will create a default zero-argument constructor, a copy constructor, a series of argument-per-field constructors and a destructor. All user constructors are defined after this. Because operators are never part of the type definition they may be added at any time, including on built-in types. \section{Polymorphism} works on any type @T@: \begin{cfa} @forall( T )@ @T@ identity( @T@ val ) { return val; } int forty_two = identity( 42 ); // T bound to int, forty_two == 42 \end{cfa} forall( T ) T identity( T val ) { return val; } int forty_two = identity( 42 ); char capital_a = identity( 'A' ); \end{cfa} Each use of a polymorphic declaration will resolve its polymorphic parameters (in this case, just @T@) to concrete types (@int@ in the first use and @char@ in the second). To allow a polymorphic function to be separately compiled, the type @T@ must be types used in a function, \eg: \begin{cfa} forall( T @| { void do_once(T); }@) // assertion forall( T | { void do_once(T); }) void do_twice(T value) { do_once(value); do_once(value); } void do_once(@int@ i) { ... }  // provide assertion @int@ i; do_twice(i); // implicitly pass assertion do_once to do_twice \end{cfa} Any object with a type fulfilling the assertion may be passed as an argument to a @do_twice@ call. \end{cfa} A polymorphic function can be used in the same way as a normal function.  The all the variables replaced with the concrete types from the arguments) is defined at a call site. \begin{cfa} void do_once(int i) { ... } int i; do_twice(i); \end{cfa} Any object with a type fulfilling the assertion may be passed as an argument to a @do_twice@ call. Note, a function named @do_once@ is not required in the scope of @do_twice@ to call. \begin{cfa} void do_once(double y) { ... } // global void do_once(double y) { ... } int quadruple(int x) { void do_once(int y) { y = y * 2; } // local do_twice(x); // using local "do_once" void do_once(int y) { y = y * 2; } do_twice(x); return x; } function. The matched assertion function is then passed as a function pointer to @do_twice@ and called within it. The global definition of @do_once@ is ignored. To avoid typing long lists of assertions, constraints can be collect into and the @forall@ list in the previous example is replaced with the trait. \begin{cfa} forall(dtype T | @done_once(T)@) forall(dtype T | done_once(T)) \end{cfa} In general, a trait can contain an arbitrary number of assertions, both declarations instead of parameters, returns, and local variable declarations. \begin{cfa} forall(dtype @T@) forall(dtype T) struct node { node(@T@) * next;  // generic linked node @T@ * data; } node(@int@) inode; \end{cfa} The generic type @node(T)@ is an example of a polymorphic-type usage.  Like \Cpp template usage, a polymorphic-type usage must specify a type parameter. node(T) * next;  // generic linked node T * data; } node(int) inode; \end{cfa} The generic type @node(T)@ is an example of a polymorphic type usage.  Like \Cpp template usage, a polymorphic type usage must specify a type parameter. There are many other polymorphism features in \CFA but these are the ones used Each coroutine has a @main@ function, which takes a reference to a coroutine object and returns @void@. \begin{cfa}[numbers=left] void main(@CountUp & this@) { // argument matches trait is_coroutine unsigned int up = 0;  // retained between calls while (true) { next = up; // make "up" available outside function @suspend;@$\label{suspend}$ up += 1; \begin{cfa} void main(CountUp & this) { for (unsigned int next = 0 ; true ; ++next) { next = up; suspend;$\label{suspend}$ } } @mutex@. \begin{cfa} void example(MonitorA & @mutex@ argA, MonitorB & @mutex@ argB); void example(MonitorA & mutex argA, MonitorB & mutex argB); \end{cfa} When the function is called, it implicitly acquires the monitor lock for all of