Changeset caa649b


Ignore:
Timestamp:
Mar 6, 2018, 12:11:11 PM (4 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
aaron-thesis, arm-eh, 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, resolv-new, with_gc
Children:
520145b, e5d4e5c, e6c5e79
Parents:
094476d (diff), 1feb535f (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:
2 added
2 deleted
35 edited

Legend:

Unmodified
Added
Removed
  • doc/bibliography/pl.bib

    r094476d rcaa649b  
    66876687    contributer = {pabuhr@plg},
    66886688    author      = {{TIOBE Index}},
    6689     year        = {March 2017},
     6689    year        = {February 2018},
    66906690    url         = {http://www.tiobe.com/tiobe_index},
    66916691}
  • doc/papers/general/Paper.tex

    r094476d rcaa649b  
    1313\usepackage{pslatex}                                            % reduce size of san serif font
    1414\usepackage[plainpages=false,pdfpagelabels,pdfpagemode=UseNone,pagebackref=true,breaklinks=true,colorlinks=true,linkcolor=blue,citecolor=blue,urlcolor=blue]{hyperref}
     15\urlstyle{sf}
     16\usepackage{breakurl}
    1517
    1618\setlength{\textheight}{9in}
     
    199201The C programming language is a foundational technology for modern computing with millions of lines of code implementing everything from commercial operating-systems to hobby projects.
    200202This installation base and the programmers producing it represent a massive software-engineering investment spanning decades and likely to continue for decades more.
    201 The TIOBE~\cite{TIOBE} ranks the top 5 most popular programming languages as: Java 16\%, \Textbf{C 7\%}, \Textbf{\CC 5\%}, \Csharp 4\%, Python 4\% = 36\%, where the next 50 languages are less than 3\% each with a long tail.
     203The TIOBE~\cite{TIOBE} ranks the top 5 most \emph{popular} programming languages as: Java 15\%, \Textbf{C 12\%}, \Textbf{\CC 5.5\%}, Python 5\%, \Csharp 4.5\% = 42\%, where the next 50 languages are less than 4\% each with a long tail.
    202204The top 3 rankings over the past 30 years are:
    203205\begin{center}
     
    205207\lstDeleteShortInline@%
    206208\begin{tabular}{@{}rccccccc@{}}
    207                 & 2017  & 2012  & 2007  & 2002  & 1997  & 1992  & 1987          \\ \hline
    208 Java    & 1             & 1             & 1             & 1             & 12    & -             & -                     \\
    209 \Textbf{C}      & \Textbf{2}& \Textbf{2}& \Textbf{2}& \Textbf{2}& \Textbf{1}& \Textbf{1}& \Textbf{1}    \\
    210 \CC             & 3             & 3             & 3             & 3             & 2             & 2             & 4                     \\
     209                & 2018  & 2013  & 2008  & 2003  & 1998  & 1993  & 1988  \\ \hline
     210Java    & 1             & 2             & 1             & 1             & 18    & -             & -             \\
     211\Textbf{C}& \Textbf{2} & \Textbf{1} & \Textbf{2} & \Textbf{2} & \Textbf{1} & \Textbf{1} & \Textbf{1} \\
     212\CC             & 3             & 4             & 3             & 3             & 2             & 2             & 5             \\
    211213\end{tabular}
    212214\lstMakeShortInline@%
     
    227229\CFA is currently implemented as a source-to-source translator from \CFA to the gcc-dialect of C~\cite{GCCExtensions}, allowing it to leverage the portability and code optimizations provided by gcc, meeting goals (1)--(3).
    228230Ultimately, a compiler is necessary for advanced features and optimal performance.
    229 
    230 This paper identifies shortcomings in existing approaches to generic and variadic data types in C-like languages and presents a design for generic and variadic types avoiding those shortcomings.
     231All of the features discussed in this paper are working, unless a feature states it is a future feature for completion.
     232
     233
     234\section{Polymorphic Functions}
     235
     236\CFA introduces both ad-hoc and parametric polymorphism to C, with a design originally formalized by Ditchfield~\cite{Ditchfield92}, and first implemented by Bilson~\cite{Bilson03}.
     237Shortcomings are identified in existing approaches to generic and variadic data types in C-like languages and how these shortcomings are avoided in \CFA.
    231238Specifically, the solution is both reusable and type-checked, as well as conforming to the design goals of \CFA with ergonomic use of existing C abstractions.
    232 The new constructs are empirically compared with both standard C and \CC; the results show the new design is comparable in performance.
    233 
    234 \section{Polymorphic Functions}
    235 
    236 \CFA introduces both ad-hoc and parametric polymorphism to C, with a design originally formalized by Ditchfield~\cite{Ditchfield92}, and first implemented by Bilson~\cite{Bilson03}.
     239The new constructs are empirically compared with C and \CC approaches via performance experiments in Section~\ref{sec:eval}.
     240
    237241
    238242\subsection{Name Overloading}
    239 
     243\label{s:NameOverloading}
     244
     245\begin{quote}
     246There are only two hard things in Computer Science: cache invalidation and \emph{naming things} -- Phil Karlton
     247\end{quote}
    240248C already has a limited form of ad-hoc polymorphism in the form of its basic arithmetic operators, which apply to a variety of different types using identical syntax.
    241249\CFA extends the built-in operator overloading by allowing users to define overloads for any function, not just operators, and even any variable;
     
    245253
    246254\begin{cfa}
    247 int max(int a, int b) { return a < b ? b : a; }  // (1)
    248 double max(double a, double b) { return a < b ? b : a; }  // (2)
    249 
    250 int max = INT_MAX;     // (3)
    251 double max = DBL_MAX;  // (4)
    252 
    253 max(7, -max);   $\C{// uses (1) and (3), by matching int from constant 7}$
    254 max(max, 3.14); $\C{// uses (2) and (4), by matching double from constant 3.14}$
    255 
    256 //max(max, -max);  $\C{// ERROR: ambiguous}$
    257 int m = max(max, -max); $\C{// uses (1) once and (3) twice, by matching return type}$
    258 \end{cfa}
    259 
    260 \Celeven did add @_Generic@ expressions, which can be used in preprocessor macros to provide a form of ad-hoc polymorphism; however, this polymorphism is both functionally and ergonomically inferior to \CFA name overloading.
     255int max = 2147483647;                                           $\C[3.75in]{// (1)}$
     256double max = 1.7976931348623157E+308;   $\C{// (2)}$
     257int max( int a, int b ) { return a < b ? b : a; }  $\C{// (3)}$
     258double max( double a, double b ) { return a < b ? b : a; }  $\C{// (4)}\CRT$
     259max( 7, -max );                                                         $\C{// uses (3) and (1), by matching int from constant 7}$
     260max( max, 3.14 );                                                       $\C{// uses (4) and (2), by matching double from constant 3.14}$
     261max( max, -max );                                                       $\C{// ERROR: ambiguous}$
     262int m = max( max, -max );                                       $\C{// uses (3) and (1) twice, by matching return type}$
     263\end{cfa}
     264\CFA maximizes the ability to reuse names to aggressively address the naming problem.
     265In some cases, hundreds of names can be reduced to tens, resulting in a significant cognitive reduction for a programmer.
     266In the above, the name @max@ has a consistent meaning, and a programmer only needs to remember the single concept: maximum.
     267To prevent significant ambiguities, \CFA uses the return type in selecting overloads, \eg in the assignment to @m@, the compiler use @m@'s type to unambiguously select the most appropriate call to function @max@ (as does Ada).
     268As is shown later, there are a number of situations where \CFA takes advantage of available type information to disambiguate, where other programming languages generate ambiguities.
     269
     270\Celeven added @_Generic@ expressions, which can be used in preprocessor macros to provide a form of ad-hoc polymorphism; however, this polymorphism is both functionally and ergonomically inferior to \CFA name overloading.
    261271The macro wrapping the generic expression imposes some limitations; as an example, it could not implement the example above, because the variables @max@ would collide with the functions @max@.
    262272Ergonomic limitations of @_Generic@ include the necessity to put a fixed list of supported types in a single place and manually dispatch to appropriate overloads, as well as possible namespace pollution from the functions dispatched to, which must all have distinct names.
    263 Though name-overloading removes a major use-case for @_Generic@ expressions, \CFA does implement @_Generic@ for backwards-compatibility purposes. \TODO{actually implement that}
     273Though name-overloading removes a major use-case for @_Generic@ expressions, \CFA implements @_Generic@ for backwards-compatibility purposes. \TODO{actually implement that}
    264274
    265275% http://fanf.livejournal.com/144696.html
     
    288298For example, the function @twice@ can be defined using the \CFA syntax for operator overloading:
    289299\begin{cfa}
    290 forall( otype T `| { T ?+?(T, T); }` ) T twice( T x ) { return x + x; } $\C{// ? denotes operands}$
     300forall( otype T `| { T ?+?(T, T); }` ) T twice( T x ) { return x `+` x; }       $\C{// ? denotes operands}$
    291301int val = twice( twice( 3.7 ) );
    292302\end{cfa}
     
    343353\begin{cfa}
    344354forall( otype T | { int ?<?( T, T ); } ) void qsort( const T * arr, size_t size ) { /* use C qsort */ }
    345 {       int ?<?( double x, double y ) { return x `>` y; }       $\C{// locally override behaviour}$
     355{
     356        int ?<?( double x, double y ) { return x `>` y; }       $\C{// locally override behaviour}$
    346357        qsort( vals, size );                                    $\C{// descending sort}$
    347358}
     
    414425\section{Generic Types}
    415426
    416 One of the known shortcomings of standard C is that it does not provide reusable type-safe abstractions for generic data structures and algorithms.
     427A significant shortcoming of standard C is the lack of reusable type-safe abstractions for generic data structures and algorithms.
    417428Broadly speaking, there are three approaches to implement abstract data-structures in C.
    418429One approach is to write bespoke data-structures for each context in which they are needed.
    419430While this approach is flexible and supports integration with the C type-checker and tooling, it is also tedious and error-prone, especially for more complex data structures.
    420 A second approach is to use @void *@--based polymorphism, \eg the C standard-library functions @bsearch@ and @qsort@; an approach which does allow reuse of code for common functionality.
    421 However, basing all polymorphism on @void *@ eliminates the type-checker's ability to ensure that argument types are properly matched, often requiring a number of extra function parameters, pointer indirection, and dynamic allocation that would not otherwise be needed.
     431A second approach is to use @void *@--based polymorphism, \eg the C standard-library functions @bsearch@ and @qsort@, which allows reuse of code with common functionality.
     432However, basing all polymorphism on @void *@ eliminates the type-checker's ability to ensure that argument types are properly matched, often requiring a number of extra function parameters, pointer indirection, and dynamic allocation that is not otherwise needed.
    422433A third approach to generic code is to use preprocessor macros, which does allow the generated code to be both generic and type-checked, but errors may be difficult to interpret.
    423434Furthermore, writing and using preprocessor macros can be unnatural and inflexible.
     
    434445};
    435446forall( otype T ) T value( pair( const char *, T ) p ) { return p.second; }
    436 forall( dtype F, otype T ) T value_p( pair( F *, T * ) p ) { return * p.second; }
     447forall( dtype F, otype T ) T value( pair( F *, T * ) p ) { return *p.second; }
    437448
    438449pair( const char *, int ) p = { "magic", 42 };
    439 int magic = value( p );
     450int i = value( p );
    440451pair( void *, int * ) q = { 0, &p.second };
    441 magic = value_p( q );
     452i = value( q );
    442453double d = 1.0;
    443454pair( double *, double * ) r = { &d, &d };
    444 d = value_p( r );
     455d = value( r );
    445456\end{cfa}
    446457
     
    589600[ double ] foo$\(_2\)$( int );
    590601void bar( int, double, double );
    591 bar( foo( 3 ), foo( 3 ) );
     602`bar`( foo( 3 ), foo( 3 ) );
    592603\end{cfa}
    593604The type-resolver only has the tuple return-types to resolve the call to @bar@ as the @foo@ parameters are identical, which involves unifying the possible @foo@ functions with @bar@'s parameter list.
     
    835846Since @sum@\(_0\) does not accept any arguments, it is not a valid candidate function for the call @sum(10, 20, 30)@.
    836847In order to call @sum@\(_1\), @10@ is matched with @x@, and the argument resolution moves on to the argument pack @rest@, which consumes the remainder of the argument list and @Params@ is bound to @[20, 30]@.
    837 The process continues unitl @Params@ is bound to @[]@, requiring an assertion @int sum()@, which matches @sum@\(_0\) and terminates the recursion.
     848The process continues until @Params@ is bound to @[]@, requiring an assertion @int sum()@, which matches @sum@\(_0\) and terminates the recursion.
    838849Effectively, this algorithm traces as @sum(10, 20, 30)@ $\rightarrow$ @10 + sum(20, 30)@ $\rightarrow$ @10 + (20 + sum(30))@ $\rightarrow$ @10 + (20 + (30 + sum()))@ $\rightarrow$ @10 + (20 + (30 + 0))@.
    839850
     
    979990\section{Control Structures}
    980991
    981 \CFA identifies missing and problematic control structures in C, and extends and modifies these control structures to increase functionality and safety.
     992\CFA identifies inconsistent, problematic, and missing control structures in C, and extends, modifies, and adds to control structures to increase functionality and safety.
     993
     994
     995\subsection{\texorpdfstring{\LstKeywordStyle{if} Statement}{if Statement}}
     996
     997The @if@ expression allows declarations, similar to @for@ declaration expression:
     998\begin{cfa}
     999if ( int x = f() ) ...                                          $\C{// x != 0}$
     1000if ( int x = f(), y = g() ) ...                         $\C{// x != 0 \&\& y != 0}$
     1001if ( int x = f(), y = g(); `x < y` ) ...        $\C{// relational expression}$
     1002\end{cfa}
     1003Unless a relational expression is specified, each variable is compared not equal to 0, which is the standard semantics for the @if@ expression, and the results are combined using the logical @&&@ operator.\footnote{\CC only provides a single declaration always compared not equal to 0.}
     1004The scope of the declaration(s) is local to the @if@ statement but exist within both the ``then'' and ``else'' clauses.
     1005
     1006
     1007\subsection{\texorpdfstring{\LstKeywordStyle{switch} Statement}{switch Statement}}
     1008
     1009There are a number of deficiencies with the C @switch@ statements: enumerating @case@ lists, placement of @case@ clauses, scope of the switch body, and fall through between case clauses.
     1010
     1011C has no shorthand for specifying a list of case values, whether the list is non-contiguous or contiguous\footnote{C provides this mechanism via fall through.}.
     1012\CFA provides a shorthand for a non-contiguous list:
     1013\begin{cquote}
     1014\lstDeleteShortInline@%
     1015\begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
     1016\multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
     1017\begin{cfa}
     1018case 2, 10, 34, 42:
     1019\end{cfa}
     1020&
     1021\begin{cfa}
     1022case 2: case 10: case 34: case 42:
     1023\end{cfa}
     1024\end{tabular}
     1025\lstMakeShortInline@%
     1026\end{cquote}
     1027for a contiguous list:\footnote{gcc provides the same mechanism with awkward syntax, \lstinline@2 ... 42@, where spaces are required around the ellipse.}
     1028\begin{cquote}
     1029\lstDeleteShortInline@%
     1030\begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
     1031\multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
     1032\begin{cfa}
     1033case 2~42:
     1034\end{cfa}
     1035&
     1036\begin{cfa}
     1037case 2: case 3: ... case 41: case 42:
     1038\end{cfa}
     1039\end{tabular}
     1040\lstMakeShortInline@%
     1041\end{cquote}
     1042and a combination:
     1043\begin{cfa}
     1044case -12~-4, -1~5, 14~21, 34~42:
     1045\end{cfa}
     1046
     1047C allows placement of @case@ clauses \emph{within} statements nested in the @switch@ body (see Duff's device~\cite{Duff83});
     1048\begin{cfa}
     1049switch ( i ) {
     1050  case 0:
     1051        for ( int i = 0; i < 10; i += 1 ) {
     1052                ...
     1053  `case 1:`             // no initialization of loop index
     1054                ...
     1055        }
     1056}
     1057\end{cfa}
     1058\CFA precludes this form of transfer into a control structure because it causes undefined behaviour, especially with respect to missed initialization, and provides very limited functionality.
     1059
     1060C allows placement of declaration within the @switch@ body and unreachable code at the start, resulting in undefined behaviour:
     1061\begin{cfa}
     1062switch ( x ) {
     1063        `int y = 1;`                                                    $\C{// unreachable initialization}$
     1064        `x = 7;`                                                                $\C{// unreachable code without label/branch}$
     1065  case 0:
     1066        ...
     1067        `int z = 0;`                                                    $\C{// unreachable initialization, cannot appear after case}$
     1068        z = 2;
     1069  case 1:
     1070        `x = z;`                                                                $\C{// without fall through, z is undefined}$
     1071}
     1072\end{cfa}
     1073\CFA allows the declaration of local variables, \eg @y@, at the start of the @switch@ with scope across the entire @switch@ body, \ie all @case@ clauses.
     1074\CFA disallows the declaration of local variable, \eg @z@, directly within the @switch@ body, because a declaration cannot occur immediately after a @case@ since a label can only be attached to a statement, and the use of @z@ is undefined in @case 1@ as neither storage allocation nor initialization may have occurred.
     1075
     1076C @switch@ provides multiple entry points into the statement body, but once an entry point is selected, control continues across \emph{all} @case@ clauses until the end of the @switch@ body, called \newterm{fall through};
     1077@case@ clauses are made disjoint by the @break@ statement.
     1078While the ability to fall through \emph{is} a useful form of control flow, it does not match well with programmer intuition, resulting in many errors from missing @break@ statements.
     1079For backwards compatibility, \CFA provides a \emph{new} control structure, @choose@, which mimics @switch@, but reverses the meaning of fall through (see Figure~\ref{f:ChooseSwitchStatements}).
     1080Collectively, these enhancements reduce programmer burden and increase readability and safety.
     1081
     1082\begin{figure}
     1083\centering
     1084\lstDeleteShortInline@%
     1085\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
     1086\multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     1087\begin{cfa}
     1088`choose` ( day ) {
     1089  case Mon~Thu:  // program
     1090
     1091  case Fri:  // program
     1092        wallet += pay;
     1093        `fallthrough;`
     1094  case Sat:  // party
     1095        wallet -= party;
     1096
     1097  case Sun:  // rest
     1098
     1099  default:  // error
     1100}
     1101\end{cfa}
     1102&
     1103\begin{cfa}
     1104switch ( day ) {
     1105  case Mon: case Tue: case Wed: case Thu:  // program
     1106        `break;`
     1107  case Fri:  // program
     1108        wallet += pay;
     1109
     1110  case Sat:  // party
     1111        wallet -= party;
     1112        `break;`
     1113  case Sun:  // rest
     1114        `break;`
     1115  default:  // error
     1116}
     1117\end{cfa}
     1118\end{tabular}
     1119\lstMakeShortInline@%
     1120\caption{\lstinline|choose| versus \lstinline|switch| Statements}
     1121\label{f:ChooseSwitchStatements}
     1122\end{figure}
     1123
     1124\begin{comment}
     1125Forgotten @break@ statements at the end of @switch@ cases are a persistent sort of programmer error in C, and the @break@ statements themselves introduce visual clutter and an un-C-like keyword-based block delimiter.
     1126\CFA addresses this error by introducing a @choose@ statement, which works identically to a @switch@ except that its default end-of-case behaviour is to break rather than to fall through for all non-empty cases.
     1127Since empty cases like @case 7:@ in @case 7: case 11:@ still have fall-through semantics and explicit @break@ is still allowed at the end of a @choose@ case, many idiomatic uses of @switch@ in standard C can be converted to @choose@ statements by simply changing the keyword.
     1128Where fall-through is desired for a non-empty case, it can be specified with the new @fallthrough@ statement, making @choose@ equivalently powerful to @switch@, but more concise in the common case where most non-empty cases end with a @break@ statement, as in the example below:
     1129
     1130\begin{cfa}
     1131choose( i ) {
     1132        case 2:
     1133                printf("even ");
     1134                fallthrough;
     1135        case 3: case 5: case 7:
     1136                printf("small prime\n");
     1137        case 4,6,8,9:
     1138                printf("small composite\n");
     1139        case 13~19:
     1140                printf("teen\n");
     1141        default:
     1142                printf("something else\n");
     1143}
     1144\end{cfa}
     1145\end{comment}
    9821146
    9831147
     
    10391203                } else {
    10401204                        ... goto `LIF`; ...
    1041                 } `L3:` ;
     1205                } `LIF:` ;
    10421206        } `LS:` ;
    10431207} `LC:` ;
     
    10891253
    10901254
    1091 \subsection{\texorpdfstring{Enhanced \LstKeywordStyle{switch} Statement}{Enhanced switch Statement}}
    1092 
    1093 There are a number of deficiencies with the C @switch@ statements: enumerating @case@ lists, placement of @case@ clauses, scope of the switch body, and fall through between case clauses.
    1094 
    1095 C has no shorthand for specifying a list of case values, whether the list is non-contiguous or contiguous\footnote{C provides this mechanism via fall through.}.
    1096 \CFA provides a shorthand for a non-contiguous list:
     1255\subsection{Exception Handling}
     1256
     1257The following framework for \CFA exception handling is in place, excluding a run-time type information and dynamic casts.
     1258\CFA provides two forms of exception handling: \newterm{fix-up} and \newterm{recovery} (see Figure~\ref{f:CFAExceptionHandling}).
     1259Both mechanisms provide dynamic call to a handler using dynamic name-lookup, where fix-up has dynamic return and recovery has static return from the handler.
     1260\CFA restricts exception types to those defined by aggregate type @exception@.
     1261The form of the raise dictates the set of handlers examined during propagation: \newterm{resumption propagation} (@resume@) only examines resumption handlers (@catchResume@); \newterm{terminating propagation} (@throw@) only examines termination handlers (@catch@).
     1262If @resume@ or @throw@ have no exception type, it is a reresume/rethrow, meaning the currently exception continues propagation.
     1263If there is no current exception, the reresume/rethrow results in a runtime error.
     1264
     1265\begin{figure}
    10971266\begin{cquote}
    10981267\lstDeleteShortInline@%
    1099 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    1100 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
    1101 \begin{cfa}
    1102 case 2, 10, 34, 42:
    1103 \end{cfa}
    1104 &
    1105 \begin{cfa}
    1106 case 2: case 10: case 34: case 42:
     1268\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
     1269\multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{Resumption}}      & \multicolumn{1}{c}{\textbf{Termination}}      \\
     1270\begin{cfa}
     1271`exception R { int fix; };`
     1272void f() {
     1273        R r;
     1274        ... `resume( r );` ...
     1275        ... r.fix // control does return here after handler
     1276}
     1277`try` {
     1278        ... f(); ...
     1279} `catchResume( R r )` {
     1280        ... r.fix = ...; // return correction to raise
     1281} // dynamic return to _Resume
     1282\end{cfa}
     1283&
     1284\begin{cfa}
     1285`exception T {};`
     1286void f() {
     1287
     1288        ... `throw( T{} );` ...
     1289        // control does NOT return here after handler
     1290}
     1291`try` {
     1292        ... f(); ...
     1293} `catch( T t )` {
     1294        ... // recover and continue
     1295} // static return to next statement
    11071296\end{cfa}
    11081297\end{tabular}
    11091298\lstMakeShortInline@%
    11101299\end{cquote}
    1111 for a contiguous list:\footnote{gcc provides the same mechanism with awkward syntax, \lstinline@2 ... 42@, where spaces are required around the ellipse.}
     1300\caption{\CFA Exception Handling}
     1301\label{f:CFAExceptionHandling}
     1302\end{figure}
     1303
     1304The set of exception types in a list of catch clause may include both a resumption and termination handler:
     1305\begin{cfa}
     1306try {
     1307        ... resume( `R{}` ); ...
     1308} catchResume( `R` r ) { ... throw( R{} ); ... } $\C{\color{red}// H1}$
     1309   catch( `R` r ) { ... }                                       $\C{\color{red}// H2}$
     1310
     1311\end{cfa}
     1312The resumption propagation raises @R@ and the stack is not unwound;
     1313the exception is caught by the @catchResume@ clause and handler H1 is invoked.
     1314The termination propagation in handler H1 raises @R@ and the stack is unwound;
     1315the exception is caught by the @catch@ clause and handler H2 is invoked.
     1316The termination handler is available because the resumption propagation did not unwind the stack.
     1317
     1318An additional feature is conditional matching in a catch clause:
     1319\begin{cfa}
     1320try {
     1321        ... write( `datafile`, ... ); ...               $\C{// may throw IOError}$
     1322        ... write( `logfile`, ... ); ...
     1323} catch ( IOError err; `err.file == datafile` ) { ... } $\C{// handle datafile error}$
     1324   catch ( IOError err; `err.file == logfile` ) { ... } $\C{// handle logfile error}$
     1325   catch ( IOError err ) { ... }                        $\C{// handler error from other files}$
     1326\end{cfa}
     1327where the throw inserts the failing file-handle in the I/O exception.
     1328Conditional catch cannot be trivially mimicked by other mechanisms because once an exception is caught, handler clauses in that @try@ statement are no longer eligible..
     1329
     1330The resumption raise can specify an alternate stack on which to raise an exception, called a \newterm{nonlocal raise}:
     1331\begin{cfa}
     1332resume( $\emph{exception-type}$, $\emph{alternate-stack}$ )
     1333resume( $\emph{alternate-stack}$ )
     1334\end{cfa}
     1335These overloads of @resume@ raise the specified exception or the currently propagating exception (reresume) at another coroutine or task~\cite{Delisle18}.
     1336Nonlocal raise is restricted to resumption to provide the exception handler the greatest flexibility because processing the exception does not unwind its stack, allowing it to continue after the handle returns.
     1337
     1338To facilitate nonlocal exception, \CFA provides dynamic enabling and disabling of nonlocal exception-propagation.
     1339The constructs for controlling propagation of nonlocal exceptions are the @enable@ and the @disable@ blocks:
    11121340\begin{cquote}
    11131341\lstDeleteShortInline@%
    1114 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    1115 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
    1116 \begin{cfa}
    1117 case 2~42:
    1118 \end{cfa}
    1119 &
    1120 \begin{cfa}
    1121 case 2: case 3: ... case 41: case 42:
     1342\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
     1343\begin{cfa}
     1344enable $\emph{exception-type-list}$ {
     1345        // allow non-local resumption
     1346}
     1347\end{cfa}
     1348&
     1349\begin{cfa}
     1350disable $\emph{exception-type-list}$ {
     1351        // disallow non-local resumption
     1352}
    11221353\end{cfa}
    11231354\end{tabular}
    11241355\lstMakeShortInline@%
    11251356\end{cquote}
    1126 and a combination:
    1127 \begin{cfa}
    1128 case -12~-4, -1~5, 14~21, 34~42:
    1129 \end{cfa}
    1130 
    1131 C allows placement of @case@ clauses \emph{within} statements nested in the @switch@ body (see Duff's device~\cite{Duff83});
    1132 \begin{cfa}
    1133 switch ( i ) {
    1134   case 0:
    1135         for ( int i = 0; i < 10; i += 1 ) {
    1136                 ...
    1137   `case 1:`             // no initialization of loop index
    1138                 ...
    1139         }
    1140 }
    1141 \end{cfa}
    1142 \CFA precludes this form of transfer into a control structure because it causes undefined behaviour, especially with respect to missed initialization, and provides very limited functionality.
    1143 
    1144 C allows placement of declaration within the @switch@ body and unreachable code at the start, resulting in undefined behaviour:
    1145 \begin{cfa}
    1146 switch ( x ) {
    1147         `int y = 1;`                            $\C{// unreachable initialization}$
    1148         `x = 7;`                                        $\C{// unreachable code without label/branch}$
    1149   case 0:
    1150         ...
    1151         `int z = 0;`                            $\C{// unreachable initialization, cannot appear after case}$
    1152         z = 2;
    1153   case 1:
    1154         `x = z;`                                        $\C{// without fall through, z is undefined}$
    1155 }
    1156 \end{cfa}
    1157 \CFA allows the declaration of local variables, \eg @y@, at the start of the @switch@ with scope across the entire @switch@ body, \ie all @case@ clauses.
    1158 \CFA disallows the declaration of local variable, \eg @z@, directly within the @switch@ body, because a declaration cannot occur immediately after a @case@ since a label can only be attached to a statement, and the use of @z@ is undefined in @case 1@ as neither storage allocation nor initialization may have occurred.
    1159 
    1160 C @switch@ provides multiple entry points into the statement body, but once an entry point is selected, control continues across \emph{all} @case@ clauses until the end of the @switch@ body, called \newterm{fall through};
    1161 @case@ clauses are made disjoint by the @break@ statement.
    1162 While the ability to fall through \emph{is} a useful form of control flow, it does not match well with programmer intuition, resulting in many errors from missing @break@ statements.
    1163 For backwards compatibility, \CFA provides a \emph{new} control structure, @choose@, which mimics @switch@, but reverses the meaning of fall through:
    1164 \begin{cquote}
    1165 \lstDeleteShortInline@%
    1166 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    1167 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
    1168 \begin{cfa}
    1169 `choose` ( day ) {
    1170   case Mon~Thu:  // program
    1171 
    1172   case Fri:  // program
    1173         wallet += pay;
    1174         `fallthrough;`
    1175   case Sat:  // party
    1176         wallet -= party;
    1177 
    1178   case Sun:  // rest
    1179 
    1180   default:  // error
    1181 }
    1182 \end{cfa}
    1183 &
    1184 \begin{cfa}
    1185 switch ( day ) {
    1186   case Mon: case Tue: case Wed: case Thu:  // program
    1187         `break;`
    1188   case Fri:  // program
    1189         wallet += pay;
    1190 
    1191   case Sat:  // party
    1192         wallet -= party;
    1193         `break;`
    1194   case Sun:  // rest
    1195         `break;`
    1196   default:  // error
    1197 }
    1198 \end{cfa}
    1199 \end{tabular}
    1200 \lstMakeShortInline@%
    1201 \end{cquote}
    1202 Collectively, these enhancements reduce programmer burden and increase readability and safety.
    1203 
    1204 \begin{comment}
    1205 Forgotten @break@ statements at the end of @switch@ cases are a persistent sort of programmer error in C, and the @break@ statements themselves introduce visual clutter and an un-C-like keyword-based block delimiter.
    1206 \CFA addresses this error by introducing a @choose@ statement, which works identically to a @switch@ except that its default end-of-case behaviour is to break rather than to fall through for all non-empty cases.
    1207 Since empty cases like @case 7:@ in @case 7: case 11:@ still have fall-through semantics and explicit @break@ is still allowed at the end of a @choose@ case, many idiomatic uses of @switch@ in standard C can be converted to @choose@ statements by simply changing the keyword.
    1208 Where fall-through is desired for a non-empty case, it can be specified with the new @fallthrough@ statement, making @choose@ equivalently powerful to @switch@, but more concise in the common case where most non-empty cases end with a @break@ statement, as in the example below:
    1209 
    1210 \begin{cfa}
    1211 choose( i ) {
    1212         case 2:
    1213                 printf("even ");
    1214                 fallthrough;
    1215         case 3: case 5: case 7:
    1216                 printf("small prime\n");
    1217         case 4,6,8,9:
    1218                 printf("small composite\n");
    1219         case 13~19:
    1220                 printf("teen\n");
    1221         default:
    1222                 printf("something else\n");
    1223 }
    1224 \end{cfa}
    1225 \end{comment}
     1357The arguments for @enable@/@disable@ specify the exception types allowed to be propagated or postponed, respectively.
     1358Specifying no exception type is shorthand for specifying all exception types.
     1359Both @enable@ and @disable@ blocks can be nested, turning propagation on/off on entry, and on exit, the specified exception types are restored to their prior state.
     1360
     1361Finally, \CFA provides a Java like  @finally@ clause after the catch clauses:
     1362\begin{cfa}
     1363try {
     1364        ... f(); ...
     1365// catchResume or catch clauses
     1366} `finally` {
     1367        // house keeping
     1368}
     1369\end{cfa}
     1370The finally clause is always executed, i.e., if the try block ends normally or if an exception is raised.
     1371If an exception is raised and caught, the handler is run before the finally clause.
     1372Like a destructor (see Section~\ref{s:ConstructorsDestructors}), a finally clause can raise an exception but not if there is an exception being propagated.
     1373Mimicking the @finally@ clause with mechanisms like RAII is non-trivially when there are multiple types and local accesses.
    12261374
    12271375
     
    12381386S s, as[10];
    12391387\end{cfa}
    1240 However, routines manipulating aggregates must repeat the aggregate name to access its containing fields:
     1388However, functions manipulating aggregates must repeat the aggregate name to access its containing fields:
    12411389\begin{cfa}
    12421390void f( S s ) {
     
    12561404}
    12571405\end{C++}
    1258 Object-oriented nesting of member routines in a \lstinline[language=C++]@class@ allows eliding \lstinline[language=C++]@this->@ because of lexical scoping.
     1406Object-oriented nesting of member functions in a \lstinline[language=C++]@class@ allows eliding \lstinline[language=C++]@this->@ because of lexical scoping.
    12591407However, for other aggregate parameters, qualification is necessary:
    12601408\begin{cfa}
     
    12861434        'with' '(' $\emph{expression-list}$ ')' $\emph{compound-statement}$
    12871435\end{cfa}
    1288 and may appear as the body of a routine or nested within a routine body.
     1436and may appear as the body of a function or nested within a function body.
    12891437Each expression in the expression-list provides a type and object.
    12901438The type must be an aggregate type.
     
    13131461Qualification or a cast is used to disambiguate.
    13141462
    1315 There is an interesting problem between parameters and the routine @with@, \eg:
     1463There is an interesting problem between parameters and the function @with@, \eg:
    13161464\begin{cfa}
    13171465void ?{}( S & s, int i ) with ( s ) {           $\C{// constructor}$
     
    13191467}
    13201468\end{cfa}
    1321 Here, the assignment @s.i = i@ means @s.i = s.i@, which is meaningless, and there is no mechanism to qualify the parameter @i@, making the assignment impossible using the routine @with@.
     1469Here, the assignment @s.i = i@ means @s.i = s.i@, which is meaningless, and there is no mechanism to qualify the parameter @i@, making the assignment impossible using the function @with@.
    13221470To solve this problem, parameters are treated like an initialized aggregate:
    13231471\begin{cfa}
     
    13271475} params;
    13281476\end{cfa}
    1329 and implicitly opened \emph{after} a routine open, to give them higher priority:
     1477and implicitly opened \emph{after} a function open, to give them higher priority:
    13301478\begin{cfa}
    13311479void ?{}( S & s, int i ) with ( s ) `with( $\emph{\color{red}params}$ )` {
     
    13551503
    13561504
    1357 \subsection{Exception Handling}
    1358 
    1359 The following framework for \CFA exception handling is in place, excluding a run-time type information and dynamic casts.
    1360 \CFA provides two forms of exception handling: \newterm{fix-up} and \newterm{recovery} (see Figure~\ref{f:CFAExceptionHandling}).
    1361 Both mechanisms provide dynamic call to a handler using dynamic name-lookup, where fix-up has dynamic return and recovery has static return from the handler.
    1362 \CFA restricts exception types to those defined by aggregate type @exception@.
    1363 The form of the raise dictates the set of handlers examined during propagation: \newterm{resumption propagation} (@resume@) only examines resumption handlers (@catchResume@); \newterm{terminating propagation} (@throw@) only examines termination handlers (@catch@).
    1364 If @resume@ or @throw@ have no exception type, it is a reresume/rethrow, meaning the currently exception continues propagation.
    1365 If there is no current exception, the reresume/rethrow results in a runtime error.
    1366 
    1367 \begin{figure}
    1368 \begin{cquote}
    1369 \lstDeleteShortInline@%
    1370 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    1371 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{Resumption}}       & \multicolumn{1}{c}{\textbf{Recovery}} \\
    1372 \begin{cfa}
    1373 `exception R { int fix; };`
    1374 void f() {
    1375         R r;
    1376         ... `resume( r );` ...
    1377         ... r.fix // control does return here after handler
    1378 }
    1379 `try` {
    1380         ... f(); ...
    1381 } `catchResume( R r )` {
    1382         ... r.fix = ...; // return correction to raise
    1383 } // dynamic return to _Resume
    1384 \end{cfa}
    1385 &
    1386 \begin{cfa}
    1387 `exception T {};`
    1388 void f() {
    1389 
    1390         ... `throw( T{} );` ...
    1391         // control does NOT return here after handler
    1392 }
    1393 `try` {
    1394         ... f(); ...
    1395 } `catch( T t )` {
    1396         ... // recover and continue
    1397 } // static return to next statement
    1398 \end{cfa}
    1399 \end{tabular}
    1400 \lstMakeShortInline@%
    1401 \end{cquote}
    1402 \caption{\CFA Exception Handling}
    1403 \label{f:CFAExceptionHandling}
    1404 \end{figure}
    1405 
    1406 The set of exception types in a list of catch clause may include both a resumption and termination handler:
    1407 \begin{cfa}
    1408 try {
    1409         ... resume( `R{}` ); ...
    1410 } catchResume( `R` r ) { ... throw( R{} ); ... } $\C{\color{red}// H1}$
    1411    catch( `R` r ) { ... }                                       $\C{\color{red}// H2}$
    1412 
    1413 \end{cfa}
    1414 The resumption propagation raises @R@ and the stack is not unwound;
    1415 the exception is caught by the @catchResume@ clause and handler H1 is invoked.
    1416 The termination propagation in handler H1 raises @R@ and the stack is unwound;
    1417 the exception is caught by the @catch@ clause and handler H2 is invoked.
    1418 The termination handler is available because the resumption propagation did not unwind the stack.
    1419 
    1420 An additional feature is conditional matching in a catch clause:
    1421 \begin{cfa}
    1422 try {
    1423         ... write( `datafile`, ... ); ...               $\C{// may throw IOError}$
    1424         ... write( `logfile`, ... ); ...
    1425 } catch ( IOError err; `err.file == datafile` ) { ... } $\C{// handle datafile error}$
    1426    catch ( IOError err; `err.file == logfile` ) { ... } $\C{// handle logfile error}$
    1427    catch ( IOError err ) { ... }                        $\C{// handler error from other files}$
    1428 \end{cfa}
    1429 where the throw inserts the failing file-handle in the I/O exception.
    1430 Conditional catch cannot be trivially mimicked by other mechanisms because once an exception is caught, handler clauses in that @try@ statement are no longer eligible..
    1431 
    1432 The resumption raise can specify an alternate stack on which to raise an exception, called a \newterm{nonlocal raise}:
    1433 \begin{cfa}
    1434 resume( $\emph{exception-type}$, $\emph{alternate-stack}$ )
    1435 resume( $\emph{alternate-stack}$ )
    1436 \end{cfa}
    1437 These overloads of @resume@ raise the specified exception or the currently propagating exception (reresume) at another coroutine or task~\cite{Delisle18}.
    1438 Nonlocal raise is restricted to resumption to provide the exception handler the greatest flexibility because processing the exception does not unwind its stack, allowing it to continue after the handle returns.
    1439 
    1440 To facilitate nonlocal exception, \CFA provides dynamic enabling and disabling of nonlocal exception-propagation.
    1441 The constructs for controlling propagation of nonlocal exceptions are the @enable@ and the @disable@ blocks:
    1442 \begin{cquote}
    1443 \lstDeleteShortInline@%
    1444 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    1445 \begin{cfa}
    1446 enable $\emph{exception-type-list}$ {
    1447         // allow non-local resumption
    1448 }
    1449 \end{cfa}
    1450 &
    1451 \begin{cfa}
    1452 disable $\emph{exception-type-list}$ {
    1453         // disallow non-local resumption
    1454 }
    1455 \end{cfa}
    1456 \end{tabular}
    1457 \lstMakeShortInline@%
    1458 \end{cquote}
    1459 The arguments for @enable@/@disable@ specify the exception types allowed to be propagated or postponed, respectively.
    1460 Specifying no exception type is shorthand for specifying all exception types.
    1461 Both @enable@ and @disable@ blocks can be nested, turning propagation on/off on entry, and on exit, the specified exception types are restored to their prior state.
    1462 
    1463 Finally, \CFA provides a Java like  @finally@ clause after the catch clauses:
    1464 \begin{cfa}
    1465 try {
    1466         ... f(); ...
    1467 // catchResume or catch clauses
    1468 } `finally` {
    1469         // house keeping
    1470 }
    1471 \end{cfa}
    1472 The finally clause is always executed, i.e., if the try block ends normally or if an exception is raised.
    1473 If an exception is raised and caught, the handler is run before the finally clause.
    1474 Like a destructor (see Section~\ref{s:ConstructorsDestructors}), a finally clause can raise an exception but not if there is an exception being propagated.
    1475 Mimicking the @finally@ clause with mechanisms like RAII is non-trivially when there are multiple types and local accesses.
    1476 
    1477 
    14781505\section{Declarations}
    14791506
     
    15031530Is this an array of 5 pointers to integers or a pointer to an array of 5 integers?
    15041531If there is any doubt, it implies productivity and safety issues even for basic programs.
    1505 Another example of confusion results from the fact that a routine name and its parameters are embedded within the return type, mimicking the way the return value is used at the routine's call site.
    1506 For example, a routine returning a pointer to an array of integers is defined and used in the following way:
     1532Another example of confusion results from the fact that a function name and its parameters are embedded within the return type, mimicking the way the return value is used at the function's call site.
     1533For example, a function returning a pointer to an array of integers is defined and used in the following way:
    15071534\begin{cfa}
    15081535int `(*`f`())[`5`]` {...};                                      $\C{// definition}$
    15091536 ... `(*`f`())[`3`]` += 1;                                      $\C{// usage}$
    15101537\end{cfa}
    1511 Essentially, the return type is wrapped around the routine name in successive layers (like an onion).
     1538Essentially, the return type is wrapped around the function name in successive layers (like an onion).
    15121539While attempting to make the two contexts consistent is a laudable goal, it has not worked out in practice.
    15131540
    1514 \CFA provides its own type, variable and routine declarations, using a different syntax.
     1541\CFA provides its own type, variable and function declarations, using a different syntax.
    15151542The new declarations place qualifiers to the left of the base type, while C declarations place qualifiers to the right.
    15161543The qualifiers have the same meaning but are ordered left to right to specify a variable's type.
     
    15401567\end{cquote}
    15411568The only exception is bit field specification, which always appear to the right of the base type.
    1542 % Specifically, the character @*@ is used to indicate a pointer, square brackets @[@\,@]@ are used to represent an array or function return value, and parentheses @()@ are used to indicate a routine parameter.
     1569% Specifically, the character @*@ is used to indicate a pointer, square brackets @[@\,@]@ are used to represent an array or function return value, and parentheses @()@ are used to indicate a function parameter.
    15431570However, unlike C, \CFA type declaration tokens are distributed across all variables in the declaration list.
    15441571For instance, variables @x@ and @y@ of type pointer to integer are defined in \CFA as follows:
     
    16261653\lstMakeShortInline@%
    16271654\end{cquote}
    1628 Specifiers must appear at the start of a \CFA routine declaration\footnote{\label{StorageClassSpecifier}
     1655Specifiers must appear at the start of a \CFA function declaration\footnote{\label{StorageClassSpecifier}
    16291656The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature.~\cite[\S~6.11.5(1)]{C11}}.
    16301657
    1631 The new declaration syntax can be used in other contexts where types are required, \eg casts and the pseudo-routine @sizeof@:
     1658The new declaration syntax can be used in other contexts where types are required, \eg casts and the pseudo-function @sizeof@:
    16321659\begin{cquote}
    16331660\lstDeleteShortInline@%
     
    16471674\end{cquote}
    16481675
    1649 The syntax of the new routine prototype declaration follows directly from the new routine definition syntax;
     1676The syntax of the new function-prototype declaration follows directly from the new function-definition syntax;
    16501677as well, parameter names are optional, \eg:
    16511678\begin{cfa}
     
    16561683[ * int, int ] j ( int );                                       $\C{// returning pointer to int and int, with int parameter}$
    16571684\end{cfa}
    1658 This syntax allows a prototype declaration to be created by cutting and pasting source text from the routine definition header (or vice versa).
    1659 Like 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, \eg:
     1685This syntax allows a prototype declaration to be created by cutting and pasting source text from the function-definition header (or vice versa).
     1686Like C, it is possible to declare multiple function-prototypes in a single declaration, where the return type is distributed across \emph{all} function names in the declaration list, \eg:
    16601687\begin{cquote}
    16611688\lstDeleteShortInline@%
     
    16721699\lstMakeShortInline@%
    16731700\end{cquote}
    1674 where \CFA allows the last routine in the list to define its body.
    1675 
    1676 The syntax for pointers to \CFA routines specifies the pointer name on the right, \eg:
    1677 \begin{cfa}
    1678 * [ int x ] () fp;                                                      $\C{// pointer to routine returning int with no parameters}$
    1679 * [ * int ] ( int y ) gp;                                       $\C{// pointer to routine returning pointer to int with int parameter}$
    1680 * [ ] ( int, char ) hp;                                         $\C{// pointer to routine returning no result with int and char parameters}$
    1681 * [ * int, int ] ( int ) jp;                            $\C{// pointer to routine returning pointer to int and int, with int parameter}$
    1682 \end{cfa}
    1683 Note, a routine name cannot be specified:
    1684 \begin{cfa}
    1685 * [ int x ] f () fp;                                            $\C{// routine name "f" is disallowed}$
     1701where \CFA allows the last function in the list to define its body.
     1702
     1703The syntax for pointers to \CFA functions specifies the pointer name on the right, \eg:
     1704\begin{cfa}
     1705* [ int x ] () fp;                                                      $\C{// pointer to function returning int with no parameters}$
     1706* [ * int ] ( int y ) gp;                                       $\C{// pointer to function returning pointer to int with int parameter}$
     1707* [ ] ( int, char ) hp;                                         $\C{// pointer to function returning no result with int and char parameters}$
     1708* [ * int, int ] ( int ) jp;                            $\C{// pointer to function returning pointer to int and int, with int parameter}$
     1709\end{cfa}
     1710Note, a function name cannot be specified:
     1711\begin{cfa}
     1712* [ int x ] f () fp;                                            $\C{// function name "f" is disallowed}$
    16861713\end{cfa}
    16871714
     
    19031930Destruction parameters are useful for specifying storage-management actions, such as de-initialize but not deallocate.}.
    19041931\begin{cfa}
    1905 struct VLA {
    1906         int len, * data;
    1907 };
    1908 void ?{}( VLA & vla ) with ( vla ) {            $\C{// default constructor}$
    1909         len = 10;  data = alloc( len );                 $\C{// shallow copy}$
    1910 }
    1911 void ^?{}( VLA & vla ) with ( vla ) {           $\C{// destructor}$
    1912         free( data );
    1913 }
     1932struct VLA { int len, * data; };
     1933void ?{}( VLA & vla ) with ( vla ) { len = 10;  data = alloc( len ); }  $\C{// default constructor}$
     1934void ^?{}( VLA & vla ) with ( vla ) { free( data ); } $\C{// destructor}$
    19141935{
    19151936        VLA x;                                                                  $\C{// implicit:  ?\{\}( x );}$
    19161937}                                                                                       $\C{// implicit:  ?\^{}\{\}( x );}$
    19171938\end{cfa}
    1918 (Note, the example is purposely kept simple by using shallow-copy semantics.)
    19191939@VLA@ is a \newterm{managed type}\footnote{
    19201940A managed type affects the runtime environment versus a self-contained type.}: a type requiring a non-trivial constructor or destructor, or with a field of a managed type.
     
    19241944\CFA also provides syntax for \newterm{initialization} and \newterm{copy}:
    19251945\begin{cfa}
    1926 void ?{}( VLA & vla, int size, char fill ) with ( vla ) {       $\C{// initialization}$
     1946void ?{}( VLA & vla, int size, char fill ) with ( vla ) {  $\C{// initialization}$
    19271947        len = size;  data = alloc( len, fill );
    19281948}
    1929 void ?{}( VLA & vla, VLA other ) {                      $\C{// copy}$
     1949void ?{}( VLA & vla, VLA other ) {                      $\C{// copy, shallow}$
    19301950        vla.len = other.len;  vla.data = other.data;
    19311951}
    19321952\end{cfa}
     1953(Note, the example is purposely kept simple by using shallow-copy semantics.)
    19331954An initialization constructor-call has the same syntax as a C initializer, except the initialization values are passed as arguments to a matching constructor (number and type of paremeters).
    19341955\begin{cfa}
     
    19441965\begin{cfa}
    19451966{
    1946         VLA x,  y = { 20, 0x01 },  z = y;
    1947         // implicit:  ?{}( x );  ?{}( y, 20, 0x01 );  ?{}( z, y ); z points to y
     1967        VLA  x,            y = { 20, 0x01 },     z = y; $\C{// z points to y}$
     1968        //      ?{}( x );  ?{}( y, 20, 0x01 );  ?{}( z, y );
    19481969        ^x{};                                                                   $\C{// deallocate x}$
    19491970        x{};                                                                    $\C{// reallocate x}$
     
    19521973        y{ x };                                                                 $\C{// reallocate y, points to x}$
    19531974        x{};                                                                    $\C{// reallocate x, not pointing to y}$
    1954         // implicit:  ^?{}(z);  ^?{}(y);  ^?{}(x);
     1975        // ^?{}(z);  ^?{}(y);  ^?{}(x);
    19551976}
    19561977\end{cfa}
     
    19832004C already includes limited polymorphism for literals -- @0@ can be either an integer or a pointer literal, depending on context, while the syntactic forms of literals of the various integer and float types are very similar, differing from each other only in suffix.
    19842005In keeping with the general \CFA approach of adding features while respecting the ``C-style'' of doing things, C's polymorphic constants and typed literal syntax are extended to interoperate with user-defined types, while maintaining a backwards-compatible semantics.
    1985 A trivial example is allowing the underscore to separate prefixes, digits, and suffixes in all \CFA constants, as in Ada, \eg @0x`_`1.ffff`_`ffff`_`p`_`128`_`l@.
     2006A trivial example is allowing the underscore, as in Ada, to separate prefixes, digits, and suffixes in all \CFA constants, \eg @0x`_`1.ffff`_`ffff`_`p`_`128`_`l@.
     2007
     2008
     2009\subsection{Integral Suffixes}
     2010
     2011Additional integral suffixes are added to cover all the integral types and lengths.
     2012\begin{cquote}
     2013\lstDeleteShortInline@%
     2014\begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}
     2015\begin{cfa}
     201620`_hh`     // signed char
     201721`_hhu`   // unsigned char
     201822`_h`       // signed short int
     201923`_uh`     // unsigned short int
     202024`z`         // size_t
     2021\end{cfa}
     2022&
     2023\begin{cfa}
     202420`_L8`      // int8_t
     202521`_ul8`     // uint8_t
     202622`_l16`     // int16_t
     202723`_ul16`   // uint16_t
     202824`_l32`     // int32_t
     2029\end{cfa}
     2030&
     2031\begin{cfa}
     203225`_ul32`      // uint32_t
     203326`_l64`        // int64_t
     203427`_l64u`      // uint64_t
     203526`_L128`     // int128
     203627`_L128u`   // unsigned int128
     2037\end{cfa}
     2038\end{tabular}
     2039\lstMakeShortInline@%
     2040\end{cquote}
    19862041
    19872042
     
    20002055
    20012056
    2002 \subsection{Integral Suffixes}
    2003 
    2004 Additional integral suffixes are added to cover all the integral types and lengths.
    2005 \begin{cquote}
     2057\subsection{User Literals}
     2058
     2059For readability, it is useful to associate units to scale literals, \eg weight (stone, pound, kilogram) or time (seconds, minutes, hours).
     2060The left of Figure~\ref{f:UserLiteral} shows the \CFA alternative call-syntax (literal argument before function name), using the backquote, to convert basic literals into user literals.
     2061The backquote is a small character, making the unit (function name) predominate.
     2062For examples, the multi-precision integers in Section~\ref{s:MultiPrecisionIntegers} make use of user literals:
     2063{\lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}}
     2064\begin{cfa}
     2065y = 9223372036854775807L|`mp| * 18446744073709551615UL|`mp|;
     2066y = "12345678901234567890123456789"|`mp| + "12345678901234567890123456789"|`mp|;
     2067\end{cfa}
     2068Because \CFA uses a standard function, all types and literals are applicable, as well as overloading and conversions.
     2069}%
     2070
     2071The right of Figure~\ref{f:UserLiteral} shows the equivalent \CC version using the underscore for the call-syntax.
     2072However, \CC restricts the types, \eg @unsigned long long int@ and @long double@ to represent integral and floating literals.
     2073After which, user literals must match (no conversions);
     2074hence, it is necessary to overload the unit with all appropriate types.
     2075Finally, the use of the single quote as a separator is restricted to digits, precluding its use in the literal prefix or suffix, and causes problems with most IDEs, which must be extended to deal with this alternate use of the single quote.
     2076
     2077\begin{figure}
     2078\centering
     2079\lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}}
    20062080\lstDeleteShortInline@%
    2007 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}
    2008 \begin{cfa}
    2009 20_hh     // signed char
    2010 21_hhu   // unsigned char
    2011 22_h      // signed short int
    2012 23_uh    // unsigned short int
    2013 24z        // size_t
    2014 \end{cfa}
    2015 &
    2016 \begin{cfa}
    2017 20_L8     // int8_t
    2018 21_ul8    // uint8_t
    2019 22_l16    // int16_t
    2020 23_ul16  // uint16_t
    2021 24_l32    // int32_t
    2022 \end{cfa}
    2023 &
    2024 \begin{cfa}
    2025 25_ul32      // uint32_t
    2026 26_l64        // int64_t
    2027 27_l64u      // uint64_t
    2028 26_L128     // int128
    2029 27_L128u  // unsigned int128
     2081\begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
     2082\multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{\CC}}      \\
     2083\begin{cfa}
     2084struct W {
     2085        double stones;
     2086};
     2087void ?{}( W & w ) { w.stones = 0; }
     2088void ?{}( W & w, double w ) { w.stones = w; }
     2089W ?+?( W l, W r ) {
     2090        return (W){ l.stones + r.stones };
     2091}
     2092W |?`st|( double w ) { return (W){ w }; }
     2093W |?`lb|( double w ) { return (W){ w / 14.0 }; }
     2094W |?`kg|( double w ) { return (W) { w * 0.16 }; }
     2095
     2096
     2097
     2098int main() {
     2099        W w, heavy = { 20 };
     2100        w = 155|`lb|;
     2101        w = 0b_1111|`st|;
     2102        w = 0_233|`lb|;
     2103        w = 0x_9b_u|`kg|;
     2104        w = 5.5|`st| + 8|`kg| + 25.01|`lb| + heavy;
     2105}
     2106\end{cfa}
     2107&
     2108\begin{cfa}
     2109struct W {
     2110    double stones;
     2111    W() { stones = 0.0; }
     2112    W( double w ) { stones = w; }
     2113};
     2114W operator+( W l, W r ) {
     2115        return W( l.stones + r.stones );
     2116}
     2117W |operator"" _st|( unsigned long long int w ) { return W( w ); }
     2118W |operator"" _lb|( unsigned long long int w ) { return W( w / 14.0 ); }
     2119W |operator"" _kg|( unsigned long long int w ) { return W( w * 0.16 ); }
     2120W |operator"" _st|( long double w ) { return W( w ); }
     2121W |operator"" _lb|( long double w ) { return W( w / 14.0 ); }
     2122W |operator"" _kg|( long double w ) { return W( w * 0.16 ); }
     2123int main() {
     2124        W w, heavy = { 20 };
     2125        w = 155|_lb|;
     2126        w = 0b1111|_lb|;       // error, binary unsupported
     2127        w = 0${\color{red}'}$233|_lb|;          // quote separator
     2128        w = 0x9b|_kg|;
     2129        w = 5.5d|_st| + 8|_kg| + 25.01|_lb| + heavy;
     2130}
    20302131\end{cfa}
    20312132\end{tabular}
    20322133\lstMakeShortInline@%
    2033 \end{cquote}
    2034 
    2035 
    2036 \subsection{Units}
    2037 
    2038 Alternative call syntax (literal argument before routine name) to convert basic literals into user literals.
    2039 
    2040 {\lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}}
    2041 \begin{cfa}
    2042 struct Weight { double stones; };
    2043 void ?{}( Weight & w ) { w.stones = 0; }        $\C{// operations}$
    2044 void ?{}( Weight & w, double w ) { w.stones = w; }
    2045 Weight ?+?( Weight l, Weight r ) { return (Weight){ l.stones + r.stones }; }
    2046 
    2047 Weight |?`st|( double w ) { return (Weight){ w }; } $\C{// backquote for units}$
    2048 Weight |?`lb|( double w ) { return (Weight){ w / 14.0 }; }
    2049 Weight |?`kg|( double w ) { return (Weight) { w * 0.1575}; }
    2050 
    2051 int main() {
    2052         Weight w, heavy = { 20 };                               $\C{// 20 stone}$
    2053         w = 155|`lb|;
    2054         w = 0x_9b_u|`lb|;                                               $\C{// hexadecimal unsigned weight (155)}$
    2055         w = 0_233|`lb|;                                                 $\C{// octal weight (155)}$
    2056         w = 5|`st| + 8|`kg| + 25|`lb| + heavy;
    2057 }
    2058 \end{cfa}
    2059 }%
     2134\caption{User Literal}
     2135\label{f:UserLiteral}
     2136\end{figure}
    20602137
    20612138
     
    20672144In many cases, the interface is an inline wrapper providing overloading during compilation but zero cost at runtime.
    20682145The following sections give a glimpse of the interface reduction to many C libraries.
    2069 In many cases, @signed@/@unsigned@ @char@ and @short@ routines are available (but not shown) to ensure expression computations remain in a single type, as conversions can distort results.
     2146In many cases, @signed@/@unsigned@ @char@, @short@, and @_Complex@ functions are available (but not shown) to ensure expression computations remain in a single type, as conversions can distort results.
    20702147
    20712148
     
    20952172\begin{cquote}
    20962173\lstDeleteShortInline@%
    2097 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    2098 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
     2174\lstset{basicstyle=\linespread{0.9}\sf\small}
     2175\begin{tabular}{@{}l@{\hspace{0.5\parindentlnth}}l@{}}
     2176\multicolumn{1}{c@{\hspace{0.5\parindentlnth}}}{\textbf{\CFA}}  & \multicolumn{1}{c}{\textbf{C}}        \\
    20992177\begin{cfa}
    21002178MIN
    21012179MAX
    2102 M_PI
    2103 M_E
    2104 \end{cfa}
    2105 &
    2106 \begin{cfa}
    2107 SCHAR_MIN, CHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN, LLONG_MIN,
    2108 SCHAR_MAX, UCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, LLONG_MAX,
    2109 M_PI, M_PIl, M_CPI, M_CPIl,
    2110 M_E, M_El, M_CE, M_CEl
     2180PI
     2181E
     2182\end{cfa}
     2183&
     2184\begin{cfa}
     2185SCHAR_MIN, CHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN, LLONG_MIN, FLT_MIN, DBL_MIN, LDBL_MIN
     2186SCHAR_MAX, UCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, LLONG_MAX, FLT_MAX, DBL_MAX, LDBL_MAX
     2187M_PI, M_PIl
     2188M_E, M_El
    21112189\end{cfa}
    21122190\end{tabular}
     
    21172195\subsection{Math}
    21182196
    2119 C library @math.h@ provides many mathematical routines.
    2120 \CFA routine overloading is used to condense these mathematical routines, \eg:
     2197C library @math.h@ provides many mathematical functions.
     2198\CFA function overloading is used to condense these mathematical functions, \eg:
    21212199\begin{cquote}
    21222200\lstDeleteShortInline@%
     
    21372215\lstMakeShortInline@%
    21382216\end{cquote}
    2139 The result is a significant reduction in names to access math routines, \eg:
     2217The result is a significant reduction in names to access math functions, \eg:
    21402218\begin{cquote}
    21412219\lstDeleteShortInline@%
     
    21562234\lstMakeShortInline@%
    21572235\end{cquote}
    2158 While \Celeven has type-generic math~\cite[\S~7.25]{C11} in @tgmath.h@ to provide a similar mechanism, these macros are limited, matching a routine name with a single set of floating type(s).
     2236While \Celeven has type-generic math~\cite[\S~7.25]{C11} in @tgmath.h@ to provide a similar mechanism, these macros are limited, matching a function name with a single set of floating type(s).
    21592237For example, it is impossible to overload @atan@ for both one and two arguments;
    2160 instead the names @atan@ and @atan2@ are required.
    2161 The key observation is that only a restricted set of type-generic macros are provided for a limited set of routine names, which do not generalize across the type system, as in \CFA.
     2238instead the names @atan@ and @atan2@ are required (see Section~\ref{s:NameOverloading}).
     2239The key observation is that only a restricted set of type-generic macros are provided for a limited set of function names, which do not generalize across the type system, as in \CFA.
    21622240
    21632241
    21642242\subsection{Standard}
    21652243
    2166 C library @stdlib.h@ provides many general routines.
    2167 \CFA routine overloading is used to condense these utility routines, \eg:
     2244C library @stdlib.h@ provides many general functions.
     2245\CFA function overloading is used to condense these utility functions, \eg:
    21682246\begin{cquote}
    21692247\lstDeleteShortInline@%
     
    21842262\lstMakeShortInline@%
    21852263\end{cquote}
    2186 The result is a significant reduction in names to access utility routines, \eg:
     2264The result is a significant reduction in names to access utility functions, \eg:
    21872265\begin{cquote}
    21882266\lstDeleteShortInline@%
     
    22032281\lstMakeShortInline@%
    22042282\end{cquote}
    2205 In additon, there are polymorphic routines, like @min@ and @max@, which work on any type with operators @?<?@ or @?>?@.
     2283In additon, there are polymorphic functions, like @min@ and @max@, which work on any type with operators @?<?@ or @?>?@.
    22062284
    22072285The following shows one example where \CFA \emph{extends} an existing standard C interface to reduce complexity and provide safety.
     
    22202298An array may be filled, resized, or aligned.
    22212299\end{description}
    2222 Table~\ref{t:StorageManagementOperations} shows the capabilities provided by C/\Celeven allocation-routines and how all the capabilities can be combined into two \CFA routines.
    2223 
    2224 \CFA storage-management routines extend the C equivalents by overloading, providing shallow type-safety, and removing the need to specify the base allocation-size.
    2225 The following example contrasts \CFA and C storage-allocation operation performing the same operations with the same type safety:
    2226 \begin{cquote}
    2227 \begin{cfa}[aboveskip=0pt]
    2228 size_t  dim = 10;                                                       $\C{// array dimension}$
    2229 char fill = '\xff';                                                     $\C{// initialization fill value}$
    2230 int * ip;
    2231 \end{cfa}
    2232 \lstDeleteShortInline@%
    2233 \begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
    2234 \multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
    2235 \begin{cfa}
    2236 ip = alloc();
    2237 ip = alloc( fill );
    2238 ip = alloc( dim );
    2239 ip = alloc( dim, fill );
    2240 ip = alloc( ip, 2 * dim );
    2241 ip = alloc( ip, 4 * dim, fill );
    2242 
    2243 ip = align_alloc( 16 );
    2244 ip = align_alloc( 16, fill );
    2245 ip = align_alloc( 16, dim );
    2246 ip = align_alloc( 16, dim, fill );
    2247 \end{cfa}
    2248 &
    2249 \begin{cfa}
    2250 ip = (int *)malloc( sizeof( int ) );
    2251 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, sizeof( int ) );
    2252 ip = (int *)malloc( dim * sizeof( int ) );
    2253 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) );
    2254 ip = (int *)realloc( ip, 2 * dim * sizeof( int ) );
    2255 ip = (int *)realloc( ip, 4 * dim * sizeof( int ) ); memset( ip, fill, 4 * dim * sizeof( int ) );
    2256 
    2257 ip = memalign( 16, sizeof( int ) );
    2258 ip = memalign( 16, sizeof( int ) ); memset( ip, fill, sizeof( int ) );
    2259 ip = memalign( 16, dim * sizeof( int ) );
    2260 ip = memalign( 16, dim * sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) );
    2261 \end{cfa}
    2262 \end{tabular}
    2263 \lstMakeShortInline@%
    2264 \end{cquote}
    2265 Variadic @new@ (see Section~\ref{sec:variadic-tuples}) cannot support the same overloading because extra parameters are for initialization.
    2266 Hence, there are @new@ and @anew@ routines for single and array variables, and the fill value is the arguments to the constructor, \eg:
    2267 \begin{cfa}
    2268 struct S { int i, j; };
    2269 void ?{}( S & s, int i, int j ) { s.i = i; s.j = j; }
    2270 S * s = new( 2, 3 );                                            $\C{// allocate storage and run constructor}$
    2271 S * as = anew( dim, 2, 3 );                                     $\C{// each array element initialized to 2, 3}$
    2272 \end{cfa}
    2273 Note, \CC can only initialization array elements via the default constructor.
    2274 
    2275 Finally, the \CFA memory-allocator has \newterm{sticky properties} for dynamic storage: fill and alignment are remembered with an object's storage in the heap.
    2276 When a @realloc@ is performed, the sticky properties are respected, so that new storage is correctly aligned and initialized with the fill character.
     2300Table~\ref{t:StorageManagementOperations} shows the capabilities provided by C/\Celeven allocation-functions and how all the capabilities can be combined into two \CFA functions.
     2301\CFA storage-management functions extend the C equivalents by overloading, providing shallow type-safety, and removing the need to specify the base allocation-size.
     2302Figure~\ref{f:StorageAllocation} contrasts \CFA and C storage-allocation operation performing the same operations with the same type safety.
    22772303
    22782304\begin{table}
     
    23002326\end{table}
    23012327
     2328\begin{figure}
     2329\centering
     2330\begin{cquote}
     2331\begin{cfa}[aboveskip=0pt]
     2332size_t  dim = 10;                                                       $\C{// array dimension}$
     2333char fill = '\xff';                                                     $\C{// initialization fill value}$
     2334int * ip;
     2335\end{cfa}
     2336\lstDeleteShortInline@%
     2337\begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
     2338\multicolumn{1}{c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}     & \multicolumn{1}{c}{\textbf{C}}        \\
     2339\begin{cfa}
     2340ip = alloc();
     2341ip = alloc( fill );
     2342ip = alloc( dim );
     2343ip = alloc( dim, fill );
     2344ip = alloc( ip, 2 * dim );
     2345ip = alloc( ip, 4 * dim, fill );
     2346
     2347ip = align_alloc( 16 );
     2348ip = align_alloc( 16, fill );
     2349ip = align_alloc( 16, dim );
     2350ip = align_alloc( 16, dim, fill );
     2351\end{cfa}
     2352&
     2353\begin{cfa}
     2354ip = (int *)malloc( sizeof( int ) );
     2355ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, sizeof( int ) );
     2356ip = (int *)malloc( dim * sizeof( int ) );
     2357ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) );
     2358ip = (int *)realloc( ip, 2 * dim * sizeof( int ) );
     2359ip = (int *)realloc( ip, 4 * dim * sizeof( int ) ); memset( ip, fill, 4 * dim * sizeof( int ) );
     2360
     2361ip = memalign( 16, sizeof( int ) );
     2362ip = memalign( 16, sizeof( int ) ); memset( ip, fill, sizeof( int ) );
     2363ip = memalign( 16, dim * sizeof( int ) );
     2364ip = memalign( 16, dim * sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) );
     2365\end{cfa}
     2366\end{tabular}
     2367\lstMakeShortInline@%
     2368\end{cquote}
     2369\caption{\CFA versus C Storage-Allocation}
     2370\label{f:StorageAllocation}
     2371\end{figure}
     2372
     2373Variadic @new@ (see Section~\ref{sec:variadic-tuples}) cannot support the same overloading because extra parameters are for initialization.
     2374Hence, there are @new@ and @anew@ functions for single and array variables, and the fill value is the arguments to the constructor, \eg:
     2375\begin{cfa}
     2376struct S { int i, j; };
     2377void ?{}( S & s, int i, int j ) { s.i = i; s.j = j; }
     2378S * s = new( 2, 3 );                                            $\C{// allocate storage and run constructor}$
     2379S * as = anew( dim, 2, 3 );                                     $\C{// each array element initialized to 2, 3}$
     2380\end{cfa}
     2381Note, \CC can only initialization array elements via the default constructor.
     2382
     2383Finally, the \CFA memory-allocator has \newterm{sticky properties} for dynamic storage: fill and alignment are remembered with an object's storage in the heap.
     2384When a @realloc@ is performed, the sticky properties are respected, so that new storage is correctly aligned and initialized with the fill character.
     2385
    23022386
    23032387\subsection{I/O}
     
    23872471}%
    23882472\end{itemize}
    2389 There are routines to set and get the separator string, and manipulators to toggle separation on and off in the middle of output.
     2473There are functions to set and get the separator string, and manipulators to toggle separation on and off in the middle of output.
    23902474
    23912475
     
    23942478
    23952479\CFA has an interface to the GMP multi-precision signed-integers~\cite{GMP}, similar to the \CC interface provided by GMP.
    2396 The \CFA interface wraps GMP routines into operator routines to make programming with multi-precision integers identical to using fixed-sized integers.
     2480The \CFA interface wraps GMP functions into operator functions to make programming with multi-precision integers identical to using fixed-sized integers.
    23972481The \CFA type name for multi-precision signed-integers is @Int@ and the header file is @gmp@.
    23982482The following multi-precision factorial programs contrast using GMP with the \CFA and C interfaces.
     
    24392523Since all these languages share a subset essentially comprising standard C, maximal-performance benchmarks would show little runtime variance, other than in length and clarity of source code.
    24402524A more illustrative benchmark measures the costs of idiomatic usage of each language's features.
    2441 Figure~\ref{fig:BenchmarkTest} shows the \CFA benchmark tests for a generic stack based on a singly linked-list, a generic pair-data-structure, and a variadic @print@ routine similar to that in Section~\ref{sec:variadic-tuples}.
     2525Figure~\ref{fig:BenchmarkTest} shows the \CFA benchmark tests for a generic stack based on a singly linked-list, a generic pair-data-structure, and a variadic @print@ function similar to that in Section~\ref{sec:variadic-tuples}.
    24422526The benchmark test is similar for C and \CC.
    24432527The experiment uses element types @int@ and @pair(_Bool, char)@, and pushes $N=40M$ elements on a generic stack, copies the stack, clears one of the stacks, finds the maximum value in the other stack, and prints $N/2$ (to reduce graph height) constants.
     
    24462530\begin{cfa}[xleftmargin=3\parindentlnth,aboveskip=0pt,belowskip=0pt]
    24472531int main( int argc, char * argv[] ) {
    2448         FILE * out = fopen( "cfa-out.txt", "w" );
    2449         int maxi = 0, vali = 42;
    2450         stack(int) si, ti;
    2451 
    2452         REPEAT_TIMED( "push_int", N, push( &si, vali ); )
    2453         TIMED( "copy_int", ti = si; )
    2454         TIMED( "clear_int", clear( &si ); )
    2455         REPEAT_TIMED( "pop_int", N,
    2456                 int xi = pop( &ti ); if ( xi > maxi ) { maxi = xi; } )
    2457         REPEAT_TIMED( "print_int", N/2, print( out, vali, ":", vali, "\n" ); )
    2458 
    2459         pair(_Bool, char) maxp = { (_Bool)0, '\0' }, valp = { (_Bool)1, 'a' };
    2460         stack(pair(_Bool, char)) sp, tp;
    2461 
    2462         REPEAT_TIMED( "push_pair", N, push( &sp, valp ); )
    2463         TIMED( "copy_pair", tp = sp; )
    2464         TIMED( "clear_pair", clear( &sp ); )
    2465         REPEAT_TIMED( "pop_pair", N,
    2466                 pair(_Bool, char) xp = pop( &tp ); if ( xp > maxp ) { maxp = xp; } )
    2467         REPEAT_TIMED( "print_pair", N/2, print( out, valp, ":", valp, "\n" ); )
    2468         fclose(out);
     2532        ofstream out = { "cfa-out.txt" };
     2533        int max = 0, val = 42;
     2534        stack( int ) s, t;
     2535
     2536        REPEAT_TIMED( "push_int", N, push( s, val ); )
     2537        TIMED( "copy_int", t = s; )
     2538        TIMED( "clear_int", clear( s ); )
     2539        REPEAT_TIMED( "pop_int", N, int v = pop( t ); max = max( v, max ); )
     2540        REPEAT_TIMED( "print_int", N/2, out | val | ':' | val | endl; )
     2541
     2542        pair( _Bool, char ) max = { false, '\0' }, val = { true, 'a' };
     2543        stack( pair( _Bool, char ) ) s, t;
     2544
     2545        REPEAT_TIMED( "push_pair", N, push( s, val ); )
     2546        TIMED( "copy_pair", t = s; )
     2547        TIMED( "clear_pair", clear( s ); )
     2548        REPEAT_TIMED( "pop_pair", N, pair(_Bool, char) v = pop( t ); max = max( v, max ); )
     2549        REPEAT_TIMED( "print_pair", N/2, out | val | ':' | val | endl; )
    24692550}
    24702551\end{cfa}
     
    25372618\CC is the most similar language to \CFA;
    25382619both are extensions to C with source and runtime backwards compatibility.
    2539 The fundamental difference is in their engineering approach to C compatibility and programmer expectation.
    2540 While \CC provides good backwards compatibility with C, it has a steep learning curve for many of its extensions.
     2620The fundamental difference is the engineering approach to maintain C compatibility and programmer expectation.
     2621While \CC provides good compatibility with C, it has a steep learning curve for many of its extensions.
    25412622For example, polymorphism is provided via three disjoint mechanisms: overloading, inheritance, and templates.
    25422623The overloading is restricted because resolution does not use the return type, inheritance requires learning object-oriented programming and coping with a restricted nominal-inheritance hierarchy, templates cannot be separately compiled resulting in compilation/code bloat and poor error messages, and determining how these mechanisms interact and which to use is confusing.
    25432624In contrast, \CFA has a single facility for polymorphic code supporting type-safe separate-compilation of polymorphic functions and generic (opaque) types, which uniformly leverage the C procedural paradigm.
    2544 The key mechanism to support separate compilation is \CFA's \emph{explicit} use of assumed properties for a type.
    2545 Until \CC concepts~\cite{C++Concepts} are standardized (anticipated for \CCtwenty), \CC provides no way to specify the requirements of a generic function in code beyond compilation errors during template expansion;
     2625The key mechanism to support separate compilation is \CFA's \emph{explicit} use of assumed type properties.
     2626Until \CC concepts~\cite{C++Concepts} are standardized (anticipated for \CCtwenty), \CC provides no way to specify the requirements of a generic function beyond compilation errors during template expansion;
    25462627furthermore, \CC concepts are restricted to template polymorphism.
    25472628
     
    25942675
    25952676
     2677\subsection{Control Structures / Declarations / Literals}
     2678
     2679
    25962680\section{Conclusion and Future Work}
    25972681
     
    26202704
    26212705The authors would like to recognize the design assistance of Glen Ditchfield, Richard Bilson, and Thierry Delisle on the features described in this paper, and thank Magnus Madsen for feedback in the writing.
    2622 %This work is supported in part by a corporate partnership with \grantsponsor{Huawei}{Huawei Ltd.}{http://www.huawei.com}, and Aaron Moss and Peter Buhr are funded by the \grantsponsor{Natural Sciences and Engineering Research Council} of Canada.
     2706This work is supported through a corporate partnership with Huawei Ltd.\ (\url{http://www.huawei.com}), and Aaron Moss and Peter Buhr are funded by the Natural Sciences and Engineering Research Council of Canada.
     2707
    26232708% the first author's \grantsponsor{NSERC-PGS}{NSERC PGS D}{http://www.nserc-crsng.gc.ca/Students-Etudiants/PG-CS/BellandPostgrad-BelletSuperieures_eng.asp} scholarship.
    26242709
     
    26402725\CFA
    26412726\begin{cfa}[xleftmargin=2\parindentlnth,aboveskip=0pt,belowskip=0pt]
     2727forall(otype T) struct stack_node;
     2728forall(otype T) struct stack {
     2729        stack_node(T) * head;
     2730};
    26422731forall(otype T) struct stack_node {
    26432732        T value;
    26442733        stack_node(T) * next;
    26452734};
    2646 forall(otype T) void ?{}(stack(T) * s) { (&s->head){ 0 }; }
    2647 forall(otype T) void ?{}(stack(T) * s, stack(T) t) {
    2648         stack_node(T) ** crnt = &s->head;
     2735forall(otype T) void ?{}( stack(T) & s ) { (s.head){ 0 }; }
     2736forall(otype T) void ?{}( stack(T) & s, stack(T) t ) {
     2737        stack_node(T) ** crnt = &s.head;
    26492738        for ( stack_node(T) * next = t.head; next; next = next->next ) {
    2650                 *crnt = ((stack_node(T) *)malloc()){ next->value }; /***/
     2739                stack_node(T) * new_node = ((stack_node(T)*)malloc());
     2740                (*new_node){ next->value }; /***/
     2741                *crnt = new_node;
    26512742                stack_node(T) * acrnt = *crnt;
    26522743                crnt = &acrnt->next;
     
    26542745        *crnt = 0;
    26552746}
    2656 forall(otype T) stack(T) ?=?(stack(T) * s, stack(T) t) {
    2657         if ( s->head == t.head ) return *s;
    2658         clear(s);
     2747forall(otype T) stack(T) ?=?( stack(T) & s, stack(T) t ) {
     2748        if ( s.head == t.head ) return s;
     2749        clear( s );
    26592750        s{ t };
    2660         return *s;
    2661 }
    2662 forall(otype T) void ^?{}(stack(T) * s) { clear(s); }
    2663 forall(otype T) _Bool empty(const stack(T) * s) { return s->head == 0; }
    2664 forall(otype T) void push(stack(T) * s, T value) {
    2665         s->head = ((stack_node(T) *)malloc()){ value, s->head }; /***/
    2666 }
    2667 forall(otype T) T pop(stack(T) * s) {
    2668         stack_node(T) * n = s->head;
    2669         s->head = n->next;
    2670         T x = n->value;
    2671         ^n{};
    2672         free(n);
    2673         return x;
    2674 }
    2675 forall(otype T) void clear(stack(T) * s) {
    2676         for ( stack_node(T) * next = s->head; next; ) {
     2751        return s;
     2752}
     2753forall(otype T) void ^?{}( stack(T) & s) { clear( s ); }
     2754forall(otype T) _Bool empty( const stack(T) & s ) { return s.head == 0; }
     2755forall(otype T) void push( stack(T) & s, T value ) {
     2756        stack_node(T) * new_node = ((stack_node(T)*)malloc());
     2757        (*new_node){ value, s.head }; /***/
     2758        s.head = new_node;
     2759}
     2760forall(otype T) T pop( stack(T) & s ) {
     2761        stack_node(T) * n = s.head;
     2762        s.head = n->next;
     2763        T v = n->value;
     2764        delete( n );
     2765        return v;
     2766}
     2767forall(otype T) void clear( stack(T) & s ) {
     2768        for ( stack_node(T) * next = s.head; next; ) {
    26772769                stack_node(T) * crnt = next;
    26782770                next = crnt->next;
    2679                 delete(crnt);
     2771                delete( crnt );
    26802772        }
    2681         s->head = 0;
     2773        s.head = 0;
    26822774}
    26832775\end{cfa}
     
    28272919
    28282920
    2829 \begin{comment}
    2830 
    2831 \subsubsection{bench.h}
    2832 (\texttt{bench.hpp} is similar.)
    2833 
    2834 \lstinputlisting{evaluation/bench.h}
    2835 
    2836 \subsection{C}
    2837 
    2838 \subsubsection{c-stack.h} ~
    2839 
    2840 \lstinputlisting{evaluation/c-stack.h}
    2841 
    2842 \subsubsection{c-stack.c} ~
    2843 
    2844 \lstinputlisting{evaluation/c-stack.c}
    2845 
    2846 \subsubsection{c-pair.h} ~
    2847 
    2848 \lstinputlisting{evaluation/c-pair.h}
    2849 
    2850 \subsubsection{c-pair.c} ~
    2851 
    2852 \lstinputlisting{evaluation/c-pair.c}
    2853 
    2854 \subsubsection{c-print.h} ~
    2855 
    2856 \lstinputlisting{evaluation/c-print.h}
    2857 
    2858 \subsubsection{c-print.c} ~
    2859 
    2860 \lstinputlisting{evaluation/c-print.c}
    2861 
    2862 \subsubsection{c-bench.c} ~
    2863 
    2864 \lstinputlisting{evaluation/c-bench.c}
    2865 
    2866 \subsection{\CFA}
    2867 
    2868 \subsubsection{cfa-stack.h} ~
    2869 
    2870 \lstinputlisting{evaluation/cfa-stack.h}
    2871 
    2872 \subsubsection{cfa-stack.c} ~
    2873 
    2874 \lstinputlisting{evaluation/cfa-stack.c}
    2875 
    2876 \subsubsection{cfa-print.h} ~
    2877 
    2878 \lstinputlisting{evaluation/cfa-print.h}
    2879 
    2880 \subsubsection{cfa-print.c} ~
    2881 
    2882 \lstinputlisting{evaluation/cfa-print.c}
    2883 
    2884 \subsubsection{cfa-bench.c} ~
    2885 
    2886 \lstinputlisting{evaluation/cfa-bench.c}
    2887 
    2888 \subsection{\CC}
    2889 
    2890 \subsubsection{cpp-stack.hpp} ~
    2891 
    2892 \lstinputlisting[language=c++]{evaluation/cpp-stack.hpp}
    2893 
    2894 \subsubsection{cpp-print.hpp} ~
    2895 
    2896 \lstinputlisting[language=c++]{evaluation/cpp-print.hpp}
    2897 
    2898 \subsubsection{cpp-bench.cpp} ~
    2899 
    2900 \lstinputlisting[language=c++]{evaluation/cpp-bench.cpp}
    2901 
    2902 \subsection{\CCV}
    2903 
    2904 \subsubsection{object.hpp} ~
    2905 
    2906 \lstinputlisting[language=c++]{evaluation/object.hpp}
    2907 
    2908 \subsubsection{cpp-vstack.hpp} ~
    2909 
    2910 \lstinputlisting[language=c++]{evaluation/cpp-vstack.hpp}
    2911 
    2912 \subsubsection{cpp-vstack.cpp} ~
    2913 
    2914 \lstinputlisting[language=c++]{evaluation/cpp-vstack.cpp}
    2915 
    2916 \subsubsection{cpp-vprint.hpp} ~
    2917 
    2918 \lstinputlisting[language=c++]{evaluation/cpp-vprint.hpp}
    2919 
    2920 \subsubsection{cpp-vbench.cpp} ~
    2921 
    2922 \lstinputlisting[language=c++]{evaluation/cpp-vbench.cpp}
    2923 \end{comment}
    2924 
    29252921\end{document}
    29262922
  • doc/papers/general/evaluation/cfa-bench.c

    r094476d rcaa649b  
    1 #include <stdio.h>
     1#include <fstream>
     2#include <stdlib>
     3#include <stdbool.h>
    24#include "bench.h"
    35#include "cfa-stack.h"
     
    57#include "cfa-print.h"
    68
    7 int main( int argc, char *argv[] ) {
    8         FILE * out = fopen( "/dev/null", "w" );
    9         int maxi = 0, vali = 42;
    10         stack(int) si, ti;
     9int main( int argc, char * argv[] ) {
     10        ofstream out = { "/dev/null" };
     11        int max = 0, val = 42;
     12        stack( int ) s, t;
    1113
    12         REPEAT_TIMED( "push_int", N, push( &si, vali ); )
    13         TIMED( "copy_int", ti = si; )
    14         TIMED( "clear_int", clear( &si ); )
    15         REPEAT_TIMED( "pop_int", N,
    16                 int xi = pop( &ti );
    17                 if ( xi > maxi ) { maxi = xi; } )
    18         REPEAT_TIMED( "print_int", N/2, print( out, vali, ":", vali, "\n" ); )
     14        REPEAT_TIMED( "push_int", N, push( s, val ); )
     15        TIMED( "copy_int", t = s; )
     16        TIMED( "clear_int", clear( s ); )
     17        REPEAT_TIMED( "pop_int", N, int x = pop( t ); max = max( x, max ); )
     18        REPEAT_TIMED( "print_int", N/2, out | val | ':' | val | endl; )
    1919
    20         pair(_Bool, char) maxp = { (_Bool)0, '\0' }, valp = { (_Bool)1, 'a' };
    21         stack(pair(_Bool, char)) sp, tp;
     20        pair( _Bool, char ) max = { (_Bool)false, '\0' }, val = { (_Bool)true, 'a' };
     21        stack( pair( _Bool, char ) ) s, t;
    2222
    23         REPEAT_TIMED( "push_pair", N, push( &sp, valp ); )
    24         TIMED( "copy_pair", tp = sp; )
    25         TIMED( "clear_pair", clear( &sp ); )
    26         REPEAT_TIMED( "pop_pair", N,
    27                 pair(_Bool, char) xp = pop( &tp );
    28                 if ( xp > maxp ) { maxp = xp; } )
    29         REPEAT_TIMED( "print_pair", N/2, print( out, valp, ":", valp, "\n" ); )
    30         fclose(out);
     23        REPEAT_TIMED( "push_pair", N, push( s, val ); )
     24        TIMED( "copy_pair", t = s; )
     25        TIMED( "clear_pair", clear( s ); )
     26        REPEAT_TIMED( "pop_pair", N, pair(_Bool, char) x = pop( t ); max = max( x, max ); )
     27        REPEAT_TIMED( "print_pair", N/2, out | val | ':' | val | endl; )
    3128}
  • doc/papers/general/evaluation/cfa-pair.c

    r094476d rcaa649b  
    11#include "cfa-pair.h"
     2#include "fstream"
    23
    3 forall(otype R, otype S 
     4forall(otype R, otype S
    45        | { int ?==?(R, R); int ?<?(R, R); int ?<?(S, S); })
    56int ?<?(pair(R, S) p, pair(R, S) q) {
     
    78}
    89
    9 forall(otype R, otype S 
     10forall(otype R, otype S
    1011        | { int ?==?(R, R); int ?<?(R, R); int ?<=?(S, S); })
    1112int ?<=?(pair(R, S) p, pair(R, S) q) {
     
    2324}
    2425
    25 forall(otype R, otype S 
     26forall(otype R, otype S
    2627        | { int ?==?(R, R); int ?>?(R, R); int ?>?(S, S); })
    2728int ?>?(pair(R, S) p, pair(R, S) q) {
     
    2930}
    3031
    31 forall(otype R, otype S 
     32forall(otype R, otype S
    3233        | { int ?==?(R, R); int ?>?(R, R); int ?>=?(S, S); })
    3334int ?>=?(pair(R, S) p, pair(R, S) q) {
    3435        return p.first > q.first || ( p.first == q.first && p.second >= q.second );
    3536}
     37
     38forall(otype R, otype S)
     39forall(dtype ostype | ostream( ostype ) | { ostype & ?|?( ostype &, R ); ostype & ?|?( ostype &, S );  })
     40ostype & ?|?( ostype & os, pair(R, S) p ) {
     41        return os | '[' | p.first | ',' | p.second | ']';
     42} // ?|?
  • doc/papers/general/evaluation/cfa-pair.h

    r094476d rcaa649b  
    11#pragma once
     2
     3#include "iostream"
    24
    35forall(otype R, otype S) struct pair {
     
    2729        | { int ?==?(R, R); int ?>?(R, R); int ?>=?(S, S); })
    2830int ?>=?(pair(R, S) p, pair(R, S) q);
     31
     32forall(otype R, otype S)
     33forall(dtype ostype | ostream( ostype ) | { ostype & ?|?( ostype &, pair(R, S) ); })
     34ostype & ?|?( ostype & os, pair(R, S) );
  • doc/papers/general/evaluation/cfa-stack.c

    r094476d rcaa649b  
    44forall(otype T) struct stack_node {
    55        T value;
    6         stack_node(T)* next;
     6        stack_node(T) * next;
    77};
     8forall(otype T) void ?{}( stack_node(T) & node, T value, stack_node(T) * next ) {
     9    node.value = value;
     10    node.next = next;
     11}
    812
    9 forall(otype T) void ?{}(stack(T)* s) { (&s->head){ 0 }; }
     13forall(otype T) void ?{}( stack(T) & s ) { (s.head){ 0 }; }
    1014
    11 forall(otype T) void ?{}(stack(T)* s, stack(T) t) {
    12         stack_node(T)** crnt = &s->head;
    13         for ( stack_node(T)* next = t.head; next; next = next->next ) {
    14                 *crnt = ((stack_node(T)*)malloc()){ next->value }; /***/
    15                 stack_node(T)* acrnt = *crnt;
     15forall(otype T) void ?{}( stack(T) & s, stack(T) t ) {
     16        stack_node(T) ** crnt = &s.head;
     17        for ( stack_node(T) * next = t.head; next; next = next->next ) {
     18                // *crnt = new( next->value, 0 );
     19                stack_node(T)* new_node = ((stack_node(T)*)malloc());
     20                (*new_node){ next->value }; /***/
     21                *crnt = new_node;
     22                stack_node(T) * acrnt = *crnt;
    1623                crnt = &acrnt->next;
    1724        }
     
    1926}
    2027
    21 forall(otype T) stack(T) ?=?(stack(T)* s, stack(T) t) {
    22         if ( s->head == t.head ) return *s;
    23         clear(s);
     28forall(otype T) stack(T) ?=?( stack(T) & s, stack(T) t ) {
     29        if ( s.head == t.head ) return s;
     30        clear( s );
    2431        s{ t };
    25         return *s;
     32        return s;
    2633}
    2734
    28 forall(otype T) void ^?{}(stack(T)* s) { clear(s); }
     35forall(otype T) void ^?{}( stack(T) & s) { clear( s ); }
    2936
    30 forall(otype T) _Bool empty(const stack(T)* s) { return s->head == 0; }
     37forall(otype T) _Bool empty( const stack(T) & s ) { return s.head == 0; }
    3138
    32 forall(otype T) void push(stack(T)* s, T value) {
    33         s->head = ((stack_node(T)*)malloc()){ value, s->head }; /***/
     39forall(otype T) void push( stack(T) & s, T value ) {
     40        // s.head = new( value, s.head );
     41        stack_node(T)* new_node = ((stack_node(T)*)malloc());
     42        (*new_node){ value, s.head }; /***/
     43        s.head = new_node;
    3444}
    3545
    36 forall(otype T) T pop(stack(T)* s) {
    37         stack_node(T)* n = s->head;
    38         s->head = n->next;
    39         T x = n->value;
    40         ^n{};
    41         free(n);
    42         return x;
     46forall(otype T) T pop( stack(T) & s ) {
     47        stack_node(T) * n = s.head;
     48        s.head = n->next;
     49        T v = n->value;
     50        delete( n );
     51        return v;
    4352}
    4453
    45 forall(otype T) void clear(stack(T)* s) {
    46     for ( stack_node(T)* next = s->head; next; ) {
    47                 stack_node(T)* crnt = next;
     54forall(otype T) void clear( stack(T) & s ) {
     55        for ( stack_node(T) * next = s.head; next; ) {
     56                stack_node(T) * crnt = next;
    4857                next = crnt->next;
    49                 delete(crnt);
     58                delete( crnt );
    5059        }
    51         s->head = 0;
     60        s.head = 0;
    5261}
  • doc/papers/general/evaluation/cfa-stack.h

    r094476d rcaa649b  
    33forall(otype T) struct stack_node;
    44forall(otype T) struct stack {
    5         stack_node(T)* head;
     5        stack_node(T) * head;
    66};
    77
    8 forall(otype T) void ?{}(stack(T)* s);
    9 forall(otype T) void ?{}(stack(T)* s, stack(T) t);
    10 forall(otype T) stack(T) ?=?(stack(T)* s, stack(T) t);
    11 forall(otype T) void ^?{}(stack(T)* s);
     8forall(otype T) void ?{}( stack(T) & s );
     9forall(otype T) void ?{}( stack(T) & s, stack(T) t );
     10forall(otype T) stack(T) ?=?( stack(T) & s, stack(T) t );
     11forall(otype T) void ^?{}( stack(T) & s);
    1212
    13 forall(otype T) _Bool empty(const stack(T)* s);
    14 forall(otype T) void push(stack(T)* s, T value);
    15 forall(otype T) T pop(stack(T)* s);
    16 forall(otype T) void clear(stack(T)* s);
     13forall(otype T) _Bool empty( const stack(T) & s );
     14forall(otype T) void push( stack(T) & s, T value );
     15forall(otype T) T pop( stack(T) & s );
     16forall(otype T) void clear( stack(T) & s );
  • src/Common/PassVisitor.impl.h

    r094476d rcaa649b  
    22772277}
    22782278
    2279 
     2279//--------------------------------------------------------------------------
     2280// TupleType
    22802281template< typename pass_type >
    22812282void PassVisitor< pass_type >::visit( TupleType * node ) {
    2282         VISIT_BODY( node );
    2283 }
    2284 
     2283        VISIT_START( node );
     2284
     2285        maybeAccept_impl( node->forall, *this );
     2286        maybeAccept_impl( node->types, *this );
     2287        maybeAccept_impl( node->members, *this );
     2288
     2289        VISIT_END( node );
     2290}
     2291
     2292template< typename pass_type >
     2293Type * PassVisitor< pass_type >::mutate( TupleType * node ) {
     2294        MUTATE_START( node );
     2295
     2296        maybeMutate_impl( node->forall, *this );
     2297        maybeMutate_impl( node->types, *this );
     2298        maybeMutate_impl( node->members, *this );
     2299
     2300        MUTATE_END( Type, node );
     2301}
     2302
     2303//--------------------------------------------------------------------------
     2304// TypeofType
    22852305template< typename pass_type >
    22862306void PassVisitor< pass_type >::visit( TypeofType * node ) {
    2287         VISIT_BODY( node );
    2288 }
    2289 
     2307        VISIT_START( node );
     2308
     2309        assert( node->expr );
     2310        maybeAccept_impl( node->expr, *this );
     2311
     2312        VISIT_END( node );
     2313}
     2314
     2315template< typename pass_type >
     2316Type * PassVisitor< pass_type >::mutate( TypeofType * node ) {
     2317        MUTATE_START( node );
     2318
     2319        assert( node->expr );
     2320        maybeMutate_impl( node->expr, *this );
     2321
     2322        MUTATE_END( Type, node );
     2323}
     2324
     2325//--------------------------------------------------------------------------
     2326// AttrType
    22902327template< typename pass_type >
    22912328void PassVisitor< pass_type >::visit( AttrType * node ) {
    2292         VISIT_BODY( node );
    2293 }
    2294 
     2329        VISIT_START( node );
     2330
     2331        if ( node->isType ) {
     2332                assert( node->type );
     2333                maybeAccept_impl( node->type, *this );
     2334        } else {
     2335                assert( node->expr );
     2336                maybeAccept_impl( node->expr, *this );
     2337        } // if
     2338
     2339        VISIT_END( node );
     2340}
     2341
     2342template< typename pass_type >
     2343Type * PassVisitor< pass_type >::mutate( AttrType * node ) {
     2344        MUTATE_START( node );
     2345
     2346        if ( node->isType ) {
     2347                assert( node->type );
     2348                maybeMutate_impl( node->type, *this );
     2349        } else {
     2350                assert( node->expr );
     2351                maybeMutate_impl( node->expr, *this );
     2352        } // if
     2353
     2354        MUTATE_END( Type, node );
     2355}
     2356
     2357//--------------------------------------------------------------------------
     2358// VarArgsType
    22952359template< typename pass_type >
    22962360void PassVisitor< pass_type >::visit( VarArgsType * node ) {
    2297         VISIT_BODY( node );
    2298 }
    2299 
     2361        VISIT_START( node );
     2362
     2363        maybeAccept_impl( node->forall, *this );
     2364
     2365        VISIT_END( node );
     2366}
     2367
     2368template< typename pass_type >
     2369Type * PassVisitor< pass_type >::mutate( VarArgsType * node ) {
     2370        MUTATE_START( node );
     2371
     2372        maybeMutate_impl( node->forall, *this );
     2373
     2374        MUTATE_END( Type, node );
     2375}
     2376
     2377//--------------------------------------------------------------------------
     2378// ZeroType
    23002379template< typename pass_type >
    23012380void PassVisitor< pass_type >::visit( ZeroType * node ) {
    2302         VISIT_BODY( node );
    2303 }
    2304 
     2381        VISIT_START( node );
     2382
     2383        maybeAccept_impl( node->forall, *this );
     2384
     2385        VISIT_END( node );
     2386}
     2387
     2388template< typename pass_type >
     2389Type * PassVisitor< pass_type >::mutate( ZeroType * node ) {
     2390        MUTATE_START( node );
     2391
     2392        maybeMutate_impl( node->forall, *this );
     2393
     2394        MUTATE_END( Type, node );
     2395}
     2396
     2397//--------------------------------------------------------------------------
     2398// OneType
    23052399template< typename pass_type >
    23062400void PassVisitor< pass_type >::visit( OneType * node ) {
    2307         VISIT_BODY( node );
    2308 }
    2309 
     2401        VISIT_START( node );
     2402
     2403        maybeAccept_impl( node->forall, *this );
     2404
     2405        VISIT_END( node );
     2406}
     2407
     2408template< typename pass_type >
     2409Type * PassVisitor< pass_type >::mutate( OneType * node ) {
     2410        MUTATE_START( node );
     2411
     2412        maybeMutate_impl( node->forall, *this );
     2413
     2414        MUTATE_END( Type, node );
     2415}
     2416
     2417//--------------------------------------------------------------------------
     2418// Designation
    23102419template< typename pass_type >
    23112420void PassVisitor< pass_type >::visit( Designation * node ) {
    23122421        VISIT_START( node );
    23132422
    2314         maybeAccept_impl( node->get_designators(), *this );
     2423        maybeAccept_impl( node->designators, *this );
    23152424
    23162425        VISIT_END( node );
     
    23212430        MUTATE_START( node );
    23222431
    2323         maybeMutate_impl( node->get_designators(), *this );
     2432        maybeMutate_impl( node->designators, *this );
    23242433
    23252434        MUTATE_END( Designation, node );
     
    23322441        VISIT_START( node );
    23332442
    2334         visitExpression( node->get_value() );
     2443        visitExpression( node->value );
    23352444
    23362445        VISIT_END( node );
     
    23412450        MUTATE_START( node );
    23422451
    2343         node->set_value( mutateExpression( node->get_value() ) );
     2452        node->value = mutateExpression( node->value );
    23442453
    23452454        MUTATE_END( Initializer, node );
    23462455}
    23472456
     2457//--------------------------------------------------------------------------
     2458// ListInit
    23482459template< typename pass_type >
    23492460void PassVisitor< pass_type >::visit( ListInit * node ) {
    2350         VISIT_BODY( node );
    2351 }
    2352 
     2461        VISIT_START( node );
     2462
     2463        maybeAccept_impl( node->designations, *this );
     2464        maybeAccept_impl( node->initializers, *this );
     2465
     2466        VISIT_END( node );
     2467}
     2468
     2469template< typename pass_type >
     2470Initializer * PassVisitor< pass_type >::mutate( ListInit * node ) {
     2471        MUTATE_START( node );
     2472
     2473        maybeMutate_impl( node->designations, *this );
     2474        maybeMutate_impl( node->initializers, *this );
     2475
     2476        MUTATE_END( Initializer, node );
     2477}
     2478
     2479//--------------------------------------------------------------------------
     2480// ConstructorInit
    23532481template< typename pass_type >
    23542482void PassVisitor< pass_type >::visit( ConstructorInit * node ) {
    2355         VISIT_BODY( node );
    2356 }
    2357 
     2483        VISIT_START( node );
     2484
     2485        maybeAccept_impl( node->ctor, *this );
     2486        maybeAccept_impl( node->dtor, *this );
     2487        maybeAccept_impl( node->init, *this );
     2488
     2489        VISIT_END( node );
     2490}
     2491
     2492template< typename pass_type >
     2493Initializer * PassVisitor< pass_type >::mutate( ConstructorInit * node ) {
     2494        MUTATE_START( node );
     2495
     2496        maybeMutate_impl( node->ctor, *this );
     2497        maybeMutate_impl( node->dtor, *this );
     2498        maybeMutate_impl( node->init, *this );
     2499
     2500        MUTATE_END( Initializer, node );
     2501}
     2502
     2503//--------------------------------------------------------------------------
     2504// Subrange
    23582505template< typename pass_type >
    23592506void PassVisitor< pass_type >::visit( Subrange * node ) {
    2360         VISIT_BODY( node );
    2361 }
    2362 
     2507        VISIT_START( node );
     2508
     2509        VISIT_END( node );
     2510}
     2511
     2512template< typename pass_type >
     2513Subrange * PassVisitor< pass_type >::mutate( Subrange * node  )  {
     2514        MUTATE_START( node );
     2515
     2516        MUTATE_END( Subrange, node );
     2517}
     2518
     2519//--------------------------------------------------------------------------
     2520// Attribute
    23632521template< typename pass_type >
    23642522void PassVisitor< pass_type >::visit( Constant * node ) {
    2365         VISIT_BODY( node );
    2366 }
    2367 
     2523        VISIT_START( node );
     2524
     2525        VISIT_END( node );
     2526}
     2527
     2528template< typename pass_type >
     2529Constant * PassVisitor< pass_type >::mutate( Constant * node  )  {
     2530        MUTATE_START( node );
     2531
     2532        MUTATE_END( Constant, node );
     2533}
     2534
     2535//--------------------------------------------------------------------------
     2536// Attribute
    23682537template< typename pass_type >
    23692538void PassVisitor< pass_type >::visit( Attribute * node ) {
    2370         VISIT_BODY( node );
    2371 }
    2372 
    2373 //---------------------------------------------------------------------------------------------------------------
    2374 
    2375 template< typename pass_type >
    2376 Type * PassVisitor< pass_type >::mutate( TupleType * node ) {
    2377         MUTATE_BODY( Type, node );
    2378 }
    2379 
    2380 template< typename pass_type >
    2381 Type * PassVisitor< pass_type >::mutate( TypeofType * node ) {
    2382         MUTATE_BODY( Type, node );
    2383 }
    2384 
    2385 template< typename pass_type >
    2386 Type * PassVisitor< pass_type >::mutate( AttrType * node ) {
    2387         MUTATE_BODY( Type, node );
    2388 }
    2389 
    2390 template< typename pass_type >
    2391 Type * PassVisitor< pass_type >::mutate( VarArgsType * node ) {
    2392         MUTATE_BODY( Type, node );
    2393 }
    2394 
    2395 template< typename pass_type >
    2396 Type * PassVisitor< pass_type >::mutate( ZeroType * node ) {
    2397         MUTATE_BODY( Type, node );
    2398 }
    2399 
    2400 template< typename pass_type >
    2401 Type * PassVisitor< pass_type >::mutate( OneType * node ) {
    2402         MUTATE_BODY( Type, node );
    2403 }
    2404 
    2405 template< typename pass_type >
    2406 Initializer * PassVisitor< pass_type >::mutate( ListInit * node ) {
    2407         MUTATE_BODY( Initializer, node );
    2408 }
    2409 
    2410 template< typename pass_type >
    2411 Initializer * PassVisitor< pass_type >::mutate( ConstructorInit * node ) {
    2412         MUTATE_BODY( Initializer, node );
    2413 }
    2414 
    2415 template< typename pass_type >
    2416 Subrange * PassVisitor< pass_type >::mutate( Subrange * node  )  {
    2417         MUTATE_BODY( Subrange, node );
    2418 }
    2419 
    2420 template< typename pass_type >
    2421 Constant * PassVisitor< pass_type >::mutate( Constant * node  )  {
    2422         MUTATE_BODY( Constant, node );
     2539        VISIT_START( node );
     2540
     2541        maybeAccept_impl( node->parameters, *this );
     2542
     2543        VISIT_END( node );
    24232544}
    24242545
    24252546template< typename pass_type >
    24262547Attribute * PassVisitor< pass_type >::mutate( Attribute * node  )  {
    2427         MUTATE_BODY( Attribute, node );
    2428 }
    2429 
     2548        MUTATE_START( node );
     2549
     2550        maybeMutate_impl( node->parameters, *this );
     2551
     2552        MUTATE_END( Attribute, node );
     2553}
     2554
     2555//--------------------------------------------------------------------------
     2556// TypeSubstitution
    24302557template< typename pass_type >
    24312558TypeSubstitution * PassVisitor< pass_type >::mutate( TypeSubstitution * node ) {
  • src/Common/SemanticError.cc

    r094476d rcaa649b  
    1414//
    1515
     16#include <cstdarg>
    1617#include <cstdio>                                                                               // for fileno, stderr
    1718#include <unistd.h>                                                                             // for isatty
     
    5051}
    5152
    52 void SemanticWarningImpl( CodeLocation location, std::string msg ) {
     53namespace {
     54        // convert format string and arguments into a single string
     55        std::string fmtToString(const char * fmt, va_list ap) {
     56                int size = 128;
     57                while ( true ) {
     58                        char buf[size];
     59                        va_list args;
     60                        va_copy( args, ap );
     61                        int n = vsnprintf(&buf[0], size, fmt, args);
     62                        va_end( args );
     63                        if ( n < size && n >= 0 ) return buf;
     64                        size *= 2;
     65                }
     66                assert( false );
     67        }
     68}
     69
     70void SemanticWarningImpl( CodeLocation location, Warning, const char * const fmt, ... ) {
     71        va_list args;
     72        va_start(args, fmt);
     73        std::string msg = fmtToString( fmt, args );
     74        va_end(args);
    5375        std::cerr << ErrorHelpers::bold() << location << ErrorHelpers::warning_str() << ErrorHelpers::reset_font() << msg << std::endl;
    5476}
  • src/Common/SemanticError.h

    r094476d rcaa649b  
    3737
    3838constexpr const char * const WarningFormats[] = {
    39 
     39        "self assignment of expression: %s",
    4040};
    4141
    4242enum class Warning {
     43        SelfAssignment,
    4344        NUMBER_OF_WARNINGS, //This MUST be the last warning
    4445};
     
    4950);
    5051
    51 #define SemanticWarning(loc, id, ...) SemanticWarningImpl(loc, id, WarningFormats[id], __VA_ARGS__)
     52#define SemanticWarning(loc, id, ...) SemanticWarningImpl(loc, id, WarningFormats[(int)id], __VA_ARGS__)
    5253
    5354void SemanticWarningImpl (CodeLocation loc, Warning warn, const char * const fmt, ...) __attribute__((format(printf, 3, 4)));
     
    7172}
    7273
    73 
    74 
    75 
    7674// Local Variables: //
    7775// tab-width: 4 //
  • src/Common/utility.h

    r094476d rcaa649b  
    162162}
    163163
     164#define toCString( ... ) toString( __VA_ARGS__ ).c_str()
     165
    164166// replace element of list with all elements of another list
    165167template< typename T >
  • src/GenPoly/Specialize.cc

    r094476d rcaa649b  
    200200        }
    201201
    202         struct EnvTrimmer {
    203                 TypeSubstitution * env, * newEnv;
    204                 EnvTrimmer( TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
    205                 void previsit( TypeDecl * tyDecl ) {
    206                         // transfer known bindings for seen type variables
    207                         if ( Type * t = env->lookup( tyDecl->name ) ) {
    208                                 newEnv->add( tyDecl->name, t );
    209                         }
    210                 }
    211         };
    212 
    213         /// reduce environment to just the parts that are referenced in a given expression
    214         TypeSubstitution * trimEnv( ApplicationExpr * expr, TypeSubstitution * env ) {
    215                 if ( env ) {
    216                         TypeSubstitution * newEnv = new TypeSubstitution();
    217                         PassVisitor<EnvTrimmer> trimmer( env, newEnv );
    218                         expr->accept( trimmer );
    219                         return newEnv;
    220                 }
    221                 return nullptr;
    222         }
    223 
    224202        /// Generates a thunk that calls `actual` with type `funType` and returns its address
    225203        Expression * Specialize::createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) {
     
    265243                }
    266244
    267                 appExpr->set_env( trimEnv( appExpr, env ) );
     245                appExpr->env = TypeSubstitution::newFromExpr( appExpr, env );
    268246                if ( inferParams ) {
    269247                        appExpr->get_inferParams() = *inferParams;
  • src/InitTweak/FixInit.cc

    r094476d rcaa649b  
    6868                typedef std::unordered_map< int, int > UnqCount;
    6969
     70                struct SelfAssignChecker {
     71                        void previsit( ApplicationExpr * appExpr );
     72                };
     73
    7074                struct InsertImplicitCalls : public WithTypeSubstitution {
    7175                        /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which
     
    183187                };
    184188
    185                 class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors> {
     189                class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors>, public WithTypeSubstitution {
    186190                  public:
    187191                        FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){}
     
    235239
    236240        void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) {
     241                PassVisitor<SelfAssignChecker> checker;
     242                acceptAll( translationUnit, checker );
     243
    237244                // fixes ConstructorInit for global variables. should happen before fixInitializers.
    238245                InitTweak::fixGlobalInit( translationUnit, filename, inLibrary );
     
    311318                }
    312319
     320                namespace {
     321                        // Relatively simple structural comparison for expressions, needed to determine
     322                        // if two expressions are "the same" (used to determine if self assignment occurs)
     323                        struct StructuralChecker {
     324                                Expression * stripCasts( Expression * expr ) {
     325                                        // this might be too permissive. It's possible that only particular casts are relevant.
     326                                        while ( CastExpr * cast = dynamic_cast< CastExpr * >( expr ) ) {
     327                                                expr = cast->arg;
     328                                        }
     329                                        return expr;
     330                                }
     331
     332                                void previsit( Expression * ) {
     333                                        // anything else does not qualify
     334                                        isSimilar = false;
     335                                }
     336
     337                                template<typename T>
     338                                T * cast( Expression * node ) {
     339                                        // all expressions need to ignore casts, so this bit has been factored out
     340                                        return dynamic_cast< T * >( stripCasts( node ) );
     341                                }
     342
     343                                // ignore casts
     344                                void previsit( CastExpr * ) {}
     345
     346                                void previsit( MemberExpr * memExpr ) {
     347                                        if ( MemberExpr * otherMember = cast< MemberExpr >( other ) ) {
     348                                                if ( otherMember->member == memExpr->member ) {
     349                                                        other = otherMember->aggregate;
     350                                                        return;
     351                                                }
     352                                        }
     353                                        isSimilar = false;
     354                                }
     355
     356                                void previsit( VariableExpr * varExpr ) {
     357                                        if ( VariableExpr * otherVar = cast< VariableExpr >( other ) ) {
     358                                                if ( otherVar->var == varExpr->var ) {
     359                                                        return;
     360                                                }
     361                                        }
     362                                        isSimilar = false;
     363                                }
     364
     365                                void previsit( AddressExpr * ) {
     366                                        if ( AddressExpr * addrExpr = cast< AddressExpr >( other ) ) {
     367                                                other = addrExpr->arg;
     368                                                return;
     369                                        }
     370                                        isSimilar = false;
     371                                }
     372
     373                                Expression * other = nullptr;
     374                                bool isSimilar = true;
     375                        };
     376
     377                        bool structurallySimilar( Expression * e1, Expression * e2 ) {
     378                                PassVisitor<StructuralChecker> checker;
     379                                checker.pass.other = e2;
     380                                e1->accept( checker );
     381                                return checker.pass.isSimilar;
     382                        }
     383                }
     384
     385                void SelfAssignChecker::previsit( ApplicationExpr * appExpr ) {
     386                        DeclarationWithType * function = getFunction( appExpr );
     387                        if ( isAssignment( function ) ) {
     388                                if ( appExpr->args.size() == 2 ) {
     389                                        // check for structural similarity (same variable use, ignore casts, etc. - but does not look too deeply, anything looking like a function is off limits)
     390                                        if ( structurallySimilar( appExpr->args.front(), appExpr->args.back() ) ) {
     391                                                SemanticWarning( appExpr->location, Warning::SelfAssignment, toCString( appExpr->args.front() ) );
     392                                        }
     393                                }
     394                        }
     395                }
     396
    313397                Expression * InsertImplicitCalls::postmutate( ApplicationExpr * appExpr ) {
    314398                        if ( VariableExpr * function = dynamic_cast< VariableExpr * > ( appExpr->get_function() ) ) {
     
    364448                        ResolvExpr::findVoidExpression( resolved, indexer );
    365449                        assert( resolved );
    366                         if ( resolved->get_env() ) {
     450                        if ( resolved->env ) {
    367451                                // Extract useful information and discard new environments. Keeping them causes problems in PolyMutator passes.
    368                                 env->add( *resolved->get_env() );
    369                                 delete resolved->get_env();
    370                                 resolved->set_env( nullptr );
     452                                env->add( *resolved->env );
     453                                delete resolved->env;
     454                                resolved->env = nullptr;
    371455                        } // if
    372456                        delete stmt;
     
    550634                        // add destructors after current statement
    551635                        for ( Expression * dtor : dtors ) {
     636                                // take relevant bindings from environment
     637                                assert( ! dtor->env );
     638                                dtor->env =  maybeClone( env );
    552639                                stmtsToAddAfter.push_back( new ExprStmt( dtor ) );
    553640                        } // for
  • src/Makefile.in

    r094476d rcaa649b  
    247247        SynTree/driver_cfa_cpp-TypeDecl.$(OBJEXT) \
    248248        SynTree/driver_cfa_cpp-Initializer.$(OBJEXT) \
    249         SynTree/driver_cfa_cpp-Visitor.$(OBJEXT) \
    250         SynTree/driver_cfa_cpp-Mutator.$(OBJEXT) \
    251249        SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT) \
    252250        SynTree/driver_cfa_cpp-Attribute.$(OBJEXT) \
     
    527525        SynTree/FunctionDecl.cc SynTree/AggregateDecl.cc \
    528526        SynTree/NamedTypeDecl.cc SynTree/TypeDecl.cc \
    529         SynTree/Initializer.cc SynTree/Visitor.cc SynTree/Mutator.cc \
    530         SynTree/TypeSubstitution.cc SynTree/Attribute.cc \
    531         SynTree/VarExprReplacer.cc Tuples/TupleAssignment.cc \
    532         Tuples/TupleExpansion.cc Tuples/Explode.cc \
    533         Virtual/ExpandCasts.cc
     527        SynTree/Initializer.cc SynTree/TypeSubstitution.cc \
     528        SynTree/Attribute.cc SynTree/VarExprReplacer.cc \
     529        Tuples/TupleAssignment.cc Tuples/TupleExpansion.cc \
     530        Tuples/Explode.cc Virtual/ExpandCasts.cc
    534531MAINTAINERCLEANFILES = Parser/parser.output ${libdir}/${notdir \
    535532        ${cfa_cpplib_PROGRAMS}}
     
    911908SynTree/driver_cfa_cpp-Initializer.$(OBJEXT): SynTree/$(am__dirstamp) \
    912909        SynTree/$(DEPDIR)/$(am__dirstamp)
    913 SynTree/driver_cfa_cpp-Visitor.$(OBJEXT): SynTree/$(am__dirstamp) \
    914         SynTree/$(DEPDIR)/$(am__dirstamp)
    915 SynTree/driver_cfa_cpp-Mutator.$(OBJEXT): SynTree/$(am__dirstamp) \
    916         SynTree/$(DEPDIR)/$(am__dirstamp)
    917910SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT):  \
    918911        SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
     
    10531046@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-FunctionType.Po@am__quote@
    10541047@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Initializer.Po@am__quote@
    1055 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Mutator.Po@am__quote@
    10561048@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-NamedTypeDecl.Po@am__quote@
    10571049@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ObjectDecl.Po@am__quote@
     
    10691061@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-VarArgsType.Po@am__quote@
    10701062@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-VarExprReplacer.Po@am__quote@
    1071 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Visitor.Po@am__quote@
    10721063@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-VoidType.Po@am__quote@
    10731064@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ZeroOneType.Po@am__quote@
     
    24782469@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    24792470@am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Initializer.obj `if test -f 'SynTree/Initializer.cc'; then $(CYGPATH_W) 'SynTree/Initializer.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Initializer.cc'; fi`
    2480 
    2481 SynTree/driver_cfa_cpp-Visitor.o: SynTree/Visitor.cc
    2482 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Visitor.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Visitor.Tpo -c -o SynTree/driver_cfa_cpp-Visitor.o `test -f 'SynTree/Visitor.cc' || echo '$(srcdir)/'`SynTree/Visitor.cc
    2483 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Visitor.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Visitor.Po
    2484 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/Visitor.cc' object='SynTree/driver_cfa_cpp-Visitor.o' libtool=no @AMDEPBACKSLASH@
    2485 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    2486 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Visitor.o `test -f 'SynTree/Visitor.cc' || echo '$(srcdir)/'`SynTree/Visitor.cc
    2487 
    2488 SynTree/driver_cfa_cpp-Visitor.obj: SynTree/Visitor.cc
    2489 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Visitor.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Visitor.Tpo -c -o SynTree/driver_cfa_cpp-Visitor.obj `if test -f 'SynTree/Visitor.cc'; then $(CYGPATH_W) 'SynTree/Visitor.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Visitor.cc'; fi`
    2490 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Visitor.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Visitor.Po
    2491 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/Visitor.cc' object='SynTree/driver_cfa_cpp-Visitor.obj' libtool=no @AMDEPBACKSLASH@
    2492 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    2493 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Visitor.obj `if test -f 'SynTree/Visitor.cc'; then $(CYGPATH_W) 'SynTree/Visitor.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Visitor.cc'; fi`
    2494 
    2495 SynTree/driver_cfa_cpp-Mutator.o: SynTree/Mutator.cc
    2496 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Mutator.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Mutator.Tpo -c -o SynTree/driver_cfa_cpp-Mutator.o `test -f 'SynTree/Mutator.cc' || echo '$(srcdir)/'`SynTree/Mutator.cc
    2497 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Mutator.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Mutator.Po
    2498 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/Mutator.cc' object='SynTree/driver_cfa_cpp-Mutator.o' libtool=no @AMDEPBACKSLASH@
    2499 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    2500 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Mutator.o `test -f 'SynTree/Mutator.cc' || echo '$(srcdir)/'`SynTree/Mutator.cc
    2501 
    2502 SynTree/driver_cfa_cpp-Mutator.obj: SynTree/Mutator.cc
    2503 @am__fastdepCXX_TRUE@   $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Mutator.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Mutator.Tpo -c -o SynTree/driver_cfa_cpp-Mutator.obj `if test -f 'SynTree/Mutator.cc'; then $(CYGPATH_W) 'SynTree/Mutator.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Mutator.cc'; fi`
    2504 @am__fastdepCXX_TRUE@   $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Mutator.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Mutator.Po
    2505 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      $(AM_V_CXX)source='SynTree/Mutator.cc' object='SynTree/driver_cfa_cpp-Mutator.obj' libtool=no @AMDEPBACKSLASH@
    2506 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    2507 @am__fastdepCXX_FALSE@  $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Mutator.obj `if test -f 'SynTree/Mutator.cc'; then $(CYGPATH_W) 'SynTree/Mutator.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Mutator.cc'; fi`
    25082471
    25092472SynTree/driver_cfa_cpp-TypeSubstitution.o: SynTree/TypeSubstitution.cc
  • src/Parser/ExpressionNode.cc

    r094476d rcaa649b  
    1010// Created On       : Sat May 16 13:17:07 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Sep 27 22:51:55 2017
    13 // Update Count     : 781
     12// Last Modified On : Sat Mar  3 18:22:33 2018
     13// Update Count     : 796
    1414//
    1515
     
    5858static inline bool checkD( char c ) { return c == 'd' || c == 'D'; }
    5959static inline bool checkI( char c ) { return c == 'i' || c == 'I'; }
     60static inline bool checkB( char c ) { return c == 'b' || c == 'B'; }
    6061static inline bool checkX( char c ) { return c == 'x' || c == 'X'; }
    6162
     
    116117
    117118        unsigned long long int v;                                                       // converted integral value
    118         size_t last = str.length() - 1;                                         // last character of constant
     119        size_t last = str.length() - 1;                                         // last subscript of constant
    119120        Expression * ret;
    120121
     
    129130        } // if
    130131
    131         if ( str[0] == '0' ) {                                                          // octal/hex constant ?
     132        // Cannot be "0"
     133
     134        if ( str[0] == '0' ) {                                                          // radix character ?
    132135                dec = false;
    133                 if ( last != 0 && checkX( str[1] ) ) {                  // hex constant ?
     136                if ( checkX( str[1] ) ) {                                               // hex constant ?
    134137                        sscanf( (char *)str.c_str(), "%llx", &v );
     138                        //printf( "%llx %llu\n", v, v );
     139                } else if ( checkB( str[1] ) ) {                                // binary constant ?
     140                        v = 0;
     141                        for ( unsigned int i = 2;; i += 1 ) {           // compute value
     142                                if ( str[i] == '1' ) v |= 1;
     143                          if ( i == last ) break;
     144                                v <<= 1;
     145                        } // for
    135146                        //printf( "%llx %llu\n", v, v );
    136147                } else {                                                                                // octal constant
  • src/Parser/lex.ll

    r094476d rcaa649b  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Thu Feb 22 18:11:27 2018
    13  * Update Count     : 637
     12 * Last Modified On : Sat Mar  3 18:38:16 2018
     13 * Update Count     : 640
    1414 */
    1515
     
    7777%}
    7878
     79binary [0-1]
    7980octal [0-7]
    8081nonzero [1-9]
     
    103104nonzero_digits ({nonzero})|({nonzero}({decimal}|"_")*{decimal})
    104105decimal_constant {nonzero_digits}{integer_suffix_opt}
     106
     107binary_digits ({binary})|({binary}({binary}|"_")*{binary})
     108binary_prefix "0"[bB]"_"?
     109binary_constant {binary_prefix}{binary_digits}{integer_suffix_opt}
    105110
    106111hex_digits ({hex})|({hex}({hex}|"_")*{hex})
     
    315320
    316321                                /* numeric constants */
     322{binary_constant} { NUMERIC_RETURN(INTEGERconstant); }
     323{octal_constant} { NUMERIC_RETURN(INTEGERconstant); }
    317324{decimal_constant} { NUMERIC_RETURN(INTEGERconstant); }
    318 {octal_constant} { NUMERIC_RETURN(INTEGERconstant); }
    319325{hex_constant}  { NUMERIC_RETURN(INTEGERconstant); }
    320326{floating_decimal}      { NUMERIC_RETURN(FLOATING_DECIMALconstant); } // must appear before floating_constant
  • src/ResolvExpr/Resolver.cc

    r094476d rcaa649b  
    788788                stmtExpr->accept( resolver );
    789789                stmtExpr->computeResult();
     790                // xxx - aggregate the environments from all statements? Possibly in AlternativeFinder instead?
    790791        }
    791792
     
    793794                visit_children = false;
    794795                // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit
    795                 maybeAccept( ctorInit->get_ctor(), *visitor );
    796                 maybeAccept( ctorInit->get_dtor(), *visitor );
     796                maybeAccept( ctorInit->ctor, *visitor );
     797                maybeAccept( ctorInit->dtor, *visitor );
    797798
    798799                // found a constructor - can get rid of C-style initializer
    799                 delete ctorInit->get_init();
    800                 ctorInit->set_init( NULL );
     800                delete ctorInit->init;
     801                ctorInit->init = nullptr;
    801802
    802803                // intrinsic single parameter constructors and destructors do nothing. Since this was
    803804                // implicitly generated, there's no way for it to have side effects, so get rid of it
    804805                // to clean up generated code.
    805                 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->get_ctor() ) ) {
    806                         delete ctorInit->get_ctor();
    807                         ctorInit->set_ctor( NULL );
    808                 }
    809 
    810                 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->get_dtor() ) ) {
    811                         delete ctorInit->get_dtor();
    812                         ctorInit->set_dtor( NULL );
     806                if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) {
     807                        delete ctorInit->ctor;
     808                        ctorInit->ctor = nullptr;
     809                }
     810
     811                if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) {
     812                        delete ctorInit->dtor;
     813                        ctorInit->dtor = nullptr;
    813814                }
    814815
  • src/ResolvExpr/TypeEnvironment.cc

    r094476d rcaa649b  
    118118                        env.push_back( newClass );
    119119                } // for
     120        }
     121
     122        void TypeEnvironment::add( const TypeSubstitution & sub ) {
     123                EqvClass newClass;
     124                for ( auto p : sub ) {
     125                        newClass.vars.insert( p.first );
     126                        newClass.type = p.second->clone();
     127                        newClass.allowWidening = false;
     128                        // Minimal assumptions. Not technically correct, but might be good enough, and
     129                        // is the best we can do at the moment since information is lost in the
     130                        // transition to TypeSubstitution
     131                        newClass.data = TypeDecl::Data{ TypeDecl::Dtype, false };
     132                        add( newClass );
     133                }
    120134        }
    121135
  • src/ResolvExpr/TypeEnvironment.h

    r094476d rcaa649b  
    7676                void add( const EqvClass &eqvClass );
    7777                void add( const Type::ForallList &tyDecls );
     78                void add( const TypeSubstitution & sub );
    7879                template< typename SynTreeClass > int apply( SynTreeClass *&type ) const;
    7980                template< typename SynTreeClass > int applyFree( SynTreeClass *&type ) const;
  • src/SynTree/Mutator.h

    r094476d rcaa649b  
    2222class Mutator {
    2323  protected:
    24         Mutator();
    25         virtual ~Mutator();
     24        Mutator() = default;
     25        virtual ~Mutator() = default;
    2626  public:
    2727        virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ) = 0;
  • src/SynTree/TypeSubstitution.cc

    r094476d rcaa649b  
    104104bool TypeSubstitution::empty() const {
    105105        return typeEnv.empty() && varEnv.empty();
     106}
     107
     108namespace {
     109        struct EnvTrimmer {
     110                TypeSubstitution * env, * newEnv;
     111                EnvTrimmer( TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
     112                void previsit( TypeDecl * tyDecl ) {
     113                        // transfer known bindings for seen type variables
     114                        if ( Type * t = env->lookup( tyDecl->name ) ) {
     115                                newEnv->add( tyDecl->name, t );
     116                        }
     117                }
     118        };
     119} // namespace
     120
     121/// reduce environment to just the parts that are referenced in a given expression
     122TypeSubstitution * TypeSubstitution::newFromExpr( Expression * expr, TypeSubstitution * env ) {
     123        if ( env ) {
     124                TypeSubstitution * newEnv = new TypeSubstitution();
     125                PassVisitor<EnvTrimmer> trimmer( env, newEnv );
     126                expr->accept( trimmer );
     127                return newEnv;
     128        }
     129        return nullptr;
    106130}
    107131
  • src/SynTree/TypeSubstitution.h

    r094476d rcaa649b  
    5555        void extract( TypeInstListIterator begin, TypeInstListIterator end, TypeSubstitution &result );
    5656
     57        /// create a new TypeSubstitution using bindings from env containing all of the type variables in expr
     58        static TypeSubstitution * newFromExpr( Expression * expr, TypeSubstitution * env );
     59
    5760        void normalize();
    5861
     
    7982        TypeEnvType typeEnv;
    8083        VarEnvType varEnv;
     84
     85  public:
     86        // has to come after declaration of typeEnv
     87        auto begin()       -> decltype( typeEnv.begin() ) { return typeEnv.begin(); }
     88        auto   end()       -> decltype( typeEnv.  end() ) { return typeEnv.  end(); }
     89        auto begin() const -> decltype( typeEnv.begin() ) { return typeEnv.begin(); }
     90        auto   end() const -> decltype( typeEnv.  end() ) { return typeEnv.  end(); }
    8191};
    8292
  • src/SynTree/Visitor.h

    r094476d rcaa649b  
    2121class Visitor {
    2222  protected:
    23         Visitor();
    24         virtual ~Visitor();
     23        Visitor() = default;
     24        virtual ~Visitor() = default;
    2525  public:
    2626        // visit: Default implementation of all functions visits the children
  • src/SynTree/module.mk

    r094476d rcaa649b  
    4646       SynTree/TypeDecl.cc \
    4747       SynTree/Initializer.cc \
    48        SynTree/Visitor.cc \
    49        SynTree/Mutator.cc \
    5048       SynTree/TypeSubstitution.cc \
    5149       SynTree/Attribute.cc \
  • src/Tuples/TupleAssignment.cc

    r094476d rcaa649b  
    281281        }
    282282
    283         // removes environments from subexpressions within statement exprs, which could throw off later passes like those in Box which rely on PolyMutator.
     283        // removes environments from subexpressions within statement exprs, which could throw off later passes like those in Box which rely on PolyMutator, and adds the bindings to the compositeEnv
    284284        // xxx - maybe this should happen in alternative finder for every StmtExpr?
    285         // xxx - it's possible that these environments could contain some useful information. Maybe the right thing to do is aggregate the environments and pass the aggregate back to be added into the compositeEnv
    286285        struct EnvRemover {
    287286                void previsit( ExprStmt * stmt ) {
    288                         delete stmt->expr->env;
    289                         stmt->expr->env = nullptr;
    290                 }
     287                        assert( compositeEnv );
     288                        if ( stmt->expr->env ) {
     289                                compositeEnv->add( *stmt->expr->env );
     290                                delete stmt->expr->env;
     291                                stmt->expr->env = nullptr;
     292                        }
     293                }
     294
     295                ResolvExpr::TypeEnvironment * compositeEnv = nullptr;
    291296        };
    292297
     
    300305                        ResolvExpr::resolveCtorInit( ctorInit, spotter.currentFinder.get_indexer() ); // resolve ctor/dtors for the new object
    301306                        PassVisitor<EnvRemover> rm; // remove environments from subexpressions of StmtExprs
     307                        rm.pass.compositeEnv = &compositeEnv;
    302308                        ctorInit->accept( rm );
    303309                }
  • src/libcfa/limits

    r094476d rcaa649b  
    1010// Created On       : Wed Apr  6 18:06:52 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul  7 09:33:57 2017
    13 // Update Count     : 7
     12// Last Modified On : Thu Mar  1 16:20:54 2018
     13// Update Count     : 13
    1414//
    1515
     
    1818// Integral Constants
    1919
     20extern const signed char MIN;
     21extern const unsigned char MIN;
    2022extern const short int MIN;
     23extern const unsigned short int MIN;
    2124extern const int MIN;
     25extern const unsigned int MIN;
    2226extern const long int MIN;
     27extern const unsigned long int MIN;
    2328extern const long long int MIN;
     29extern const unsigned long long int MIN;
    2430
     31extern const signed char MAX;
     32extern const unsigned char MAX;
    2533extern const short int MAX;
    2634extern const unsigned short int MAX;
     
    3341
    3442// Floating-Point Constants
     43
     44extern const float MIN;
     45extern const double MIN;
     46extern const long double MIN;
     47extern const float _Complex MIN;
     48extern const double _Complex MIN;
     49extern const long double _Complex MIN;
     50
     51extern const float MAX;
     52extern const double MAX;
     53extern const long double MAX;
     54extern const float _Complex MAX;
     55extern const double _Complex MAX;
     56extern const long double _Complex MAX;
    3557
    3658extern const float PI;                                                                  // pi
     
    5577extern const long double _2_SQRT_PI;                                    // 2 / sqrt(pi)
    5678
    57 extern const _Complex PI;                                                               // pi
    58 extern const _Complex PI_2;                                                             // pi / 2
    59 extern const _Complex PI_4;                                                             // pi / 4
    60 extern const _Complex _1_PI;                                                    // 1 / pi
    61 extern const _Complex _2_PI;                                                    // 2 / pi
    62 extern const _Complex _2_SQRT_PI;                                               // 2 / sqrt(pi)
     79extern const float _Complex PI;                                                 // pi
     80extern const float _Complex PI_2;                                               // pi / 2
     81extern const float _Complex PI_4;                                               // pi / 4
     82extern const float _Complex _1_PI;                                              // 1 / pi
     83extern const float _Complex _2_PI;                                              // 2 / pi
     84extern const float _Complex _2_SQRT_PI;                                 // 2 / sqrt(pi)
    6385
    64 extern const long _Complex PI;                                                  // pi
    65 extern const long _Complex PI_2;                                                // pi / 2
    66 extern const long _Complex PI_4;                                                // pi / 4
    67 extern const long _Complex _1_PI;                                               // 1 / pi
    68 extern const long _Complex _2_PI;                                               // 2 / pi
    69 extern const long _Complex _2_SQRT_PI;                                  // 2 / sqrt(pi)
     86extern const double _Complex PI;                                                // pi
     87extern const double _Complex PI_2;                                              // pi / 2
     88extern const double _Complex PI_4;                                              // pi / 4
     89extern const double _Complex _1_PI;                                             // 1 / pi
     90extern const double _Complex _2_PI;                                             // 2 / pi
     91extern const double _Complex _2_SQRT_PI;                                // 2 / sqrt(pi)
     92
     93extern const long double _Complex PI;                                   // pi
     94extern const long double _Complex PI_2;                                 // pi / 2
     95extern const long double _Complex PI_4;                                 // pi / 4
     96extern const long double _Complex _1_PI;                                // 1 / pi
     97extern const long double _Complex _2_PI;                                // 2 / pi
     98extern const long double _Complex _2_SQRT_PI;                   // 2 / sqrt(pi)
    7099
    71100extern const float E;                                                                   // e
     
    93122extern const long double _1_SQRT_2;                                             // 1/sqrt(2)
    94123
    95 extern const _Complex E;                                                                // e
    96 extern const _Complex LOG2_E;                                                   // log_2(e)
    97 extern const _Complex LOG10_E;                                                  // log_10(e)
    98 extern const _Complex LN_2;                                                             // log_e(2)
    99 extern const _Complex LN_10;                                                    // log_e(10)
    100 extern const _Complex SQRT_2;                                                   // sqrt(2)
    101 extern const _Complex _1_SQRT_2;                                                // 1 / sqrt(2)
     124extern const float _Complex E;                                                  // e
     125extern const float _Complex LOG2_E;                                             // log_2(e)
     126extern const float _Complex LOG10_E;                                    // log_10(e)
     127extern const float _Complex LN_2;                                               // log_e(2)
     128extern const float _Complex LN_10;                                              // log_e(10)
     129extern const float _Complex SQRT_2;                                             // sqrt(2)
     130extern const float _Complex _1_SQRT_2;                                  // 1 / sqrt(2)
    102131
    103 extern const long _Complex E;                                                   // e
    104 extern const long _Complex LOG2_E;                                              // log_2(e)
    105 extern const long _Complex LOG10_E;                                             // log_10(e)
    106 extern const long _Complex LN_2;                                                // log_e(2)
    107 extern const long _Complex LN_10;                                               // log_e(10)
    108 extern const long _Complex SQRT_2;                                              // sqrt(2)
    109 extern const long _Complex _1_SQRT_2;                                   // 1 / sqrt(2)
     132extern const double _Complex E;                                                 // e
     133extern const double _Complex LOG2_E;                                    // log_2(e)
     134extern const double _Complex LOG10_E;                                   // log_10(e)
     135extern const double _Complex LN_2;                                              // log_e(2)
     136extern const double _Complex LN_10;                                             // log_e(10)
     137extern const double _Complex SQRT_2;                                    // sqrt(2)
     138extern const double _Complex _1_SQRT_2;                                 // 1 / sqrt(2)
     139
     140extern const long double _Complex E;                                    // e
     141extern const long double _Complex LOG2_E;                               // log_2(e)
     142extern const long double _Complex LOG10_E;                              // log_10(e)
     143extern const long double _Complex LN_2;                                 // log_e(2)
     144extern const long double _Complex LN_10;                                // log_e(10)
     145extern const long double _Complex SQRT_2;                               // sqrt(2)
     146extern const long double _Complex _1_SQRT_2;                    // 1 / sqrt(2)
    110147
    111148// Local Variables: //
  • src/libcfa/limits.c

    r094476d rcaa649b  
    1010// Created On       : Wed Apr  6 18:06:52 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Sep 12 10:34:48 2016
    13 // Update Count     : 17
     12// Last Modified On : Thu Mar  1 16:22:51 2018
     13// Update Count     : 74
    1414//
    1515
     16#include <limits.h>
     17#include <float.h>
     18#define __USE_GNU                                                                               // get M_* constants
     19#include <math.h>
     20#include <complex.h>
    1621#include "limits"
    1722
    1823// Integral Constants
    1924
    20 const short int MIN = -32768;
    21 const int MIN = -2147483648;
    22 #if __WORDSIZE == 64
    23 const long int MIN = -9223372036854775807L - 1L;
    24 #else
    25 const long int MIN = (int)MIN;
    26 #endif // M64
    27 const long long int MIN = -9223372036854775807LL - 1LL;
     25const signed char MIN = SCHAR_MIN;
     26const unsigned char MIN = 0;
     27const short int MIN = SHRT_MIN;
     28const unsigned short int MIN = 0;
     29const int MIN = INT_MIN;
     30const unsigned int MIN = 0;
     31const long int MIN = LONG_MIN;
     32const unsigned long int MIN = 0;
     33const long long int MIN = LLONG_MIN;
     34const unsigned long long int MIN = 0;
    2835
    29 const short int MAX = 32767;
    30 const unsigned short int MAX = 65535;
    31 const int MAX = 2147483647;
    32 const unsigned int MAX = 4294967295_U;
    33 #if __WORDSIZE == 64
    34 const long int MAX = 9223372036854775807_L;
    35 #else
    36 const long int MAX = (int)MAX;
    37 #endif // M64
    38 const unsigned long int MAX = 4294967295_U;
    39 const long long int MAX = 9223372036854775807_LL;
    40 const unsigned long long int MAX = 18446744073709551615_ULL;
     36const signed char MAX = SCHAR_MAX;
     37const unsigned char MAX = UCHAR_MAX;
     38const short int MAX = SHRT_MAX;
     39const unsigned short int MAX = USHRT_MAX;
     40const int MAX = INT_MAX;
     41const unsigned int MAX = UINT_MAX;
     42const long int MAX = LONG_MAX;
     43const unsigned long int MAX = ULONG_MAX;
     44const long long int MAX = LLONG_MAX;
     45const unsigned long long int MAX = ULLONG_MAX;
    4146
    4247// Floating-Point Constants
    4348
    44 const float PI = 3.141592_F;                                                    // pi
    45 const float PI_2 = 1.570796_F;                                                  // pi / 2
    46 const float PI_4 = 0.7853981_F;                                                 // pi / 4
    47 const float _1_PI = 0.3183098_F;                                                // 1 / pi
    48 const float _2_PI = 0.6366197_F;                                                // 2 / pi
    49 const float _2_SQRT_PI = 1.128379_F;                                    // 2 / sqrt(pi)
     49const float MIN = FLT_MIN;
     50const double MIN = DBL_MIN;
     51const long double MIN = LDBL_MIN;
     52const float _Complex MIN = __FLT_MIN__ + __FLT_MIN__ * I;
     53const double _Complex MIN = DBL_MIN +  DBL_MIN * I;
     54const long double _Complex MIN = LDBL_MIN + LDBL_MIN * I;
    5055
    51 const double PI = 3.14159265358979323846_D;                             // pi
    52 const double PI_2 = 1.57079632679489661923_D;                   // pi / 2
    53 const double PI_4 = 0.78539816339744830962_D;                   // pi / 4
    54 const double _1_PI = 0.31830988618379067154_D;                  // 1 / pi
    55 const double _2_PI = 0.63661977236758134308_D;                  // 2 / pi
    56 const double _2_SQRT_PI = 1.12837916709551257390_D;             // 2 / sqrt(pi)
     56const float MAX = FLT_MAX;
     57const double MAX = DBL_MAX;
     58const long double MAX = LDBL_MAX;
     59const float _Complex MAX = FLT_MAX + FLT_MAX * I;
     60const double _Complex MAX = DBL_MAX + DBL_MAX * I;
     61const long double _Complex MAX = LDBL_MAX + LDBL_MAX * I;
    5762
    58 const long double PI = 3.1415926535897932384626433832795029_DL; // pi
    59 const long double PI_2 = 1.5707963267948966192313216916397514_DL; // pi / 2
    60 const long double PI_4 = 0.7853981633974483096156608458198757_DL; // pi / 4
    61 const long double _1_PI = 0.3183098861837906715377675267450287_DL; // 1 / pi
    62 const long double _2_PI = 0.6366197723675813430755350534900574_DL; // 2 / pi
    63 const long double _2_SQRT_PI = 1.1283791670955125738961589031215452_DL; // 2 / sqrt(pi)
     63const float PI = (float)M_PI;                                                   // pi
     64const float PI_2 = (float)M_PI_2;                                               // pi / 2
     65const float PI_4 = (float)M_PI_4;                                               // pi / 4
     66const float _1_PI = (float)M_1_PI;                                              // 1 / pi
     67const float _2_PI = (float)M_2_PI;                                              // 2 / pi
     68const float _2_SQRT_PI = (float)M_2_SQRTPI;                             // 2 / sqrt(pi)
    6469
    65 const double _Complex PI = 3.14159265358979323846_D+0.0_iD;     // pi
    66 const double _Complex PI_2 = 1.57079632679489661923_D+0.0_iD; // pi / 2
    67 const double _Complex PI_4 = 0.78539816339744830962_D+0.0_iD; // pi / 4
    68 const double _Complex _1_PI = 0.31830988618379067154_D+0.0_iD; // 1 / pi
    69 const double _Complex _2_PI = 0.63661977236758134308_D+0.0_iD; // 2 / pi
    70 const double _Complex _2_SQRT_PI = 1.12837916709551257390_D+0.0_iD; // 2 / sqrt(pi)
     70const double PI = M_PI;                                                                 // pi
     71const double PI_2 = M_PI_2;                                                             // pi / 2
     72const double PI_4 = M_PI_4;                                                             // pi / 4
     73const double _1_PI = M_1_PI;                                                    // 1 / pi
     74const double _2_PI = M_2_PI;                                                    // 2 / pi
     75const double _2_SQRT_PI = M_2_SQRTPI;                                   // 2 / sqrt(pi)
    7176
    72 const long double _Complex PI = 3.1415926535897932384626433832795029_L+0.0iL; // pi
    73 const long double _Complex PI_2 = 1.5707963267948966192313216916397514_L+0.0iL; // pi / 2
    74 const long double _Complex PI_4 = 0.7853981633974483096156608458198757_L+0.0iL; // pi / 4
    75 const long double _Complex _1_PI = 0.3183098861837906715377675267450287_L+0.0iL; // 1 / pi
    76 const long double _Complex _2_PI = 0.6366197723675813430755350534900574_L+0.0iL; // 2 / pi
    77 const long double _Complex _2_SQRT_PI = 1.1283791670955125738961589031215452_L+0.0iL; // 2 / sqrt(pi)
     77const long double PI = M_PIl;                                                   // pi
     78const long double PI_2 = M_PI_2l;                                               // pi / 2
     79const long double PI_4 = M_PI_4l;                                               // pi / 4
     80const long double _1_PI = M_1_PIl;                                              // 1 / pi
     81const long double _2_PI = M_2_PIl;                                              // 2 / pi
     82const long double _2_SQRT_PI = M_2_SQRTPIl;                             // 2 / sqrt(pi)
    7883
    79 const float E = 2.718281;                                                               // e
    80 const float LOG2_E = 1.442695;                                                  // log_2(e)
    81 const float LOG10_E = 0.4342944;                                                // log_10(e)
    82 const float LN_2 = 0.6931471;                                                   // log_e(2)
    83 const float LN_10 = 2.302585;                                                   // log_e(10)
    84 const float SQRT_2 = 1.414213;                                                  // sqrt(2)
    85 const float _1_SQRT_2 = 0.7071067;                                              // 1 / sqrt(2)
     84const float _Complex PI = (float)M_PI + 0.0_iF;                 // pi
     85const float _Complex PI_2 = (float)M_PI_2 + 0.0_iF;             // pi / 2
     86const float _Complex PI_4 = (float)M_PI_4 + 0.0_iF;             // pi / 4
     87const float _Complex _1_PI = (float)M_1_PI + 0.0_iF;    // 1 / pi
     88const float _Complex _2_PI = (float)M_2_PI + 0.0_iF;    // 2 / pi
     89const float _Complex _2_SQRT_PI = (float)M_2_SQRTPI + 0.0_iF; // 2 / sqrt(pi)
    8690
    87 const double E = 2.7182818284590452354_D;                               // e
    88 const double LOG2_E = 1.4426950408889634074_D;                  // log_2(e)
    89 const double LOG10_E = 0.43429448190325182765_D;                // log_10(e)
    90 const double LN_2 = 0.69314718055994530942_D;                   // log_e(2)
    91 const double LN_10 = 2.30258509299404568402_D;                  // log_e(10)
    92 const double SQRT_2 = 1.41421356237309504880_D;                 // sqrt(2)
    93 const double _1_SQRT_2 = 0.70710678118654752440_D;              // 1 / sqrt(2)
     91const double _Complex PI = M_PI + 0.0_iD;                               // pi
     92const double _Complex PI_2 = M_PI_2 + 0.0_iD;                   // pi / 2
     93const double _Complex PI_4 = M_PI_4 + 0.0_iD;                   // pi / 4
     94const double _Complex _1_PI = M_1_PI + 0.0_iD;                  // 1 / pi
     95const double _Complex _2_PI = M_2_PI + 0.0_iD;                  // 2 / pi
     96const double _Complex _2_SQRT_PI = M_2_SQRTPI + 0.0_iD; // 2 / sqrt(pi)
    9497
    95 const long double E = 2.7182818284590452353602874713526625_DL; // e
    96 const long double LOG2_E = 1.4426950408889634073599246810018921_DL; // log_2(e)
    97 const long double LOG10_E = 0.4342944819032518276511289189166051_DL; // log_10(e)
    98 const long double LN_2 = 0.6931471805599453094172321214581766_DL; // log_e(2)
    99 const long double LN_10 = 2.3025850929940456840179914546843642_DL; // log_e(10)
    100 const long double SQRT_2 = 1.4142135623730950488016887242096981_DL; // sqrt(2)
    101 const long double _1_SQRT_2 = 0.7071067811865475244008443621048490_DL; // 1/sqrt(2)
     98const long double _Complex PI = M_PIl + 0.0_iL;                 // pi
     99const long double _Complex PI_2 = M_PI_2l + 0.0_iL;             // pi / 2
     100const long double _Complex PI_4 = M_PI_4l + 0.0_iL;             // pi / 4
     101const long double _Complex _1_PI = M_1_PIl + 0.0_iL;    // 1 / pi
     102const long double _Complex _2_PI = M_2_PIl + 0.0_iL;    // 2 / pi
     103const long double _Complex _2_SQRT_PI = M_2_SQRTPIl + 0.0_iL; // 2 / sqrt(pi)
    102104
    103 const double _Complex E = 2.7182818284590452354_D+0.0_iD; // e
    104 const double _Complex LOG2_E = 1.4426950408889634074_D+0.0_iD; // log_2(e)
    105 const double _Complex LOG10_E = 0.43429448190325182765_D+0.0_iD; // log_10(e)
    106 const double _Complex LN_2 = 0.69314718055994530942_D+0.0_iD; // log_e(2)
    107 const double _Complex LN_10 = 2.30258509299404568402_D+0.0_iD; // log_e(10)
    108 const double _Complex SQRT_2 = 1.41421356237309504880_D+0.0_iD; // sqrt(2)
    109 const double _Complex _1_SQRT_2 = 0.70710678118654752440_D+0.0_iD; // 1 / sqrt(2)
     105const float E = (float)M_E;                                                             // e
     106const float LOG2_E = (float)M_LOG2E;                                    // log_2(e)
     107const float LOG10_E = (float)M_LOG10E;                                  // log_10(e)
     108const float LN_2 = (float)M_LN2;                                                // log_e(2)
     109const float LN_10 = (float)M_LN10;                                              // log_e(10)
     110const float SQRT_2 = (float)M_SQRT2;                                    // sqrt(2)
     111const float _1_SQRT_2 = (float)M_SQRT1_2;                               // 1 / sqrt(2)
    110112
    111 const long double _Complex E = 2.7182818284590452353602874713526625_L+0.0_iL; // e
    112 const long double _Complex LOG2_E = 1.4426950408889634073599246810018921_L+0.0_iL; // log_2(e)
    113 const long double _Complex LOG10_E = 0.4342944819032518276511289189166051_L+0.0_iL; // log_10(e)
    114 const long double _Complex LN_2 = 0.6931471805599453094172321214581766_L+0.0_iL; // log_e(2)
    115 const long double _Complex LN_10 = 2.3025850929940456840179914546843642_L+0.0_iL; // log_e(10)
    116 const long double _Complex SQRT_2 = 1.4142135623730950488016887242096981_L+0.0_iL; // sqrt(2)
    117 const long double _Complex _1_SQRT_2 = 0.7071067811865475244008443621048490_L+0.0_iL; // 1 / sqrt(2)
     113const double E = M_E;                                                                   // e
     114const double LOG2_E = M_LOG2E;                                                  // log_2(e)
     115const double LOG10_E = M_LOG10E;                                                // log_10(e)
     116const double LN_2 = M_LN2;                                                              // log_e(2)
     117const double LN_10 = M_LN10;                                                    // log_e(10)
     118const double SQRT_2 = M_SQRT2;                                                  // sqrt(2)
     119const double _1_SQRT_2 = M_SQRT1_2;                                             // 1 / sqrt(2)
     120
     121const long double E = M_El;                                                             // e
     122const long double LOG2_E = M_LOG2El;                                    // log_2(e)
     123const long double LOG10_E = M_LOG10El;                                  // log_10(e)
     124const long double LN_2 = M_LN2l;                                                // log_e(2)
     125const long double LN_10 = M_LN10l;                                              // log_e(10)
     126const long double SQRT_2 = M_SQRT2l;                                    // sqrt(2)
     127const long double _1_SQRT_2 = M_SQRT1_2l;                               // 1 / sqrt(2)
     128
     129const float _Complex E = M_E + 0.0_iF;                                  // e
     130const float _Complex LOG2_E = M_LOG2E + 0.0_iF;                 // log_2(e)
     131const float _Complex LOG10_E = M_LOG10E + 0.0_iF;               // log_10(e)
     132const float _Complex LN_2 = M_LN2 + 0.0_iF;                             // log_e(2)
     133const float _Complex LN_10 = M_LN10 + 0.0_iF;                   // log_e(10)
     134const float _Complex SQRT_2 = M_SQRT2 + 0.0_iF;                 // sqrt(2)
     135const float _Complex _1_SQRT_2 = M_SQRT1_2 + 0.0_iF;    // 1 / sqrt(2)
     136
     137const double _Complex E = M_E + 0.0_iD;                                 // e
     138const double _Complex LOG2_E = M_LOG2E + 0.0_iD;                // log_2(e)
     139const double _Complex LOG10_E = M_LOG10E + 0.0_iD;              // log_10(e)
     140const double _Complex LN_2 = M_LN2 + 0.0_iD;                    // log_e(2)
     141const double _Complex LN_10 = M_LN10 + 0.0_iD;                  // log_e(10)
     142const double _Complex SQRT_2 = M_SQRT2 + 0.0_iD;                // sqrt(2)
     143const double _Complex _1_SQRT_2 = M_SQRT1_2 + 0.0_iD;   // 1 / sqrt(2)
     144
     145const long double _Complex E = M_El + 0.0_iL;                   // e
     146const long double _Complex LOG2_E = M_LOG2El + 0.0_iL;  // log_2(e)
     147const long double _Complex LOG10_E = M_LOG10El + 0.0_iL; // log_10(e)
     148const long double _Complex LN_2 = M_LN2l + 0.0_iL;              // log_e(2)
     149const long double _Complex LN_10 = M_LN10l + 0.0_iL;    // log_e(10)
     150const long double _Complex SQRT_2 = M_SQRT2l + 0.0_iL;  // sqrt(2)
     151const long double _Complex _1_SQRT_2 = M_SQRT1_2l + 0.0_iL; // 1 / sqrt(2)
    118152
    119153// Local Variables: //
  • src/tests/.expect/KRfunctions.x86.txt

    r094476d rcaa649b  
    8282    signed int __a__i_2;
    8383    signed int __b__i_2;
    84     signed int *(*_tmp_cp_ret0)(signed int __x__i_1, signed int __y__i_1);
    85     ((void)(__x__PFPi_ii__2=(((void)(_tmp_cp_ret0=__f10__FPFPi_ii__iPiPid__1(3, (&__a__i_2), (&__b__i_2), 3.5))) , _tmp_cp_ret0)));
    86     ((void)(_tmp_cp_ret0) /* ^?{} */);
     84    signed int *(*_tmp_cp_ret2)(signed int __x__i_1, signed int __y__i_1);
     85    ((void)(__x__PFPi_ii__2=(((void)(_tmp_cp_ret2=__f10__FPFPi_ii__iPiPid__1(3, (&__a__i_2), (&__b__i_2), 3.5))) , _tmp_cp_ret2)));
     86    ((void)(_tmp_cp_ret2) /* ^?{} */);
    8787    const signed int __f1__FCi_iPiPi__2(signed int __a__i_2, signed int *__b__Pi_2, signed int *__c__Pi_2){
    8888        __attribute__ ((unused)) const signed int ___retval_f1__Ci_2;
  • src/tests/.expect/literals.x64.txt

    r094476d rcaa649b  
    522522signed int __main__Fi___1(){
    523523    __attribute__ ((unused)) signed int ___retval_main__i_1;
     524    ((void)0b01101011);
     525    ((void)0b01101011u);
     526    ((void)0b01101011l);
     527    ((void)0b01101011ll);
     528    ((void)0b01101011ul);
     529    ((void)0b01101011lu);
     530    ((void)0b01101011ull);
     531    ((void)0b01101011llu);
     532    ((void)(+0b01101011));
     533    ((void)(+0b01101011u));
     534    ((void)(+0b01101011l));
     535    ((void)(+0b01101011ll));
     536    ((void)(+0b01101011ul));
     537    ((void)(+0b01101011lu));
     538    ((void)(+0b01101011ull));
     539    ((void)(+0b01101011llu));
     540    ((void)(-0b01101011));
     541    ((void)(-0b01101011u));
     542    ((void)(-0b01101011l));
     543    ((void)(-0b01101011ll));
     544    ((void)(-0b01101011ul));
     545    ((void)(-0b01101011lu));
     546    ((void)(-0b01101011ull));
     547    ((void)(-0b01101011llu));
    524548    ((void)01234567);
    525549    ((void)01234567u);
     
    10171041    ((void)(-0X0123456789.0123456789P-09F));
    10181042    ((void)(-0X0123456789.0123456789P-09L));
     1043    ((void)((signed char )0b01101011));
     1044    ((void)((signed short int )0b01101011));
     1045    ((void)((signed int )0b01101011));
     1046    ((void)((signed long int )0b01101011));
     1047    ((void)((__int128 )0b01101011));
     1048    ((void)((unsigned char )0b01101011u));
     1049    ((void)((signed short int )0b01101011u));
     1050    ((void)((unsigned int )0b01101011u));
     1051    ((void)((signed long int )0b01101011u));
     1052    ((void)((__int128 )0b01101011u));
     1053    ((void)(+((signed int )((signed char )0b01101011))));
     1054    ((void)(+((signed int )((signed short int )0b01101011))));
     1055    ((void)(+((signed int )0b01101011)));
     1056    ((void)(+((signed long int )0b01101011)));
     1057    ((void)(+((float )((__int128 )0b01101011))));
     1058    ((void)(+((signed int )((unsigned char )0b01101011u))));
     1059    ((void)(+((signed int )((signed short int )0b01101011u))));
     1060    ((void)(+((unsigned int )0b01101011u)));
     1061    ((void)(+((signed long int )0b01101011u)));
     1062    ((void)(+((float )((__int128 )0b01101011u))));
     1063    ((void)(-((signed int )((signed char )0b01101011))));
     1064    ((void)(-((signed int )((signed short int )0b01101011))));
     1065    ((void)(-((signed int )0b01101011)));
     1066    ((void)(-((signed long int )0b01101011)));
     1067    ((void)(-((float )((__int128 )0b01101011))));
     1068    ((void)(-((signed int )((unsigned char )0b01101011u))));
     1069    ((void)(-((signed int )((signed short int )0b01101011u))));
     1070    ((void)(-((unsigned int )0b01101011u)));
     1071    ((void)(-((signed long int )0b01101011u)));
     1072    ((void)(-((float )((__int128 )0b01101011u))));
    10191073    ((void)((signed char )01234567));
    10201074    ((void)((signed short int )01234567));
  • src/tests/.expect/user_literals.txt

    r094476d rcaa649b  
    1111.0714285714286
    2 11.07225
     215
    3311.0714285714286
     424.8
     511.248
    4611.0714285714286
    5 11.0714285714286
    6 22.0457142857143
     728.0657142857143
    78secs 1
    89secs 23
  • src/tests/Makefile.am

    r094476d rcaa649b  
    123123        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
    124124
     125# Warnings
     126warnings/self-assignment: warnings/self-assignment.c @CFA_BINDIR@/@CFA_NAME@
     127        ${CC} ${AM_CFLAGS} ${CFLAGS} ${<} 2> ${@} -fsyntax-only
  • src/tests/Makefile.in

    r094476d rcaa649b  
    800800        ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}
    801801
     802# Warnings
     803warnings/self-assignment: warnings/self-assignment.c @CFA_BINDIR@/@CFA_NAME@
     804        ${CC} ${AM_CFLAGS} ${CFLAGS} ${<} 2> ${@} -fsyntax-only
     805
    802806# Tell versions [3.59,3.63) of GNU make to not export all variables.
    803807# Otherwise a system limit (for SysV at least) may be exceeded.
  • src/tests/limits.c

    r094476d rcaa649b  
    1010// Created On       : Tue May 10 20:44:20 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 10 20:45:28 2016
    13 // Update Count     : 1
     12// Last Modified On : Thu Mar  1 16:21:55 2018
     13// Update Count     : 7
    1414//
    1515
     
    1818// Integral Constants
    1919
     20signed char m = MIN;
     21unsigned char m = MIN;
    2022short int m = MIN;
     23unsigned short int m = MIN;
    2124int m = MIN;
     25unsigned int m = MIN;
    2226long int m = MIN;
     27unsigned long int m = MIN;
    2328long long int m = MIN;
     29unsigned long long int m = MIN;
    2430
     31signed char M = MAX;
     32unsigned char M = MAX;
    2533short int M = MAX;
    2634unsigned short int M = MAX;
     
    3341
    3442// Floating-Point Constants
     43
     44float m = MIN;
     45double m = MIN;
     46long double m = MIN;
     47float _Complex m = MIN;
     48double _Complex m = MIN;
     49long double _Complex m = MIN;
     50
     51float M = MAX;
     52double M = MAX;
     53long double M = MAX;
     54float _Complex M = MAX;
     55double _Complex M = MAX;
     56long double _Complex M = MAX;
    3557
    3658float pi = PI;
     
    5577long double _2_sqrt_pi = _2_SQRT_PI;
    5678
    57 _Complex pi = PI;
    58 _Complex pi_2 = PI_2;
    59 _Complex pi_4 = PI_4;
    60 _Complex _1_pi = _1_PI;
    61 _Complex _2_pi = _2_PI;
    62 _Complex _2_sqrt_pi = _2_SQRT_PI;
     79float _Complex pi = PI;
     80float _Complex pi_2 = PI_2;
     81float _Complex pi_4 = PI_4;
     82float _Complex _1_pi = _1_PI;
     83float _Complex _2_pi = _2_PI;
     84float _Complex _2_sqrt_pi = _2_SQRT_PI;
    6385
    64 long _Complex pi = PI;
    65 long _Complex pi_2 = PI_2;
    66 long _Complex pi_4 = PI_4;
    67 long _Complex _1_pi = _1_PI;
    68 long _Complex _2_pi = _2_PI;
    69 long _Complex _2_sqrt_pi = _2_SQRT_PI;
     86double _Complex pi = PI;
     87double _Complex pi_2 = PI_2;
     88double _Complex pi_4 = PI_4;
     89double _Complex _1_pi = _1_PI;
     90double _Complex _2_pi = _2_PI;
     91double _Complex _2_sqrt_pi = _2_SQRT_PI;
     92
     93long double _Complex pi = PI;
     94long double _Complex pi_2 = PI_2;
     95long double _Complex pi_4 = PI_4;
     96long double _Complex _1_pi = _1_PI;
     97long double _Complex _2_pi = _2_PI;
     98long double _Complex _2_sqrt_pi = _2_SQRT_PI;
    7099
    71100float e = E;
     
    93122long double _1_sqrt_2 = _1_SQRT_2;
    94123
    95 _Complex e = E;
    96 _Complex log2_e = LOG2_E;
    97 _Complex log10_e = LOG10_E;
    98 _Complex ln_2 = LN_2;
    99 _Complex ln_10 = LN_10;
    100 _Complex sqrt_2 = SQRT_2;
    101 _Complex _1_sqrt_2 = _1_SQRT_2;
     124float _Complex e = E;
     125float _Complex log2_e = LOG2_E;
     126float _Complex log10_e = LOG10_E;
     127float _Complex ln_2 = LN_2;
     128float _Complex ln_10 = LN_10;
     129float _Complex sqrt_2 = SQRT_2;
     130float _Complex _1_sqrt_2 = _1_SQRT_2;
    102131
    103 long _Complex e = E;
    104 long _Complex log2_e = LOG2_E;
    105 long _Complex log10_e = LOG10_E;
    106 long _Complex ln_2 = LN_2;
    107 long _Complex ln_10 = LN_10;
    108 long _Complex sqrt_2 = SQRT_2;
    109 long _Complex _1_sqrt_2 = _1_SQRT_2;
     132double _Complex e = E;
     133double _Complex log2_e = LOG2_E;
     134double _Complex log10_e = LOG10_E;
     135double _Complex ln_2 = LN_2;
     136double _Complex ln_10 = LN_10;
     137double _Complex sqrt_2 = SQRT_2;
     138double _Complex _1_sqrt_2 = _1_SQRT_2;
     139
     140long double _Complex e = E;
     141long double _Complex log2_e = LOG2_E;
     142long double _Complex log10_e = LOG10_E;
     143long double _Complex ln_2 = LN_2;
     144long double _Complex ln_10 = LN_10;
     145long double _Complex sqrt_2 = SQRT_2;
     146long double _Complex _1_sqrt_2 = _1_SQRT_2;
    110147
    111148int main(int argc, char const *argv[]) {
  • src/tests/literals.c

    r094476d rcaa649b  
    1010// Created On       : Sat Sep  9 16:34:38 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Sep 25 20:26:00 2017
    13 // Update Count     : 132
     12// Last Modified On : Sun Mar  4 10:41:31 2018
     13// Update Count     : 134
    1414//
    1515
     
    3131// integer literals
    3232
     33        // binary
     34         0b01101011;   0b01101011u;   0b01101011l;   0b01101011ll;   0b01101011ul;   0b01101011lu;   0b01101011ull;   0b01101011llu;
     35        +0b01101011;  +0b01101011u;  +0b01101011l;  +0b01101011ll;  +0b01101011ul;  +0b01101011lu;  +0b01101011ull;  +0b01101011llu;
     36        -0b01101011;  -0b01101011u;  -0b01101011l;  -0b01101011ll;  -0b01101011ul;  -0b01101011lu;  -0b01101011ull;  -0b01101011llu;
     37
    3338        // octal
    3439         01234567;   01234567u;   01234567l;   01234567ll;   01234567ul;   01234567lu;   01234567ull;   01234567llu;
     
    148153#ifdef __CFA__
    149154// fixed-size length
     155
     156        // binary
     157         0b01101011_l8;   0b01101011_l16;   0b01101011_l32;   0b01101011_l64;   0b01101011_l128;   0b01101011_l8u;   0b01101011_ul16;   0b01101011_l32u;   0b01101011_ul64;   0b01101011_ul128;
     158        +0b01101011_l8;  +0b01101011_l16;  +0b01101011_l32;  +0b01101011_l64;  +0b01101011_l128;  +0b01101011_l8u;  +0b01101011_ul16;  +0b01101011_l32u;  +0b01101011_ul64;  +0b01101011_ul128;
     159        -0b01101011_l8;  -0b01101011_l16;  -0b01101011_l32;  -0b01101011_l64;  -0b01101011_l128;  -0b01101011_l8u;  -0b01101011_ul16;  -0b01101011_l32u;  -0b01101011_ul64;  -0b01101011_ul128;
    150160
    151161        // octal
  • src/tests/user_literals.c

    r094476d rcaa649b  
    1010// Created On       : Wed Sep  6 21:40:50 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Dec  7 09:12:36 2017
    13 // Update Count     : 50
     12// Last Modified On : Sun Mar  4 11:14:02 2018
     13// Update Count     : 52
    1414//
    1515
     
    3131
    3232
    33 struct Weight {
    34         double stones;
    35 };
    36 void ?{}( Weight & w ) { w.stones = 0; }                                // operations
     33struct Weight { double stones; };
     34void ?{}( Weight & w ) { w.stones = 0; }
    3735void ?{}( Weight & w, double w ) { w.stones = w; }
    38 Weight ?+?( Weight l, Weight r ) { return (Weight){ l.stones + r.stones }; }
     36Weight ?+?( Weight l, Weight r ) {
     37        return (Weight){ l.stones + r.stones };
     38}
    3939ofstream & ?|?( ofstream & os, Weight w ) { return os | w.stones; }
    4040
    4141Weight ?`st( double w ) { return (Weight){ w }; }               // backquote for user literals
    4242Weight ?`lb( double w ) { return (Weight){ w / 14.0 }; }
    43 Weight ?`kg( double w ) { return (Weight) { w * 0.1575}; }
    44 
     43Weight ?`kg( double w ) { return (Weight) { w * 0.16 }; }
    4544
    4645int main() {
    47         Weight w, hw = { 14 };                                                          // 14 stone
    48         w = 11`st + 1`lb;
     46        Weight w, heavy = { 20 };                                                       // 20 stone
     47        w = 155`lb;
     48        sout | w | endl;
     49        w = 0b_1111`st;
     50        sout | w | endl;
     51        w = 0_233`lb;                                                                           // octal weight (155)
     52        sout | w | endl;
     53        w = 0x_9b_u`kg;
    4954        sout | w | endl;
    5055        w = 70.3`kg;
    5156        sout | w | endl;
    52         w = 155`lb;
     57        w = 11`st + 1`lb;
    5358        sout | w | endl;
    54         w = 0x_9b_u`lb;                                                                         // hexadecimal unsigned weight (155)
    55         sout | w | endl;
    56         w = 0_233`lb;                                                                           // octal weight (155)
    57         sout | w | endl;
    58         w = 5`st + 8`kg + 25`lb + hw;
     59        w = 5`st + 8`kg + 25`lb + heavy;
    5960        sout | w | endl;
    6061
Note: See TracChangeset for help on using the changeset viewer.