Changeset b202dc2 for doc/user

Mar 28, 2021, 11:08:44 PM (3 years ago)
Peter A. Buhr <pabuhr@…>
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
31fc80f, 659fb73

first draft of enumeration section

1 edited


  • doc/user/user.tex

    r9e234f0b rb202dc2  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Sun Mar  7 21:50:24 2021
    14 %% Update Count     : 4574
     13%% Last Modified On : Sat Mar 27 09:55:55 2021
     14%% Update Count     : 4796
     2168An \newterm{enumeration} is a compile-time mechanism to give names to constants.
     2169There is no runtime manifestation of an enumeration.
     2170Their purpose is code-readability and maintenance -- changing an enum's value automatically updates all name usages during compilation.
     2172An enumeration defines a type containing a set of names, each called an \newterm{enumeration constant} (shortened to \newterm{enum}) with a fixed (©const©) value.
     2174enum Days { Mon, Tue, Wed, Thu, Fri, Sat, Sun }; // enumeration type definition, set of 7 names
     2175Days days = Mon; // enumeration type declaration and initialization
     2177The set of enums are injected into the scope of the definition and use the variable namespace.
     2178Hence, enums may be overloaded with enum/variable/function names.
     2180enum Foo { Bar };
     2181enum Goo { Bar };       $\C[1.75in]{// overload Foo.Bar}$
     2182int Foo;                        $\C{// type/variable separate namespace}$
     2183double Bar;                     $\C{// overload Foo.Bar, Goo.Bar}\CRT$
     2185An anonymous enumeration is used to inject enums with specific values into a scope:
     2187enum { Prime = 103, BufferSize = 1024 };
     2189An enumeration is better than using the C \Index{preprocessor}
     2191#define Mon 0
     2193#define Sun 6
     2195or C constant declarations
     2197const int Mon = 0, ..., Sun = 6;
     2199because the enumeration is succinct, has automatic numbering, can appear in ©case© labels, does not use storage, and is part of the language type-system.
     2200Finally, the type of an enum is implicitly or explicitly specified and the constant value can be implicitly or explicitly specified.
     2201Note, enum values may be repeated in an enumeration.
     2204\subsection{Enum type}
     2206While an enumeration defines a new set-type of names, its underlying enums can be any ©const© type, and an enum's value comes from this type.
     2207\CFA provides an automatic conversion from an enum to its base type, \eg comparing/printing an enum compares/prints its value rather than the enum name.
     2208The default enum type is ©int©.
     2209Hence, ©Days© is the set type ©Mon©, ©Tue©, ...\,, ©Sun©, while the type of each enum is ©int© and each enum represents a fixed integral value.
     2210If no values are specified for an integral enum type, the enums are automatically numbered by one from left to right starting at zero.
     2211Hence, the value of enum ©Mon© is 0, ©Tue© is 1, ...\,, ©Sun© is 6.
     2212If a value is specified, numbering continues by one from that value.
     2213It an enum value is an expression, the compiler performs constant-folding to obtain a constant value.
     2215Other integral types with associated values can be explicitly specified.
     2217enum( @char@ ) Letter { A @= 'A'@,  B,  C,  I @= 'I'@,  J,  K };
     2218enum( @long long int@ ) BigNum { X = 123_456_789_012_345,  Y = 345_012_789_456_123 };
     2220For enumeration ©Letter©, enum ©A©'s value is explicitly set to ©'A'©, with ©B© and ©C© implicitly numbered with increasing values from ©'A'©, and similarly for enums ©I©, ©J©, and ©K©.
     2221Note, an enum is an immutable constant, \ie ©A = B© is disallowed;
     2222by transitivity, an enum's type is implicitly ©const©.
     2223Hence, a constant/enum cannot appear in a mutuable context nor is a constant/enum addressable (rvalue).
     2225Non-integral enum types have the restriction that all enums \emph{must} be explicitly specified, \ie incrementing by one for the next enum is not done even if supported by the enum type, \eg ©double©.
     2227// non-integral numeric
     2228enum( double ) Math { PI_2 = 1.570796, PI = 3.141597,  E = 2.718282 }
     2229// pointer
     2230enum( char * ) Name { Fred = "Fred",  Mary = "Mary",  Jane = "Jane" };
     2231int i, j, k;
     2232enum( int * ) ptr { I = &i,  J = &j,  K = &k };
     2233enum( int & ) ref { I = i,  J = j,  K = k };
     2234// tuple
     2235enum( [int, int] ) { T = [ 1, 2 ] };
     2236// function
     2237void f() {...}   void g() {...}
     2238enum( void (*)() ) funs { F = f,  F = g };
     2239// aggregate
     2240struct S { int i, j; };
     2241enum( S ) s { A = { 3,  4 }, B = { 7,  8 } };
     2242// enumeration
     2243enum( Letter ) Greek { Alph = A, Beta = B, /* more enums */  }; // alphabet intersection
     2245Enumeration ©Greek© may have more or less enums than ©Letter©, but the enum values \emph{must} be from ©Letter©.
     2246Therefore, ©Greek© enums are a subset of type ©Letter© and are type compatible with enumeration ©Letter©, but ©Letter© enums are not type compatible with enumeration ©Greek©.
     2248The following examples illustrate the difference between the enumeration type and the type of its enums.
     2250Math m = PI;    $\C[1.5in]{// allowed}$
     2251double d = PI;  $\C{// allowed, conversion to base type}$
     2252m = E;                  $\C{// allowed}$
     2253m = Alph;               $\C{// {\color{red}disallowed}}$
     2254m = 3.141597;   $\C{// {\color{red}disallowed}}$
     2255d = E;                  $\C{// allowed, conversion to base type}$
     2256d = m;                  $\C{// {\color{red}disallowed}}$
     2257d = Alph;               $\C{// {\color{red}disallowed}}$
     2258Letter l = A;   $\C{// allowed}$
     2259Greek g = Alph; $\C{// allowed}$
     2260l = Alph;               $\C{// allowed, conversion to base type}$
     2261g = A;                  $\C{// {\color{red}disallowed}}\CRT$
     2264A constructor \emph{cannot} be used to initialize enums because a constructor executes at runtime.
     2265A fallback is to substitute C-style initialization overriding the constructor with ©@=©.
     2267enum( struct vec3 ) Axis { Up $@$= { 1, 0, 0 }, Left $@$= ..., Front $@$= ... }
     2269Finally, enumeration variables are assignable and comparable only if the appropriate operators are defined for its enum type.
     2274\Index{Plan-9}\index{inheritance!enumeration} inheritance may be used with enumerations.
     2276enum( const char * ) Name2 { @inline Name@, Jack = "Jack", Jill = "Jill" };
     2277enum @/* inferred */@  Name3 { @inline Name@, @inline Name2@, Sue = "Sue", Tom = "Tom" };
     2279Enumeration ©Name2© inherits all the enums and their values from enumeration ©Name© by containment, and a ©Name© enumeration is a subtype of enumeration ©Name2©.
     2280Note, enums must be unique in inheritance but enum values may be repeated.
     2281The enum type for the inheriting type must be the same as the inherited type;
     2282hence the enum type may be omitted for the inheriting enumeration and it is inferred from the inherited enumeration, as for ©Name3©.
     2283When inheriting from integral types, automatic numbering may be used, so the inheritance placement left to right is important.
     2285Specifically, the inheritance relationship for ©Name©s is:
     2287Name $\(\subseteq\)$ Name2 $\(\subseteq\)$ Name3 $\(\subseteq\)$ const char * // enum type of Name
     2289Hence, given
     2291void f( Name );
     2292void g( Name2 );
     2293void h( Name3 );
     2294void j( const char * );
     2296the following calls are valid
     2298f( Fred );
     2299g( Fred );   g( Jill );
     2300h( Fred );   h( Jill );   h( Sue );
     2301j( Fred );    j( Jill );    j( Sue );    j( 'W' );
     2303Note, the validity of calls is the same for call by reference as for call by value, and ©const© restrictions are the same as for other types.
     2305Enums cannot be created at runtime, so inheritence problems, such as contra-variance do not apply.
     2306Only instances of the enum base-type may be created at runtime.
     2309The invariance of references, as I show at the bottom, is easy to overlook.  Not shown, but on the same topic, is that returns work in the opposite direction as parameters.  Hopefully our existing type rules already know both those facts, so that we'd only have to provide the rules that I suggest using the by-value parameters.
     2311The Fred, Jack, and Mary declarations are picked verbatim from our earlier whiteboard, just repeated here for reference.
     2314// Fred is a subset of char *
     2315enum char * Fred { A = "A", B = "B", C = "C" };
     2316// Jack is a subset of Fred
     2317enum enum Fred Jack { W = A, Y = C};
     2318// Mary is a superset of Fred
     2319enum Mary { inline Fred, D = "hello" };
     2321// Demonstrating invariance of references
     2323[void] frcs( & * char x ) { char * x0 = x; x = "bye"; }
     2324[void] frf ( & Fred   x ) { Fred   x0 = x; x = B;     }
     2325[void] frj ( & Jack   x ) { Jack   x0 = x; x = W;     }
     2326[void] frm ( & Mary   x ) { Mary   x0 = x; x = D;     }
     2328char * vcs;
     2329Fred   vf;
     2330Jack   vj;
     2331Mary   vm;
     2333// all variant calls: bad  (here are noteworthy examples)
     2334             frcs( vf  );  // can't assign "bye" to vf
     2335             frm ( vf  );  // can't assign D     to vf
     2336             frf ( vj  );  // can't assign B     to vj
     2337vf  = B    ; frj ( vf  );  // can't assign B     to frj.x0
     2338vcs = "bye"; frf ( vcs );  // can't assign "bye" to frf.x0
     2341This example is really great. However, I think it's work explicitly doing one with ©const &©.
    21662345\section{Routine Definition}
    2168 \CFA also supports a new syntax for routine definition, as well as \Celeven and K\&R routine syntax.
     2347\CFA supports a new syntax for routine definition, as well as \Celeven and K\&R routine syntax.
    21692348The point of the new syntax is to allow returning multiple values from a routine~\cite{Galletly96,CLU}, \eg:
    21752354where routine ©f© has three output (return values) and three input parameters.
    2176 Existing C syntax cannot be extended with multiple return types because it is impossible to embed a single routine name within multiple return type specifications.
     2355Existing C syntax cannot be extended with multiple return types because it is impossible to embed a single routine name within multiple return type-specifications.
    21782357In detail, the brackets, ©[]©, enclose the result type, where each return value is named and that name is a local variable of the particular return type.\footnote{
    22002379int (*f(x))[ 5 ] int x; {}
    2202 The string ``©int (*f(x))[ 5 ]©'' declares a K\&R style routine of type returning a pointer to an array of 5 integers, while the string ``©[ 5 ] int x©'' declares a \CFA style parameter x of type array of 5 integers.
     2381The string ``©int (*f(x))[ 5 ]©'' declares a K\&R style routine of type returning a pointer to an array of 5 integers, while the string ``©[ 5 ] int x©'' declares a \CFA style parameter ©x© of type array of 5 integers.
    22032382Since the strings overlap starting with the open bracket, ©[©, there is an ambiguous interpretation for the string.
    22042383As well, \CFA-style declarations cannot be used to declare parameters for C-style routine-definitions because of the following ambiguity:
    41204299\CFA provides a fine-grained solution where a \Index{recursive lock} is acquired and released indirectly via a manipulator ©acquire© or instantiating an \Index{RAII} type specific for the kind of stream: ©osacquire©\index{ostream@©ostream©!osacquire@©osacquire©} for output streams and ©isacquire©\index{isacquire@©isacquire©}\index{istream@©istream©!isacquire@©isacquire©} for input streams.
    4122 The common usage is manipulator ©acquire©\index{ostream@©ostream©!acquire@©acquire©} to lock a stream during a single cascaded I/O expression, where it should appear as the first item in a cascade list, \eg:
     4301The common usage is manipulator ©acquire©\index{ostream@©ostream©!acquire@©acquire©} to lock a stream during a single cascaded I/O expression, with the manipulator appearing as the first item in a cascade list, \eg:
    41244303$\emph{thread\(_1\)}$ : sout | @acquire@ | "abc " | "def ";   // manipulator
    41424321In summary, the stream lock is acquired by the ©acquire© manipulator and implicitly released at the end of the cascaded I/O expression ensuring all operations in the expression occur atomically.
    4144 To lock a stream across multiple I/O operations, declare an instance of the appropriate ©osacquire© or ©isacquire© type to implicitly acquire and release the stream lock for the object's duration, \eg:
     4323To lock a stream across multiple I/O operations, an object of type ©osacquire© or ©isacquire© is declared to implicitly acquire/release the stream lock providing mutual exclusion for the object's duration, \eg:
    41464325{       // acquire sout for block duration
Note: See TracChangeset for help on using the changeset viewer.