Changeset 6c2ba38


Ignore:
Timestamp:
Nov 28, 2017, 3:52:06 PM (7 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
383e159, 8d5b9cf
Parents:
cf966b5 (diff), 8a0a64d9 (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.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Files:
9 added
32 edited

Legend:

Unmodified
Added
Removed
  • .gitignore

    rcf966b5 r6c2ba38  
    2525include
    2626share
     27*.class
    2728
    2829# src executables, for lib and bin
  • doc/refrat/refrat.tex

    rcf966b5 r6c2ba38  
    1111%% Created On       : Wed Apr  6 14:52:25 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Sun Aug  6 10:25:31 2017
    14 %% Update Count     : 105
     13%% Last Modified On : Tue Aug 15 18:46:31 2017
     14%% Update Count     : 106
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    492492
    493493\begin{rationale}
    494 The use of ``©?©'' in identifiers means that some C programs are not \CFA programs.  For instance, the sequence of characters ``©(i < 0)?--i:i©'' is legal in a C program, but a
    495 \CFA compiler detects a syntax error because it treats ``©?--©'' as an identifier, not as the two tokens ``©?©'' and ``©--©''.
     494The use of ``©?©'' in identifiers means that some C programs are not \CFA programs.
     495For instance, the sequence of characters ``©(i < 0)?--i:i©'' is legal in a C program, but a \CFA compiler detects a syntax error because it treats ``©?--©'' as an identifier, not as the two tokens ``©?©'' and ``©--©''.
    496496\end{rationale}
    497497
  • doc/user/user.tex

    rcf966b5 r6c2ba38  
    1111%% Created On       : Wed Apr  6 14:53:29 2016
    1212%% Last Modified By : Peter A. Buhr
    13 %% Last Modified On : Sun Aug  6 10:24:21 2017
    14 %% Update Count     : 3036
     13%% Last Modified On : Mon Nov 27 18:09:59 2017
     14%% Update Count     : 3143
    1515%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1616
     
    5959\CFAStyle                                                                                               % use default CFA format-style
    6060\lstnewenvironment{C++}[1][]                            % use C++ style
    61 {\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®}#1}}
     61{\lstset{language=C++,moredelim=**[is][\protect\color{red}]{®}{®},#1}}
    6262{}
    6363
     
    777777  case 7:
    778778        ...
    779         ®break®                                         §\C{// redundant explicit end of switch
     779        ®break®                                         §\C{// explicit end of switch (redundant)
    780780  default:
    781781        j = 3;
     
    806806                ®int k = 0;®                    §\C{// allowed at different nesting levels}§
    807807                ...
     808          ®case 2:®                                     §\C{// disallow case in nested statements}§
    808809        }
    809810  ...
     
    962963\end{cfa}
    963964
     965The components in the "with" clause
     966
     967  with a, b, c { ... }
     968
     969serve 2 purposes: each component provides a type and object. The type must be a
     970structure type. Enumerations are already opened, and I think a union is opened
     971to some extent, too. (Or is that just unnamed unions?) The object is the target
     972that the naked structure-fields apply to. The components are open in "parallel"
     973at the scope of the "with" clause/statement, so opening "a" does not affect
     974opening "b", etc. This semantic is different from Pascal, which nests the
     975openings.
     976
     977Having said the above, it seems reasonable to allow a "with" component to be an
     978expression. The type is the static expression-type and the object is the result
     979of the expression. Again, the type must be an aggregate. Expressions require
     980parenthesis around the components.
     981
     982  with( a, b, c ) { ... }
     983
     984Does this now make sense?
     985
     986Having written more CFA code, it is becoming clear to me that I *really* want
     987the "with" to be implemented because I hate having to type all those object
     988names for fields. It's a great way to drive people away from the language.
     989
    964990
    965991\section{Exception Handling}
     
    9771003try {
    9781004        f(...);
    979 } catch( E e : §boolean-predicate§ ) {                  §\C[8cm]{// termination handler}§
     1005} catch( E e ; §boolean-predicate§ ) {                  §\C[8cm]{// termination handler}§
    9801006        // recover and continue
    981 } catchResume( E e : §boolean-predicate§ ) {    §\C{// resumption handler}\CRT§
     1007} catchResume( E e ; §boolean-predicate§ ) {    §\C{// resumption handler}\CRT§
    9821008        // repair and return
    9831009} finally {
     
    18721898\end{cfa}
    18731899This syntax allows a prototype declaration to be created by cutting and pasting source text from the routine definition header (or vice versa).
    1874 It is possible to declare multiple routine-prototypes in a single declaration, but the entire type specification is distributed across \emph{all} routine names in the declaration list (see~\VRef{s:Declarations}), \eg:
    1875 \begin{quote2}
    1876 \begin{tabular}{@{}l@{\hspace{3em}}l@{}}
    1877 \multicolumn{1}{c@{\hspace{3em}}}{\textbf{\CFA}}        & \multicolumn{1}{c}{\textbf{C}}        \\
    1878 \begin{cfa}
    1879 [ int ] f( int ), g;
    1880 \end{cfa}
    1881 &
    1882 \begin{cfa}
    1883 int f( int ), g( int );
    1884 \end{cfa}
    1885 \end{tabular}
    1886 \end{quote2}
     1900Like C, it is possible to declare multiple routine-prototypes in a single declaration, where the return type is distributed across \emph{all} routine names in the declaration list (see~\VRef{s:Declarations}), \eg:
     1901\begin{cfa}
     1902C :             const double bar1(), bar2( int ), bar3( double );
     1903§\CFA§: [const double] foo(), foo( int ), foo( double ) { return 3.0; }
     1904\end{cfa}
     1905\CFA allows the last routine in the list to define its body.
     1906
    18871907Declaration qualifiers can only appear at the start of a \CFA routine declaration,\footref{StorageClassSpecifier} \eg:
    18881908\begin{cfa}
     
    22352255\label{s:MRV_Functions}
    22362256
    2237 In standard C, functions can return at most one value.
     2257In C and most programming languages, functions return at most one value;
     2258however, many operations have multiple outcomes, some exceptional (see~\VRef{s:ExceptionHandling}).
    22382259To emulate functions with multiple return values, \emph{\Index{aggregation}} and/or \emph{\Index{aliasing}} is used.
    2239 In the former situation, the function designer creates a record type that combines all of the return values into a single type.
    2240 For example, consider a function returning the most frequently occurring letter in a string, and its frequency.
    2241 This example is complex enough to illustrate that an array is insufficient, since arrays are homogeneous, and demonstrates a potential pitfall that exists with aliasing.
    2242 \begin{cfa}
    2243 struct mf_ret {
    2244         int freq;
    2245         char ch;
    2246 };
    2247 
    2248 struct mf_ret most_frequent(const char * str) {
    2249         char freqs [26] = { 0 };
    2250         struct mf_ret ret = { 0, 'a' };
    2251         for (int i = 0; str[i] != '\0'; ++i) {
    2252                 if (isalpha(str[i])) {        // only count letters
    2253                         int ch = tolower(str[i]);   // convert to lower case
    2254                         int idx = ch-'a';
    2255                         if (++freqs[idx] > ret.freq) {  // update on new max
    2256                           ret.freq = freqs[idx];
    2257                           ret.ch = ch;
    2258                         }
    2259                 }
    2260         }
    2261         return ret;
    2262 }
    2263 
    2264 const char * str = "hello world";
    2265 struct mf_ret ret = most_frequent(str);
    2266 printf("%s -- %d %c\n", str, ret.freq, ret.ch);
    2267 \end{cfa}
    2268 Of note, the designer must come up with a name for the return type and for each of its fields.
    2269 Unnecessary naming is a common programming language issue, introducing verbosity and a complication of the user's mental model.
    2270 That is, adding another named type creates another association in the programmer's mind that needs to be kept track of when reading and writing code.
    2271 As such, this technique is effective when used sparingly, but can quickly get out of hand if many functions need to return different combinations of types.
    2272 
    2273 In the latter approach, the designer simulates multiple return values by passing the additional return values as pointer parameters.
    2274 The pointer parameters are assigned inside of the routine body to emulate a return.
    2275 Using the same example,
    2276 \begin{cfa}
    2277 int most_frequent(const char * str, char * ret_ch) {
    2278         char freqs [26] = { 0 };
    2279         int ret_freq = 0;
    2280         for (int i = 0; str[i] != '\0'; ++i) {
    2281                 if (isalpha(str[i])) {        // only count letters
    2282                         int ch = tolower(str[i]);   // convert to lower case
    2283                         int idx = ch-'a';
    2284                         if (++freqs[idx] > ret_freq) {  // update on new max
    2285                           ret_freq = freqs[idx];
    2286                           *ret_ch = ch;   // assign to out parameter
    2287                         }
    2288                 }
    2289         }
    2290         return ret_freq;  // only one value returned directly
    2291 }
    2292 
    2293 const char * str = "hello world";
    2294 char ch;                            // pre-allocate return value
    2295 int freq = most_frequent(str, &ch); // pass return value as out parameter
    2296 printf("%s -- %d %c\n", str, freq, ch);
    2297 \end{cfa}
    2298 Notably, using this approach, the caller is directly responsible for allocating storage for the additional temporary return values, which complicates the call site with a sequence of variable declarations leading up to the call.
    2299 Also, while a disciplined use of ©const© can give clues about whether a pointer parameter is going to be used as an out parameter, it is not immediately obvious from only the routine signature whether the callee expects such a parameter to be initialized before the call.
    2300 Furthermore, while many C routines that accept pointers are designed so that it is safe to pass ©NULL© as a parameter, there are many C routines that are not null-safe.
    2301 On a related note, C does not provide a standard mechanism to state that a parameter is going to be used as an additional return value, which makes the job of ensuring that a value is returned more difficult for the compiler.
    2302 Interestingly, there is a subtle bug in the previous example, in that ©ret_ch© is never assigned for a string that does not contain any letters, which can lead to undefined behaviour.
    2303 In this particular case, it turns out that the frequency return value also doubles as an error code, where a frequency of 0 means the character return value should be ignored.
     2260
     2261In the former approach, a record type is created combining all of the return values.
     2262For example, consider C's \Indexc{div} function, which returns the quotient and remainder for a division of an integer value.
     2263\begin{cfa}
     2264typedef struct { int quot, rem; } div_t;        §\C[7cm]{// from include stdlib.h}§
     2265div_t div( int num, int den );
     2266div_t qr = div( 13, 5 );                                        §\C{// return quotient/remainder aggregate}§
     2267printf( "%d %d\n", qr.quot, qr.rem );           §\C{// print quotient/remainder}§
     2268\end{cfa}
     2269This approach requires a name for the return type and fields, where \Index{naming} is a common programming-language issue.
     2270That is, naming creates an association that must be managed when reading and writing code.
     2271While effective when used sparingly, this approach does not scale when functions need to return multiple combinations of types.
     2272
     2273In the latter approach, additional return values are passed as pointer parameters.
     2274A pointer parameter is assigned inside the routine to emulate a return.
     2275For example, consider C's \Indexc{modf} function, which returns the integral and fractional part of a floating-point value.
     2276\begin{cfa}
     2277double modf( double x, double * i );            §\C{// from include math.h}§
     2278double intp, frac = modf( 13.5, &intp );        §\C{// return integral and fractional components}§
     2279printf( "%g %g\n", intp, frac );                        §\C{// print integral/fractional components}§
     2280\end{cfa}
     2281This approach requires allocating storage for the return values, which complicates the call site with a sequence of variable declarations leading to the call.
     2282Also, while a disciplined use of ©const© can give clues about whether a pointer parameter is used as an \Index{out parameter}, it is not obvious from the routine signature whether the callee expects such a parameter to be initialized before the call.
     2283Furthermore, while many C routines that accept pointers are safe for a ©NULL© argument, there are many C routines that are not null-safe.
     2284Finally, C does not provide a mechanism to state that a parameter is going to be used as an additional return value, which makes the job of ensuring that a value is returned more difficult for the compiler.
    23042285Still, not every routine with multiple return values should be required to return an error code, and error codes are easily ignored, so this is not a satisfying solution.
    23052286As with the previous approach, this technique can simulate multiple return values, but in practice it is verbose and error prone.
    23062287
    2307 In \CFA, functions can be declared to return multiple values with an extension to the function declaration syntax.
     2288\CFA allows functions to return multiple values by extending the function declaration syntax.
    23082289Multiple return values are declared as a comma-separated list of types in square brackets in the same location that the return type appears in standard C function declarations.
     2290\begin{cfa}
     2291[ char, int, double ] f( ... );
     2292\end{cfa}
    23092293The ability to return multiple values from a function requires a new syntax for the return statement.
    23102294For consistency, the return statement in \CFA accepts a comma-separated list of expressions in square brackets.
    2311 The expression resolution phase of the \CFA translator ensures that the correct form is used depending on the values being returned and the return type of the current function.
     2295\begin{cfa}
     2296return [ c, i, d ];
     2297\end{cfa}
     2298The expression resolution ensures the correct form is used depending on the values being returned and the return type of the current function.
    23122299A multiple-returning function with return type ©T© can return any expression that is implicitly convertible to ©T©.
    2313 Using the running example, the ©most_frequent© function can be written using multiple return values as such,
    2314 \begin{cfa}
    2315 [int, char] most_frequent(const char * str) {
    2316         char freqs [26] = { 0 };
    2317         int ret_freq = 0;
    2318         char ret_ch = 'a';  // arbitrary default value for consistent results
    2319         for (int i = 0; str[i] != '\0'; ++i) {
    2320                 if (isalpha(str[i])) {        // only count letters
    2321                         int ch = tolower(str[i]);   // convert to lower case
    2322                         int idx = ch-'a';
    2323                         if (++freqs[idx] > ret_freq) {  // update on new max
    2324                           ret_freq = freqs[idx];
    2325                           ret_ch = ch;
    2326                         }
    2327                 }
    2328         }
    2329         return [ret_freq, ret_ch];
    2330 }
    2331 \end{cfa}
    2332 This approach provides the benefits of compile-time checking for appropriate return statements as in aggregation, but without the required verbosity of declaring a new named type, which precludes the bug seen with out-parameters.
    2333 
    2334 The addition of multiple-return-value functions necessitates a syntax for accepting multiple values at the call-site.
     2300
     2301A common use of a function's output is input to another function.
     2302\CFA allows this case, without any new syntax;
     2303a multiple-returning function can be used in any of the contexts where an expression is allowed.
     2304When a function call is passed as an argument to another call, the best match of actual arguments to formal parameters is evaluated given all possible expression interpretations in the current scope.
     2305\begin{cfa}
     2306void g( int, int );                                                     §\C{// 1}§
     2307void g( double, double );                                       §\C{// 2}§
     2308g( div( 13, 5 ) );                                                      §\C{// select 1}§
     2309g( modf( 13.5 ) );                                                      §\C{// select 2}§
     2310\end{cfa}
     2311In this case, there are two overloaded ©g© routines.
     2312Both calls to ©g© expect two arguments that are matched by the two return values from ©div© and ©modf©. respectively, which are fed directly to the first and second parameters of ©g©.
     2313As well, both calls to ©g© have exact type matches for the two different versions of ©g©, so these exact matches are chosen.
     2314When type matches are not exact, conversions are used to find a best match.
     2315
     2316The previous examples can be rewritten passing the multiple returned-values directly to the ©printf© function call.
     2317\begin{cfa}
     2318[ int, int ] div( int x, int y );                       §\C{// from include stdlib}§
     2319printf( "%d %d\n", div( 13, 5 ) );                      §\C{// print quotient/remainder}§
     2320
     2321[ double, double ] modf( double x );            §\C{// from include math}§
     2322printf( "%g %g\n", modf( 13.5 ) );                      §\C{// print integral/fractional components}§
     2323\end{cfa}
     2324This approach provides the benefits of compile-time checking for appropriate return statements as in aggregation, but without the required verbosity of declaring a new named type.
     2325
     2326Finally, the addition of multiple-return-value functions necessitates a syntax for retaining the multiple values at the call-site versus their temporary existence during a call.
    23352327The simplest mechanism for retaining a return value in C is variable assignment.
    2336 By assigning the return value into a variable, its value can be retrieved later at any point in the program.
     2328By assigning the multiple return-values into multiple variables, the values can be retrieved later.
    23372329As such, \CFA allows assigning multiple values from a function into multiple variables, using a square-bracketed list of lvalue expressions on the left side.
    23382330\begin{cfa}
    2339 const char * str = "hello world";
    2340 int freq;
    2341 char ch;
    2342 [freq, ch] = most_frequent(str);  // assign into multiple variables
    2343 printf("%s -- %d %c\n", str, freq, ch);
    2344 \end{cfa}
    2345 It is also common to use a function's output as the input to another function.
    2346 \CFA also allows this case, without any new syntax.
    2347 When a function call is passed as an argument to another call, the expression resolver attempts to find the best match of actual arguments to formal parameters given all of the possible expression interpretations in the current scope \cite{Bilson03}.
    2348 For example,
    2349 \begin{cfa}
    2350 void process(int);       // (1)
    2351 void process(char);      // (2)
    2352 void process(int, char); // (3)
    2353 void process(char, int); // (4)
    2354 
    2355 process(most_frequent("hello world"));  // selects (3)
    2356 \end{cfa}
    2357 In this case, there is only one option for a function named ©most_frequent© that takes a string as input.
    2358 This function returns two values, one ©int© and one ©char©.
    2359 There are four options for a function named ©process©, but only two that accept two arguments, and of those the best match is (3), which is also an exact match.
    2360 This expression first calls ©most_frequent("hello world")©, which produces the values ©3© and ©'l'©, which are fed directly to the first and second parameters of (3), respectively.
    2361 
    2362 \section{Tuple Expressions}
     2331int quot, rem;
     2332[ quot, rem ] = div( 13, 5 );                           §\C{// assign multiple variables}§
     2333printf( "%d %d\n", quot, rem );                         §\C{// print quotient/remainder}\CRT§
     2334\end{cfa}
     2335Here, the multiple return-values are matched in much the same way as passing multiple return-values to multiple parameters in a call.
     2336
     2337
     2338\subsection{Expressions}
     2339
    23632340Multiple-return-value functions provide \CFA with a new syntax for expressing a combination of expressions in the return statement and a combination of types in a function signature.
    2364 These notions can be generalized to provide \CFA with \emph{tuple expressions} and \emph{tuple types}.
     2341These notions are generalized to provide \CFA with \newterm{tuple expression}s and \newterm{tuple type}s.
    23652342A tuple expression is an expression producing a fixed-size, ordered list of values of heterogeneous types.
    2366 The type of a tuple expression is the tuple of the subexpression types, or a \emph{tuple type}.
     2343The type of a tuple expression is the tuple of the subexpression types, or a tuple type.
     2344
    23672345In \CFA, a tuple expression is denoted by a comma-separated list of expressions enclosed in square brackets.
    23682346For example, the expression ©[5, 'x', 10.5]© has type ©[int, char, double]©.
     
    23712349The order of evaluation of the components in a tuple expression is unspecified, to allow a compiler the greatest flexibility for program optimization.
    23722350It is, however, guaranteed that each component of a tuple expression is evaluated for side-effects, even if the result is not used.
    2373 Multiple-return-value functions can equivalently be called \emph{tuple-returning functions}.
    2374 
    2375 \subsection{Tuple Variables}
    2376 The call-site of the ©most_frequent© routine has a notable blemish, in that it required the preallocation of return variables in a manner similar to the aliasing example, since it is impossible to declare multiple variables of different types in the same declaration in standard C.
    2377 In \CFA, it is possible to overcome this restriction by declaring a \emph{tuple variable}.
    2378 \begin{cfa}[emph=ret, emphstyle=\color{red}]
    2379 const char * str = "hello world";
    2380 [int, char] ret = most_frequent(str);  // initialize tuple variable
    2381 printf("%s -- %d %c\n", str, ret);
    2382 \end{cfa}
    2383 It is now possible to accept multiple values into a single piece of storage, in much the same way that it was previously possible to pass multiple values from one function call to another.
    2384 These variables can be used in any of the contexts where a tuple expression is allowed, such as in the ©printf© function call.
    2385 As in the ©process© example, the components of the tuple value are passed as separate parameters to ©printf©, allowing very simple printing of tuple expressions.
    2386 One way to access the individual components is with a simple assignment, as in previous examples.
    2387 \begin{cfa}
    2388 int freq;
    2389 char ch;
    2390 [freq, ch] = ret;
    2391 \end{cfa}
    2392 
    2393 \begin{sloppypar}
     2351Multiple-return-value functions can equivalently be called \newterm{tuple-returning functions}.
     2352
     2353
     2354\subsection{Variables}
     2355
     2356The previous call of ©div© still requires the preallocation of multiple return-variables in a manner similar to the aliasing example.
     2357In \CFA, it is possible to overcome this restriction by declaring a \newterm{tuple variable}.
     2358\begin{cfa}
     2359[int, int] ®qr® = div( 13, 5 );                 §\C{// initialize tuple variable}§
     2360printf( "%d %d\n", ®qr® );                              §\C{// print quotient/remainder}§
     2361\end{cfa}
     2362It is now possible to match the multiple return-values to a single variable, in much the same way as \Index{aggregation}.
     2363As well, the components of the tuple value are passed as separate parameters to ©printf©, allowing direct printing of tuple variables.
     2364One way to access the individual components of a tuple variable is with assignment.
     2365\begin{cfa}
     2366[ quot, rem ] = qr;                                             §\C{// assign multiple variables}§
     2367\end{cfa}
     2368
    23942369In addition to variables of tuple type, it is also possible to have pointers to tuples, and arrays of tuples.
    23952370Tuple types can be composed of any types, except for array types, since array assignment is disallowed, which makes tuple assignment difficult when a tuple contains an array.
    23962371\begin{cfa}
    2397 [double, int] di;
    2398 [double, int] * pdi
    2399 [double, int] adi[10];
     2372[ double, int ] di;
     2373[ double, int ] * pdi
     2374[ double, int ] adi[10];
    24002375\end{cfa}
    24012376This examples declares a variable of type ©[double, int]©, a variable of type pointer to ©[double, int]©, and an array of ten ©[double, int]©.
    2402 \end{sloppypar}
    2403 
    2404 \subsection{Tuple Indexing}
    2405 
    2406 At times, it is desirable to access a single component of a tuple-valued expression without creating unnecessary temporary variables to assign to.
    2407 Given a tuple-valued expression ©e© and a compile-time constant integer $i$ where $0 \leq i < n$, where $n$ is the number of components in ©e©, ©e.i© accesses the $i$\textsuperscript{th} component of ©e©.
    2408 For example,
     2377
     2378
     2379\subsection{Indexing}
     2380
     2381It is also possible to access a single component of a tuple-valued expression without creating temporary variables.
     2382Given a tuple-valued expression $e$np and a compile-time constant integer $i$ where $0 \leq i < n$, where $n$ is the number of components in $e$, $e.i$ accesses the $i^{\:th}$ component of $e$, \eg:
    24092383\begin{cfa}
    24102384[int, double] x;
     
    24172391p->0 = 5;                                                               §\C{// access int component of tuple pointed-to by p}§
    24182392g( x.1, x.0 );                                                  §\C{// rearrange x to pass to g}§
    2419 double z = [x, f()].0.1;                                §\C{// access second component of first component of tuple expression}§
    2420 \end{cfa}
    2421 As seen above, tuple-index expressions can occur on any tuple-typed expression, including tuple-returning functions, square-bracketed tuple expressions, and other tuple-index expressions, provided the retrieved component is also a tuple.
     2393double z = [ x, f() ].0.1;                              §\C{// access second component of first component of tuple expression}§
     2394\end{cfa}
     2395Tuple-index expressions can occur on any tuple-typed expression, including tuple-returning functions, square-bracketed tuple expressions, and other tuple-index expressions, provided the retrieved component is also a tuple.
    24222396This feature was proposed for \KWC but never implemented \cite[p.~45]{Till89}.
    24232397
     2398
    24242399\subsection{Flattening and Structuring}
     2400
    24252401As evident in previous examples, tuples in \CFA do not have a rigid structure.
    24262402In function call contexts, tuples support implicit flattening and restructuring conversions.
     
    24652441There is only a single definition of ©f©, and 3 arguments with only single interpretations.
    24662442First, the argument alternative list ©[5, 10.2], 4© is flattened to produce the argument list ©5, 10.2, 4©.
    2467 Next, the parameter matching algorithm begins, with $P = $©int© and $A = $©int©, which unifies exactly.
    2468 Moving to the next parameter and argument, $P = $©[double, int]© and $A = $©double©.
    2469 This time, the parameter is a tuple type, so the algorithm applies recursively with $P' = $©double© and $A = $©double©, which unifies exactly.
    2470 Then $P' = $©int© and $A = $©double©, which again unifies exactly.
     2443Next, the parameter matching algorithm begins, with $P =$© int© and $A =$© int©, which unifies exactly.
     2444Moving to the next parameter and argument, $P =$© [double, int]© and $A =$© double©.
     2445This time, the parameter is a tuple type, so the algorithm applies recursively with $P' =$© double© and $A =$© double©, which unifies exactly.
     2446Then $P' =$© int© and $A =$© double©, which again unifies exactly.
    24712447At this point, the end of $P'$ has been reached, so the arguments ©10.2, 4© are structured into the tuple expression ©[10.2, 4]©.
    24722448Finally, the end of the parameter list $P$ has also been reached, so the final expression is ©f(5, [10.2, 4])©.
    24732449
    2474 \section{Tuple Assignment}
     2450
     2451\subsection{Assignment}
    24752452\label{s:TupleAssignment}
    2476 An assignment where the left side of the assignment operator has a tuple type is called tuple assignment.
    2477 There are two kinds of tuple assignment depending on whether the right side of the assignment operator has a tuple type or a non-tuple type, called \emph{Multiple} and \emph{Mass} Assignment, respectively.
     2453
     2454An assignment where the left side of the assignment operator has a tuple type is called \newterm{tuple assignment}.
     2455There are two kinds of tuple assignment depending on whether the right side of the assignment operator has a non-tuple or tuple type, called \newterm[mass assignment]{mass} and \newterm[multiple assignment]{multiple} assignment, respectively.
    24782456\begin{cfa}
    24792457int x;
    24802458double y;
    24812459[int, double] z;
    2482 [y, x] = 3.14;  // mass assignment
    2483 [x, y] = z;     // multiple assignment
    2484 z = 10;         // mass assignment
    2485 z = [x, y];     // multiple assignment
     2460[y, x] = 3.14;                                                  §\C{// mass assignment}§
     2461[x, y] = z;                                                         §\C{// multiple assignment}§
     2462z = 10;                                                         §\C{// mass assignment}§
     2463z = [x, y];                                                             §\C{// multiple assignment}§
    24862464\end{cfa}
    24872465Let $L_i$ for $i$ in $[0, n)$ represent each component of the flattened left side, $R_i$ represent each component of the flattened right side of a multiple assignment, and $R$ represent the right side of a mass assignment.
     
    24902468For example, the following is invalid because the number of components on the left does not match the number of components on the right.
    24912469\begin{cfa}
    2492 [int, int] x, y, z;
    2493 [x, y] = z;   // multiple assignment, invalid 4 != 2
     2470[ int, int ] x, y, z;
     2471[ x, y ] = z;                                              §\C{// multiple assignment, invalid 4 != 2}§
    24942472\end{cfa}
    24952473Multiple assignment assigns $R_i$ to $L_i$ for each $i$.
     
    25072485\begin{cfa}
    25082486int x = 10, y = 20;
    2509 [x, y] = [y, x];
     2487[ x, y ] = [ y, x ];
    25102488\end{cfa}
    25112489After executing this code, ©x© has the value ©20© and ©y© has the value ©10©.
     
    25262504        int a, b;
    25272505        double c, d;
    2528         [void] f([int, int]);
    2529         f([c, a] = [b, d] = 1.5);  // assignments in parameter list
     2506        [ void ] f( [ int, int ] );
     2507        f( [ c, a ] = [ b, d ] = 1.5 );  // assignments in parameter list
    25302508\end{cfa}
    25312509The tuple expression begins with a mass assignment of ©1.5© into ©[b, d]©, which assigns ©1.5© into ©b©, which is truncated to ©1©, and ©1.5© into ©d©, producing the tuple ©[1, 1.5]© as a result.
     
    25332511Finally, the tuple ©[1, 1]© is used as an expression in the call to ©f©.
    25342512
    2535 \subsection{Tuple Construction}
     2513
     2514\subsection{Construction}
     2515
    25362516Tuple construction and destruction follow the same rules and semantics as tuple assignment, except that in the case where there is no right side, the default constructor or destructor is called on each component of the tuple.
    25372517As constructors and destructors did not exist in previous versions of \CFA or in \KWC, this is a primary contribution of this thesis to the design of tuples.
     
    25692549The initialization of ©s© with ©t© works by default because ©t© is flattened into its components, which satisfies the generated field constructor ©?{}(S *, int, double)© to initialize the first two values.
    25702550
    2571 \section{Member-Access Tuple Expression}
     2551
     2552\subsection{Member-Access Expression}
    25722553\label{s:MemberAccessTuple}
    2573 It is possible to access multiple fields from a single expression using a \emph{Member-Access Tuple Expression}.
     2554
     2555Tuples may be used to select multiple fields of a record by field name.
    25742556The result is a single tuple-valued expression whose type is the tuple of the types of the members.
    25752557For example,
    25762558\begin{cfa}
    2577 struct S { int x; double y; char * z; } s;
     2559struct S { char x; int y; double z; } s;
    25782560s.[x, y, z];
    25792561\end{cfa}
    2580 Here, the type of ©s.[x, y, z]© is ©[int, double, char *]©.
    2581 A member tuple expression has the form ©a.[x, y, z];© where ©a© is an expression with type ©T©, where ©T© supports member access expressions, and ©x, y, z© are all members of ©T© with types ©T$_x$©, ©T$_y$©, and ©T$_z$© respectively.
    2582 Then the type of ©a.[x, y, z]© is ©[T_x, T_y, T_z]©.
    2583 
    2584 Since tuple index expressions are a form of member-access expression, it is possible to use tuple-index expressions in conjunction with member tuple expressions to manually restructure a tuple (\eg, rearrange components, drop components, duplicate components, etc.).
    2585 \begin{cfa}
    2586 [int, int, long, double] x;
    2587 void f(double, long);
    2588 
    2589 f(x.[0, 3]);          // f(x.0, x.3)
    2590 x.[0, 1] = x.[1, 0];  // [x.0, x.1] = [x.1, x.0]
    2591 [long, int, long] y = x.[2, 0, 2];
    2592 \end{cfa}
    2593 
    2594 It is possible for a member tuple expression to contain other member access expressions.
    2595 For example,
     2562Here, the type of ©s.[ x, y, z ]© is ©[ char, int, double ]©.
     2563A member tuple expression has the form \emph{e}©.[x, y, z];© where \emph{e} is an expression with type ©T©, where ©T© supports member access expressions, and ©x, y, z© are all members of ©T© with types ©T$_x$©, ©T$_y$©, and ©T$_z$© respectively.
     2564Then the type of \emph{e}©.[x, y, z]© is ©[T$_x$, T$_y$, T$_z$]©.
     2565
     2566A member-access tuple may be used anywhere a tuple can be used, \eg:
     2567\begin{cfa}
     2568s.[ y, z, x ] = [ 3, 3.2, 'x' ];                §\C{// equivalent to s.x = 'x', s.y = 3, s.z = 3.2}§
     2569f( s.[ y, z ] );                                                §\C{// equivalent to f( s.y, s.z )}§
     2570\end{cfa}
     2571Note, the fields appearing in a record-field tuple may be specified in any order;
     2572also, it is unnecessary to specify all the fields of a struct in a multiple record-field tuple.
     2573
     2574Since tuple-index expressions are a form of member-access expression, it is possible to use tuple-index expressions in conjunction with member-access expressions to restructure a tuple (\eg, rearrange components, drop components, duplicate components, etc.).
     2575\begin{cfa}
     2576[ int, int, long, double ] x;
     2577void f( double, long );
     2578
     2579f( x.[ 0, 3 ] );                                                §\C{// f( x.0, x.3 )}§
     2580x.[ 0, 1 ] = x.[ 1, 0 ];                                §\C{// [ x.0, x.1 ] = [ x.1, x.0 ]}§
     2581[ long, int, long ] y = x.[ 2, 0, 2 ];
     2582\end{cfa}
     2583
     2584It is possible for a member tuple expression to contain other member access expressions, \eg:
    25962585\begin{cfa}
    25972586struct A { double i; int j; };
    25982587struct B { int * k; short l; };
    25992588struct C { int x; A y; B z; } v;
    2600 v.[x, y.[i, j], z.k];
    2601 \end{cfa}
    2602 This expression is equivalent to ©[v.x, [v.y.i, v.y.j], v.z.k]©.
    2603 That is, the aggregate expression is effectively distributed across the tuple, which allows simple and easy access to multiple components in an aggregate, without repetition.
     2589v.[ x, y.[ i, j ], z.k ];
     2590\end{cfa}
     2591This expression is equivalent to ©[ v.x, [ v.y.i, v.y.j ], v.z.k ]©.
     2592That is, the aggregate expression is effectively distributed across the tuple allowing simple and easy access to multiple components in an aggregate without repetition.
    26042593It is guaranteed that the aggregate expression to the left of the ©.© in a member tuple expression is evaluated exactly once.
    2605 As such, it is safe to use member tuple expressions on the result of a side-effecting function.
    2606 \begin{cfa}
    2607 [int, float, double] f();
    2608 [double, float] x = f().[2, 1];
     2594As such, it is safe to use member tuple expressions on the result of a function with side-effects.
     2595\begin{cfa}
     2596[ int, float, double ] f();
     2597[ double, float ] x = f().[ 2, 1 ];             §\C{// f() called once}§
    26092598\end{cfa}
    26102599
     
    26122601Since \CFA permits these tuple-access expressions using structures, unions, and tuples, \emph{member tuple expression} or \emph{field tuple expression} is more appropriate.
    26132602
    2614 It is possible to extend member-access expressions further.
    2615 Currently, a member-access expression whose member is a name requires that the aggregate is a structure or union, while a constant integer member requires the aggregate to be a tuple.
    2616 In the interest of orthogonal design, \CFA could apply some meaning to the remaining combinations as well.
    2617 For example,
    2618 \begin{cfa}
    2619 struct S { int x, y; } s;
    2620 [S, S] z;
    2621 
    2622 s.x;  // access member
    2623 z.0;  // access component
    2624 
    2625 s.1;  // ???
    2626 z.y;  // ???
    2627 \end{cfa}
    2628 One possibility is for ©s.1© to select the second member of ©s©.
    2629 Under this interpretation, it becomes possible to not only access members of a struct by name, but also by position.
    2630 Likewise, it seems natural to open this mechanism to enumerations as well, wherein the left side would be a type, rather than an expression.
    2631 One benefit of this interpretation is familiarity, since it is extremely reminiscent of tuple-index expressions.
    2632 On the other hand, it could be argued that this interpretation is brittle in that changing the order of members or adding new members to a structure becomes a brittle operation.
    2633 This problem is less of a concern with tuples, since modifying a tuple affects only the code that directly uses the tuple, whereas modifying a structure has far reaching consequences for every instance of the structure.
    2634 
    2635 As for ©z.y©, one interpretation is to extend the meaning of member tuple expressions.
    2636 That is, currently the tuple must occur as the member, \ie to the right of the dot.
    2637 Allowing tuples to the left of the dot could distribute the member across the elements of the tuple, in much the same way that member tuple expressions distribute the aggregate across the member tuple.
    2638 In this example, ©z.y© expands to ©[z.0.y, z.1.y]©, allowing what is effectively a very limited compile-time field-sections map operation, where the argument must be a tuple containing only aggregates having a member named ©y©.
    2639 It is questionable how useful this would actually be in practice, since structures often do not have names in common with other structures, and further this could cause maintainability issues in that it encourages programmers to adopt very simple naming conventions to maximize the amount of overlap between different types.
    2640 Perhaps more useful would be to allow arrays on the left side of the dot, which would likewise allow mapping a field access across the entire array, producing an array of the contained fields.
    2641 The immediate problem with this idea is that C arrays do not carry around their size, which would make it impossible to use this extension for anything other than a simple stack allocated array.
    2642 
    2643 Supposing this feature works as described, it would be necessary to specify an ordering for the expansion of member-access expressions versus member-tuple expressions.
    2644 \begin{cfa}
    2645 struct { int x, y; };
    2646 [S, S] z;
    2647 z.[x, y];  // ???
    2648 // => [z.0, z.1].[x, y]
    2649 // => [z.0.x, z.0.y, z.1.x, z.1.y]
    2650 // or
    2651 // => [z.x, z.y]
    2652 // => [[z.0, z.1].x, [z.0, z.1].y]
    2653 // => [z.0.x, z.1.x, z.0.y, z.1.y]
    2654 \end{cfa}
    2655 Depending on exactly how the two tuples are combined, different results can be achieved.
    2656 As such, a specific ordering would need to be imposed to make this feature useful.
    2657 Furthermore, this addition moves a member-tuple expression's meaning from being clear statically to needing resolver support, since the member name needs to be distributed appropriately over each member of the tuple, which could itself be a tuple.
    2658 
    2659 A second possibility is for \CFA to have named tuples, as they exist in Swift and D.
    2660 \begin{cfa}
    2661 typedef [int x, int y] Point2D;
    2662 Point2D p1, p2;
    2663 p1.x + p1.y + p2.x + p2.y;
    2664 p1.0 + p1.1 + p2.0 + p2.1;  // equivalent
    2665 \end{cfa}
    2666 In this simpler interpretation, a tuple type carries with it a list of possibly empty identifiers.
    2667 This approach fits naturally with the named return-value feature, and would likely go a long way towards implementing it.
    2668 
    2669 Ultimately, the first two extensions introduce complexity into the model, with relatively little perceived benefit, and so were dropped from consideration.
    2670 Named tuples are a potentially useful addition to the language, provided they can be parsed with a reasonable syntax.
    2671 
    2672 
    2673 \section{Casting}
     2603
     2604\subsection{Casting}
     2605
    26742606In C, the cast operator is used to explicitly convert between types.
    26752607In \CFA, the cast operator has a secondary use, which is type ascription, since it forces the expression resolution algorithm to choose the lowest cost conversion to the target type.
     
    27252657That is, it is invalid to cast ©[int, int]© to ©[int, int, int]©.
    27262658
    2727 \section{Polymorphism}
     2659
     2660\subsection{Polymorphism}
     2661
    27282662Due to the implicit flattening and structuring conversions involved in argument passing, ©otype© and ©dtype© parameters are restricted to matching only with non-tuple types.
    27292663The integration of polymorphism, type assertions, and monomorphic specialization of tuple-assertions are a primary contribution of this thesis to the design of tuples.
     
    27782712Until this point, it has been assumed that assertion arguments must match the parameter type exactly, modulo polymorphic specialization (\ie, no implicit conversions are applied to assertion arguments).
    27792713This decision presents a conflict with the flexibility of tuples.
    2780 \subsection{Assertion Inference}
     2714
     2715
     2716\subsubsection{Assertion Inference}
     2717
    27812718\begin{cfa}
    27822719int f([int, double], double);
     
    29022839Unfortunately, C's syntax for subscripts precluded treating them as tuples.
    29032840The C subscript list has the form ©[i][j]...© and not ©[i, j, ...]©.
    2904 Therefore, there is no syntactic way for a routine returning multiple values to specify the different subscript values, \eg ©f[g()]© always means a single subscript value because there is only one set of brackets.
     2841Therefore, there is no syntactic way for a routine returning multiple values to specify the different subscript values, \eg ©f[ g() ]© always means a single subscript value because there is only one set of brackets.
    29052842Fixing this requires a major change to C because the syntactic form ©M[i, j, k]© already has a particular meaning: ©i, j, k© is a comma expression.
    29062843\end{rationale}
     
    29512888
    29522889
    2953 \section{Mass Assignment}
     2890\subsection{Mass Assignment}
    29542891
    29552892\CFA permits assignment to several variables at once using mass assignment~\cite{CLU}.
     
    29912928
    29922929
    2993 \section{Multiple Assignment}
     2930\subsection{Multiple Assignment}
    29942931
    29952932\CFA also supports the assignment of several values at once, known as multiple assignment~\cite{CLU,Galletly96}.
     
    30322969
    30332970
    3034 \section{Cascade Assignment}
     2971\subsection{Cascade Assignment}
    30352972
    30362973As in C, \CFA mass and multiple assignments can be cascaded, producing cascade assignment.
     
    30482985\end{cfa}
    30492986As in C, the rightmost assignment is performed first, \ie assignment parses right to left.
    3050 
    3051 
    3052 \section{Field Tuples}
    3053 
    3054 Tuples may be used to select multiple fields of a record by field name.
    3055 Its general form is:
    3056 \begin{cfa}
    3057 §\emph{expr}§ . [ §\emph{fieldlist}§ ]
    3058 §\emph{expr}§ -> [ §\emph{fieldlist}§ ]
    3059 \end{cfa}
    3060 \emph{expr} is any expression yielding a value of type record, \eg ©struct©, ©union©.
    3061 Each element of \emph{ fieldlist} is an element of the record specified by \emph{expr}.
    3062 A record-field tuple may be used anywhere a tuple can be used. An example of the use of a record-field tuple is
    3063 the following:
    3064 \begin{cfa}
    3065 struct s {
    3066         int f1, f2;
    3067         char f3;
    3068         double f4;
    3069 } v;
    3070 v.[ f3, f1, f2 ] = ['x', 11, 17 ];      §\C{// equivalent to v.f3 = 'x', v.f1 = 11, v.f2 = 17}§
    3071 f( v.[ f3, f1, f2 ] );                          §\C{// equivalent to f( v.f3, v.f1, v.f2 )}§
    3072 \end{cfa}
    3073 Note, the fields appearing in a record-field tuple may be specified in any order;
    3074 also, it is unnecessary to specify all the fields of a struct in a multiple record-field tuple.
    3075 
    3076 If a field of a ©struct© is itself another ©struct©, multiple fields of this subrecord can be specified using a nested record-field tuple, as in the following example:
    3077 \begin{cfa}
    3078 struct inner {
    3079         int f2, f3;
    3080 };
    3081 struct outer {
    3082         int f1;
    3083         struct inner i;
    3084         double f4;
    3085 } o;
    3086 
    3087 o.[ f1, i.[ f2, f3 ], f4 ] = [ 11, 12, 13, 3.14159 ];
    3088 \end{cfa}
    30892987
    30902988
  • src/Concurrency/Waitfor.cc

    rcf966b5 r6c2ba38  
    416416                                makeAccStatement( acceptables, index, "is_dtor", detectIsDtor( clause.target.function )                                    , indexer ),
    417417                                makeAccStatement( acceptables, index, "func"   , new CastExpr( clause.target.function, fptr_t )                            , indexer ),
    418                                 makeAccStatement( acceptables, index, "list"   , new VariableExpr( monitors )                                              , indexer ),
     418                                makeAccStatement( acceptables, index, "data"   , new VariableExpr( monitors )                                              , indexer ),
    419419                                makeAccStatement( acceptables, index, "size"   , new ConstantExpr( Constant::from_ulong( clause.target.arguments.size() ) ), indexer ),
    420420                                setter->clone()
  • src/GenPoly/Box.cc

    rcf966b5 r6c2ba38  
    855855                        DeclarationWithType *adapteeDecl = adapterType->get_parameters().front();
    856856                        adapteeDecl->set_name( "_adaptee" );
     857                        // do not carry over attributes to real type parameters/return values
     858                        for ( DeclarationWithType * dwt : realType->parameters ) {
     859                                deleteAll( dwt->get_type()->attributes );
     860                                dwt->get_type()->attributes.clear();
     861                        }
     862                        for ( DeclarationWithType * dwt : realType->returnVals ) {
     863                                deleteAll( dwt->get_type()->attributes );
     864                                dwt->get_type()->attributes.clear();
     865                        }
    857866                        ApplicationExpr *adapteeApp = new ApplicationExpr( new CastExpr( new VariableExpr( adapteeDecl ), new PointerType( Type::Qualifiers(), realType ) ) );
    858867                        Statement *bodyStmt;
  • src/GenPoly/InstantiateGeneric.cc

    rcf966b5 r6c2ba38  
    210210                PassVisitor<GenericInstantiator> instantiator;
    211211
    212                 mutateAll( translationUnit, fixer );
     212                // mutateAll( translationUnit, fixer );
    213213                mutateAll( translationUnit, instantiator );
    214214        }
  • src/Parser/ParseNode.h

    rcf966b5 r6c2ba38  
    1010// Created On       : Sat May 16 13:28:16 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Sep 23 18:11:22 2017
    13 // Update Count     : 821
     12// Last Modified On : Mon Nov 27 17:33:35 2017
     13// Update Count     : 824
    1414//
    1515
     
    292292        DeclarationNode * set_extension( bool exten ) { extension = exten; return this; }
    293293  public:
     294        DeclarationNode * get_last() { return (DeclarationNode *)ParseNode::get_last(); }
     295
    294296        struct Variable_t {
    295297//              const std::string * name;
  • src/Parser/TypeData.cc

    rcf966b5 r6c2ba38  
    792792
    793793
    794 NamedTypeDecl * buildSymbolic( const TypeData * td, const string & name, Type::StorageClasses scs, LinkageSpec::Spec linkage ) {
     794NamedTypeDecl * buildSymbolic( const TypeData * td, std::list< Attribute * > attributes, const string & name, Type::StorageClasses scs, LinkageSpec::Spec linkage ) {
    795795        assert( td->kind == TypeData::Symbolic );
    796796        NamedTypeDecl * ret;
     
    803803        buildList( td->symbolic.params, ret->get_parameters() );
    804804        buildList( td->symbolic.assertions, ret->get_assertions() );
     805        ret->base->attributes.splice( ret->base->attributes.end(), attributes );
    805806        return ret;
    806807} // buildSymbolic
     
    866867                return buildEnum( td, attributes, linkage );
    867868        } else if ( td->kind == TypeData::Symbolic ) {
    868                 return buildSymbolic( td, name, scs, linkage );
     869                return buildSymbolic( td, attributes, name, scs, linkage );
    869870        } else {
    870871                return (new ObjectDecl( name, scs, linkage, bitfieldWidth, typebuild( td ), init, attributes ))->set_asmName( asmName );
  • src/Parser/parser.yy

    rcf966b5 r6c2ba38  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Nov 20 09:45:36 2017
    13 // Update Count     : 2945
     12// Last Modified On : Mon Nov 27 17:23:35 2017
     13// Update Count     : 2992
    1414//
    1515
     
    345345%type<en> type_list
    346346
    347 %type<decl> type_qualifier type_qualifier_name type_qualifier_list_opt type_qualifier_list
     347%type<decl> type_qualifier type_qualifier_name forall type_qualifier_list_opt type_qualifier_list
    348348%type<decl> type_specifier type_specifier_nobody
    349349
     
    379379//   `---'                                              matches start of TYPEGENname '('
    380380// Must be:
    381 // Foo( int ) ( *fp )( int );
     381//   Foo( int ) ( *fp )( int );
    382382
    383383// Order of these lines matters (low-to-high precedence).
     
    10581058with_statement:
    10591059        WITH '(' tuple_expression_list ')' statement
    1060                 { $$ = nullptr; }                                                               // FIX ME
     1060                { throw SemanticError("With clause is currently unimplemented."); $$ = nullptr; } // FIX ME
    10611061        ;
    10621062
     
    10641064mutex_statement:
    10651065        MUTEX '(' argument_expression_list ')' statement
    1066                 { $$ = nullptr; }                                                               // FIX ME
     1066                { throw SemanticError("Mutex statement is currently unimplemented."); $$ = nullptr; } // FIX ME
    10671067        ;
    10681068
     
    12801280        c_declaration pop ';'
    12811281        | cfa_declaration pop ';'                                                       // CFA
     1282        | STATICASSERT '(' constant_expression ',' string_literal ')' ';' // C11
     1283                { throw SemanticError("Static assert is currently unimplemented."); $$ = nullptr; }     // FIX ME
    12821284        ;
    12831285
     
    13621364                        $$ = $3->addQualifiers( $1 )->addQualifiers( $2 );
    13631365                }
    1364         | cfa_function_declaration pop ',' push identifier_or_type_name
    1365                 {
    1366                         typedefTable.addToEnclosingScope( *$5, TypedefTable::ID );
    1367                         $$ = $1->appendList( $1->cloneType( $5 ) );
     1366        | cfa_function_declaration pop ',' push identifier_or_type_name '(' push cfa_parameter_type_list_opt pop ')'
     1367                {
     1368                        // Append the return type at the start (left-hand-side) to each identifier in the list.
     1369                        DeclarationNode * ret = new DeclarationNode;
     1370                        ret->type = maybeClone( $1->type->base );
     1371                        $$ = $1->appendList( DeclarationNode::newFunction( $5, ret, $8, nullptr, true ) );
    13681372                }
    13691373        ;
     
    15871591        | ATOMIC
    15881592                { $$ = DeclarationNode::newTypeQualifier( Type::Atomic ); }
    1589         | FORALL '('
     1593        | forall
     1594        ;
     1595
     1596forall:
     1597        FORALL '('
    15901598                {
    15911599                        typedefTable.enterScope();
     
    23742382                        $$ = $2;
    23752383                }
     2384        | forall '{' external_definition_list '}'                       // CFA, namespace
    23762385        ;
    23772386
     
    23992408with_clause_opt:
    24002409        // empty
    2401                 { $$ = nullptr; }                                                               // FIX ME
     2410                { $$ = nullptr; }
    24022411        | WITH '(' tuple_expression_list ')'
    2403                 { $$ = nullptr; }                                                               // FIX ME
     2412                { throw SemanticError("With clause is currently unimplemented."); $$ = nullptr; } // FIX ME
    24042413        ;
    24052414
     
    24092418                        typedefTable.addToEnclosingScope( TypedefTable::ID );
    24102419                        typedefTable.leaveScope();
    2411                         $$ = $1->addFunctionBody( $3 );
     2420                        // Add the function body to the last identifier in the function definition list, i.e., foo3:
     2421                        //   [const double] foo1(), foo2( int ), foo3( double ) { return 3.0; }
     2422                        $1->get_last()->addFunctionBody( $3 );
     2423                        $$ = $1;
    24122424                }
    24132425        | declaration_specifier function_declarator with_clause_opt compound_statement
     
    24182430                        $$ = $2->addFunctionBody( $4 )->addType( $1 );
    24192431                }
     2432                // handles default int return type, OBSOLESCENT (see 1)
    24202433        | type_qualifier_list function_declarator with_clause_opt compound_statement
    24212434                {
     
    24242437                        $$ = $2->addFunctionBody( $4 )->addQualifiers( $1 );
    24252438                }
     2439                // handles default int return type, OBSOLESCENT (see 1)
    24262440        | declaration_qualifier_list function_declarator with_clause_opt compound_statement
    24272441                {
     
    24302444                        $$ = $2->addFunctionBody( $4 )->addQualifiers( $1 );
    24312445                }
     2446                // handles default int return type, OBSOLESCENT (see 1)
    24322447        | declaration_qualifier_list type_qualifier_list function_declarator with_clause_opt compound_statement
    24332448                {
     
    24452460                        $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5 )->addType( $1 );
    24462461                }
     2462                // handles default int return type, OBSOLESCENT (see 1)
    24472463        | type_qualifier_list KR_function_declarator KR_declaration_list_opt with_clause_opt compound_statement
    24482464                {
     
    24512467                        $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5 )->addQualifiers( $1 );
    24522468                }
    2453 
    2454                 // Old-style K&R function definition with "implicit int" type_specifier, OBSOLESCENT (see 4)
     2469                // handles default int return type, OBSOLESCENT (see 1)
    24552470        | declaration_qualifier_list KR_function_declarator KR_declaration_list_opt with_clause_opt compound_statement
    24562471                {
     
    24592474                        $$ = $2->addOldDeclList( $3 )->addFunctionBody( $5 )->addQualifiers( $1 );
    24602475                }
     2476                // handles default int return type, OBSOLESCENT (see 1)
    24612477        | declaration_qualifier_list type_qualifier_list KR_function_declarator KR_declaration_list_opt with_clause_opt compound_statement
    24622478                {
  • src/SymTab/Autogen.cc

    rcf966b5 r6c2ba38  
    372372                                continue;
    373373                        }
    374                         memCtorType->parameters.push_back( new ObjectDecl( field->name, Type::StorageClasses(), LinkageSpec::Cforall, 0, field->get_type()->clone(), 0 ) );
     374                        // do not carry over field's attributes to parameter type
     375                        Type * paramType = field->get_type()->clone();
     376                        deleteAll( paramType->attributes );
     377                        paramType->attributes.clear();
     378                        // add a parameter corresponding to this field
     379                        memCtorType->parameters.push_back( new ObjectDecl( field->name, Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType, nullptr ) );
    375380                        FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting );
    376381                        makeFieldCtorBody( aggregateDecl->members.begin(), aggregateDecl->members.end(), ctor );
     
    503508                                break;
    504509                        }
    505                         memCtorType->parameters.push_back( new ObjectDecl( field->name, Type::StorageClasses(), LinkageSpec::Cforall, nullptr, field->get_type()->clone(), nullptr ) );
     510                        // do not carry over field's attributes to parameter type
     511                        Type * paramType = field->get_type()->clone();
     512                        deleteAll( paramType->attributes );
     513                        paramType->attributes.clear();
     514                        // add a parameter corresponding to this field
     515                        memCtorType->parameters.push_back( new ObjectDecl( field->name, Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType, nullptr ) );
    506516                        FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting );
    507517                        ObjectDecl * srcParam = strict_dynamic_cast<ObjectDecl *>( ctor->type->parameters.back() );
  • src/SymTab/Validate.cc

    rcf966b5 r6c2ba38  
    201201                Declaration * postmutate( TraitDecl * contextDecl );
    202202
     203                void premutate( FunctionType * ftype );
     204
    203205          private:
    204206                template<typename AggDecl>
     
    214216                TypeDeclMap typedeclNames;
    215217                int scopeLevel;
     218                bool inFunctionType = false;
    216219        };
    217220
     
    725728                        Type *ret = def->second.first->base->clone();
    726729                        ret->get_qualifiers() |= typeInst->get_qualifiers();
     730                        // attributes are not carried over from typedef to function parameters/return values
     731                        if ( ! inFunctionType ) {
     732                                ret->attributes.splice( ret->attributes.end(), typeInst->attributes );
     733                        } else {
     734                                deleteAll( ret->attributes );
     735                                ret->attributes.clear();
     736                        }
    727737                        // place instance parameters on the typedef'd type
    728738                        if ( ! typeInst->parameters.empty() ) {
     
    901911        Declaration *EliminateTypedef::postmutate( TraitDecl * traitDecl ) {
    902912                return handleAggregate( traitDecl );
     913        }
     914
     915        void EliminateTypedef::premutate( FunctionType * ) {
     916                GuardValue( inFunctionType );
     917                inFunctionType = true;
    903918        }
    904919
  • src/benchmark/Makefile.am

    rcf966b5 r6c2ba38  
    9494        ctxswitch-cfa_thread.run        \
    9595        ctxswitch-upp_coroutine.run     \
    96         ctxswitch-upp_thread.run
     96        ctxswitch-upp_thread.run        \
     97        ctxswitch-goroutine.run         \
     98        ctxswitch-java_thread.run
    9799
    98100ctxswitch-cfa_coroutine$(EXEEXT):
     
    111113        @@BACKEND_CC@ ctxswitch/pthreads.c  -DBENCH_N=50000000  -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    112114
     115ctxswitch-goroutine$(EXEEXT):
     116        @go build -o a.out ctxswitch/goroutine.go
     117
     118ctxswitch-java_thread$(EXEEXT):
     119        @javac ctxswitch/JavaThread.java
     120        @echo "#!/bin/sh" > a.out
     121        @echo "cd ctxswitch && java JavaThread" >> a.out
     122        @chmod a+x a.out
     123
    113124## =========================================================================================================
    114125mutex$(EXEEXT) :\
    115126        mutex-function.run      \
     127        mutex-fetch_add.run     \
    116128        mutex-pthread_lock.run  \
    117129        mutex-upp.run           \
    118130        mutex-cfa1.run          \
    119131        mutex-cfa2.run          \
    120         mutex-cfa4.run
     132        mutex-cfa4.run          \
     133        mutex-java_thread.run
    121134
    122135mutex-function$(EXEEXT):
    123136        @@BACKEND_CC@ mutex/function.c    -DBENCH_N=500000000   -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    124137
     138mutex-fetch_add$(EXEEXT):
     139        @@BACKEND_CC@ mutex/fetch_add.c   -DBENCH_N=500000000   -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     140
    125141mutex-pthread_lock$(EXEEXT):
    126142        @@BACKEND_CC@ mutex/pthreads.c    -DBENCH_N=50000000    -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     
    137153mutex-cfa4$(EXEEXT):
    138154        @${CC}        mutex/cfa4.c        -DBENCH_N=5000000     -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     155
     156mutex-java_thread$(EXEEXT):
     157        @javac mutex/JavaThread.java
     158        @echo "#!/bin/sh" > a.out
     159        @echo "cd mutex && java JavaThread" >> a.out
     160        @chmod a+x a.out
    139161
    140162## =========================================================================================================
     
    143165        signal-cfa1.run         \
    144166        signal-cfa2.run         \
    145         signal-cfa4.run
     167        signal-cfa4.run         \
     168        signal-java_thread.run
    146169
    147170signal-upp$(EXEEXT):
     
    156179signal-cfa4$(EXEEXT):
    157180        @${CC}        schedint/cfa4.c     -DBENCH_N=500000      -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     181
     182signal-java_thread$(EXEEXT):
     183        @javac schedint/JavaThread.java
     184        @echo "#!/bin/sh" > a.out
     185        @echo "cd schedint && java JavaThread" >> a.out
     186        @chmod a+x a.out
     187
    158188
    159189## =========================================================================================================
     
    183213        creation-cfa_thread.run                 \
    184214        creation-upp_coroutine.run              \
    185         creation-upp_thread.run
     215        creation-upp_thread.run                 \
     216        creation-goroutine.run                  \
     217        creation-java_thread.run
    186218
    187219creation-cfa_coroutine$(EXEEXT):
     
    202234creation-pthread$(EXEEXT):
    203235        @@BACKEND_CC@ creation/pthreads.c  -DBENCH_N=250000     -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     236
     237creation-goroutine$(EXEEXT):
     238        @go build -o a.out creation/goroutine.go
     239
     240creation-java_thread$(EXEEXT):
     241        @javac creation/JavaThread.java
     242        @echo "#!/bin/sh" > a.out
     243        @echo "cd creation && java JavaThread" >> a.out
     244        @chmod a+x a.out
    204245
    205246## =========================================================================================================
  • src/benchmark/Makefile.in

    rcf966b5 r6c2ba38  
    507507        ctxswitch-cfa_thread.run        \
    508508        ctxswitch-upp_coroutine.run     \
    509         ctxswitch-upp_thread.run
     509        ctxswitch-upp_thread.run        \
     510        ctxswitch-goroutine.run         \
     511        ctxswitch-java_thread.run
    510512
    511513ctxswitch-cfa_coroutine$(EXEEXT):
     
    524526        @@BACKEND_CC@ ctxswitch/pthreads.c  -DBENCH_N=50000000  -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    525527
     528ctxswitch-goroutine$(EXEEXT):
     529        @go build -o a.out ctxswitch/goroutine.go
     530
     531ctxswitch-java_thread$(EXEEXT):
     532        @javac ctxswitch/JavaThread.java
     533        @echo "#!/bin/sh" > a.out
     534        @echo "cd ctxswitch && java JavaThread" >> a.out
     535        @chmod a+x a.out
     536
    526537mutex$(EXEEXT) :\
    527538        mutex-function.run      \
     539        mutex-fetch_add.run     \
    528540        mutex-pthread_lock.run  \
    529541        mutex-upp.run           \
    530542        mutex-cfa1.run          \
    531543        mutex-cfa2.run          \
    532         mutex-cfa4.run
     544        mutex-cfa4.run          \
     545        mutex-java_thread.run
    533546
    534547mutex-function$(EXEEXT):
    535548        @@BACKEND_CC@ mutex/function.c    -DBENCH_N=500000000   -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
    536549
     550mutex-fetch_add$(EXEEXT):
     551        @@BACKEND_CC@ mutex/fetch_add.c   -DBENCH_N=500000000   -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     552
    537553mutex-pthread_lock$(EXEEXT):
    538554        @@BACKEND_CC@ mutex/pthreads.c    -DBENCH_N=50000000    -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     
    549565mutex-cfa4$(EXEEXT):
    550566        @${CC}        mutex/cfa4.c        -DBENCH_N=5000000     -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     567
     568mutex-java_thread$(EXEEXT):
     569        @javac mutex/JavaThread.java
     570        @echo "#!/bin/sh" > a.out
     571        @echo "cd mutex && java JavaThread" >> a.out
     572        @chmod a+x a.out
    551573
    552574signal$(EXEEXT) :\
     
    567589signal-cfa4$(EXEEXT):
    568590        @${CC}        schedint/cfa4.c     -DBENCH_N=500000      -I. -nodebug -lrt -quiet @CFA_FLAGS@ ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     591
     592signal-java_thread$(EXEEXT):
     593        @javac schedint/JavaThread.java
     594        @echo "#!/bin/sh" > a.out
     595        @echo "cd schedint && java JavaThread" >> a.out
     596        @chmod a+x a.out
    569597
    570598waitfor$(EXEEXT) :\
     
    592620        creation-cfa_thread.run                 \
    593621        creation-upp_coroutine.run              \
    594         creation-upp_thread.run
     622        creation-upp_thread.run                 \
     623        creation-goroutine.run                  \
     624        creation-java_thread.run
    595625
    596626creation-cfa_coroutine$(EXEEXT):
     
    611641creation-pthread$(EXEEXT):
    612642        @@BACKEND_CC@ creation/pthreads.c  -DBENCH_N=250000     -I. -lrt -pthread                    ${AM_CFLAGS} ${CFLAGS} ${ccflags}
     643
     644creation-goroutine$(EXEEXT):
     645        @go build -o a.out creation/goroutine.go
     646
     647creation-java_thread$(EXEEXT):
     648        @javac creation/JavaThread.java
     649        @echo "#!/bin/sh" > a.out
     650        @echo "cd creation && java JavaThread" >> a.out
     651        @chmod a+x a.out
    613652
    614653compile$(EXEEXT) :\
  • src/benchmark/bench.h

    rcf966b5 r6c2ba38  
    11#pragma once
    22
    3 #if defined(__CFORALL__)
     3#if defined(__cforall)
    44extern "C" {
    55#endif
     
    88        #include <sys/times.h>                                  // times
    99        #include <time.h>
    10 #if defined(__CFORALL__)
     10#if defined(__cforall)
    1111}
    1212#endif
  • src/libcfa/Makefile.am

    rcf966b5 r6c2ba38  
    100100        math                            \
    101101        gmp                             \
     102        bits/containers.h               \
    102103        bits/defs.h             \
    103104        bits/locks.h            \
  • src/libcfa/Makefile.in

    rcf966b5 r6c2ba38  
    264264        containers/result containers/vector concurrency/coroutine \
    265265        concurrency/thread concurrency/kernel concurrency/monitor \
    266         ${shell echo stdhdr/*} math gmp bits/defs.h bits/locks.h \
    267         concurrency/invoke.h libhdr.h libhdr/libalign.h \
     266        ${shell echo stdhdr/*} math gmp bits/containers.h bits/defs.h \
     267        bits/locks.h concurrency/invoke.h libhdr.h libhdr/libalign.h \
    268268        libhdr/libdebug.h libhdr/libtools.h
    269269HEADERS = $(nobase_cfa_include_HEADERS)
     
    437437        math                            \
    438438        gmp                             \
     439        bits/containers.h               \
    439440        bits/defs.h             \
    440441        bits/locks.h            \
  • src/libcfa/bits/containers.h

    rcf966b5 r6c2ba38  
    1515#pragma once
    1616
    17 #include <stddef.h>
     17#include "bits/defs.h"
     18#include "libhdr.h"
    1819
    19 #include "libhdr.h"
     20//-----------------------------------------------------------------------------
     21// Array
     22//-----------------------------------------------------------------------------
     23
     24#ifdef __cforall
     25        forall(dtype T)
     26#else
     27        #define T void
     28#endif
     29struct __small_array {
     30        T *           data;
     31        __lock_size_t size;
     32};
     33#undef T
     34
     35#ifdef __cforall
     36        #define __small_array_t(T) __small_array(T)
     37#else
     38        #define __small_array_t(T) struct __small_array
     39#endif
     40
     41#ifdef __cforall
     42        // forall(otype T | sized(T))
     43        // static inline void ?{}(__small_array(T) & this) {}
     44
     45        forall(dtype T | sized(T))
     46        static inline T& ?[?]( __small_array(T) & this, __lock_size_t idx) {
     47                return ((typeof(this.data))this.data)[idx];
     48        }
     49
     50        forall(dtype T | sized(T))
     51        static inline T& ?[?]( const __small_array(T) & this, __lock_size_t idx) {
     52                return ((typeof(this.data))this.data)[idx];
     53        }
     54
     55        forall(dtype T | sized(T))
     56        static inline T* begin( const __small_array(T) & this ) {
     57                return ((typeof(this.data))this.data);
     58        }
     59
     60        forall(dtype T | sized(T))
     61        static inline T* end( const __small_array(T) & this ) {
     62                return ((typeof(this.data))this.data) + this.size;
     63        }
     64#endif
    2065
    2166//-----------------------------------------------------------------------------
     
    2368//-----------------------------------------------------------------------------
    2469
    25 #ifdef __CFORALL__
     70#ifdef __cforall
    2671        trait is_node(dtype T) {
    2772                T*& get_next( T& );
     
    3277// Stack
    3378//-----------------------------------------------------------------------------
    34 #ifdef __CFORALL__
     79#ifdef __cforall
    3580        forall(dtype TYPE | is_node(TYPE))
    3681        #define T TYPE
     
    4186        T * top;
    4287};
     88#undef T
    4389
    44 #ifdef __CFORALL__
     90#ifdef __cforall
    4591#define __stack_t(T) __stack(T)
    4692#else
     
    4894#endif
    4995
    50 #ifdef __CFORALL__
     96#ifdef __cforall
    5197        forall(dtype T | is_node(T))
    52         void ?{}( __stack(T) & this ) {
    53                 this.top = NULL;
     98        static inline void ?{}( __stack(T) & this ) {
     99                (this.top){ NULL };
    54100        }
    55101
    56102        forall(dtype T | is_node(T) | sized(T))
    57         void push( __stack(T) & this, T * val ) {
     103        static inline void push( __stack(T) & this, T * val ) {
    58104                verify( !get_next( *val ) );
    59105                get_next( *val ) = this.top;
     
    62108
    63109        forall(dtype T | is_node(T) | sized(T))
    64         T * pop( __stack(T) & this ) {
     110        static inline T * pop( __stack(T) & this ) {
    65111                T * top = this.top;
    66112                if( top ) {
     
    75121// Queue
    76122//-----------------------------------------------------------------------------
    77 #ifdef __CFORALL__
    78         forall(dtype T | is_node(T))
     123#ifdef __cforall
     124        forall(dtype TYPE | is_node(TYPE))
    79125        #define T TYPE
    80126#else
     
    85131        T ** tail;
    86132};
     133#undef T
    87134
    88 #ifdef __CFORALL__
     135#ifdef __cforall
     136#define __queue_t(T) __queue(T)
     137#else
     138#define __queue_t(T) struct __queue
     139#endif
     140
     141#ifdef __cforall
    89142        forall(dtype T | is_node(T))
    90         void ?{}( __queue(T) & this ) {
    91                 this.head = NULL;
    92                 this.tail = &this.head;
     143        static inline void ?{}( __queue(T) & this ) {
     144                (this.head){ NULL };
     145                (this.tail){ &this.head };
    93146        }
    94147
    95148        forall(dtype T | is_node(T) | sized(T))
    96         void append( __queue(T) & this, T * val ) {
     149        static inline void append( __queue(T) & this, T * val ) {
    97150                verify(this.tail != NULL);
    98151                *this.tail = val;
     
    101154
    102155        forall(dtype T | is_node(T) | sized(T))
    103         T * pop_head( __queue(T) & this ) {
     156        static inline T * pop_head( __queue(T) & this ) {
    104157                T * head = this.head;
    105158                if( head ) {
     
    114167
    115168        forall(dtype T | is_node(T) | sized(T))
    116         T * remove( __queue(T) & this, T ** it ) {
     169        static inline T * remove( __queue(T) & this, T ** it ) {
    117170                T * val = *it;
    118171                verify( val );
  • src/libcfa/bits/defs.h

    rcf966b5 r6c2ba38  
    1717
    1818#include <stdbool.h>
     19#include <stddef.h>
    1920#include <stdint.h>
    2021
     
    2223#define likely  (x)    __builtin_expect(!!(x), 1)
    2324#define thread_local _Thread_local
     25
     26typedef void (*fptr_t)();
     27typedef int_fast16_t __lock_size_t;
     28
     29#ifdef __cforall
     30#define __cfa_anonymous_object
     31#else
     32#define __cfa_anonymous_object __cfa_anonymous_object
     33#endif
  • src/libcfa/bits/locks.h

    rcf966b5 r6c2ba38  
    5656} __ALIGN__;
    5757
    58 #ifdef __CFORALL__
     58#ifdef __cforall
    5959        extern void yield( unsigned int );
    6060        extern thread_local struct thread_desc *    volatile this_thread;
  • src/libcfa/concurrency/invoke.h

    rcf966b5 r6c2ba38  
    1414//
    1515
     16#include "bits/containers.h"
    1617#include "bits/defs.h"
    1718#include "bits/locks.h"
    1819
    19 #ifdef __CFORALL__
     20#ifdef __cforall
    2021extern "C" {
    2122#endif
     
    2526#define _INVOKE_H_
    2627
    27         typedef void (*fptr_t)();
    28         typedef int_fast16_t __lock_size_t;
    29 
    30         struct __thread_queue_t {
    31                 struct thread_desc * head;
    32                 struct thread_desc ** tail;
    33         };
    34 
    35         struct __condition_stack_t {
    36                 struct __condition_criterion_t * top;
    37         };
    38 
    39         #ifdef __CFORALL__
     28        #ifdef __cforall
    4029        extern "Cforall" {
    41                 void ?{}( struct __thread_queue_t & );
    42                 void append( struct __thread_queue_t &, struct thread_desc * );
    43                 struct thread_desc * pop_head( struct __thread_queue_t & );
    44                 struct thread_desc * remove( struct __thread_queue_t &, struct thread_desc ** );
    45 
    46                 void ?{}( struct __condition_stack_t & );
    47                 void push( struct __condition_stack_t &, struct __condition_criterion_t * );
    48                 struct __condition_criterion_t * pop( struct __condition_stack_t & );
     30                static inline struct thread_desc             * & get_next( struct thread_desc             & this );
     31                static inline struct __condition_criterion_t * & get_next( struct __condition_criterion_t & this );
    4932        }
    5033        #endif
     
    10083
    10184                // list of acceptable functions, null if any
    102                 struct __acceptable_t * clauses;
    103 
    104                 // number of acceptable functions
    105                 __lock_size_t size;
     85                __small_array_t(struct __acceptable_t) __cfa_anonymous_object;
    10686        };
    10787
     
    11494
    11595                // queue of threads that are blocked waiting for the monitor
    116                 struct __thread_queue_t entry_queue;
     96                __queue_t(struct thread_desc) entry_queue;
    11797
    11898                // stack of conditions to run next once we exit the monitor
    119                 struct __condition_stack_t signal_stack;
     99                __stack_t(struct __condition_criterion_t) signal_stack;
    120100
    121101                // monitor routines can be called recursively, we need to keep track of that
     
    131111        struct __monitor_group_t {
    132112                // currently held monitors
    133                 struct monitor_desc ** list;
    134 
    135                 // number of currently held monitors
    136                 __lock_size_t size;
     113                __small_array_t(monitor_desc*) __cfa_anonymous_object;
    137114
    138115                // last function that acquired monitors
     
    159136     };
    160137
    161      #ifdef __CFORALL__
     138     #ifdef __cforall
    162139     extern "Cforall" {
    163                 static inline monitor_desc * ?[?]( const __monitor_group_t & this, ptrdiff_t index ) {
    164                         return this.list[index];
     140                static inline thread_desc * & get_next( thread_desc & this ) {
     141                        return this.next;
     142                }
     143
     144                static inline struct __condition_criterion_t * & get_next( struct __condition_criterion_t & this );
     145
     146                static inline void ?{}(__monitor_group_t & this) {
     147                        (this.data){NULL};
     148                        (this.size){0};
     149                        (this.func){NULL};
     150                }
     151
     152                static inline void ?{}(__monitor_group_t & this, struct monitor_desc ** data, __lock_size_t size, fptr_t func) {
     153                        (this.data){data};
     154                        (this.size){size};
     155                        (this.func){func};
    165156                }
    166157
    167158                static inline bool ?==?( const __monitor_group_t & lhs, const __monitor_group_t & rhs ) {
    168                         if( (lhs.list != 0) != (rhs.list != 0) ) return false;
     159                        if( (lhs.data != 0) != (rhs.data != 0) ) return false;
    169160                        if( lhs.size != rhs.size ) return false;
    170161                        if( lhs.func != rhs.func ) return false;
     
    177168
    178169                        return true;
     170                }
     171
     172                static inline void ?=?(__monitor_group_t & lhs, const __monitor_group_t & rhs) {
     173                        lhs.data = rhs.data;
     174                        lhs.size = rhs.size;
     175                        lhs.func = rhs.func;
    179176                }
    180177        }
     
    210207#endif //_INVOKE_PRIVATE_H_
    211208#endif //! defined(__CFA_INVOKE_PRIVATE__)
    212 #ifdef __CFORALL__
     209#ifdef __cforall
    213210}
    214211#endif
  • src/libcfa/concurrency/kernel

    rcf966b5 r6c2ba38  
    2626//-----------------------------------------------------------------------------
    2727// Locks
    28 // // Lock the spinlock, spin if already acquired
    29 // void lock      ( spinlock * DEBUG_CTX_PARAM2 );
    30 
    31 // // Lock the spinlock, yield repeatedly if already acquired
    32 // void lock_yield( spinlock * DEBUG_CTX_PARAM2 );
    33 
    34 // // Lock the spinlock, return false if already acquired
    35 // bool try_lock  ( spinlock * DEBUG_CTX_PARAM2 );
    36 
    37 // // Unlock the spinlock
    38 // void unlock    ( spinlock * );
    39 
    4028struct semaphore {
    4129        __spinlock_t lock;
    4230        int count;
    43         __thread_queue_t waiting;
     31        __queue_t(thread_desc) waiting;
    4432};
    4533
     
    5745
    5846        // Ready queue for threads
    59         __thread_queue_t ready_queue;
     47        __queue_t(thread_desc) ready_queue;
    6048
    6149        // Preemption rate on this cluster
  • src/libcfa/concurrency/kernel.c

    rcf966b5 r6c2ba38  
    164164
    165165void ?{}(cluster & this) {
    166         ( this.ready_queue ){};
     166        (this.ready_queue){};
    167167        ( this.ready_queue_lock ){};
    168168
     
    611611}
    612612
    613 //-----------------------------------------------------------------------------
    614 // Queues
    615 void ?{}( __thread_queue_t & this ) {
    616         this.head = NULL;
    617         this.tail = &this.head;
    618 }
    619 
    620 void append( __thread_queue_t & this, thread_desc * t ) {
    621         verify(this.tail != NULL);
    622         *this.tail = t;
    623         this.tail = &t->next;
    624 }
    625 
    626 thread_desc * pop_head( __thread_queue_t & this ) {
    627         thread_desc * head = this.head;
    628         if( head ) {
    629                 this.head = head->next;
    630                 if( !head->next ) {
    631                         this.tail = &this.head;
    632                 }
    633                 head->next = NULL;
    634         }
    635         return head;
    636 }
    637 
    638 thread_desc * remove( __thread_queue_t & this, thread_desc ** it ) {
    639         thread_desc * thrd = *it;
    640         verify( thrd );
    641 
    642         (*it) = thrd->next;
    643 
    644         if( this.tail == &thrd->next ) {
    645                 this.tail = it;
    646         }
    647 
    648         thrd->next = NULL;
    649 
    650         verify( (this.head == NULL) == (&this.head == this.tail) );
    651         verify( *this.tail == NULL );
    652         return thrd;
    653 }
    654 
    655 void ?{}( __condition_stack_t & this ) {
    656         this.top = NULL;
    657 }
    658 
    659 void push( __condition_stack_t & this, __condition_criterion_t * t ) {
    660         verify( !t->next );
    661         t->next = this.top;
    662         this.top = t;
    663 }
    664 
    665 __condition_criterion_t * pop( __condition_stack_t & this ) {
    666         __condition_criterion_t * top = this.top;
    667         if( top ) {
    668                 this.top = top->next;
    669                 top->next = NULL;
    670         }
    671         return top;
    672 }
    673 
    674613// Local Variables: //
    675614// mode: c //
  • src/libcfa/concurrency/monitor

    rcf966b5 r6c2ba38  
    3434        this.recursion     = 0;
    3535        this.mask.accepted = NULL;
    36         this.mask.clauses  = NULL;
     36        this.mask.data     = NULL;
    3737        this.mask.size     = 0;
    3838        this.dtor_node     = NULL;
     
    4040
    4141struct monitor_guard_t {
    42         monitor_desc ** m;
    43         __lock_size_t   count;
    44         monitor_desc ** prev_mntrs;
    45         __lock_size_t   prev_count;
    46         fptr_t          prev_func;
     42        monitor_desc **         m;
     43        __lock_size_t           count;
     44        __monitor_group_t prev;
    4745};
    4846
     
    5149
    5250struct monitor_dtor_guard_t {
    53         monitor_desc * m;
    54         monitor_desc ** prev_mntrs;
    55         __lock_size_t   prev_count;
    56         fptr_t          prev_func;
     51        monitor_desc *    m;
     52        __monitor_group_t prev;
    5753};
    5854
     
    8379};
    8480
     81static inline __condition_criterion_t * & get_next( __condition_criterion_t & this ) {
     82        return this.next;
     83}
     84
    8585struct __condition_node_t {
    8686        // Thread that needs to be woken when all criteria are met
     
    100100};
    101101
    102 struct __condition_blocked_queue_t {
    103         __condition_node_t * head;
    104         __condition_node_t ** tail;
    105 };
     102static inline __condition_node_t * & get_next( __condition_node_t & this ) {
     103        return this.next;
     104}
    106105
    107106void ?{}(__condition_node_t & this, thread_desc * waiting_thread, __lock_size_t count, uintptr_t user_info );
     
    109108void ?{}(__condition_criterion_t & this, monitor_desc * target, __condition_node_t * owner );
    110109
    111 void ?{}( __condition_blocked_queue_t & );
    112 void append( __condition_blocked_queue_t &, __condition_node_t * );
    113 __condition_node_t * pop_head( __condition_blocked_queue_t & );
    114 
    115110struct condition {
    116111        // Link list which contains the blocked threads as-well as the information needed to unblock them
    117         __condition_blocked_queue_t blocked;
     112        __queue_t(__condition_node_t) blocked;
    118113
    119114        // Array of monitor pointers (Monitors are NOT contiguous in memory)
  • src/libcfa/concurrency/monitor.c

    rcf966b5 r6c2ba38  
    280280static inline void enter( __monitor_group_t monitors ) {
    281281        for( __lock_size_t i = 0; i < monitors.size; i++) {
    282                 __enter_monitor_desc( monitors.list[i], monitors );
     282                __enter_monitor_desc( monitors[i], monitors );
    283283        }
    284284}
     
    303303
    304304        // Save previous thread context
    305         this.[prev_mntrs, prev_count, prev_func] = this_thread->monitors.[list, size, func];
     305        this.prev = this_thread->monitors;
    306306
    307307        // Update thread context (needed for conditions)
    308         this_thread->monitors.[list, size, func] = [m, count, func];
     308        (this_thread->monitors){m, count, func};
    309309
    310310        // LIB_DEBUG_PRINT_SAFE("MGUARD : enter %d\n", count);
     
    328328
    329329        // Restore thread context
    330         this_thread->monitors.[list, size, func] = this.[prev_mntrs, prev_count, prev_func];
     330        this_thread->monitors = this.prev;
    331331}
    332332
     
    338338
    339339        // Save previous thread context
    340         this.[prev_mntrs, prev_count, prev_func] = this_thread->monitors.[list, size, func];
     340        this.prev = this_thread->monitors;
    341341
    342342        // Update thread context (needed for conditions)
    343         this_thread->monitors.[list, size, func] = [m, 1, func];
     343        (this_thread->monitors){m, 1, func};
    344344
    345345        __enter_monitor_dtor( this.m, func );
     
    352352
    353353        // Restore thread context
    354         this_thread->monitors.[list, size, func] = this.[prev_mntrs, prev_count, prev_func];
     354        this_thread->monitors = this.prev;
    355355}
    356356
     
    437437
    438438                for(int i = 0; i < this.monitor_count; i++) {
    439                         if ( this.monitors[i] != this_thrd->monitors.list[i] ) {
    440                                 abortf( "Signal on condition %p made with different monitor, expected %p got %i", &this, this.monitors[i], this_thrd->monitors.list[i] );
     439                        if ( this.monitors[i] != this_thrd->monitors[i] ) {
     440                                abortf( "Signal on condition %p made with different monitor, expected %p got %i", &this, this.monitors[i], this_thrd->monitors[i] );
    441441                        }
    442442                }
     
    510510                "Possible cause is not checking if the condition is empty before reading stored data."
    511511        );
    512         return this.blocked.head->user_info;
     512        return ((typeof(this.blocked.head))this.blocked.head)->user_info;
    513513}
    514514
     
    554554                if( next ) {
    555555                        *mask.accepted = index;
    556                         if( mask.clauses[index].is_dtor ) {
     556                        __acceptable_t& accepted = mask[index];
     557                        if( accepted.is_dtor ) {
    557558                                LIB_DEBUG_PRINT_BUFFER_LOCAL( "Kernel : dtor already there\n");
    558                                 verifyf( mask.clauses[index].size == 1        , "ERROR: Accepted dtor has more than 1 mutex parameter." );
    559 
    560                                 monitor_desc * mon2dtor = mask.clauses[index].list[0];
     559                                verifyf( accepted.size == 1, "ERROR: Accepted dtor has more than 1 mutex parameter." );
     560
     561                                monitor_desc * mon2dtor = accepted[0];
    561562                                verifyf( mon2dtor->dtor_node, "ERROR: Accepted monitor has no dtor_node." );
    562563
     
    596597
    597598                        LIB_DEBUG_PRINT_BUFFER_LOCAL( "Kernel : accepted %d\n", *mask.accepted);
    598 
    599599                        return;
    600600                }
     
    671671static inline void reset_mask( monitor_desc * this ) {
    672672        this->mask.accepted = NULL;
    673         this->mask.clauses = NULL;
     673        this->mask.data = NULL;
    674674        this->mask.size = 0;
    675675}
     
    697697
    698698static inline bool is_accepted( monitor_desc * this, const __monitor_group_t & group ) {
    699         __acceptable_t * it = this->mask.clauses; // Optim
     699        __acceptable_t * it = this->mask.data; // Optim
    700700        __lock_size_t count = this->mask.size;
    701701
     
    820820        if( !this.monitors ) {
    821821                // LIB_DEBUG_PRINT_SAFE("Branding\n");
    822                 assertf( thrd->monitors.list != NULL, "No current monitor to brand condition %p", thrd->monitors.list );
     822                assertf( thrd->monitors.data != NULL, "No current monitor to brand condition %p", thrd->monitors.data );
    823823                this.monitor_count = thrd->monitors.size;
    824824
    825825                this.monitors = (monitor_desc **)malloc( this.monitor_count * sizeof( *this.monitors ) );
    826826                for( int i = 0; i < this.monitor_count; i++ ) {
    827                         this.monitors[i] = thrd->monitors.list[i];
     827                        this.monitors[i] = thrd->monitors[i];
    828828                }
    829829        }
     
    832832static inline [thread_desc *, int] search_entry_queue( const __waitfor_mask_t & mask, monitor_desc * monitors [], __lock_size_t count ) {
    833833
    834         __thread_queue_t & entry_queue = monitors[0]->entry_queue;
     834        __queue_t(thread_desc) & entry_queue = monitors[0]->entry_queue;
    835835
    836836        // For each thread in the entry-queue
     
    841841                // For each acceptable check if it matches
    842842                int i = 0;
    843                 __acceptable_t * end = mask.clauses + mask.size;
    844                 for( __acceptable_t * it = mask.clauses; it != end; it++, i++ ) {
     843                __acceptable_t * end   = end  (mask);
     844                __acceptable_t * begin = begin(mask);
     845                for( __acceptable_t * it = begin; it != end; it++, i++ ) {
    845846                        // Check if we have a match
    846847                        if( *it == (*thrd_it)->monitors ) {
     
    872873        __lock_size_t max = 0;
    873874        for( __lock_size_t i = 0; i < mask.size; i++ ) {
    874                 max += mask.clauses[i].size;
     875                __acceptable_t & accepted = mask[i];
     876                max += accepted.size;
    875877        }
    876878        return max;
     
    880882        __lock_size_t size = 0;
    881883        for( __lock_size_t i = 0; i < mask.size; i++ ) {
    882                 __libcfa_small_sort( mask.clauses[i].list, mask.clauses[i].size );
    883                 for( __lock_size_t j = 0; j < mask.clauses[i].size; j++) {
    884                         insert_unique( storage, size, mask.clauses[i].list[j] );
     884                __acceptable_t & accepted = mask[i];
     885                __libcfa_small_sort( accepted.data, accepted.size );
     886                for( __lock_size_t j = 0; j < accepted.size; j++) {
     887                        insert_unique( storage, size, accepted[j] );
    885888                }
    886889        }
     
    888891        __libcfa_small_sort( storage, size );
    889892        return size;
    890 }
    891 
    892 void ?{}( __condition_blocked_queue_t & this ) {
    893         this.head = NULL;
    894         this.tail = &this.head;
    895 }
    896 
    897 void append( __condition_blocked_queue_t & this, __condition_node_t * c ) {
    898         verify(this.tail != NULL);
    899         *this.tail = c;
    900         this.tail = &c->next;
    901 }
    902 
    903 __condition_node_t * pop_head( __condition_blocked_queue_t & this ) {
    904         __condition_node_t * head = this.head;
    905         if( head ) {
    906                 this.head = head->next;
    907                 if( !head->next ) {
    908                         this.tail = &this.head;
    909                 }
    910                 head->next = NULL;
    911         }
    912         return head;
    913893}
    914894
  • src/libcfa/exception.h

    rcf966b5 r6c2ba38  
    1717
    1818
    19 #ifdef __CFORALL__
     19#ifdef __cforall
    2020extern "C" {
    2121#endif
     
    6868struct __cfaehm__cleanup_hook {};
    6969
    70 #ifdef __CFORALL__
     70#ifdef __cforall
    7171}
    7272#endif
  • src/libcfa/stdhdr/assert.h

    rcf966b5 r6c2ba38  
    44// The contents of this file are covered under the licence agreement in the
    55// file "LICENCE" distributed with Cforall.
    6 // 
    7 // assert.h -- 
    8 // 
     6//
     7// assert.h --
     8//
    99// Author           : Peter A. Buhr
    1010// Created On       : Mon Jul  4 23:25:26 2016
     
    1212// Last Modified On : Mon Jul 31 23:09:32 2017
    1313// Update Count     : 13
    14 // 
     14//
    1515
    16 #ifdef __CFORALL__
     16#ifdef __cforall
    1717extern "C" {
    18 #endif //__CFORALL__
     18#endif //__cforall
    1919
    2020#include_next <assert.h>
     
    3030#endif
    3131
    32 #ifdef __CFORALL__
     32#ifdef __cforall
    3333} // extern "C"
    34 #endif //__CFORALL__
     34#endif //__cforall
    3535
    3636// Local Variables: //
  • src/libcfa/virtual.h

    rcf966b5 r6c2ba38  
    1616#pragma once
    1717
    18 #ifdef __CFORALL__
     18#ifdef __cforall
    1919extern "C" {
    2020#endif
     
    3535                struct __cfa__parent_vtable const * const * child );
    3636
    37 #ifdef __CFORALL__
     37#ifdef __cforall
    3838}
    3939#endif
  • src/tests/Makefile.am

    rcf966b5 r6c2ba38  
    1111## Created On       : Sun May 31 09:08:15 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Tue Oct 10 14:04:40 2017
    14 ## Update Count     : 47
     13## Last Modified On : Mon Nov 27 21:34:33 2017
     14## Update Count     : 48
    1515###############################################################################
    1616
     
    118118        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
    119119
     120functions: functions.c @CFA_BINDIR@/@CFA_NAME@
     121        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
     122
    120123KRfunctions : KRfunctions.c @CFA_BINDIR@/@CFA_NAME@
    121124        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
  • src/tests/Makefile.in

    rcf966b5 r6c2ba38  
    871871        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
    872872
     873functions: functions.c @CFA_BINDIR@/@CFA_NAME@
     874        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
     875
    873876KRfunctions : KRfunctions.c @CFA_BINDIR@/@CFA_NAME@
    874877        ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@}
  • src/tests/designations.c

    rcf966b5 r6c2ba38  
    1717// In particular, since the syntax for designations in Cforall differs from that of C, preprocessor substitution
    1818// is used for the designation syntax
    19 #ifdef __CFORALL__
     19#ifdef __cforall
    2020#define DES :
    2121#else
  • src/tests/functions.c

    rcf966b5 r6c2ba38  
    1010// Created On       : Wed Aug 17 08:39:58 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Aug 17 08:40:52 2016
    13 // Update Count     : 1
     12// Last Modified On : Mon Nov 27 18:08:54 2017
     13// Update Count     : 11
    1414//
    1515
     
    6666// Cforall extensions
    6767
    68 [] f( );
     68// [] f( );
    6969[int] f( );
    70 [] f(int);
     70// [] f(int);
    7171[int] f(int);
    72 [] f( ) {}
     72// [] f( ) {}
    7373[int] f( ) {}
    74 [] f(int) {}
     74// [] f(int) {}
    7575[int] f(int) {}
    7676
    7777[int x] f( );
    78 [] f(int x);
    79 [int x] f(int x);
    80 [int x] f( ) {}
    81 [] f(int x) {}
    82 [int x] f(int x) {}
     78// [] f(int x);
     79//[int x] f(int x);
     80//[int x] f( ) {}
     81// [] f(int x) {}
     82//[int x] f(int x) {}
    8383
    8484[int, int x] f( );
    85 [] f(int, int x);
     85// [] f(int, int x);
    8686[int, int x] f(int, int x);
    8787[int, int x] f( ) {}
    88 [] f(int, int x) {}
     88// [] f(int, int x) {}
    8989[int, int x] f(int, int x) {}
    9090
    9191[int, int x, int] f( );
    92 [] f(int, int x, int);
     92// [] f(int, int x, int);
    9393[int, int x, int] f(int, int x, int);
    9494[int, int x, int] f( ) {}
    95 [] f(int, int x, int) {}
     95// [] f(int, int x, int) {}
    9696[int, int x, int] f(int, int x, int) {}
    9797
    9898[int, int x, * int y] f( );
    99 [] f(int, int x, * int y);
     99// [] f(int, int x, * int y);
    100100[int, int x, * int y] f(int, int x, * int y);
    101101[int, int x, * int y] f( ) {}
    102 [] f(int, int x, * int y) {}
     102// [] f(int, int x, * int y) {}
    103103[int, int x, * int y] f(int, int x, * int y) {}
    104104
    105 [ int ] f11( int ), f12;  // => int f11( int ), f12( int );
     105// function prototypes
     106
     107[ int ] f11( int ), f12();  // => int f11( int ), f12( void );
     108
     109const double bar1(), bar2( int ), bar3( double );               // C version
     110[const double] foo(), foo( int ), foo( double ) { return 3.0; } // CFA version
     111struct S { int i; };
     112[S] rtn( int ) {}
     113
    106114
    107115[int] f(
     
    109117        [int](int)
    110118        ) {
    111         int (*(*p)[][10])[][3];
     119        int (*(*pc)[][10])[][3];
    112120        * [][10] * [][3] int p;
    113121        * [] * [int](int) p;
  • src/tests/polymorphism.c

    rcf966b5 r6c2ba38  
    4747        S s;
    4848        s.i = i;
    49         assert(s.i == i);
     49        assertf(s.i == i, "struct operation fails in polymorphic context.");
    5050
    5151        B b;
     
    7373        {
    7474                // test aggregates with polymorphic members
    75                 typedef uint32_t x_type;
    76                 typedef uint64_t y_type;
     75                typedef __attribute__((aligned(8))) uint32_t x_type;
     76                typedef __attribute__((aligned(8))) uint64_t y_type;
    7777
    7878                x_type x = 3;
     
    8989                // ensure that the size of aggregates with polymorphic members
    9090                // matches the size of the aggregates in a monomorphic context
    91                 assert( struct_size(x, y) == sizeof(S) );
    92                 assert( union_size(x, y) == sizeof(U) );
     91                size_t ssz = struct_size(x, y);
     92                size_t usz = union_size(x, y);
     93                assertf( ssz == sizeof(S), "struct size differs in polymorphic context: %zd / %zd", ssz, sizeof(S));
     94                assertf( usz == sizeof(U), "union size differs in polymorphic context: %zd / %zd", usz, sizeof(U));
    9395
    9496                y_type ?=?(y_type & this, zero_t) {
     
    111113                u.f2 = 0;
    112114                u.f1 = x;
    113                 assert(ret == u.f2);
     115                assertf(ret == u.f2, "union operation fails in polymorphic context.");
    114116        }
    115117}
Note: See TracChangeset for help on using the changeset viewer.