Changeset ff29f08 for doc/papers/general


Ignore:
Timestamp:
May 18, 2018, 2:09:21 PM (7 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
new-env, with_gc
Children:
2472a19
Parents:
f6f0cca3 (diff), c7d8100c (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 remote-tracking branch 'origin/master' into with_gc

Location:
doc/papers/general
Files:
1 added
18 edited

Legend:

Unmodified
Added
Removed
  • doc/papers/general/.gitignore

    rf6f0cca3 rff29f08  
    88Paper.out.ps
    99WileyNJD-AMA.bst
     10evaluation.zip
  • doc/papers/general/Makefile

    rf6f0cca3 rff29f08  
    4545        @rm -frv ${DOCUMENT} ${BASE}.ps WileyNJD-AMA.bst ${BASE}.out.ps ${Build}
    4646
     47Paper.zip :
     48        zip -x general/.gitignore -x general/"*AMA*" -x general/Paper.out.ps -x general/Paper.tex.plain -x general/evaluation.zip -x general/mail -x general/response -x general/test.c -x general/evaluation.zip -x general/Paper.tex.plain -x general/Paper.ps -x general/Paper.pdf -x general/"*build*" -x general/evaluation/.gitignore -x general/evaluation/timing.xlsx -r Paper.zip general
     49
     50evaluation.zip :
     51        zip -x evaluation/.gitignore  -x evaluation/timing.xlsx -x evaluation/timing.dat -r evaluation.zip evaluation
     52
    4753# File Dependencies #
    4854
     
    6672## Define the default recipes.
    6773
    68 ${Build}:
     74${Build} :
    6975        mkdir -p ${Build}
    7076
    71 ${BASE}.out.ps:
    72         ln -fs build/Paper.out.ps .
     77${BASE}.out.ps : ${Build}
     78        ln -fs ${Build}/Paper.out.ps .
    7379
    74 WileyNJD-AMA.bst:
     80WileyNJD-AMA.bst :
    7581        ln -fs ../AMA/AMA-stix/ama/WileyNJD-AMA.bst .
    7682
    77 ${GRAPHS} : timing.gp timing.dat
     83${GRAPHS} : ${Build} timing.gp timing.dat
    7884        gnuplot -e Build="'${Build}/'" evaluation/timing.gp
    7985
    80 %.tex : %.fig
     86%.tex : %.fig ${Build}
    8187        fig2dev -L eepic $< > ${Build}/$@
    8288
    83 %.ps : %.fig
     89%.ps : %.fig ${Build}
    8490        fig2dev -L ps $< > ${Build}/$@
    8591
    86 %.pstex : %.fig
     92%.pstex : %.fig ${Build}
    8793        fig2dev -L pstex $< > ${Build}/$@
    8894        fig2dev -L pstex_t -p ${Build}/$@ $< > ${Build}/$@_t
  • doc/papers/general/Paper.tex

    rf6f0cca3 rff29f08  
    5454\newcommand{\TODO}[1]{} % TODO elided
    5555
     56%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     57
    5658% Default underscore is too low and wide. Cannot use lstlisting "literate" as replacing underscore
    5759% removes it as a variable-name character so keywords in variables are highlighted. MUST APPEAR
     
    6062\renewcommand{\textunderscore}{\leavevmode\makebox[1.2ex][c]{\rule{1ex}{0.075ex}}}
    6163
     64\renewcommand*{\thefootnote}{\Alph{footnote}} % hack because fnsymbol does not work
     65%\renewcommand*{\thefootnote}{\fnsymbol{footnote}}
     66
    6267\makeatletter
    6368% parindent is relative, i.e., toggled on/off in environments like itemize, so store the value for
     
    7479\setlength{\gcolumnposn}{3.5in}
    7580\setlength{\columnposn}{\gcolumnposn}
     81
    7682\newcommand{\C}[2][\@empty]{\ifx#1\@empty\else\global\setlength{\columnposn}{#1}\global\columnposn=\columnposn\fi\hfill\makebox[\textwidth-\columnposn][l]{\lst@basicstyle{\LstCommentStyle{#2}}}}
    7783\newcommand{\CRT}{\global\columnposn=\gcolumnposn}
     
    159165literate={-}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.1ex}}}}1 {^}{\raisebox{0.6ex}{$\scriptstyle\land\,$}}1
    160166        {~}{\raisebox{0.3ex}{$\scriptstyle\sim\,$}}1 % {`}{\ttfamily\upshape\hspace*{-0.1ex}`}1
    161         {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1ex][c]{\raisebox{0.4ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex{\textgreater}}2,
     167        {<}{\textrm{\textless}}1 {>}{\textrm{\textgreater}}1
     168        {<-}{$\leftarrow$}2 {=>}{$\Rightarrow$}2 {->}{\makebox[1ex][c]{\raisebox{0.5ex}{\rule{0.8ex}{0.075ex}}}\kern-0.2ex{\textrm{\textgreater}}}2,
    162169moredelim=**[is][\color{red}]{`}{`},
    163170}% lstset
     
    173180\lstMakeShortInline@%
    174181
     182\let\OLDthebibliography\thebibliography
     183\renewcommand\thebibliography[1]{
     184  \OLDthebibliography{#1}
     185  \setlength{\parskip}{0pt}
     186  \setlength{\itemsep}{4pt plus 0.3ex}
     187}
    175188
    176189\title{\texorpdfstring{\protect\CFA : Adding Modern Programming Language Features to C}{Cforall : Adding Modern Programming Language Features to C}}
     
    190203The 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.
    191204This installation base and the programmers producing it represent a massive software-engineering investment spanning decades and likely to continue for decades more.
    192 Nevertheless, C, first standardized over thirty years ago, lacks many features that make programming in more modern languages safer and more productive.
    193 
    194 The goal of the \CFA project is to create an extension of C that provides modern safety and productivity features while still ensuring strong backwards compatibility with C and its programmers.
    195 Prior projects have attempted similar goals but failed to honour C programming-style; for instance, adding object-oriented or functional programming with garbage collection is a non-starter for many C developers.
     205Nevertheless, C, first standardized almost forty years ago, lacks many features that make programming in more modern languages safer and more productive.
     206
     207The goal of the \CFA project (pronounced ``C-for-all'') is to create an extension of C that provides modern safety and productivity features while still ensuring strong backwards compatibility with C and its programmers.
     208Prior projects have attempted similar goals but failed to honour C programming-style;
     209for instance, adding object-oriented or functional programming with garbage collection is a non-starter for many C developers.
    196210Specifically, \CFA is designed to have an orthogonal feature-set based closely on the C programming paradigm, so that \CFA features can be added \emph{incrementally} to existing C code-bases, and C programmers can learn \CFA extensions on an as-needed basis, preserving investment in existing code and programmers.
    197211This paper presents a quick tour of \CFA features showing how their design avoids shortcomings of similar features in C and other C-like languages.
     
    227241Love it or hate it, C is extremely popular, highly used, and one of the few systems languages.
    228242In many cases, \CC is often used solely as a better C.
    229 Nevertheless, C, first standardized over thirty years ago, lacks many features that make programming in more modern languages safer and more productive.
    230 
    231 \CFA (pronounced ``C-for-all'', and written \CFA or Cforall) is an evolutionary extension of the C programming language that aims to add modern language features to C, while maintaining both source and runtime compatibility with C and a familiar programming model for programmers.
     243Nevertheless, C, first standardized almost forty years ago~\cite{ANSI89:C}, lacks many features that make programming in more modern languages safer and more productive.
     244
     245\CFA (pronounced ``C-for-all'', and written \CFA or Cforall) is an evolutionary extension of the C programming language that adds modern language-features to C, while maintaining both source and runtime compatibility with C and a familiar programming model for programmers.
    232246The four key design goals for \CFA~\cite{Bilson03} are:
    233247(1) The behaviour of standard C code must remain the same when translated by a \CFA compiler as when translated by a C compiler;
     
    238252\CC is used similarly, but has the disadvantages of multiple legacy design-choices that cannot be updated and active divergence of the language model from C, requiring significant effort and training to incrementally add \CC to a C-based project.
    239253
    240 \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).
     254All languages features discussed in this paper are working, except some advanced exception-handling features.
     255Not discussed in this paper are the integrated concurrency-constructs and user-level threading-library~\cite{Delisle18}.
     256\CFA is an \emph{open-source} project 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).
    241257Ultimately, a compiler is necessary for advanced features and optimal performance.
    242 All features discussed in this paper are working, unless otherwise stated as under construction.
     258% @plg2[9]% cd cfa-cc/src; cloc ArgTweak CodeGen CodeTools Common Concurrency ControlStruct Designators GenPoly InitTweak MakeLibCfa.cc MakeLibCfa.h Parser ResolvExpr SymTab SynTree Tuples driver prelude main.cc
     259% -------------------------------------------------------------------------------
     260% Language                     files          blank        comment           code
     261% -------------------------------------------------------------------------------
     262% C++                            108           5420           5232          34961
     263% C/C++ Header                    86           2379           2450           8464
     264% Teamcenter def                   2            115             65           1387
     265% make                             5            168             87           1052
     266% C                               20            109            403            488
     267% awk                              1             12             26            121
     268% sed                              1              0              0              6
     269% -------------------------------------------------------------------------------
     270% SUM:                           223           8203           8263          46479
     271% -------------------------------------------------------------------------------
     272The \CFA translator is 200+ files and 46,000+ lines of code written in C/\CC.
     273Starting with a translator versus a compiler makes it easier and faster to generate and debug C object-code rather than intermediate, assembler or machine code.
     274The translator design is based on the \emph{visitor pattern}, allowing multiple passes over the abstract code-tree, which works well for incrementally adding new feature through additional visitor passes.
     275At the heart of the translator is the type resolver, which handles the polymorphic routine/type overload-resolution.
     276% @plg2[8]% cd cfa-cc/src; cloc libcfa
     277% -------------------------------------------------------------------------------
     278% Language                     files          blank        comment           code
     279% -------------------------------------------------------------------------------
     280% C                               35           1256           1240           9116
     281% C/C++ Header                    54            358           1106           1198
     282% make                             2            201            325           1167
     283% C++                              3             18             17            124
     284% Assembly                         3             56             97            111
     285% Bourne Shell                     2              2              0             25
     286% awk                              1              4              0             22
     287% -------------------------------------------------------------------------------
     288% SUM:                           100           1895           2785          11763
     289% -------------------------------------------------------------------------------
     290The \CFA runtime system is 100+ files and 11,000+ lines of code, written in \CFA.
     291Currently, the \CFA runtime is the largest \emph{user} of \CFA providing a vehicle to test the language features and implementation.
     292% @plg2[6]% cd cfa-cc/src; cloc tests examples benchmark
     293% -------------------------------------------------------------------------------
     294% Language                     files          blank        comment           code
     295% -------------------------------------------------------------------------------
     296% C                              237          12260           2869          23286
     297% make                             8            464            245           2838
     298% C/C++ Header                    22            225            175            785
     299% Python                           5            131             93            420
     300% C++                             10             48              5            201
     301% Lua                              2             31              4            126
     302% Java                             4              5              0             80
     303% Go                               2             11              9             40
     304% -------------------------------------------------------------------------------
     305% SUM:                           290          13175           3400          27776
     306% -------------------------------------------------------------------------------
     307The \CFA tests are 290+ files and 27,000+ lines of code.
     308The tests illustrate syntactic and semantic features in \CFA, plus a growing number of runtime benchmarks.
     309The tests check for correctness and are used for daily regression testing of 3800+ commits.
    243310
    244311Finally, it is impossible to describe a programming language without usages before definitions.
     
    261328There are only two hard things in Computer Science: cache invalidation and \emph{naming things} -- Phil Karlton
    262329\end{quote}
     330\vspace{-9pt}
    263331C 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.
    264332\CFA extends the built-in operator overloading by allowing users to define overloads for any function, not just operators, and even any variable;
     
    266334Code generation for these overloaded functions and variables is implemented by the usual approach of mangling the identifier names to include a representation of their type, while \CFA decides which overload to apply based on the same ``usual arithmetic conversions'' used in C to disambiguate operator overloads.
    267335As an example:
    268 
    269 \begin{cfa}
    270 int max = 2147483647;                                   $\C[4in]{// (1)}$
    271 double max = 1.7976931348623157E+308;   $\C{// (2)}$
     336\begin{cfa}
     337int max = 2147483647;                                           $\C[4in]{// (1)}$
     338double max = 1.7976931348623157E+308;           $\C{// (2)}$
    272339int max( int a, int b ) { return a < b ? b : a; }  $\C{// (3)}$
    273340double max( double a, double b ) { return a < b ? b : a; }  $\C{// (4)}\CRT$
    274 max( 7, -max );                                         $\C[2.75in]{// uses (3) and (1), by matching int from constant 7}$
     341max( 7, -max );                                         $\C{// uses (3) and (1), by matching int from constant 7}$
    275342max( max, 3.14 );                                       $\C{// uses (4) and (2), by matching double from constant 3.14}$
    276 max( max, -max );                                       $\C{// ERROR: ambiguous}$
    277 int m = max( max, -max );                       $\C{// uses (3) and (1) twice, by matching return type}\CRT$
     343max( max, -max );                                       $\C{// ERROR, ambiguous}$
     344int m = max( max, -max );                       $\C{// uses (3) and (1) twice, by matching return type}$
    278345\end{cfa}
    279346
     
    284351As 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.
    285352
    286 \Celeven added @_Generic@ expressions, which is used in preprocessor macros to provide a form of ad-hoc polymorphism;
     353\Celeven added @_Generic@ expressions~\cite[\S~6.5.1.1]{C11}, which is used with preprocessor macros to provide ad-hoc polymorphism;
    287354however, this polymorphism is both functionally and ergonomically inferior to \CFA name overloading.
    288355The macro wrapping the generic expression imposes some limitations;
    289356\eg, it cannot implement the example above, because the variables @max@ are ambiguous with the functions @max@.
    290357Ergonomic 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 dispatch functions, which must all have distinct names.
    291 For backwards compatibility, \CFA supports @_Generic@ expressions, but it is an unnecessary mechanism. \TODO{actually implement that}
     358\CFA supports @_Generic@ expressions for backwards compatibility, but it is an unnecessary mechanism. \TODO{actually implement that}
    292359
    293360% http://fanf.livejournal.com/144696.html
     
    317384\begin{cfa}
    318385forall( otype T `| { T ?+?(T, T); }` ) T twice( T x ) { return x `+` x; }  $\C{// ? denotes operands}$
    319 int val = twice( twice( 3.7 ) );
     386int val = twice( twice( 3.7 ) );  $\C{// val == 14}$
    320387\end{cfa}
    321388which works for any type @T@ with a matching addition operator.
    322389The polymorphism is achieved by creating a wrapper function for calling @+@ with @T@ bound to @double@, then passing this function to the first call of @twice@.
    323390There is now the option of using the same @twice@ and converting the result to @int@ on assignment, or creating another @twice@ with type parameter @T@ bound to @int@ because \CFA uses the return type~\cite{Cormack81,Baker82,Ada} in its type analysis.
    324 The first approach has a late conversion from @double@ to @int@ on the final assignment, while the second has an eager conversion to @int@.
     391The first approach has a late conversion from @double@ to @int@ on the final assignment, while the second has an early conversion to @int@.
    325392\CFA minimizes the number of conversions and their potential to lose information, so it selects the first approach, which corresponds with C-programmer intuition.
    326393
     
    329396A simple example is leveraging the existing type-unsafe (@void *@) C @bsearch@ to binary search a sorted float array:
    330397\begin{cfa}
    331 void * bsearch( const void * key, const void * base, size_t nmemb, size_t size, int (* compar)( const void *, const void * ));
     398void * bsearch( const void * key, const void * base, size_t nmemb, size_t size,
     399                                int (* compar)( const void *, const void * ));
    332400int comp( const void * t1, const void * t2 ) {
    333401         return *(double *)t1 < *(double *)t2 ? -1 : *(double *)t2 < *(double *)t1 ? 1 : 0;
     
    355423
    356424\CFA has replacement libraries condensing hundreds of existing C functions into tens of \CFA overloaded functions, all without rewriting the actual computations (see Section~\ref{sec:libraries}).
    357 For example, it is possible to write a type-safe \CFA wrapper @malloc@ based on the C @malloc@:
     425For example, it is possible to write a type-safe \CFA wrapper @malloc@ based on the C @malloc@, where the return type supplies the type/size of the allocation, which is impossible in most type systems.
    358426\begin{cfa}
    359427forall( dtype T | sized(T) ) T * malloc( void ) { return (T *)malloc( sizeof(T) ); }
    360 int * ip = malloc();                                            $\C{// select type and size from left-hand side}$
    361 double * dp = malloc();
    362 struct S {...} * sp = malloc();
    363 \end{cfa}
    364 where the return type supplies the type/size of the allocation, which is impossible in most type systems.
     428// select type and size from left-hand side
     429int * ip = malloc();  double * dp = malloc();  struct S {...} * sp = malloc();
     430\end{cfa}
    365431
    366432Call-site inferencing and nested functions provide a localized form of inheritance.
     
    369435\begin{cfa}
    370436forall( otype T | { int ?<?( T, T ); } ) void qsort( const T * arr, size_t size ) { /* use C qsort */ }
    371 {
     437int main() {
    372438        int ?<?( double x, double y ) { return x `>` y; } $\C{// locally override behaviour}$
    373         qsort( vals, size );                                    $\C{// descending sort}$
    374 }
    375 \end{cfa}
    376 Within the block, the nested version of @?<?@ performs @?>?@ and this local version overrides the built-in @?<?@ so it is passed to @qsort@.
     439        qsort( vals, 10 );                                                      $\C{// descending sort}$
     440}
     441\end{cfa}
     442The local version of @?<?@ performs @?>?@ overriding the built-in @?<?@ so it is passed to @qsort@.
    377443Hence, programmers can easily form local environments, adding and modifying appropriate functions, to maximize reuse of other existing functions and types.
    378444
    379 Under construction is a mechanism to distribute @forall@ over routines/types, where each block declaration is prefixed with the initial @forall@ clause significantly reducing duplication (see @stack@ examples in Section~\ref{sec:eval}):
    380 \begin{cfa}
    381 forall( otype `T` ) {                                                   $\C{// forall block}$
     445To reduce duplication, it is possible to distribute a group of @forall@ (and storage-class qualifiers) over functions/types, so each block declaration is prefixed by the group (see example in Appendix~\ref{s:CforallStack}).
     446\begin{cfa}
     447forall( otype `T` ) {                                                   $\C{// distribution block, add forall qualifier to declarations}$
    382448        struct stack { stack_node(`T`) * head; };       $\C{// generic type}$
    383         void push( stack(`T`) & s, `T` value ) ...      $\C{// generic operations}$
    384         T pop( stack(`T`) & s ) ...
    385 }
    386 \end{cfa}
    387 
    388 
     449        inline {                                                                        $\C{// nested distribution block, add forall/inline to declarations}$
     450                void push( stack(`T`) & s, `T` value ) ...      $\C{// generic operations}$
     451        }
     452}
     453\end{cfa}
     454
     455
     456\vspace*{-2pt}
    389457\subsection{Traits}
    390458
    391459\CFA provides \newterm{traits} to name a group of type assertions, where the trait name allows specifying the same set of assertions in multiple locations, preventing repetition mistakes at each function declaration:
    392 \begin{cfa}
    393 trait `summable`( otype T ) {
    394         void ?{}( T *, zero_t );                                $\C{// constructor from 0 literal}$
    395         T ?+?( T, T );                                                  $\C{// assortment of additions}$
    396         T ?+=?( T *, T );
    397         T ++?( T * );
    398         T ?++( T * );
     460
     461\begin{cquote}
     462\lstDeleteShortInline@%
     463\begin{tabular}{@{}l@{\hspace{\parindentlnth}}|@{\hspace{\parindentlnth}}l@{}}
     464\begin{cfa}
     465trait `sumable`( otype T ) {
     466        void `?{}`( T &, zero_t ); // 0 literal constructor
     467        T ?+?( T, T );                   // assortment of additions
     468        T `?+=?`( T &, T );
     469        T ++?( T & );
     470        T ?++( T & );
    399471};
    400 forall( otype T `| summable( T )` ) T sum( T a[$\,$], size_t size ) {$\C{// use trait}$
    401         `T` total = { `0` };                                    $\C{// instantiate T from 0 by calling its constructor}$
    402         for ( unsigned int i = 0; i < size; i += 1 ) total `+=` a[i]; $\C{// select appropriate +}$
     472\end{cfa}
     473&
     474\begin{cfa}
     475forall( otype T `| sumable( T )` ) // use trait
     476T sum( T a[$\,$], size_t size ) {
     477        `T` total = { `0` };  // initialize by 0 constructor
     478        for ( size_t i = 0; i < size; i += 1 )
     479                total `+=` a[i]; // select appropriate +
    403480        return total;
    404481}
    405482\end{cfa}
    406 
    407 In fact, the set of @summable@ trait operators is incomplete, as it is missing assignment for type @T@, but @otype@ is syntactic sugar for the following implicit trait:
     483\end{tabular}
     484\lstMakeShortInline@%
     485\end{cquote}
     486
     487Note, the @sumable@ trait does not include a copy constructor needed for the right side of @?+=?@ and return;
     488it is provided by @otype@, which is syntactic sugar for the following trait:
    408489\begin{cfa}
    409490trait otype( dtype T | sized(T) ) {  // sized is a pseudo-trait for types with known size and alignment
     
    423504Instead, each polymorphic function (or generic type) defines the structural type needed for its execution (polymorphic type-key), and this key is fulfilled at each call site from the lexical environment, which is similar to Go~\cite{Go} interfaces.
    424505Hence, new lexical scopes and nested functions are used extensively to create local subtypes, as in the @qsort@ example, without having to manage a nominal-inheritance hierarchy.
    425 (Nominal inheritance can be approximated with traits using marker variables or functions, as is done in Go.)
     506% (Nominal inheritance can be approximated with traits using marker variables or functions, as is done in Go.)
    426507
    427508% Nominal inheritance can be simulated with traits using marker variables or functions:
     
    462543
    463544\CC, Java, and other languages use \newterm{generic types} to produce type-safe abstract data-types.
    464 \CFA also implements generic types that integrate efficiently and naturally with the existing polymorphic functions, while retaining backwards compatibility with C and providing separate compilation.
     545\CFA generic types integrate efficiently and naturally with the existing polymorphic functions, while retaining backwards compatibility with C and providing separate compilation.
    465546However, for known concrete parameters, the generic-type definition can be inlined, like \CC templates.
    466547
    467548A generic type can be declared by placing a @forall@ specifier on a @struct@ or @union@ declaration, and instantiated using a parenthesized list of types after the type name:
    468 \begin{cfa}
    469 forall( otype R, otype S ) struct pair {
    470         R first;
    471         S second;
     549\begin{cquote}
     550\lstDeleteShortInline@%
     551\begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}}
     552\begin{cfa}
     553`forall( otype R, otype S )` struct pair {
     554        R first;        S second;
    472555};
    473 forall( otype T ) T value( pair( const char *, T ) p ) { return p.second; } $\C{// dynamic}$
    474 forall( dtype F, otype T ) T value( pair( F *, T * ) p ) { return *p.second; } $\C{// dtype-static (concrete)}$
    475 
    476 pair( const char *, int ) p = { "magic", 42 }; $\C{// concrete}$
     556`forall( otype T )` // dynamic
     557T value( pair(const char *, T) p ) { return p.second; }
     558`forall( dtype F, otype T )` // dtype-static (concrete)
     559T value( pair(F *, T * ) p) { return *p.second; }
     560\end{cfa}
     561&
     562\begin{cfa}
     563pair(const char *, int) p = {"magic", 42}; // concrete
    477564int i = value( p );
    478 pair( void *, int * ) q = { 0, &p.second }; $\C{// concrete}$
     565pair(void *, int *) q = { 0, &p.second }; // concrete
    479566i = value( q );
    480567double d = 1.0;
    481 pair( double *, double * ) r = { &d, &d }; $\C{// concrete}$
     568pair(double *, double *) r = { &d, &d }; // concrete
    482569d = value( r );
    483570\end{cfa}
     571\end{tabular}
     572\lstMakeShortInline@%
     573\end{cquote}
    484574
    485575\CFA classifies generic types as either \newterm{concrete} or \newterm{dynamic}.
    486576Concrete types have a fixed memory layout regardless of type parameters, while dynamic types vary in memory layout depending on their type parameters.
    487577A \newterm{dtype-static} type has polymorphic parameters but is still concrete.
    488 Polymorphic pointers are an example of dtype-static types, \eg @forall(dtype T) T *@ is a polymorphic type, but for any @T@, @T *@  is a fixed-sized pointer, and therefore, can be represented by a @void *@ in code generation.
     578Polymorphic pointers are an example of dtype-static types;
     579given some type variable @T@, @T@ is a polymorphic type, as is @T *@, but @T *@ has a fixed size and can therefore be represented by @void *@ in code generation.
    489580
    490581\CFA generic types also allow checked argument-constraints.
     
    503594\begin{cfa}
    504595struct _pair_conc0 {
    505         const char * first;
    506         int second;
     596        const char * first;  int second;
    507597};
    508598\end{cfa}
     
    512602\begin{cfa}
    513603struct _pair_conc1 {
    514         void * first;
    515         void * second;
     604        void * first, * second;
    516605};
    517606\end{cfa}
     
    568657Another useful pattern enabled by reused dtype-static type instantiations is zero-cost \newterm{tag-structures}.
    569658Sometimes information is only used for type-checking and can be omitted at runtime, \eg:
     659\begin{cquote}
     660\lstDeleteShortInline@%
     661\begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}}
    570662\begin{cfa}
    571663forall( dtype Unit ) struct scalar { unsigned long value; };
    572664struct metres {};
    573665struct litres {};
    574 
    575666forall( dtype U ) scalar(U) ?+?( scalar(U) a, scalar(U) b ) {
    576667        return (scalar(U)){ a.value + b.value };
    577668}
    578 scalar(metres) half_marathon = { 21_093 };
    579 scalar(litres) swimming_pool = { 2_500_000 };
    580 scalar(metres) marathon = half_marathon + half_marathon;
    581 scalar(litres) two_pools = swimming_pool + swimming_pool;
    582 marathon + swimming_pool;                                       $\C{// compilation ERROR}$
    583 \end{cfa}
     669\end{cfa}
     670&
     671\begin{cfa}
     672scalar(metres) half_marathon = { 21_098 };
     673scalar(litres) pool = { 2_500_000 };
     674scalar(metres) marathon = half_marathon +
     675                                                        half_marathon;
     676scalar(litres) two_pools = pool + pool;
     677`marathon + pool;`      // ERROR, mismatched types
     678\end{cfa}
     679\end{tabular}
     680\lstMakeShortInline@%
     681\end{cquote}
    584682@scalar@ is a dtype-static type, so all uses have a single structure definition, containing @unsigned long@, and can share the same implementations of common functions like @?+?@.
    585683These implementations may even be separately compiled, unlike \CC template functions.
     
    863961}
    864962\end{cfa}
    865 One more step permits the summation of any summable type with all arguments of the same type:
    866 \begin{cfa}
    867 trait summable( otype T ) {
     963One more step permits the summation of any sumable type with all arguments of the same type:
     964\begin{cfa}
     965trait sumable( otype T ) {
    868966        T ?+?( T, T );
    869967};
    870 forall( otype R | summable( R ) ) R sum( R x, R y ) {
     968forall( otype R | sumable( R ) ) R sum( R x, R y ) {
    871969        return x + y;
    872970}
    873 forall( otype R, ttype Params | summable(R) | { R sum(R, Params); } ) R sum(R x, R y, Params rest) {
     971forall( otype R, ttype Params | sumable(R) | { R sum(R, Params); } ) R sum(R x, R y, Params rest) {
    874972        return sum( x + y, rest );
    875973}
     
    9221020\begin{cfa}
    9231021forall( dtype T0, dtype T1 | sized(T0) | sized(T1) ) struct _tuple2 {
    924         T0 field_0;                                                             $\C{// generated before the first 2-tuple}$
    925         T1 field_1;
     1022        T0 field_0;  T1 field_1;                                        $\C{// generated before the first 2-tuple}$
    9261023};
    9271024_tuple2(int, int) f() {
    9281025        _tuple2(double, double) x;
    9291026        forall( dtype T0, dtype T1, dtype T2 | sized(T0) | sized(T1) | sized(T2) ) struct _tuple3 {
    930                 T0 field_0;                                                     $\C{// generated before the first 3-tuple}$
    931                 T1 field_1;
    932                 T2 field_2;
     1027                T0 field_0;  T1 field_1;  T2 field_2;   $\C{// generated before the first 3-tuple}$
    9331028        };
    9341029        _tuple3(int, double, int) y;
    9351030}
    9361031\end{cfa}
    937 {\sloppy
    938 Tuple expressions are then simply converted directly into compound literals, \eg @[5, 'x', 1.24]@ becomes @(_tuple3(int, char, double)){ 5, 'x', 1.24 }@.
    939 \par}%
     1032Tuple expressions are then converted directly into compound literals, \eg @[5, 'x', 1.24]@ becomes @(_tuple3(int, char,@ @double)){ 5, 'x', 1.24 }@.
    9401033
    9411034\begin{comment}
     
    10221115\lstDeleteShortInline@%
    10231116\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    1024 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     1117\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    10251118\begin{cfa}
    10261119case 2, 10, 34, 42:
     
    10371130\lstDeleteShortInline@%
    10381131\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    1039 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     1132\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    10401133\begin{cfa}
    10411134case 2~42:
     
    10901183\centering
    10911184\lstDeleteShortInline@%
    1092 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    1093 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     1185\begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}}
     1186\multicolumn{1}{@{}c|@{\hspace{\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    10941187\begin{cfa}
    10951188`choose` ( day ) {
    10961189  case Mon~Thu:  // program
    10971190
    1098   case Fri:  // program
     1191  case Fri:    // program
    10991192        wallet += pay;
    11001193        `fallthrough;`
    1101   case Sat:  // party
     1194  case Sat:   // party
    11021195        wallet -= party;
    11031196
    11041197  case Sun:  // rest
    11051198
    1106   default:  // error
     1199  default:    // print error
    11071200}
    11081201\end{cfa}
     
    11121205  case Mon: case Tue: case Wed: case Thu:  // program
    11131206        `break;`
    1114   case Fri:  // program
     1207  case Fri:    // program
    11151208        wallet += pay;
    11161209
    1117   case Sat:  // party
     1210  case Sat:   // party
    11181211        wallet -= party;
    11191212        `break;`
    11201213  case Sun:  // rest
    11211214        `break;`
    1122   default:  // error
     1215  default:    // print error
    11231216}
    11241217\end{cfa}
     
    11361229\centering
    11371230\lstDeleteShortInline@%
    1138 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    1139 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{non-terminator}}  & \multicolumn{1}{c}{\textbf{target label}}     \\
     1231\begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}}
     1232\multicolumn{1}{@{}c|@{\hspace{\parindentlnth}}}{\textbf{non-terminator}}       & \multicolumn{1}{c@{}}{\textbf{target label}}  \\
    11401233\begin{cfa}
    11411234choose ( ... ) {
     
    11801273\begin{figure}
    11811274\lstDeleteShortInline@%
    1182 \begin{tabular}{@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}
    1183 \multicolumn{1}{@{\hspace{\parindentlnth}}c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}   & \multicolumn{1}{@{\hspace{\parindentlnth}}c}{\textbf{C}}      \\
     1275\begin{tabular}{@{\hspace{\parindentlnth}}l|@{\hspace{\parindentlnth}}l@{\hspace{\parindentlnth}}l@{}}
     1276\multicolumn{1}{@{\hspace{\parindentlnth}}c|@{\hspace{\parindentlnth}}}{\textbf{\CFA}}  & \multicolumn{1}{@{\hspace{\parindentlnth}}c@{}}{\textbf{C}}   \\
    11841277\begin{cfa}
    11851278`LC:` {
     
    11891282                `LIF:` if ( ... ) {
    11901283                        `LF:` for ( ... ) {
    1191                                 `LW:` while ( ... ) {
    1192                                         ... break `LC`; ...
    1193                                         ... break `LS`; ...
    1194                                         ... break `LIF`; ...
    1195                                         ... continue `LF;` ...
    1196                                         ... break `LF`; ...
    1197                                         ... continue `LW`; ...
    1198                                         ... break `LW`; ...
    1199                                 } // while
     1284                                ... break `LC`; ...
     1285                                ... break `LS`; ...
     1286                                ... break `LIF`; ...
     1287                                ... continue `LF;` ...
     1288                                ... break `LF`; ...
    12001289                        } // for
    12011290                } else {
     
    12131302                if ( ... ) {
    12141303                        for ( ... ) {
    1215                                 while ( ... ) {
    1216                                         ... goto `LC`; ...
    1217                                         ... goto `LS`; ...
    1218                                         ... goto `LIF`; ...
    1219                                         ... goto `LFC`; ...
    1220                                         ... goto `LFB`; ...
    1221                                         ... goto `LWC`; ...
    1222                                         ... goto `LWB`; ...
    1223                                   `LWC`: ; } `LWB:` ;
     1304                                ... goto `LC`; ...
     1305                                ... goto `LS`; ...
     1306                                ... goto `LIF`; ...
     1307                                ... goto `LFC`; ...
     1308                                ... goto `LFB`; ...
    12241309                          `LFC:` ; } `LFB:` ;
    12251310                } else {
     
    12431328// continue loop
    12441329// terminate loop
    1245 // continue loop
    1246 // terminate loop
    12471330
    12481331
    12491332
    12501333// terminate if
    1251 
    1252 
    12531334
    12541335\end{cfa}
     
    12771358\subsection{Exception Handling}
    12781359
    1279 The following framework for \CFA exception handling is in place, excluding some runtime type-information and virtual functions.
     1360The following framework for \CFA exception-handling is in place, excluding some runtime type-information and virtual functions.
    12801361\CFA provides two forms of exception handling: \newterm{fix-up} and \newterm{recovery} (see Figure~\ref{f:CFAExceptionHandling})~\cite{Buhr92b,Buhr00a}.
    12811362Both 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.
     
    12881369\begin{cquote}
    12891370\lstDeleteShortInline@%
    1290 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    1291 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{Resumption}}      & \multicolumn{1}{c}{\textbf{Termination}}      \\
     1371\begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}}
     1372\multicolumn{1}{@{}c|@{\hspace{\parindentlnth}}}{\textbf{Resumption}}   & \multicolumn{1}{c@{}}{\textbf{Termination}}   \\
    12921373\begin{cfa}
    12931374`exception R { int fix; };`
     
    13551436resume( $\emph{alternate-stack}$ )
    13561437\end{cfa}
    1357 These overloads of @resume@ raise the specified exception or the currently propagating exception (reresume) at another \CFA coroutine or task\footnote{\CFA coroutine and concurrency features are discussed in a separately submitted paper.}~\cite{Delisle18}.
     1438These overloads of @resume@ raise the specified exception or the currently propagating exception (reresume) at another \CFA coroutine or task~\cite{Delisle18}.
    13581439Nonlocal 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 handler returns.
    13591440
     
    14051486If an exception is raised and caught, the handler is run before the finally clause.
    14061487Like a destructor (see Section~\ref{s:ConstructorsDestructors}), a finally clause can raise an exception but not if there is an exception being propagated.
    1407 Mimicking the @finally@ clause with mechanisms like RAII is non-trivially when there are multiple types and local accesses.
     1488Mimicking the @finally@ clause with mechanisms like RAII is non-trivial when there are multiple types and local accesses.
    14081489
    14091490
     
    14111492\label{s:WithStatement}
    14121493
    1413 Grouping heterogeneous data into \newterm{aggregate}s (structure/union) is a common programming practice, and an aggregate can be further organized into more complex structures, such as arrays and containers:
    1414 \begin{cfa}
    1415 struct S {                                                                      $\C{// aggregate}$
    1416         char c;                                                                 $\C{// fields}$
    1417         int i;
    1418         double d;
    1419 };
    1420 S s, as[10];
    1421 \end{cfa}
    1422 However, functions manipulating aggregates must repeat the aggregate name to access its containing fields:
    1423 \begin{cfa}
    1424 void f( S s ) {
    1425         `s.`c; `s.`i; `s.`d;                                    $\C{// access containing fields}$
    1426 }
    1427 \end{cfa}
    1428 which extends to multiple levels of qualification for nested aggregates.
    1429 A similar situation occurs in object-oriented programming, \eg \CC:
    1430 \begin{C++}
    1431 struct S {
    1432         char c;                                                                 $\C{// fields}$
    1433         int i;
    1434         double d;
    1435         void f() {                                                              $\C{// implicit ``this'' aggregate}$
    1436                 `this->`c; `this->`i; `this->`d;        $\C{// access containing fields}$
    1437         }
    1438 }
    1439 \end{C++}
    1440 Object-oriented nesting of member functions in a \lstinline[language=C++]@class/struct@ allows eliding \lstinline[language=C++]@this->@ because of lexical scoping.
    1441 However, for other aggregate parameters, qualification is necessary:
    1442 \begin{cfa}
     1494Heterogeneous data is often aggregated into a structure/union.
     1495To reduce syntactic noise, \CFA provides a @with@ statement (see Pascal~\cite[\S~4.F]{Pascal}) to elide aggregate field-qualification by opening a scope containing the field identifiers.
     1496\begin{cquote}
     1497\vspace*{-\baselineskip}%???
     1498\lstDeleteShortInline@%
     1499\begin{cfa}
     1500struct S { char c; int i; double d; };
    14431501struct T { double m, n; };
    1444 int S::f( T & t ) {                                                     $\C{// multiple aggregate parameters}$
    1445         c; i; d;                                                                $\C{\color{red}// this--{\textgreater}.c, this--{\textgreater}.i, this--{\textgreater}.d}$
    1446         `t.`m; `t.`n;                                                   $\C{// must qualify}$
    1447 }
    1448 \end{cfa}
    1449 
    1450 To simplify the programmer experience, \CFA provides a @with@ statement (see Pascal~\cite[\S~4.F]{Pascal}) to elide aggregate qualification to fields by opening a scope containing the field identifiers.
    1451 Hence, the qualified fields become variables with the side-effect that it is easier to optimizing field references in a block.
    1452 \begin{cfa}
    1453 void f( S & this ) `with ( this )` {            $\C{// with statement}$
    1454         c; i; d;                                                                $\C{\color{red}// this.c, this.i, this.d}$
    1455 }
    1456 \end{cfa}
    1457 with the generality of opening multiple aggregate-parameters:
    1458 \begin{cfa}
    1459 void f( S & s, T & t ) `with ( s, t )` {                $\C{// multiple aggregate parameters}$
    1460         c; i; d;                                                                $\C{\color{red}// s.c, s.i, s.d}$
    1461         m; n;                                                                   $\C{\color{red}// t.m, t.n}$
    1462 }
    1463 \end{cfa}
     1502// multiple aggregate parameters
     1503\end{cfa}
     1504\begin{tabular}{@{}l@{\hspace{\parindentlnth}}|@{\hspace{\parindentlnth}}l@{}}
     1505\begin{cfa}
     1506void f( S & s, T & t ) {
     1507        `s.`c; `s.`i; `s.`d;
     1508        `t.`m; `t.`n;
     1509}
     1510\end{cfa}
     1511&
     1512\begin{cfa}
     1513void f( S & s, T & t ) `with ( s, t )` {
     1514        c; i; d;                // no qualification
     1515        m; n;
     1516}
     1517\end{cfa}
     1518\end{tabular}
     1519\lstMakeShortInline@%
     1520\end{cquote}
     1521Object-oriented programming languages only provide implicit qualification for the receiver.
    14641522
    14651523In detail, the @with@ statement has the form:
     
    14741532The object is the implicit qualifier for the open structure-fields.
    14751533
    1476 All expressions in the expression list are open in parallel within the compound statement.
    1477 This semantic is different from Pascal, which nests the openings from left to right.
     1534All expressions in the expression list are open in parallel within the compound statement, which is different from Pascal, which nests the openings from left to right.
    14781535The difference between parallel and nesting occurs for fields with the same name and type:
    14791536\begin{cfa}
     
    14821539with ( s, t ) {
    14831540        j + k;                                                                  $\C{// unambiguous, s.j + t.k}$
    1484         m = 5.0;                                                                $\C{// unambiguous, t.m = 5.0}$
    1485         m = 1;                                                                  $\C{// unambiguous, s.m = 1}$
    1486         int a = m;                                                              $\C{// unambiguous, a = s.i }$
    1487         double b = m;                                                   $\C{// unambiguous, b = t.m}$
     1541        m = 5.0;                                                                $\C{// unambiguous, s.m = 5.0}$
     1542        m = 1;                                                                  $\C{// unambiguous, t.m = 1}$
     1543        int a = m;                                                              $\C{// unambiguous, a = t.m }$
     1544        double b = m;                                                   $\C{// unambiguous, b = s.m}$
    14881545        int c = s.i + t.i;                                              $\C{// unambiguous, qualification}$
    1489         (double)m;                                                              $\C{// unambiguous, cast}$
     1546        (double)m;                                                              $\C{// unambiguous, cast s.m}$
    14901547}
    14911548\end{cfa}
     
    15111568and implicitly opened \emph{after} a function-body open, to give them higher priority:
    15121569\begin{cfa}
    1513 void ?{}( S & s, int `i` ) with ( s ) `with( $\emph{\color{red}params}$ )` {
     1570void ?{}( S & s, int `i` ) with ( s ) `{` `with( $\emph{\color{red}params}$ )` {
    15141571        s.i = `i`; j = 3; m = 5.5;
    1515 }
     1572} `}`
    15161573\end{cfa}
    15171574Finally, a cast may be used to disambiguate among overload variables in a @with@ expression:
     
    15811638\lstDeleteShortInline@%
    15821639\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{\hspace{2\parindentlnth}}l@{}}
    1583 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     1640\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    15841641\begin{cfa}
    15851642`[5] *` int x1;
     
    16091666\lstDeleteShortInline@%
    16101667\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    1611 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     1668\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    16121669\begin{cfa}
    16131670`*` int x, y;
    1614 int y;
    1615 \end{cfa}
    1616 &
    1617 \begin{cfa}
    1618 int `*`x, `*`y;
     1671int z;
     1672\end{cfa}
     1673&
     1674\begin{cfa}
     1675int `*`x, `*`y, z;
    16191676
    16201677\end{cfa}
     
    16221679\lstMakeShortInline@%
    16231680\end{cquote}
    1624 The downside of the \CFA semantics is the need to separate regular and pointer declarations.
     1681% The downside of the \CFA semantics is the need to separate regular and pointer declarations.
     1682The separation of regular and pointer declarations by \CFA declarations enforces greater clarity with only slightly more syntax.
    16251683
    16261684\begin{comment}
     
    16291687\lstDeleteShortInline@%
    16301688\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{\hspace{2\parindentlnth}}l@{}}
    1631 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{C}}     \\
     1689\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{C}}     \\
    16321690\begin{cfa}
    16331691[ 5 ] int z;
     
    16711729\lstDeleteShortInline@%
    16721730\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{\hspace{2\parindentlnth}}l@{}}
    1673 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{C}}     \\
     1731\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{C}}     \\
    16741732\begin{cfa}
    16751733extern const * const int x;
     
    16961754\lstDeleteShortInline@%
    16971755\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    1698 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     1756\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    16991757\begin{cfa}
    17001758y = (* int)x;
     
    17241782\lstDeleteShortInline@%
    17251783\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    1726 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     1784\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    17271785\begin{cfa}
    17281786[double] foo(), foo( int ), foo( double ) {...}
     
    17421800* [ * int ] ( int y ) gp;               $\C{// pointer to function returning pointer to int with int parameter}$
    17431801* [ ] ( int, char ) hp;                 $\C{// pointer to function returning no result with int and char parameters}$
    1744 * [ * int, int ] ( int ) jp;    $\C{// pointer to function returning pointer to int and int with int parameter}$
    1745 \end{cfa}
    1746 Note, a function name cannot be specified:
    1747 \begin{cfa}
    1748 * [ int x ] f () fp;                    $\C{// function name "f" is disallowed}\CRT$
    1749 \end{cfa}
     1802* [ * int, int ] ( int ) jp;    $\C{// pointer to function returning pointer to int and int with int parameter}\CRT$
     1803\end{cfa}
     1804Note, the name of the function pointer is specified last, as for other variable declarations.
    17501805
    17511806Finally, new \CFA declarations may appear together with C declarations in the same program block, but cannot be mixed within a specific declaration.
     
    18041859This provides a much more orthogonal design for library implementors, obviating the need for workarounds such as @std::reference_wrapper@.
    18051860Secondly, \CFA references are rebindable, whereas \CC references have a fixed address.
    1806 \newsavebox{\LstBox}
    1807 \begin{lrbox}{\LstBox}
    1808 \lstset{basicstyle=\footnotesize\linespread{0.9}\sf}
    1809 \begin{cfa}
    1810 int & r = *new( int );
    1811 ...                                                                                     $\C{// non-null reference}$
    1812 delete &r;                                                                      $\C{// unmanaged (programmer) memory-management}$
    1813 r += 1;                                                                         $\C{// undefined reference}$
    1814 \end{cfa}
    1815 \end{lrbox}
    18161861Rebinding allows \CFA references to be default-initialized (\eg to a null pointer\footnote{
    1817 While effort has been made into non-null reference checking in \CC and Java, the exercise seems moot for any non-managed languages (C/\CC), given that it only handles one of many different error situations:
    1818 \begin{cquote}
    1819 \usebox{\LstBox}
    1820 \end{cquote}
    1821 }%
    1822 ) and point to different addresses throughout their lifetime, like pointers.
     1862While effort has been made into non-null reference checking in \CC and Java, the exercise seems moot for any non-managed languages (C/\CC), given that it only handles one of many different error situations, \eg using a pointer after its storage is deleted.}) and point to different addresses throughout their lifetime, like pointers.
    18231863Rebinding is accomplished by extending the existing syntax and semantics of the address-of operator in C.
    18241864
     
    18321872\begin{itemize}
    18331873\item
    1834 if @R@ is an rvalue of type {@T &@$_1 \cdots$@ &@$_r$} where $r \ge 1$ references (@&@ symbols) than @&R@ has type {@T `*`&@$_{\color{red}2} \cdots$@ &@$_{\color{red}r}$}, \\ \ie @T@ pointer with $r-1$ references (@&@ symbols).
     1874if @R@ is an rvalue of type {@T &@$_1 \cdots$@ &@$_r$} where $r \ge 1$ references (@&@ symbols) then @&R@ has type {@T `*`&@$_{\color{red}2} \cdots$@ &@$_{\color{red}r}$}, \\ \ie @T@ pointer with $r-1$ references (@&@ symbols).
    18351875       
    18361876\item
     
    18661906\end{cfa}
    18671907This allows complex values to be succinctly and efficiently passed to functions, without the syntactic overhead of explicit definition of a temporary variable or the runtime cost of pass-by-value.
    1868 \CC allows a similar binding, but only for @const@ references; the more general semantics of \CFA are an attempt to avoid the \newterm{const hell} problem, in which addition of a @const@ qualifier to one reference requires a cascading chain of added qualifiers.
     1908\CC allows a similar binding, but only for @const@ references; the more general semantics of \CFA are an attempt to avoid the \newterm{const poisoning} problem~\cite{Taylor10}, in which addition of a @const@ qualifier to one reference requires a cascading chain of added qualifiers.
    18691909
    18701910
     
    18801920\begin{tabular}{@{}l@{\hspace{3em}}l|l@{}}
    18811921\multicolumn{1}{c@{\hspace{3em}}}{\textbf{C Type Nesting}}      & \multicolumn{1}{c|}{\textbf{C Implicit Hoisting}}     & \multicolumn{1}{c}{\textbf{\CFA}}     \\
    1882 \hline
    18831922\begin{cfa}
    18841923struct S {
     
    19601999The symbol \lstinline+^+ is used for the destructor name because it was the last binary operator that could be used in a unary context.}.
    19612000The name @{}@ comes from the syntax for the initializer: @struct S { int i, j; } s = `{` 2, 3 `}`@.
    1962 Like other \CFA operators, these names represent the syntax used to call the constructor or destructor, \eg @?{}(x, ...)@ or @^{}(x, ...)@.
     2001Like other \CFA operators, these names represent the syntax used to explicitly call the constructor or destructor, \eg @s{...}@ or @^s{...}@.
    19632002The constructor and destructor have return type @void@, and the first parameter is a reference to the object type to be constructed or destructed.
    19642003While the first parameter is informally called the @this@ parameter, as in object-oriented languages, any variable name may be used.
    1965 Both constructors and destructors allow additional parametes after the @this@ parameter for specifying values for initialization/de-initialization\footnote{
     2004Both constructors and destructors allow additional parameters after the @this@ parameter for specifying values for initialization/de-initialization\footnote{
    19662005Destruction parameters are useful for specifying storage-management actions, such as de-initialize but not deallocate.}.
    19672006\begin{cfa}
    1968 struct VLA { int len, * data; };
     2007struct VLA { int len, * data; };                        $\C{// variable length array of integers}$
    19692008void ?{}( VLA & vla ) with ( vla ) { len = 10;  data = alloc( len ); }  $\C{// default constructor}$
    19702009void ^?{}( VLA & vla ) with ( vla ) { free( data ); } $\C{// destructor}$
    19712010{
    1972         VLA x;                                                                  $\C{// implicit:  ?\{\}( x );}$
    1973 }                                                                                       $\C{// implicit:  ?\^{}\{\}( x );}$
     2011        VLA x;                                                                  $\C{// implicit:\ \ x\{\};}$
     2012}                                                                                       $\C{// implicit:\ \textasciicircum{}x\{\};}$
    19742013\end{cfa}
    19752014@VLA@ is a \newterm{managed type}\footnote{
     
    19962035appropriate care is taken to not recursively call the copy constructor when initializing the second parameter.
    19972036
    1998 \CFA constructors may be explicitly call, like Java, and destructors may be explicitly called, like \CC.
     2037\CFA constructors may be explicitly called, like Java, and destructors may be explicitly called, like \CC.
    19992038Explicit calls to constructors double as a \CC-style \emph{placement syntax}, useful for construction of member fields in user-defined constructors and reuse of existing storage allocations.
    2000 While existing call syntax works for explicit calls to constructors and destructors, \CFA also provides a more concise \newterm{operator syntax} for both:
     2039Like the other operators in \CFA, there is a concise syntax for constructor/destructor function calls:
    20012040\begin{cfa}
    20022041{
    20032042        VLA  x,            y = { 20, 0x01 },     z = y; $\C{// z points to y}$
    2004         //      ?{}( x );   ?{}( y, 20, 0x01 );   ?{}( z, y );
     2043        //    x{};         y{ 20, 0x01 };          z{ z, y };
    20052044        ^x{};                                                                   $\C{// deallocate x}$
    20062045        x{};                                                                    $\C{// reallocate x}$
     
    20092048        y{ x };                                                                 $\C{// reallocate y, points to x}$
    20102049        x{};                                                                    $\C{// reallocate x, not pointing to y}$
    2011         // ^?{}(z);  ^?{}(y);  ^?{}(x);
     2050        //  ^z{};  ^y{};  ^x{};
    20122051}
    20132052\end{cfa}
     
    20302069In these cases, \CFA provides the initialization syntax \lstinline|S x `@=` {}|, and the object becomes unmanaged, so implicit constructor and destructor calls are not generated.
    20312070Any C initializer can be the right-hand side of an \lstinline|@=| initializer, \eg \lstinline|VLA a @= { 0, 0x0 }|, with the usual C initialization semantics.
    2032 The same syntax can be used in a compound literal, \eg \lstinline|a = VLA`@`{ 0, 0x0 }|, to create a C-style literal.
     2071The same syntax can be used in a compound literal, \eg \lstinline|a = (VLA)`@`{ 0, 0x0 }|, to create a C-style literal.
    20332072The point of \lstinline|@=| is to provide a migration path from legacy C code to \CFA, by providing a mechanism to incrementally convert to implicit initialization.
    20342073
     
    20462085
    20472086
     2087\begin{comment}
    20482088\subsection{Integral Suffixes}
    20492089
     
    20792119\lstMakeShortInline@%
    20802120\end{cquote}
     2121\end{comment}
    20812122
    20822123
     
    20842125
    20852126In C, @0@ has the special property that it is the only ``false'' value;
    2086 from the standard, any value that compares equal to @0@ is false, while any value that compares unequal to @0@ is true.
     2127by the standard, any value that compares equal to @0@ is false, while any value that compares unequal to @0@ is true.
    20872128As such, an expression @x@ in any boolean context (such as the condition of an @if@ or @while@ statement, or the arguments to @&&@, @||@, or @?:@\,) can be rewritten as @x != 0@ without changing its semantics.
    20882129Operator overloading in \CFA provides a natural means to implement this truth-value comparison for arbitrary types, but the C type system is not precise enough to distinguish an equality comparison with @0@ from an equality comparison with an arbitrary integer or pointer.
     
    21192160\lstDeleteShortInline@%
    21202161\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{\hspace{2\parindentlnth}}l@{\hspace{2\parindentlnth}}l@{}}
    2121 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{postfix function}}        & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{constant}}      & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{variable/expression}}   & \multicolumn{1}{c}{\textbf{postfix pointer}}  \\
     2162\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{postfix function}}     & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{constant}}      & \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{variable/expression}}   & \multicolumn{1}{c@{}}{\textbf{postfix pointer}}       \\
    21222163\begin{cfa}
    21232164int |?`h|( int s );
     
    21642205\lstset{language=CFA,moredelim=**[is][\color{red}]{|}{|},deletedelim=**[is][]{`}{`}}
    21652206\lstDeleteShortInline@%
    2166 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    2167 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{\CC}}      \\
     2207\begin{tabular}{@{}l@{\hspace{1.25\parindentlnth}}l@{}}
     2208\multicolumn{1}{@{}c@{\hspace{1.25\parindentlnth}}}{\textbf{\CFA}}      & \multicolumn{1}{c@{}}{\textbf{\CC}}   \\
    21682209\begin{cfa}
    21692210struct W {
     
    22092250        W w, heavy = { 20 };
    22102251        w = 155|_lb|;
    2211         w = 0b1111|_lb|;       // error, binary unsupported
     2252        // binary unsupported
    22122253        w = 0${\color{red}\LstBasicStyle{'}}$233|_lb|;          // quote separator
    22132254        w = 0x9b|_kg|;
     
    22392280\lstDeleteShortInline@%
    22402281\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    2241 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{Definition}}      & \multicolumn{1}{c}{\textbf{Usage}}    \\
     2282\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{Definition}}   & \multicolumn{1}{c@{}}{\textbf{Usage}} \\
    22422283\begin{cfa}
    22432284const short int `MIN` = -32768;
     
    22572298\begin{cquote}
    22582299\lstDeleteShortInline@%
    2259 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    2260 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     2300\begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
     2301\multicolumn{1}{@{}c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}  & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    22612302\begin{cfa}
    22622303MIN
     
    22672308&
    22682309\begin{cfa}
    2269 SCHAR_MIN, CHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN, LLONG_MIN, FLT_MIN, DBL_MIN, LDBL_MIN
    2270 SCHAR_MAX, UCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, LLONG_MAX, FLT_MAX, DBL_MAX, LDBL_MAX
     2310CHAR_MIN, SHRT_MIN, INT_MIN, LONG_MIN, LLONG_MIN, FLT_MIN, DBL_MIN, LDBL_MIN
     2311UCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX, LLONG_MAX, FLT_MAX, DBL_MAX, LDBL_MAX
    22712312M_PI, M_PIl
    22722313M_E, M_El
     
    22842325\lstDeleteShortInline@%
    22852326\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    2286 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{Definition}}      & \multicolumn{1}{c}{\textbf{Usage}}    \\
     2327\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{Definition}}   & \multicolumn{1}{c@{}}{\textbf{Usage}} \\
    22872328\begin{cfa}
    22882329float `log`( float x );
     
    23032344\lstDeleteShortInline@%
    23042345\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    2305 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     2346\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    23062347\begin{cfa}
    23072348log
     
    23312372\lstDeleteShortInline@%
    23322373\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    2333 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{Definition}}      & \multicolumn{1}{c}{\textbf{Usage}}    \\
     2374\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{Definition}}   & \multicolumn{1}{c@{}}{\textbf{Usage}} \\
    23342375\begin{cfa}
    23352376unsigned int `abs`( int );
     
    23502391\lstDeleteShortInline@%
    23512392\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    2352 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
     2393\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    23532394\begin{cfa}
    23542395abs
     
    23732414an allocation with a specified character.
    23742415\item[resize]
    2375 an existing allocation to decreased or increased its size.
     2416an existing allocation to decrease or increase its size.
    23762417In either case, new storage may or may not be allocated and, if there is a new allocation, as much data from the existing allocation is copied.
    23772418For an increase in storage size, new storage after the copied data may be filled.
     
    23872428
    23882429\begin{table}
     2430\caption{Storage-Management Operations}
     2431\label{t:StorageManagementOperations}
    23892432\centering
    23902433\lstDeleteShortInline@%
     
    24062449\lstDeleteShortInline~%
    24072450\lstMakeShortInline@%
    2408 \caption{Storage-Management Operations}
    2409 \label{t:StorageManagementOperations}
    24102451\end{table}
    24112452
    24122453\begin{figure}
    24132454\centering
    2414 \begin{cquote}
    2415 \begin{cfa}[aboveskip=0pt]
     2455\begin{cfa}[aboveskip=0pt,xleftmargin=0pt]
    24162456size_t  dim = 10;                                                       $\C{// array dimension}$
    24172457char fill = '\xff';                                                     $\C{// initialization fill value}$
     
    24192459\end{cfa}
    24202460\lstDeleteShortInline@%
    2421 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    2422 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{C}}        \\
    2423 \begin{cfa}
     2461\begin{tabular}{@{}l@{\hspace{\parindentlnth}}l@{}}
     2462\multicolumn{1}{@{}c@{\hspace{\parindentlnth}}}{\textbf{\CFA}}  & \multicolumn{1}{c@{}}{\textbf{C}}     \\
     2463\begin{cfa}[xleftmargin=-10pt]
    24242464ip = alloc();
    24252465ip = alloc( fill );
     
    24362476&
    24372477\begin{cfa}
    2438 ip = (int *)malloc( sizeof( int ) );
    2439 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, sizeof( int ) );
    2440 ip = (int *)malloc( dim * sizeof( int ) );
    2441 ip = (int *)malloc( sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) );
    2442 ip = (int *)realloc( ip, 2 * dim * sizeof( int ) );
    2443 ip = (int *)realloc( ip, 4 * dim * sizeof( int ) ); memset( ip, fill, 4 * dim * sizeof( int ) );
    2444 
    2445 ip = memalign( 16, sizeof( int ) );
    2446 ip = memalign( 16, sizeof( int ) ); memset( ip, fill, sizeof( int ) );
    2447 ip = memalign( 16, dim * sizeof( int ) );
    2448 ip = memalign( 16, dim * sizeof( int ) ); memset( ip, fill, dim * sizeof( int ) );
    2449 \end{cfa}
    2450 \end{tabular}
    2451 \lstMakeShortInline@%
    2452 \end{cquote}
     2478ip = (int *)malloc( sizeof(int) );
     2479ip = (int *)malloc( sizeof(int) ); memset( ip, fill, sizeof(int) );
     2480ip = (int *)malloc( dim * sizeof(int) );
     2481ip = (int *)malloc( sizeof(int) ); memset( ip, fill, dim * sizeof(int) );
     2482ip = (int *)realloc( ip, 2 * dim * sizeof(int) );
     2483ip = (int *)realloc( ip, 4 * dim * sizeof(int) ); memset( ip, fill, 4 * dim * sizeof(int));
     2484
     2485ip = memalign( 16, sizeof(int) );
     2486ip = memalign( 16, sizeof(int) ); memset( ip, fill, sizeof(int) );
     2487ip = memalign( 16, dim * sizeof(int) );
     2488ip = memalign( 16, dim * sizeof(int) ); memset( ip, fill, dim * sizeof(int) );
     2489\end{cfa}
     2490\end{tabular}
     2491\lstMakeShortInline@%
    24532492\caption{\CFA versus C Storage-Allocation}
    24542493\label{f:StorageAllocation}
     
    24632502S * as = anew( dim, 2, 3 );                                     $\C{// each array element initialized to 2, 3}$
    24642503\end{cfa}
    2465 Note, \CC can only initialization array elements via the default constructor.
     2504Note, \CC can only initialize array elements via the default constructor.
    24662505
    24672506Finally, the \CFA memory-allocator has \newterm{sticky properties} for dynamic storage: fill and alignment are remembered with an object's storage in the heap.
     
    24802519\lstDeleteShortInline@%
    24812520\begin{tabular}{@{}l@{\hspace{2\parindentlnth}}l@{}}
    2482 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{c}{\textbf{\CC}}      \\
     2521\multicolumn{1}{@{}c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{\CC}}   \\
    24832522\begin{cfa}
    24842523int x = 1, y = 2, z = 3;
     
    25352574\end{cquote}
    25362575There is a weak similarity between the \CFA logical-or operator and the Shell pipe-operator for moving data, where data flows in the correct direction for input but the opposite direction for output.
    2537 
     2576\begin{comment}
    25382577The implicit separator character (space/blank) is a separator not a terminator.
    25392578The rules for implicitly adding the separator are:
     
    25542593}%
    25552594\end{itemize}
     2595\end{comment}
    25562596There are functions to set and get the separator string, and manipulators to toggle separation on and off in the middle of output.
    25572597
     
    25682608\centering
    25692609\lstDeleteShortInline@%
    2570 \begin{tabular}{@{}l@{\hspace{2\parindentlnth}}@{\hspace{2\parindentlnth}}l@{}}
    2571 \multicolumn{1}{c@{\hspace{2\parindentlnth}}}{\textbf{\CFA}}    & \multicolumn{1}{@{\hspace{2\parindentlnth}}c}{\textbf{C}}     \\
     2610\begin{tabular}{@{}l@{\hspace{3\parindentlnth}}l@{}}
     2611\multicolumn{1}{@{}c@{\hspace{3\parindentlnth}}}{\textbf{\CFA}} & \multicolumn{1}{c@{}}{\textbf{C}}     \\
    25722612\begin{cfa}
    25732613#include <gmp>
     
    26022642
    26032643
    2604 \section{Evaluation}
     2644\section{Polymorphism Evaluation}
    26052645\label{sec:eval}
    26062646
    2607 Though \CFA provides significant added functionality over C, these features have a low runtime penalty.
    2608 In fact, \CFA's features for generic programming can enable faster runtime execution than idiomatic @void *@-based C code.
    2609 This claim is demonstrated through a set of generic-code-based micro-benchmarks in C, \CFA, and \CC (see stack implementations in Appendix~\ref{sec:BenchmarkStackImplementation}).
     2647\CFA adds parametric polymorphism to C.
     2648A runtime evaluation is performed to compare the cost of alternative styles of polymorphism.
     2649The goal is to compare just the underlying mechanism for implementing different kinds of polymorphism.
     2650% Though \CFA provides significant added functionality over C, these features have a low runtime penalty.
     2651% In fact, it is shown that \CFA's generic programming can enable faster runtime execution than idiomatic @void *@-based C code.
     2652The experiment is a set of generic-stack micro-benchmarks~\cite{CFAStackEvaluation} in C, \CFA, and \CC (see implementations in Appendix~\ref{sec:BenchmarkStackImplementations}).
    26102653Since all these languages share a subset essentially comprising standard C, maximal-performance benchmarks should show little runtime variance, differing only in length and clarity of source code.
    26112654A more illustrative comparison measures the costs of idiomatic usage of each language's features.
     
    26382681\end{figure}
    26392682
    2640 The structure of each benchmark implemented is: C with @void *@-based polymorphism, \CFA with the presented features, \CC with templates, and \CC using only class inheritance for polymorphism, called \CCV.
     2683The structure of each benchmark implemented is: C with @void *@-based polymorphism, \CFA with parametric polymorphism, \CC with templates, and \CC using only class inheritance for polymorphism, called \CCV.
    26412684The \CCV variant illustrates an alternative object-oriented idiom where all objects inherit from a base @object@ class, mimicking a Java-like interface;
    26422685hence runtime checks are necessary to safely down-cast objects.
    26432686The most notable difference among the implementations is in memory layout of generic types: \CFA and \CC inline the stack and pair elements into corresponding list and pair nodes, while C and \CCV lack such a capability and instead must store generic objects via pointers to separately-allocated objects.
    2644 Note that the C benchmark uses unchecked casts as there is no runtime mechanism to perform such checks, while \CFA and \CC provide type-safety statically.
     2687Note, the C benchmark uses unchecked casts as C has no runtime mechanism to perform such checks, while \CFA and \CC provide type-safety statically.
    26452688
    26462689Figure~\ref{fig:eval} and Table~\ref{tab:eval} show the results of running the benchmark in Figure~\ref{fig:BenchmarkTest} and its C, \CC, and \CCV equivalents.
    26472690The graph plots the median of 5 consecutive runs of each program, with an initial warm-up run omitted.
    2648 All code is compiled at \texttt{-O2} by gcc or g++ 6.3.0, with all \CC code compiled as \CCfourteen.
     2691All code is compiled at \texttt{-O2} by gcc or g++ 6.4.0, with all \CC code compiled as \CCfourteen.
    26492692The benchmarks are run on an Ubuntu 16.04 workstation with 16 GB of RAM and a 6-core AMD FX-6300 CPU with 3.5 GHz maximum clock frequency.
    26502693
     
    26572700
    26582701\begin{table}
    2659 \centering
    26602702\caption{Properties of benchmark code}
    26612703\label{tab:eval}
     2704\centering
    26622705\newcommand{\CT}[1]{\multicolumn{1}{c}{#1}}
    26632706\begin{tabular}{rrrrr}
    26642707                                                                        & \CT{C}        & \CT{\CFA}     & \CT{\CC}      & \CT{\CCV}             \\ \hline
    26652708maximum memory usage (MB)                       & 10,001        & 2,502         & 2,503         & 11,253                \\
    2666 source code size (lines)                        & 196           & 186           & 125           & 290                   \\
     2709source code size (lines)                        & 201           & 191           & 125           & 294                   \\
    26672710redundant type annotations (lines)      & 27            & 0                     & 2                     & 16                    \\
    26682711binary size (KB)                                        & 14            & 257           & 14            & 37                    \\
     
    26722715The C and \CCV variants are generally the slowest with the largest memory footprint, because of their less-efficient memory layout and the pointer-indirection necessary to implement generic types;
    26732716this inefficiency is exacerbated by the second level of generic types in the pair benchmarks.
    2674 By contrast, the \CFA and \CC variants run in roughly equivalent time for both the integer and pair of @short@ and @char@ because the storage layout is equivalent, with the inlined libraries (\ie no separate compilation) and greater maturity of the \CC compiler contributing to its lead.
     2717By contrast, the \CFA and \CC variants run in roughly equivalent time for both the integer and pair because of equivalent storage layout, with the inlined libraries (\ie no separate compilation) and greater maturity of the \CC compiler contributing to its lead.
    26752718\CCV is slower than C largely due to the cost of runtime type-checking of down-casts (implemented with @dynamic_cast@);
    2676 The outlier in the graph for \CFA, pop @pair@, results from the complexity of the generated-C polymorphic code.
    2677 The gcc compiler is unable to optimize some dead code and condense nested calls; a compiler designed for \CFA could easily perform these optimizations.
     2719The outlier for \CFA, pop @pair@, results from the complexity of the generated-C polymorphic code.
     2720The gcc compiler is unable to optimize some dead code and condense nested calls;
     2721a compiler designed for \CFA could easily perform these optimizations.
    26782722Finally, the binary size for \CFA is larger because of static linking with the \CFA libraries.
    26792723
     
    26872731Line-count is a fairly rough measure of code complexity;
    26882732another important factor is how much type information the programmer must specify manually, especially where that information is not compiler-checked.
    2689 Such unchecked type information produces a heavier documentation burden and increased potential for runtime bugs, and is much less common in \CFA than C, with its manually specified function pointer arguments and format codes, or \CCV, with its extensive use of untype-checked downcasts, \eg @object@ to @integer@ when popping a stack.
     2733Such unchecked type information produces a heavier documentation burden and increased potential for runtime bugs, and is much less common in \CFA than C, with its manually specified function pointer arguments and format codes, or \CCV, with its extensive use of un-type-checked downcasts, \eg @object@ to @integer@ when popping a stack.
    26902734To quantify this manual typing, the ``redundant type annotations'' line in Table~\ref{tab:eval} counts the number of lines on which the type of a known variable is respecified, either as a format specifier, explicit downcast, type-specific function, or by name in a @sizeof@, struct literal, or @new@ expression.
    26912735The \CC benchmark uses two redundant type annotations to create a new stack nodes, while the C and \CCV benchmarks have several such annotations spread throughout their code.
    26922736The \CFA benchmark is able to eliminate all redundant type annotations through use of the polymorphic @alloc@ function discussed in Section~\ref{sec:libraries}.
    26932737
     2738We conjecture these results scale across most generic data-types as the underlying polymorphism implement is constant.
     2739
    26942740
    26952741\section{Related Work}
     
    26972743
    26982744\subsection{Polymorphism}
     2745
     2746ML~\cite{ML} was the first language to support parametric polymorphism.
     2747Like \CFA, it supports universal type parameters, but not the use of assertions and traits to constrain type arguments.
     2748Haskell~\cite{Haskell10} combines ML-style polymorphism, polymorphic data types, and type inference with the notion of type classes, collections of overloadable methods that correspond in intent to traits in \CFA.
     2749Unlike \CFA, Haskell requires an explicit association between types and their classes that specifies the implementation of operations.
     2750These associations determine the functions that are assertion arguments for particular combinations of class and type, in contrast to \CFA where the assertion arguments are selected at function call sites based upon the set of operations in scope at that point.
     2751Haskell also severely restricts the use of overloading: an overloaded name can only be associated with a single class, and methods with overloaded names can only be defined as part of instance declarations.
    26992752
    27002753\CC provides three disjoint polymorphic extensions to C: overloading, inheritance, and templates.
     
    27502803Go does not have tuples but supports MRVF.
    27512804Java's variadic functions appear similar to C's but are type-safe using homogeneous arrays, which are less useful than \CFA's heterogeneously-typed variadic functions.
    2752 Tuples are a fundamental abstraction in most functional programming languages, such as Standard ML~\cite{sml} and~\cite{Scala}, which decompose tuples using pattern matching.
     2805Tuples are a fundamental abstraction in most functional programming languages, such as Standard ML~\cite{sml}, Haskell, and Scala~\cite{Scala}, which decompose tuples using pattern matching.
    27532806
    27542807
     
    27672820data-parallel features have not yet been added to \CFA, but are easily incorporated within its design, while concurrency primitives similar to those in $\mu$\CC have already been added~\cite{Delisle18}.
    27682821Finally, CCured~\cite{Necula02} and Ironclad \CC~\cite{DeLozier13} attempt to provide a more memory-safe C by annotating pointer types with garbage collection information; type-checked polymorphism in \CFA covers several of C's memory-safety issues, but more aggressive approaches such as annotating all pointer types with their nullability or requiring runtime garbage collection are contradictory to \CFA's backwards compatibility goals.
    2769 
    2770 
    2771 \begin{comment}
    2772 \subsection{Control Structures / Declarations / Literals}
    2773 
    2774 Java has default fall through like C/\CC.
    2775 Pascal/Ada/Go/Rust do not have default fall through.
    2776 \Csharp does not have fall through but still requires a break.
    2777 Python uses dictionary mapping. \\
    2778 \CFA choose is like Rust match.
    2779 
    2780 Java has labelled break/continue. \\
    2781 Languages with and without exception handling.
    2782 
    2783 Alternative C declarations. \\
    2784 Different references \\
    2785 Constructors/destructors
    2786 
    2787 0/1 Literals \\
    2788 user defined: D, Objective-C
    2789 \end{comment}
    27902822
    27912823
     
    28022834Finally, we demonstrate that \CFA performance for some idiomatic cases is better than C and close to \CC, showing the design is practically applicable.
    28032835
    2804 There is ongoing work on a wide range of \CFA features, including arrays with size, runtime type-information, virtual functions, user-defined conversions, concurrent primitives, and modules.
    2805 While all examples in the paper compile and run, a public beta-release of \CFA will take another 8--12 months to finalize these extensions.
    2806 There are also interesting future directions for the polymorphism design.
    2807 Notably, \CC template functions trade compile time and code bloat for optimal runtime of individual instantiations of polymorphic functions.
    2808 \CFA polymorphic functions use dynamic virtual-dispatch;
    2809 the runtime overhead of this approach is low, but not as low as inlining, and it may be beneficial to provide a mechanism for performance-sensitive code.
     2836While all examples in the paper compile and run, a public beta-release of \CFA will take 6--8 months to reduce compilation time, provide better debugging, and add a few more libraries.
     2837There is also new work on a number of \CFA features, including arrays with size, runtime type-information, virtual functions, user-defined conversions, and modules.
     2838While \CFA polymorphic functions use dynamic virtual-dispatch with low runtime overhead (see Section~\ref{sec:eval}), it is not as low as \CC template-inlining.
     2839Hence it may be beneficial to provide a mechanism for performance-sensitive code.
    28102840Two promising approaches are an @inline@ annotation at polymorphic function call sites to create a template-specialization of the function (provided the code is visible) or placing an @inline@ annotation on polymorphic function-definitions to instantiate a specialized version for some set of types (\CC template specialization).
    28112841These approaches are not mutually exclusive and allow performance optimizations to be applied only when necessary, without suffering global code-bloat.
     
    28162846
    28172847The authors would like to recognize the design assistance of Glen Ditchfield, Richard Bilson, Thierry Delisle, Andrew Beach and Brice Dobry on the features described in this paper, and thank Magnus Madsen for feedback on the writing.
    2818 This work is supported by a corporate partnership with Huawei Ltd.\ (\url{http://www.huawei.com}), and Aaron Moss and Peter Buhr are partially funded by the Natural Sciences and Engineering Research Council of Canada.
    2819 
    2820 
     2848Funding for this project has been provided by Huawei Ltd.\ (\url{http://www.huawei.com}), and Aaron Moss and Peter Buhr are partially funded by the Natural Sciences and Engineering Research Council of Canada.
     2849
     2850{%
     2851\fontsize{9bp}{12bp}\selectfont%
    28212852\bibliography{pl}
    2822 
     2853}%
    28232854
    28242855\appendix
    28252856
    2826 \section{Benchmark Stack Implementation}
    2827 \label{sec:BenchmarkStackImplementation}
    2828 
    2829 Throughout, @/***/@ designates a counted redundant type annotation; code reformatted for brevity.
    2830 
    2831 \smallskip\noindent
    2832 C
    2833 \begin{cfa}[xleftmargin=2\parindentlnth,aboveskip=0pt,belowskip=0pt]
    2834 struct stack_node {
     2857\section{Benchmark Stack Implementations}
     2858\label{sec:BenchmarkStackImplementations}
     2859
     2860Throughout, @/***/@ designates a counted redundant type annotation; code reformatted slightly for brevity.
     2861
     2862
     2863\subsection{C}
     2864
     2865\begin{flushleft}
     2866\lstDeleteShortInline@%
     2867\begin{tabular}{@{}l@{\hspace{1.8\parindentlnth}}|@{\hspace{\parindentlnth}}l@{}}
     2868\begin{cfa}[xleftmargin=0pt,aboveskip=0pt,belowskip=0pt]
     2869typedef struct node {
    28352870        void * value;
    2836         struct stack_node * next;
    2837 };
    2838 struct stack { struct stack_node* head; };
    2839 void clear_stack( struct stack * s, void (*free_el)( void * ) ) {
    2840         for ( struct stack_node * next = s->head; next; ) {
    2841                 struct stack_node * crnt = next;
    2842                 next = crnt->next;
    2843                 free_el( crnt->value );
    2844                 free( crnt );
     2871        struct node * next;
     2872} node;
     2873typedef struct stack {
     2874        struct node * head;
     2875} stack;
     2876void copy_stack( stack * s, const stack * t,
     2877                                void * (*copy)( const void * ) ) {
     2878        node ** cr = &s->head;
     2879        for (node * nx = t->head; nx; nx = nx->next) {
     2880                *cr = malloc( sizeof(node) ); /***/
     2881                (*cr)->value = copy( nx->value );
     2882                cr = &(*cr)->next;
     2883        }
     2884        *cr = NULL;
     2885}
     2886void clear_stack( stack * s, void (* free_el)( void * ) ) {
     2887        for ( node * nx = s->head; nx; ) {
     2888                node * cr = nx;
     2889                nx = cr->next;
     2890                free_el( cr->value );
     2891                free( cr );
    28452892        }
    28462893        s->head = NULL;
    28472894}
    2848 struct stack new_stack() { return (struct stack){ NULL }; /***/ }
    2849 void copy_stack( struct stack * s, const struct stack * t, void * (*copy)( const void * ) ) {
    2850         struct stack_node ** crnt = &s->head;
    2851         for ( struct stack_node * next = t->head; next; next = next->next ) {
    2852                 *crnt = malloc( sizeof(struct stack_node) ); /***/
    2853                 (*crnt)->value = copy( next->value );
    2854                 crnt = &(*crnt)->next;
    2855         }
    2856         *crnt = NULL;
    2857 }
    2858 struct stack * assign_stack( struct stack * s, const struct stack * t,
    2859                 void * (*copy_el)( const void * ), void (*free_el)( void * ) ) {
     2895\end{cfa}
     2896&
     2897\begin{cfa}[xleftmargin=0pt,aboveskip=0pt,belowskip=0pt]
     2898stack new_stack() {
     2899        return (stack){ NULL }; /***/
     2900}
     2901stack * assign_stack( stack * s, const stack * t,
     2902                                void * (*copy_el)( const void * ),
     2903                                void (*free_el)( void * ) ) {
    28602904        if ( s->head == t->head ) return s;
    28612905        clear_stack( s, free_el ); /***/
     
    28632907        return s;
    28642908}
    2865 _Bool stack_empty( const struct stack * s ) { return s->head == NULL; }
    2866 void push_stack( struct stack * s, void * v ) {
    2867         struct stack_node * n = malloc( sizeof(struct stack_node) ); /***/
    2868         *n = (struct stack_node){ v, s->head }; /***/
     2909_Bool stack_empty( const stack * s ) {
     2910        return s->head == NULL;
     2911}
     2912void push_stack( stack * s, void * v ) {
     2913        node * n = malloc( sizeof(node) ); /***/
     2914        *n = (node){ v, s->head }; /***/
    28692915        s->head = n;
    28702916}
    2871 void * pop_stack( struct stack * s ) {
    2872         struct stack_node * n = s->head;
     2917void * pop_stack( stack * s ) {
     2918        node * n = s->head;
    28732919        s->head = n->next;
    28742920        void * v = n->value;
     
    28772923}
    28782924\end{cfa}
    2879 
    2880 \medskip\noindent
    2881 \CFA
    2882 \begin{cfa}[xleftmargin=2\parindentlnth,aboveskip=0pt,belowskip=0pt]
    2883 forall( otype T ) struct stack_node {
    2884         T value;
    2885         stack_node(T) * next;
    2886 };
    2887 forall( otype T ) struct stack { stack_node(T) * head; };
    2888 forall( otype T ) void clear( stack(T) & s ) with( s ) {
    2889         for ( stack_node(T) * next = head; next; ) {
    2890                 stack_node(T) * crnt = next;
    2891                 next = crnt->next;
    2892                 ^(*crnt){};
    2893                 free(crnt);
     2925\end{tabular}
     2926\lstMakeShortInline@%
     2927\end{flushleft}
     2928
     2929
     2930\subsection{\CFA}
     2931\label{s:CforallStack}
     2932
     2933\begin{flushleft}
     2934\lstDeleteShortInline@%
     2935\begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}}
     2936\begin{cfa}[xleftmargin=0pt,aboveskip=0pt,belowskip=0pt]
     2937forall( otype T ) {
     2938        struct node {
     2939                T value;
     2940                node(T) * next;
     2941        };
     2942        struct stack { node(T) * head; };
     2943        void ?{}( stack(T) & s, stack(T) t ) { // copy
     2944                node(T) ** cr = &s.head;
     2945                for ( node(T) * nx = t.head; nx; nx = nx->next ) {
     2946                        *cr = alloc();
     2947                        ((*cr)->value){ nx->value };
     2948                        cr = &(*cr)->next;
     2949                }
     2950                *cr = 0;
    28942951        }
    2895         head = 0;
    2896 }
    2897 forall( otype T ) void ?{}( stack(T) & s ) { (s.head){ 0 }; }
    2898 forall( otype T ) void ?{}( stack(T) & s, stack(T) t ) {
    2899         stack_node(T) ** crnt = &s.head;
    2900         for ( stack_node(T) * next = t.head; next; next = next->next ) {
    2901                 *crnt = alloc();
    2902                 ((*crnt)->value){ next->value };
    2903                 crnt = &(*crnt)->next;
    2904         }
    2905         *crnt = 0;
    2906 }
    2907 forall( otype T ) stack(T) ?=?( stack(T) & s, stack(T) t ) {
    2908         if ( s.head == t.head ) return s;
    2909         clear( s );
    2910         s{ t };
    2911         return s;
    2912 }
    2913 forall( otype T ) void ^?{}( stack(T) & s) { clear( s ); }
    2914 forall( otype T ) _Bool empty( const stack(T) & s ) { return s.head == 0; }
    2915 forall( otype T ) void push( stack(T) & s, T value ) with( s ) {
    2916         stack_node(T) * n = alloc();
    2917         (*n){ value, head };
    2918         head = n;
    2919 }
    2920 forall( otype T ) T pop( stack(T) & s ) with( s ) {
    2921         stack_node(T) * n = head;
    2922         head = n->next;
    2923         T v = n->value;
    2924         ^(*n){};
    2925         free( n );
    2926         return v;
    2927 }
    2928 \end{cfa}
    2929 
    2930 \begin{comment}
    2931 forall( otype T ) {
    2932         struct stack_node {
    2933                 T value;
    2934                 stack_node(T) * next;
    2935         };
    2936         struct stack { stack_node(T) * head; };
    29372952        void clear( stack(T) & s ) with( s ) {
    2938                 for ( stack_node(T) * next = head; next; ) {
    2939                         stack_node(T) * crnt = next;
    2940                         next = crnt->next;
    2941                         ^(*crnt){};
    2942                         free(crnt);
     2953                for ( node(T) * nx = head; nx; ) {
     2954                        node(T) * cr = nx;
     2955                        nx = cr->next;
     2956                        ^(*cr){};
     2957                        free( cr );
    29432958                }
    29442959                head = 0;
    29452960        }
     2961
     2962\end{cfa}
     2963&
     2964\begin{cfa}[xleftmargin=0pt,aboveskip=0pt,belowskip=0pt]
    29462965        void ?{}( stack(T) & s ) { (s.head){ 0 }; }
    2947         void ?{}( stack(T) & s, stack(T) t ) {
    2948                 stack_node(T) ** crnt = &s.head;
    2949                 for ( stack_node(T) * next = t.head; next; next = next->next ) {
    2950                         *crnt = alloc();
    2951                         ((*crnt)->value){ next->value };
    2952                         crnt = &(*crnt)->next;
    2953                 }
    2954                 *crnt = 0;
    2955         }
     2966        void ^?{}( stack(T) & s) { clear( s ); }
    29562967        stack(T) ?=?( stack(T) & s, stack(T) t ) {
    29572968                if ( s.head == t.head ) return s;
     
    29602971                return s;
    29612972        }
    2962         void ^?{}( stack(T) & s) { clear( s ); }
    2963         _Bool empty( const stack(T) & s ) { return s.head == 0; }
     2973        _Bool empty( const stack(T) & s ) {
     2974                return s.head == 0;
     2975        }
    29642976        void push( stack(T) & s, T value ) with( s ) {
    2965                 stack_node(T) * n = alloc();
     2977                node(T) * n = alloc();
    29662978                (*n){ value, head };
    29672979                head = n;
    29682980        }
    29692981        T pop( stack(T) & s ) with( s ) {
    2970                 stack_node(T) * n = head;
     2982                node(T) * n = head;
    29712983                head = n->next;
    29722984                T v = n->value;
     
    29762988        }
    29772989}
    2978 \end{comment}
    2979 
    2980 \medskip\noindent
    2981 \CC
    2982 \begin{cfa}[xleftmargin=2\parindentlnth,aboveskip=0pt,belowskip=0pt]
     2990\end{cfa}
     2991\end{tabular}
     2992\lstMakeShortInline@%
     2993\end{flushleft}
     2994
     2995
     2996\subsection{\CC}
     2997
     2998\begin{flushleft}
     2999\lstDeleteShortInline@%
     3000\begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}}
     3001\begin{cfa}[xleftmargin=0pt,aboveskip=0pt,belowskip=0pt]
    29833002template<typename T> struct stack {
    29843003        struct node {
    29853004                T value;
    29863005                node * next;
    2987                 node( const T & v, node * n = nullptr ) : value( v ), next( n ) {}
     3006                node( const T & v, node * n = nullptr ) :
     3007                        value( v ), next( n ) {}
    29883008        };
    29893009        node * head;
    2990         stack() : head( nullptr ) {}
    2991         stack( const stack<T> & o ) { copy( o ); }
     3010        void copy( const stack<T> & o ) {
     3011                node ** cr = &head;
     3012                for ( node * nx = o.head; nx; nx = nx->next ) {
     3013                        *cr = new node{ nx->value }; /***/
     3014                        cr = &(*cr)->next;
     3015                }
     3016                *cr = nullptr;
     3017        }
    29923018        void clear() {
    2993                 for ( node * next = head; next; ) {
    2994                         node * crnt = next;
    2995                         next = crnt->next;
    2996                         delete crnt;
     3019                for ( node * nx = head; nx; ) {
     3020                        node * cr = nx;
     3021                        nx = cr->next;
     3022                        delete cr;
    29973023                }
    29983024                head = nullptr;
    29993025        }
    3000         void copy( const stack<T> & o ) {
    3001                 node ** crnt = &head;
    3002                 for ( node * next = o.head; next; next = next->next ) {
    3003                         *crnt = new node{ next->value }; /***/
    3004                         crnt = &(*crnt)->next;
    3005                 }
    3006                 *crnt = nullptr;
    3007         }
     3026\end{cfa}
     3027&
     3028\begin{cfa}[xleftmargin=0pt,aboveskip=0pt,belowskip=0pt]
     3029        stack() : head( nullptr ) {}
     3030        stack( const stack<T> & o ) { copy( o ); }
    30083031        ~stack() { clear(); }
    3009         stack & operator= ( const stack<T> & o ) {
     3032        stack & operator=( const stack<T> & o ) {
    30103033                if ( this == &o ) return *this;
    30113034                clear();
     
    30133036                return *this;
    30143037        }
    3015         bool empty() const { return head == nullptr; }
    3016         void push( const T & value ) { head = new node{ value, head };  /***/ }
     3038        bool empty() const {
     3039                return head == nullptr;
     3040        }
     3041        void push( const T & value ) {
     3042                head = new node{ value, head };  /***/
     3043        }
    30173044        T pop() {
    30183045                node * n = head;
     
    30233050        }
    30243051};
    3025 \end{cfa}
    3026 
    3027 \medskip\noindent
    3028 \CCV
    3029 \begin{cfa}[xleftmargin=2\parindentlnth,aboveskip=0pt,belowskip=0pt]
     3052
     3053\end{cfa}
     3054\end{tabular}
     3055\lstMakeShortInline@%
     3056\end{flushleft}
     3057
     3058
     3059\subsection{\CCV}
     3060
     3061\begin{flushleft}
     3062\lstDeleteShortInline@%
     3063\begin{tabular}{@{}l|@{\hspace{\parindentlnth}}l@{}}
     3064\begin{cfa}[xleftmargin=0pt,aboveskip=0pt,belowskip=0pt]
    30303065struct stack {
    30313066        struct node {
    30323067                ptr<object> value;
    30333068                node * next;
    3034                 node( const object & v, node * n = nullptr ) : value( v.new_copy() ), next( n ) {}
     3069                node( const object & v, node * n = nullptr ) :
     3070                                value( v.new_copy() ), next( n ) {}
    30353071        };
    30363072        node * head;
     3073        void copy( const stack & o ) {
     3074                node ** cr = &head;
     3075                for ( node * nx = o.head; nx; nx = nx->next ) {
     3076                        *cr = new node{ *nx->value }; /***/
     3077                        cr = &(*cr)->next;
     3078                }
     3079                *cr = nullptr;
     3080        }
    30373081        void clear() {
    3038                 for ( node * next = head; next; ) {
    3039                         node * crnt = next;
    3040                         next = crnt->next;
    3041                         delete crnt;
     3082                for ( node * nx = head; nx; ) {
     3083                        node * cr = nx;
     3084                        nx = cr->next;
     3085                        delete cr;
    30423086                }
    30433087                head = nullptr;
    30443088        }
    3045         void copy( const stack & o ) {
    3046                 node ** crnt = &head;
    3047                 for ( node * next = o.head; next; next = next->next ) {
    3048                         *crnt = new node{ *next->value }; /***/
    3049                         crnt = &(*crnt)->next;
    3050                 }
    3051                 *crnt = nullptr;
    3052         }
     3089\end{cfa}
     3090&
     3091\begin{cfa}[xleftmargin=0pt,aboveskip=0pt,belowskip=0pt]
    30533092        stack() : head( nullptr ) {}
    30543093        stack( const stack & o ) { copy( o ); }
    30553094        ~stack() { clear(); }
    3056         stack & operator= ( const stack & o ) {
     3095        stack & operator=( const stack & o ) {
    30573096                if ( this == &o ) return *this;
    30583097                clear();
     
    30603099                return *this;
    30613100        }
    3062         bool empty() const { return head == nullptr; }
    3063         void push( const object & value ) { head = new node{ value, head }; /***/ }
     3101        bool empty() const {
     3102                return head == nullptr;
     3103        }
     3104        void push( const object & value ) {
     3105                head = new node{ value, head }; /***/
     3106        }
    30643107        ptr<object> pop() {
    30653108                node * n = head;
     
    30703113        }
    30713114};
    3072 \end{cfa}
     3115
     3116\end{cfa}
     3117\end{tabular}
     3118\lstMakeShortInline@%
     3119\end{flushleft}
    30733120
    30743121
  • doc/papers/general/evaluation/c-bench.c

    rf6f0cca3 rff29f08  
    55#include "c-stack.h"
    66
    7 char* new_char( char c ) {
    8         char* q = malloc(sizeof(char)); /***/
     7char * new_char( char c ) {
     8        char* q = malloc( sizeof(char) ); /***/
    99        *q = c;
    1010        return q;
    1111}
    1212
    13 short* new_short( short s ) {
    14         short* q = malloc(sizeof(short)); /***/
     13short * new_short( short s ) {
     14        short* q = malloc( sizeof(short) ); /***/
    1515        *q = s;
    1616        return q;
     
    1818
    1919int* new_int( int i ) {
    20         int* q = malloc(sizeof(int)); /***/
     20        int* q = malloc( sizeof(int) ); /***/
    2121        *q = i;
    2222        return q;
    2323}
    2424
    25 void* copy_char( const void* p ) { return new_char( *(const char*)p ); } /***/
    26 void* copy_short( const void* p ) { return new_short( *(const short*)p ); } /***/
    27 void* copy_int( const void* p ) { return new_int( *(const int*)p ); } /***/
    28 void* copy_pair_short_char( const void* p ) { return copy_pair( p, copy_short, copy_char ); } /***/
    29 void free_pair_short_char( void* p ) { free_pair( p, free, free ); } /***/
     25void * copy_char( const void * p ) { return new_char( *(const char*)p ); } /***/
     26void * copy_short( const void * p ) { return new_short( *(const short*)p ); } /***/
     27void * copy_int( const void * p ) { return new_int( *(const int*)p ); } /***/
     28void * copy_pair_short_char( const void * p ) { return copy_pair( p, copy_short, copy_char ); } /***/
     29void free_pair_short_char( void * p ) { free_pair( p, free, free ); } /***/
    3030
    3131int cmp_char( const void* a, const void* b ) { /***/
     
    3737}
    3838
    39 int main(int argc, char** argv) {
     39int main(int argc, char * argv[] ) {
    4040        int maxi = 0, vali = 42;
    4141        struct stack si = new_stack(), ti;
  • doc/papers/general/evaluation/c-pair.c

    rf6f0cca3 rff29f08  
    22#include "c-pair.h"
    33
    4 struct pair* new_pair(void* first, void* second) {
    5         struct pair* p = malloc(sizeof(struct pair)); /***/
    6         *p = (struct pair){ first, second }; /***/
     4pair * new_pair( void * first, void * second ) {
     5        pair * p = malloc( sizeof(pair) ); /***/
     6        *p = (pair){ first, second }; /***/
    77        return p;
    88}
    99
    10 struct pair* copy_pair(const struct pair* src,
    11                 void* (*copy_first)(const void*), void* (*copy_second)(const void*)) {
     10pair * copy_pair( const pair * src,
     11                void * (* copy_first)(const void* ), void * (* copy_second)(const void *)) {
    1212        return new_pair( copy_first(src->first), copy_second(src->second) );
    1313}
    1414
    15 void free_pair(struct pair* p, void (*free_first)(void*), void (*free_second)(void*)) {
    16         free_first(p->first);
    17         free_second(p->second);
    18         free(p);
     15void free_pair( pair * p, void (* free_first)(void *), void (* free_second)(void *)) {
     16        free_first( p->first );
     17        free_second( p->second );
     18        free( p );
    1919}
    2020
    21 int cmp_pair(const struct pair* a, const struct pair* b,
    22                 int (*cmp_first)(const void*, const void*), int (*cmp_second)(const void*, const void*)) {
    23         int c = cmp_first(a->first, b->first);
    24         if ( c == 0 ) c = cmp_second(a->second, b->second);
     21int cmp_pair( const pair * a, const pair * b,
     22                int (* cmp_first)(const void *, const void *), int (* cmp_second)(const void *, const void *)) {
     23        int c = cmp_first( a->first, b->first );
     24        if ( c == 0 ) c = cmp_second( a->second, b->second );
    2525        return c;
    2626}
  • doc/papers/general/evaluation/c-pair.h

    rf6f0cca3 rff29f08  
    11#pragma once
    22
    3 struct pair {
    4         void* first;
    5         void* second;
    6 };
     3typedef struct pair {
     4        void * first;
     5        void * second;
     6} pair;
    77
    8 struct pair* new_pair(void* first, void* second);
     8pair * new_pair( void * first, void * second );
    99
    10 struct pair* copy_pair(const struct pair* src,
    11         void* (*copy_first)(const void*), void* (*copy_second)(const void*));
     10pair * copy_pair( const pair * src,
     11        void * (* copy_first)(const void *), void * (* copy_second)(const void *));
    1212
    13 void free_pair(struct pair* p, void (*free_first)(void*), void (*free_second)(void*));
     13void free_pair( pair * p, void (* free_first)(void *), void (* free_second)(void *));
    1414
    15 int cmp_pair(const struct pair* a, const struct pair* b,
    16         int (*cmp_first)(const void*, const void*), int (*cmp_second)(const void*, const void*));
     15int cmp_pair( const pair * a, const pair * b,
     16        int (* cmp_first)(const void *, const void *), int (* cmp_second)(const void *, const void *));
  • doc/papers/general/evaluation/c-print.c

    rf6f0cca3 rff29f08  
    44#include "c-print.h"
    55
    6 void print_string(FILE* out, const char* x) { fprintf(out, "%s", x); }
     6void print_string( FILE * out, const char * x ) { fprintf( out, "%s", x ); }
    77
    8 void print_bool(FILE* out, _Bool x) { fprintf(out, "%s", x ? "true" : "false"); }
     8void print_bool( FILE * out, _Bool x ) { fprintf( out, "%s", x ? "true" : "false" ); }
    99
    10 void print_char(FILE* out, char x) {
    11         if ( 0x20 <= x && x <= 0x7E ) { fprintf(out, "'%c'", x); }
    12         else { fprintf(out, "'\\%x'", x); }
     10void print_char( FILE * out, char x ) {
     11        if ( 0x20 <= x && x <= 0x7E ) { fprintf( out, "'%c'", x ); }
     12        else { fprintf( out, "'\\%x'", x ); }
    1313}
    1414
    15 void print_int(FILE* out, int x) { fprintf(out, "%d", x); }
     15void print_int( FILE * out, int x ) { fprintf( out, "%d", x ); }
    1616
    17 void print_fmt(FILE* out, char fmt, void* p) {
     17void print_fmt( FILE * out, char fmt, void * p ) {
    1818        switch( fmt ) {
    19         case 's': print_string(out, (const char*)p); break; /***/
    20         case 'b': print_bool(out, *(_Bool*)p); break; /***/
    21         case 'c': print_char(out, *(char*)p); break; /***/
    22         case 'd': print_int(out, *(int*)p); break; /***/
     19        case 's': print_string( out, (const char*)p ); break; /***/
     20        case 'b': print_bool( out, *(_Bool*)p ); break; /***/
     21        case 'c': print_char( out, *(char*)p ); break; /***/
     22        case 'd': print_int( out, *(int*)p ); break; /***/
    2323        }
    2424}
    2525
    26 void print(FILE* out, const char* fmt, ...) {
     26void print( FILE * out, const char * fmt, ... ) {
    2727        va_list args;
    2828        va_start(args, fmt);
    29         for (const char* it = fmt; *it; ++it) {
     29        for ( const char * it = fmt; *it; ++it ) {
    3030                switch( *it ) {
    31                 case 's': print_string(out, va_arg(args, const char*)); break; /***/
    32                 case 'b': print_bool(out, va_arg(args, int)); break; /***/
    33                 case 'c': print_char(out, va_arg(args, int)); break; /***/
    34                 case 'd': print_int(out, va_arg(args, int)); break; /***/
     31                case 's': print_string( out, va_arg( args, const char * ) ); break; /***/
     32                case 'b': print_bool( out, va_arg( args, int ) ); break; /***/
     33                case 'c': print_char( out, va_arg( args, int ) ); break; /***/
     34                case 'd': print_int( out, va_arg( args, int ) ); break; /***/
    3535                case 'p': {
    36                         const struct pair x = va_arg(args, const struct pair); /***/
    37                         fprintf(out, "[");
    38                         print_fmt(out, *++it, x.first); /***/
    39                         fprintf(out, ", ");
    40                         print_fmt(out, *++it, x.second); /***/
    41                         fprintf(out, "]");
     36                        const struct pair x = va_arg( args, const struct pair ); /***/
     37                        fprintf( out, "[" );
     38                        print_fmt( out, *++it, x.first ); /***/
     39                        fprintf( out, ", " );
     40                        print_fmt( out, *++it, x.second ); /***/
     41                        fprintf( out, "]" );
    4242                        break;
    4343                }
    4444                }
    4545        }
    46         va_end(args);
     46        va_end( args );
    4747}
  • doc/papers/general/evaluation/c-print.h

    rf6f0cca3 rff29f08  
    22#include <stdio.h>
    33
    4 void print_string(FILE* out, const char* x);
    5 void print_bool(FILE* out, _Bool x);
    6 void print_char(FILE* out, char x);
    7 void print_int(FILE* out, int x);
     4void print_string( FILE * out, const char * x );
     5void print_bool( FILE * out, _Bool x );
     6void print_char( FILE * out, char x );
     7void print_int( FILE * out, int x );
    88
    9 void print(FILE* out, const char* fmt, ...);
     9void print( FILE * out, const char * fmt, ... );
  • doc/papers/general/evaluation/c-stack.c

    rf6f0cca3 rff29f08  
    22#include "c-stack.h"
    33
    4 struct stack_node {
     4typedef struct node {
    55        void * value;
    6         struct stack_node * next;
    7 };
     6        struct node * next;
     7} node;
    88
    9 void clear_stack( struct stack * s, void (*free_el)( void * ) ) {
    10         for ( struct stack_node * next = s->head; next; ) {
    11                 struct stack_node * crnt = next;
    12                 next = crnt->next;
    13                 free_el( crnt->value );
    14                 free( crnt );
     9void copy_stack( stack * s, const stack * t, void * (*copy)( const void * ) ) {
     10        node ** cr = &s->head;
     11        for ( node * nx = t->head; nx; nx = nx->next ) {
     12                *cr = malloc( sizeof(node) ); /***/
     13                (*cr)->value = copy( nx->value );
     14                cr = &(*cr)->next;
     15        }
     16        *cr = NULL;
     17}
     18
     19void clear_stack( stack * s, void (* free_el)( void * ) ) {
     20        for ( node * nx = s->head; nx; ) {
     21                node * cr = nx;
     22                nx = cr->next;
     23                free_el( cr->value );
     24                free( cr );
    1525        }
    1626        s->head = NULL;
    1727}
    1828
    19 struct stack new_stack() { return (struct stack){ NULL }; /***/ }
     29stack new_stack() {
     30        return (stack){ NULL }; /***/
     31}
    2032
    21 void copy_stack( struct stack * s, const struct stack * t, void * (*copy)( const void * ) ) {
    22         struct stack_node ** crnt = &s->head;
    23         for ( struct stack_node * next = t->head; next; next = next->next ) {
    24                 *crnt = malloc( sizeof(struct stack_node) ); /***/
    25                 (*crnt)->value = copy( next->value );
    26                 crnt = &(*crnt)->next;
    27         }
    28         *crnt = NULL;
    29 }
    30 struct stack * assign_stack( struct stack * s, const struct stack * t,
     33stack * assign_stack( stack * s, const stack * t,
    3134                void * (*copy_el)( const void * ), void (*free_el)( void * ) ) {
    3235        if ( s->head == t->head ) return s;
     
    3639}
    3740
    38 _Bool stack_empty( const struct stack * s ) { return s->head == NULL; }
     41_Bool stack_empty( const stack * s ) {
     42        return s->head == NULL;
     43}
    3944
    40 void push_stack( struct stack * s, void * v ) {
    41         struct stack_node * n = malloc( sizeof(struct stack_node) ); /***/
    42         *n = (struct stack_node){ v, s->head }; /***/
     45void push_stack( stack * s, void * v ) {
     46        node * n = malloc( sizeof(node) ); /***/
     47        *n = (node){ v, s->head }; /***/
    4348        s->head = n;
    4449}
    4550
    46 void * pop_stack( struct stack * s ) {
    47         struct stack_node * n = s->head;
     51void * pop_stack( stack * s ) {
     52        node * n = s->head;
    4853        s->head = n->next;
    4954        void * v = n->value;
  • doc/papers/general/evaluation/c-stack.h

    rf6f0cca3 rff29f08  
    11#pragma once
    22
    3 struct stack_node;
    4 struct stack {
    5         struct stack_node* head;
    6 };
     3struct node;
     4typedef struct stack {
     5        struct node * head;
     6} stack;
    77
    8 struct stack new_stack();
    9 void copy_stack(struct stack* dst, const struct stack* src, void* (*copy)(const void*));
    10 struct stack* assign_stack(struct stack* dst, const struct stack* src,
    11         void* (*copy_el)(const void*), void (*free_el)(void*));
    12 void clear_stack(struct stack* s, void (*free_el)(void*));
     8void copy_stack(stack * dst, const stack * src, void * (* copy)(const void *));
     9void clear_stack(stack * s, void (*free_el)(void *));
     10stack new_stack();
     11stack * assign_stack( stack * dst, const stack * src,
     12        void * (* copy_el)(const void *), void (* free_el)(void *));
    1313
    14 _Bool stack_empty(const struct stack* s);
    15 void push_stack(struct stack* s, void* value);
    16 void* pop_stack(struct stack* s);
     14_Bool stack_empty( const stack * s );
     15void push_stack( stack * s, void * value );
     16void * pop_stack( stack * s );
  • doc/papers/general/evaluation/cfa-stack.c

    rf6f0cca3 rff29f08  
    22#include "cfa-stack.h"
    33
    4 forall( otype T ) struct stack_node {
    5         T value;
    6         stack_node(T) * next;
    7 };
     4forall( otype T ) {
     5        struct node {
     6                T value;
     7                node(T) * next;
     8        };
    89
    9 forall( otype T ) void clear( stack(T) & s ) with( s ) {
    10         for ( stack_node(T) * next = head; next; ) {
    11                 stack_node(T) * crnt = next;
    12                 next = crnt->next;
    13                 ^(*crnt){};
    14                 free(crnt);
     10        void ?{}( stack(T) & s, stack(T) t ) {          // copy
     11                node(T) ** cr = &s.head;
     12                for ( node(T) * nx = t.head; nx; nx = nx->next ) {
     13                        *cr = alloc();
     14                        ((*cr)->value){ nx->value };
     15                        cr = &(*cr)->next;
     16                }
     17                *cr = 0;
    1518        }
    16         head = 0;
     19
     20        void clear( stack(T) & s ) with( s ) {
     21                for ( node(T) * nx = head; nx; ) {
     22                        node(T) * cr = nx;
     23                        nx = cr->next;
     24                        ^(*cr){};
     25                        free( cr );
     26                }
     27                head = 0;
     28        }
     29
     30        void ?{}( stack(T) & s ) { (s.head){ 0 }; }
     31        void ^?{}( stack(T) & s) { clear( s ); }
     32
     33        stack(T) ?=?( stack(T) & s, stack(T) t ) {
     34                if ( s.head == t.head ) return s;
     35                clear( s );
     36                s{ t };
     37                return s;
     38        }
     39
     40        _Bool empty( const stack(T) & s ) {
     41                return s.head == 0;
     42        }
     43
     44        void push( stack(T) & s, T value ) with( s ) {
     45                node(T) * n = alloc();
     46                (*n){ value, head };
     47                head = n;
     48        }
     49
     50        T pop( stack(T) & s ) with( s ) {
     51                node(T) * n = head;
     52                head = n->next;
     53                T v = n->value;
     54                ^(*n){};
     55                free( n );
     56                return v;
     57        }
    1758}
    18 
    19 forall( otype T ) void ?{}( stack(T) & s ) { (s.head){ 0 }; }
    20 
    21 forall( otype T ) void ?{}( stack(T) & s, stack(T) t ) {
    22         stack_node(T) ** crnt = &s.head;
    23         for ( stack_node(T) * next = t.head; next; next = next->next ) {
    24                 *crnt = alloc();
    25                 ((*crnt)->value){ next->value };
    26                 crnt = &(*crnt)->next;
    27         }
    28         *crnt = 0;
    29 }
    30 
    31 forall( otype T ) stack(T) ?=?( stack(T) & s, stack(T) t ) {
    32         if ( s.head == t.head ) return s;
    33         clear( s );
    34         s{ t };
    35         return s;
    36 }
    37 
    38 forall( otype T ) void ^?{}( stack(T) & s) { clear( s ); }
    39 
    40 forall( otype T ) _Bool empty( const stack(T) & s ) { return s.head == 0; }
    41 
    42 forall( otype T ) void push( stack(T) & s, T value ) with( s ) {
    43         stack_node(T) * n = alloc();
    44         (*n){ value, head };
    45         head = n;
    46 }
    47 
    48 forall( otype T ) T pop( stack(T) & s ) with( s ) {
    49         stack_node(T) * n = head;
    50         head = n->next;
    51         T v = n->value;
    52         ^(*n){};
    53         free( n );
    54         return v;
    55 }
  • doc/papers/general/evaluation/cfa-stack.h

    rf6f0cca3 rff29f08  
    11#pragma once
    22
    3 forall( otype T ) struct stack_node;
    4 forall( otype T ) struct stack {
    5         stack_node(T) * head;
    6 };
     3forall( otype T ) {
     4        struct node;
     5        struct stack {
     6                node(T) * head;
     7        };
    78
    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);
     9        void ?{}( stack(T) & s, stack(T) t );
     10        void clear( stack(T) & s );
     11        void ?{}( stack(T) & s );
     12        void ^?{}( stack(T) & s);
    1213
    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 );
     14        stack(T) ?=?( stack(T) & s, stack(T) t );
     15        _Bool empty( const stack(T) & s );
     16        void push( stack(T) & s, T value );
     17        T pop( stack(T) & s );
     18}
  • doc/papers/general/evaluation/cpp-stack.hpp

    rf6f0cca3 rff29f08  
    1010        node * head;
    1111
    12         stack() : head( nullptr ) {}
    13         stack( const stack<T> & o ) { copy( o ); }
     12        void copy( const stack<T> & o ) {
     13                node ** cr = &head;
     14                for ( node * nx = o.head; nx; nx = nx->next ) {
     15                        *cr = new node{ nx->value }; /***/
     16                        cr = &(*cr)->next;
     17                }
     18                *cr = nullptr;
     19        }
    1420
    1521        void clear() {
    16                 for ( node * next = head; next; ) {
    17                         node * crnt = next;
    18                         next = crnt->next;
    19                         delete crnt;
     22                for ( node * nx = head; nx; ) {
     23                        node * cr = nx;
     24                        nx = cr->next;
     25                        delete cr;
    2026                }
    2127                head = nullptr;
    2228        }
    2329
    24         void copy( const stack<T> & o ) {
    25                 node ** crnt = &head;
    26                 for ( node * next = o.head; next; next = next->next ) {
    27                         *crnt = new node{ next->value }; /***/
    28                         crnt = &(*crnt)->next;
    29                 }
    30                 *crnt = nullptr;
    31         }
    32 
     30        stack() : head( nullptr ) {}
     31        stack( const stack<T> & o ) { copy( o ); }
    3332        ~stack() { clear(); }
    3433
    35         stack & operator= ( const stack<T> & o ) {
     34        stack & operator=( const stack<T> & o ) {
    3635                if ( this == &o ) return *this;
    3736                clear();
     
    4039        }
    4140
    42         bool empty() const { return head == nullptr; }
     41        bool empty() const {
     42                return head == nullptr;
     43        }
    4344
    44         void push( const T & value ) { head = new node{ value, head };  /***/ }
     45        void push( const T & value ) {
     46                head = new node{ value, head };  /***/
     47        }
    4548
    4649        T pop() {
  • doc/papers/general/evaluation/cpp-vstack.cpp

    rf6f0cca3 rff29f08  
    44stack::node::node( const object & v, node * n ) : value( v.new_copy() ), next( n ) {}
    55
     6void stack::copy( const stack & o ) {
     7        node ** cr = &head;
     8        for ( node * nx = o.head; nx; nx = nx->next ) {
     9                *cr = new node{ *nx->value }; /***/
     10                cr = &(*cr)->next;
     11        }
     12        *cr = nullptr;
     13}
     14
    615void stack::clear() {
    7         for ( node * next = head; next; ) {
    8                 node * crnt = next;
    9                 next = crnt->next;
    10                 delete crnt;
     16        for ( node * nx = head; nx; ) {
     17                node * cr = nx;
     18                nx = cr->next;
     19                delete cr;
    1120        }
    1221        head = nullptr;
    13 }
    14 
    15 void stack::copy( const stack & o ) {
    16         node ** crnt = &head;
    17         for ( node * next = o.head; next; next = next->next ) {
    18                 *crnt = new node{ *next->value }; /***/
    19                 crnt = &(*crnt)->next;
    20         }
    21         *crnt = nullptr;
    2222}
    2323
     
    3333}
    3434
    35 bool stack::empty() const { return head == nullptr; }
     35bool stack::empty() const {
     36        return head == nullptr;
     37}
    3638
    37 void stack::push( const object & value ) { head = new node{ value, head }; /***/ }
     39void stack::push( const object & value ) {
     40        head = new node{ value, head }; /***/
     41}
    3842
    3943ptr<object> stack::pop() {
  • doc/papers/general/evaluation/cpp-vstack.hpp

    rf6f0cca3 rff29f08  
    1010        node * head;
    1111
     12        void copy( const stack & o );
    1213        void clear();
    13         void copy( const stack & o );
    1414
    1515        stack();
  • doc/papers/general/evaluation/timing.dat

    rf6f0cca3 rff29f08  
    11"400 million repetitions"       "C"     "\\CFA{}"       "\\CC{}"        "\\CC{obj}"
    2 "push\nint"     3002    2459    1542    3269
    3 "copy\nint"     2985    2057    1539    3083
    4 "clear\nint"    1374    827     756     1469
    5 "pop\nint"      1416    1221    760     5098
    6 "push\npair"    4214    2752    950     6873
    7 "copy\npair"    6127    2105    987     7293
    8 "clear\npair"   2881    885     751     3460
    9 "pop\npair"     3046    5434    822     24962
     2"push\nint"     2911    2034    1504    3246
     3"copy\nint"     2953    1622    1526    3075
     4"clear\nint"    1397    754     753     1452
     5"pop\nint"      1446    1203    760     5016
     6"push\npair"    3673    2297    955     6971
     7"copy\npair"    6027    1183    998     7204
     8"clear\npair"   2840    773     748     3511
     9"pop\npair"     3025    5414    813     23867
     10
  • doc/papers/general/evaluation/timing.gp

    rf6f0cca3 rff29f08  
    2424set yrange [0:10]
    2525
    26 set label "25.0" at 7.125,10.5
    27 
     26set label "23.9" at 7.125,10.5
     27set style fill pattern 4 border lt -1
    2828# set datafile separator ","
    2929plot for [COL=2:5] 'evaluation/timing.dat' using (column(COL)/SCALE):xticlabels(1) title columnheader
Note: See TracChangeset for help on using the changeset viewer.